pax_global_header00006660000000000000000000000064150647051020014512gustar00rootroot0000000000000052 comment=4314f60b41f1210af3be08993e66528aecdb05ec bitsnpicas-2.1.1+ds/000077500000000000000000000000001506470510200142545ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/README.md000066400000000000000000000370701506470510200155420ustar00rootroot00000000000000# Bits'N'Picas Bits'N'Picas is a set of tools for creating and converting bitmap and emoji fonts. Bitmap font functions can be accessed both with a GUI and from a command line. Emoji font functions can only be accessed from a command line. ## Creating and Editing Bitmap Fonts with a GUI Launch the Bits'N'Picas JAR without any arguments or with the `edit` command to open the bitmap font editor GUI. `java -jar BitsNPicas.jar` `java -jar BitsNPicas.jar edit` `java -jar BitsNPicas.jar edit myfont.sfd` The input format is determined by the file extension of the input file. Supported input formats include: * `.kbitx` - Bits'N'Picas 2.x native save format * `.kbits` - Bits'N'Picas 1.x native save format * `.sfd` - FontForge (bitmaps only; outlines not supported) * `.bdf` - X11 Bitmap Distribution Format * `.psf`, `.psfu`, `.psf.gz`, `.psfu.gz` - PC Screen Font * `.suit` - Mac OS Classic font suitcase (in the resource fork) * `.dfont` - Mac OS Classic font suitcase (in the data fork) * `.nfnt` - Mac OS Classic font resource (in the data fork) * `.png` - SFont or RFont, Kreative Software's extension of SFont * `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp` - Create from image (GUI only) * `.bin`, `.rom` - Create from binary file (GUI only) * `.hex` - [GNU Unifont](http://unifoundry.com/unifont/index.html) hex format * `.cvt` - GEOS font in Convert format (including MEGA fonts) * `.fzx` - [FZX by Andrew Owen (for ZX Spectrum)](https://faqwiki.zxnet.co.uk/wiki/FZX_format) * `.u8m` - [U8/M (UTF-8 for Microcomputers)](https://github.com/kreativekorp/u8m) * `.font` - Amiga bitmap font (black and white only; color not supported) * `.fnt` - Windows `.fnt` format (not the same as `.fon`; vector fonts not supported) * `.fnt`, `.ftx` - [IBM DOS/V FONTX2 format](http://elm-chan.org/docs/dosv/fontx_e.html) * `.fnt`, `.mgf`, `.mpf` - MousePaint/MouseGraphics ToolKit font * `.fnt`, `.rbf`, `.rb11`, `.rb12` - [Rockbox Font Format](https://www.rockbox.org/wiki/FontFormat) * `.fnt`, `.fntz`, `.fnty`, `.cyf` - [Cybiko Font Format](https://web.archive.org/web/20010701031854/http://groups.yahoo.com/group/CybikoDev/files/Pazera/font.txt) * `.fnt`, `.png` - Playdate Font Format * `.set` - Apple II Hi-Res Character Generator character set * `.hmzk` - [Mi Band 2 Font Format](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Mi-Band-2-%28HMZK%29-Font-Format) * `.dsf` - [DOSStart! by Daniel L. Nice](https://web.archive.org/web/20120209004900/http://www.icdc.com/~dnice/dosstart.html) * `.sbf` - Sabriel Bitmap Font On Mac OS X you can also launch or drop a font file onto the Bits'N'Picas application. ![](wiki/screenshot.png) Bits'N'Picas can also open font, desk accessory, and system suitcases and move around fonts, desk accessories, scripts, keyboard layouts, and sounds, just like the Finder used to be able to do back in the good old days of System 7. ![](wiki/suitcases.png) A similar interface also exists for GEOS fonts. ![](wiki/geosfonts.png) ## Converting Bitmap Fonts Example: `java -jar BitsNPicas.jar convertbitmap -f ttf -o myfont.ttf myfont.sfd` This will convert the bitmap strikes in the FontForge file `myfont.sfd` to outlines in a new TrueType font file `myfont.ttf`. If, for example, the bitmap strikes are 16 pixels in height, the generated outlines will perfectly match the pixel grid at a 16-point font size. The input format is determined by the file extension of the input file. Supported input formats include: * `.kbitx` - Bits'N'Picas 2.x native save format * `.kbits` - Bits'N'Picas 1.x native save format * `.sfd` - FontForge (bitmaps only; outlines not supported) * `.bdf` - X11 Bitmap Distribution Format * `.psf`, `.psfu`, `.psf.gz`, `.psfu.gz` - PC Screen Font * `.suit` - Mac OS Classic font suitcase (in the resource fork) * `.dfont` - Mac OS Classic font suitcase (in the data fork) * `.nfnt` - Mac OS Classic font resource (in the data fork) * `.png` - SFont or RFont, Kreative Software's extension of SFont * `.hex` - [GNU Unifont](http://unifoundry.com/unifont/index.html) hex format * `.cvt` - GEOS font in Convert format (including MEGA fonts) * `.fzx` - [FZX by Andrew Owen (for ZX Spectrum)](https://faqwiki.zxnet.co.uk/wiki/FZX_format) * `.u8m` - [U8/M (UTF-8 for Microcomputers)](https://github.com/kreativekorp/u8m) * `.font` - Amiga bitmap font (black and white only; color not supported) * `.fnt` - Windows `.fnt` format (not the same as `.fon`; vector fonts not supported) * `.fnt`, `.ftx` - [IBM DOS/V FONTX2 format](http://elm-chan.org/docs/dosv/fontx_e.html) * `.fnt`, `.mgf`, `.mpf` - MousePaint/MouseGraphics ToolKit font * `.fnt`, `.rbf`, `.rb11`, `.rb12` - [Rockbox Font Format](https://www.rockbox.org/wiki/FontFormat) * `.fnt`, `.fntz`, `.fnty`, `.cyf` - [Cybiko Font Format](https://web.archive.org/web/20010701031854/http://groups.yahoo.com/group/CybikoDev/files/Pazera/font.txt) * `.fnt`, `.png` - Playdate Font Format * `.set` - Apple II Hi-Res Character Generator character set * `.hmzk` - [Mi Band 2 Font Format](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Mi-Band-2-%28HMZK%29-Font-Format) * `.dsf` - [DOSStart! by Daniel L. Nice](https://web.archive.org/web/20120209004900/http://www.icdc.com/~dnice/dosstart.html) * `.sbf` - Sabriel Bitmap Font The output format is determined by the `-f` option. Supported output formats include: * `kbitx` or `kbnp2` - Bits'N'Picas 2.x native save format * `kbits` or `kbnp1` - Bits'N'Picas 1.x native save format * `ttf` or `truetype` - TrueType * `otb` - OpenType Bitmap * `bdf` - X11 Bitmap Distribution Format * `psf`, `psf2`, `psf1`, `psfgz`, `psf2gz`, `psf1gz` - PC Screen Font * `suit` - Mac OS Classic font suitcase (in the resource fork) * `dfont` - Mac OS Classic font suitcase (in the data fork) * `nfnt` - Mac OS Classic font resource (in the data fork) * `png` or `sfont` - SDL SFont * `rfont` - RFont, Kreative Software's extension of SFont * `hex` - [GNU Unifont](http://unifoundry.com/unifont/index.html) hex format * `cvt` or `geos` - GEOS font in Convert format (with MEGA option) * `fzx` - [FZX by Andrew Owen (for ZX Spectrum)](https://faqwiki.zxnet.co.uk/wiki/FZX_format) * `u8m` - [U8/M (UTF-8 for Microcomputers)](https://github.com/kreativekorp/u8m) * `font` or `amiga` - Amiga bitmap font (black and white only; color not supported) * `fnt` or `fnt3` - Windows 3.x `.fnt` format (not the same as `.fon`) * `fnt2` - Windows 2.x `.fnt` format (also not the same as `.fon`) * `fontx2`, `fontx`, or `dosv` - [IBM DOS/V FONTX2 format](http://elm-chan.org/docs/dosv/fontx_e.html) * `mgtk`, `mgf`, `mpf`, or `mousepaint` - MousePaint/MouseGraphics ToolKit font * `rb12` - [Rockbox Font Format](https://www.rockbox.org/wiki/FontFormat) for Rockbox 2.3 or above * `rb11` - [Rockbox Font Format](https://www.rockbox.org/wiki/FontFormat) for Rockbox 2.2 or below and iPodLinux * `cybiko` - [Cybiko Font Format](https://web.archive.org/web/20010701031854/http://groups.yahoo.com/group/CybikoDev/files/Pazera/font.txt) * `playdate`, `playdate-allinone`, `playdate-fnt` - Playdate font format, all-in-one (single .fnt file) * `playdate-separate`, `playdate-fnt+png` - Playdate font format, separate .fnt and .png files * `hrcg` or `set` - Apple II Hi-Res Character Generator character set * `hmzk` - [Mi Band 2 Font Format](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Mi-Band-2-%28HMZK%29-Font-Format) * `sbf` - Sabriel Bitmap Font Additional options include: * `-s` *regex* `-r` *replacement* - Perform a search-and-replace on the font name. * `-b` - Apply a faux-bold effect. * `-w` *units* `-h` *units* - Specify the width and height of pixels in em units (for `ttf` format). * `-i` *fontid* `-z` *size* - Specify the font ID and font size (for `nfnt` or `geos` format). You can see a list of all options using the `--help` option. ## Extracting Images from Emoji/Color Fonts ### Example using Apple's `sbix` format `java -jar BitsNPicas.jar extractsbix AppleColorEmoji.ttf` This will extract the images from `AppleColorEmoji.ttf` into the directory `AppleColorEmoji.ttf.sbix.d` as PNG files. There will be several numbered subdirectories within this directory; the number corresponds to the *pixels per em* of the images within. (This is not necessarily the same thing as the image height!) The resulting directory structure will look like: ``` AppleColorEmoji.ttf AppleColorEmoji.ttf.sbix.d 20 glyph_43.png glyph_44.png ... 32 glyph_43.png glyph_44.png ... ... ``` ### Example using Adobe and Mozilla's SVG-in-OpenType format `java -jar BitsNPicas.jar extractsvg EmojiOne.otf` This will extract the SVG images from `EmojiOne.otf` into the directory `EmojiOne.otf.svg.d` as uncompressed SVG files. (If the SVG data inside the font is compressed, it will be decompressed.) The resulting directory structure will look like: ``` EmojiOne.otf EmojiOne.otf.svg.d glyph_2.svg glyph_3.svg ... ``` ### Example using Google's `CBDT`/`CBLC` format `java -jar BitsNPicas.jar extractcbdt NotoColorEmoji.ttf` This will extract the PNG images from `NotoColorEmoji.ttf` into the directory `NotoColorEmoji.ttf.cbdt.d`. There will be one or more numbered subdirectories within this directory; the number is simply the index of the BitmapSize record and has no other significance. The resulting directory structure will look like: ``` NotoColorEmoji.ttf NotoColorEmoji.ttf.cbdt.d 0000 glyph_4.png glyph_5.png .... metadata.txt .... fontinfo.txt ``` The `metadata.txt` file within each subdirectory lists all the values from the various data structures within the `CBLC` and `CBDT` tables. The `fontinfo.txt` file just lists some other values from other, unrelated tables for convenience (since many font editors cannot open fonts with `CBDT`/`CBLC` tables for you to find these values due to the lack of `glyf`/`loca` tables). ### Microsoft's `COLR`/`CPAL` format Microsoft's `COLR`/`CPAL` format is currently not supported. ## Injecting Images into Fonts to Create Emoji/Color Fonts To create an emoji/color font, you will need two things: * A plain black-and-white TrueType font into which you intend to inject the color images. * The accompanying directory of images, in the same structure and format as generated by the extraction process above. ### Example using Apple's `sbix` format `java -jar BitsNPicas.jar injectsbix MyEmoji.ttf` This will take the TrueType font file `MyEmoji.ttf` and the images in the directory `MyEmoji.ttf.sbix.d` and generate a new TrueType font file `MyEmoji.ttf.sbix.ttf` with images embedded in an `sbix` table. You can then rename this file if you like. The name of each subdirectory within the image directory must be the *pixels per em* of the images it contains. (This is not necessarily the same thing as the image height!) The file name of each image within each subdirectory must be of the form `glyph_123.png` (with the glyph index in decimal) or `char_ABCD.png` (with the Unicode code point in hexadecimal). The bottom left position of each image will be determined by the minimum X and Y coordinates of the corresponding glyph in the TrueType font file. (For Apple Color Emoji, this just happens to be set to 0,0.) ### Example using Adobe and Mozilla's SVG-in-OpenType format `java -jar BitsNPicas.jar injectsvg MyEmoji.otf` This will take the OpenType font file `MyEmoji.otf` and the SVG images in the directory `MyEmoji.otf.svg.d` and generate a new OpenType font file `MyEmoji.otf.svg.otf` with images embedded in an `SVG ` table. You can then rename this file if you like. The file name of each image within the image directory must be of the form `glyph_123_456.svg` (for a range of glyphs, with the glyph indices in decimal), `glyph_123.svg` (for a single glyph, with the glyph index in decimal), or `char_ABCD.svg` (for a single glyph, with the Unicode code point in hexadecimal). For each glyph index mapped to an SVG document, there must be an element in that document with an id corresponding to that glyph index (e.g. `id="glyph123"` for glyph index 123). Since you may not know the glyph index when specifying a code point in the image file name, you can use the placeholder `id="glyph{{{0}}}"` and it will be replaced with the appropriate glyph index during the injection process. If you specify the `-z` option before the font file name, the SVG data will be compressed using GZIP. Microsoft claims the SVG-in-OpenType format supports this, and the availability of a version of EmojiOne with GZIP-compressed SVG glyphs appears to back this up. However, I was unable to get fonts with GZIP-compressed SVG glyphs to work even in the latest version of Firefox as of this writing, so I do not recommend this. If you have a bunch of non-SVG images you would like to inject using this format, you can easily generate SVGs with embedded images using a command like the following: `java -jar BitsNPicas.jar imagetosvg -x 0 -y -700 -w 800 -h 800 myimages/*.png` This will create a corresponding SVG file for each non-SVG image file specified. The `-x`, `-y`, `-w`, `-h` options specify the position and size of the image in em units. Note that the SVG Y-axis is reversed from the TrueType Y-axis, so negative Y-coordinates are *above* the baseline and positive Y-coordinates are *below* the baseline. ### Example using Google's `CBDT`/`CBLC` format `java -jar BitsNPicas.jar injectcbdt MyEmoji.ttf` This will take the TrueType font file `MyEmoji.ttf` and the PNG images in the directory `MyEmoji.ttf.cbdt.d` and generate a new TrueType font file `MyEmoji.ttf.cbdt.ttf` with images embedded in a `CBDT` table. You can then rename this file if you like. There must be a subdirectory for each bitmap size; the names of the subdirectories do not matter. The file name of each image within each subdirectory must be of the form `glyph_123.png` (with the glyph index in decimal) or `char_ABCD.png` (with the Unicode code point in hexadecimal). It is recommended for each subdirectory to also contain a `metadata.txt` file of values to use for the various data structures within the `CBLC` and `CBDT` tables. The following is recommended at a minimum: ``` horiAscender: *ascent in pixels (normally positive)* horiDescender: *descent in pixels (normally negative)* horiWidthMax: *max character width in pixels* vertAscender: *ascent in pixels (normally positive)* vertDescender: *descent in pixels (normally negative)* vertWidthMax: *max character width in pixels* ppemX: *pixels per em* ppemY: *pixels per em* glyph: *glyph index* height: *image height in pixels* width: *image width in pixels* bearingX: *x offset in pixels* bearingY: *y offset in pixels (positive is above the baseline)* advance: *character width in pixels* endGlyph ``` For the glyph index you can also use `char_ABCD` (with the Unicode code point in hexadecimal) or `*` to cover all glyphs not otherwise specified. Fields associated with the data structure itself (various offsets, counts, and glyph index ranges, as well as anything associated with the various types of index subtables) do not need to be specified, will be ignored if specified, and will be calculated automatically. (Only index subtable format 1 and bitmap data formats 17, 18, and 19 will be used, regardless of the metadata specified.) By default, `injectcbdt` will also remove any `glyf`, `loca`, `CFF `, or `CFF2` tables from the font. To keep these tables, specify the `-g` option before the font file name. ### Microsoft's `COLR`/`CPAL` format Microsoft's `COLR`/`CPAL` format is currently not supported. bitsnpicas-2.1.1+ds/main/000077500000000000000000000000001506470510200152005ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/000077500000000000000000000000001506470510200161215ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/000077500000000000000000000000001506470510200201205ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/.classpath000077500000000000000000000004231506470510200221050ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/.gitignore000066400000000000000000000001011506470510200221000ustar00rootroot00000000000000/bin/ /dev/ /doc/ /safespace/ /*.app /*.dmg /*.jar /*.tgz /*.zip bitsnpicas-2.1.1+ds/main/java/BitsNPicas/.project000077500000000000000000000005611506470510200215740ustar00rootroot00000000000000 BitsNPicas org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature bitsnpicas-2.1.1+ds/main/java/BitsNPicas/.settings/000077500000000000000000000000001506470510200220365ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/.settings/org.eclipse.core.resources.prefs000066400000000000000000000001001506470510200302400ustar00rootroot00000000000000eclipse.preferences.version=1 encoding//dep/PkgInfo-ME=MacRoman bitsnpicas-2.1.1+ds/main/java/BitsNPicas/LICENSE000066400000000000000000001042531506470510200211320ustar00rootroot00000000000000Copyright © 2008-2015 Rebecca G. Bettencourt, Kreative Software The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Alternatively, the contents of this file may be used under the terms of the GNU Lesser General Public License (the "LGPL License"), in which case the provisions of LGPL License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the LGPL License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the LGPL License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the LGPL License. =============================================================================== MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is Kreative Java Library. The Initial Developer of the Original Code is Rebecca G. Bettencourt. Portions created by Rebecca G. Bettencourt are Copyright (C) 2007 Kreative Software. All Rights Reserved. Contributor(s): none at present. Alternatively, the contents of this file may be used under the terms of the GNU Lesser General Public License (the "LGPL License"), in which case the provisions of LGPL License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the LGPL License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the LGPL License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the LGPL License." [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] =============================================================================== GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License. “The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”. The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: * a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or * b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: * a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. * b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: * a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. * b) Accompany the Combined Work with a copy of the GNU GPL and this license document. * c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. * d) Do one of the following: o 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. o 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. * e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: * a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. * b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. bitsnpicas-2.1.1+ds/main/java/BitsNPicas/Makefile000066400000000000000000000257701506470510200215730ustar00rootroot00000000000000SRCFILES := $(shell find src -name \*.java) RESFILES := $(shell find src -type f \! -name .\* \! -name \*.java | sed s/^src\\///) PACKAGES := $(shell find src -name \*.java | sed -E s/^src\\/\|\\/[^\\/]+$$//g | grep -v \\.java$$ | sort | uniq | tr / .) all: clean bin doc BitsNPicas.jar BitsNPicas.app BitsNPicas.app.zip BitsNPicas-src.tgz MapEdit.jar MapEdit.app MapEdit.app.zip MapEdit-src.tgz KeyEdit.jar KeyEdit.app KeyEdit.app.zip KeyEdit-src.tgz eclipseall: eclipseclean BitsNPicas.jar BitsNPicas.app BitsNPicas.app.zip BitsNPicas-src.tgz MapEdit.jar MapEdit.app MapEdit.app.zip MapEdit-src.tgz KeyEdit.jar KeyEdit.app KeyEdit.app.zip KeyEdit-src.tgz clean: rm -rf bin rm -rf doc rm -rf BitsNPicas*.jar rm -rf BitsNPicas*.tgz rm -rf BitsNPicas*.app rm -rf BitsNPicas*.zip rm -rf MapEdit*.jar rm -rf MapEdit*.tgz rm -rf MapEdit*.app rm -rf MapEdit*.zip rm -rf KeyEdit*.jar rm -rf KeyEdit*.tgz rm -rf KeyEdit*.app rm -rf KeyEdit*.zip eclipseclean: rm -rf BitsNPicas*.jar rm -rf BitsNPicas*.tgz rm -rf BitsNPicas*.app rm -rf BitsNPicas*.zip rm -rf MapEdit*.jar rm -rf MapEdit*.tgz rm -rf MapEdit*.app rm -rf MapEdit*.zip rm -rf KeyEdit*.jar rm -rf KeyEdit*.tgz rm -rf KeyEdit*.app rm -rf KeyEdit*.zip bin: src mkdir -p bin ifeq ($(origin JAVACFLAGS), undefined) $(eval JAVACFLAGS = $(shell dep/minJavaVerOpts)) endif javac $(JAVACFLAGS) -classpath dep/ual.jar -sourcepath src $(SRCFILES) -d bin $(foreach res,$(RESFILES),cp src/$(res) bin/$(res);) doc: src mkdir -p doc javadoc $(JAVADOCFLAGS) -classpath dep/ual.jar -sourcepath src $(PACKAGES) -d doc BitsNPicas.jar: bin export COPYFILE_DISABLE=true find bin -name .DS_Store -delete jar cmf dep/MANIFEST.MF BitsNPicas.jar -C bin com/kreative/unicode -C bin com/kreative/bitsnpicas chmod +x BitsNPicas.jar BitsNPicas.app: BitsNPicas-Pre10.15.app BitsNPicas-MacOS10.15.app BitsNPicas-MacOS11.0.app BitsNPicas-Pre10.15.app: dep BitsNPicas.jar mkdir -p BitsNPicas-Pre10.15.app/Contents/MacOS mkdir -p BitsNPicas-Pre10.15.app/Contents/Resources/Java cp -f dep/PkgInfo BitsNPicas-Pre10.15.app/Contents cp -f dep/Info.plist BitsNPicas-Pre10.15.app/Contents cp -f dep/universalJavaApplicationStub-Pre10.15 BitsNPicas-Pre10.15.app/Contents/MacOS/BitsNPicas cp -f dep/kbnp*.icns dep/dmov*.icns dep/movr*.icns BitsNPicas-Pre10.15.app/Contents/Resources cp -f dep/*.jar BitsNPicas-Pre10.15.app/Contents/Resources/Java cp -f BitsNPicas.jar BitsNPicas-Pre10.15.app/Contents/Resources/Java BitsNPicas-MacOS10.15.app: dep BitsNPicas.jar mkdir -p BitsNPicas-MacOS10.15.app/Contents/MacOS mkdir -p BitsNPicas-MacOS10.15.app/Contents/Resources/Java cp -f dep/PkgInfo BitsNPicas-MacOS10.15.app/Contents cp -f dep/Info.plist BitsNPicas-MacOS10.15.app/Contents cp -f dep/universalJavaApplicationStub-MacOS10.15 BitsNPicas-MacOS10.15.app/Contents/MacOS/BitsNPicas cp -f dep/kbnp*.icns dep/dmov*.icns dep/movr*.icns BitsNPicas-MacOS10.15.app/Contents/Resources cp -f dep/*.jar BitsNPicas-MacOS10.15.app/Contents/Resources/Java cp -f BitsNPicas.jar BitsNPicas-MacOS10.15.app/Contents/Resources/Java BitsNPicas-MacOS11.0.app: dep BitsNPicas.jar mkdir -p BitsNPicas-MacOS11.0.app/Contents/MacOS mkdir -p BitsNPicas-MacOS11.0.app/Contents/Resources/Java cp -f dep/PkgInfo BitsNPicas-MacOS11.0.app/Contents cp -f dep/Info.plist BitsNPicas-MacOS11.0.app/Contents cp -f dep/universalJavaApplicationStub-MacOS11.0 BitsNPicas-MacOS11.0.app/Contents/MacOS/BitsNPicas cp -f dep/kbnp*.icns dep/dmov*.icns dep/movr*.icns BitsNPicas-MacOS11.0.app/Contents/Resources cp -f dep/*.jar BitsNPicas-MacOS11.0.app/Contents/Resources/Java cp -f BitsNPicas.jar BitsNPicas-MacOS11.0.app/Contents/Resources/Java BitsNPicas.app.zip: BitsNPicas.app zip -r BitsNPicas.app.zip BitsNPicas*.app BitsNPicas.dmg: BitsNPicas.app mkdir -p dmgtmp cp -R BitsNPicas-Pre10.15.app dmgtmp cp -R BitsNPicas-MacOS10.15.app dmgtmp cp -R BitsNPicas-MacOS11.0.app dmgtmp cp BitsNPicas.jar dmgtmp hdiutil create -fs HFS+ -volname "Bits'n'Picas" -srcfolder dmgtmp BitsNPicas.dmg rm -rf dmgtmp BitsNPicas-src.tgz: src export COPYFILE_DISABLE=true find src -name .DS_Store -delete tar -czf BitsNPicas-src.tgz LICENSE src/com/kreative/unicode src/com/kreative/bitsnpicas MapEdit.jar: bin export COPYFILE_DISABLE=true find bin -name .DS_Store -delete jar cmf dep/MANIFEST-ME.MF MapEdit.jar -C bin com/kreative/unicode -C bin com/kreative/mapedit chmod +x MapEdit.jar MapEdit.app: MapEdit-Pre10.15.app MapEdit-MacOS10.15.app MapEdit-MacOS11.0.app MapEdit-Pre10.15.app: dep MapEdit.jar mkdir -p MapEdit-Pre10.15.app/Contents/MacOS mkdir -p MapEdit-Pre10.15.app/Contents/Resources/Java cp -f dep/PkgInfo-ME MapEdit-Pre10.15.app/Contents/PkgInfo cp -f dep/Info-ME.plist MapEdit-Pre10.15.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-Pre10.15 MapEdit-Pre10.15.app/Contents/MacOS/MapEdit cp -f dep/mapedit*.icns MapEdit-Pre10.15.app/Contents/Resources cp -f dep/ual.jar MapEdit-Pre10.15.app/Contents/Resources/Java cp -f MapEdit.jar MapEdit-Pre10.15.app/Contents/Resources/Java MapEdit-MacOS10.15.app: dep MapEdit.jar mkdir -p MapEdit-MacOS10.15.app/Contents/MacOS mkdir -p MapEdit-MacOS10.15.app/Contents/Resources/Java cp -f dep/PkgInfo-ME MapEdit-MacOS10.15.app/Contents/PkgInfo cp -f dep/Info-ME.plist MapEdit-MacOS10.15.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-MacOS10.15 MapEdit-MacOS10.15.app/Contents/MacOS/MapEdit cp -f dep/mapedit*.icns MapEdit-MacOS10.15.app/Contents/Resources cp -f dep/ual.jar MapEdit-MacOS10.15.app/Contents/Resources/Java cp -f MapEdit.jar MapEdit-MacOS10.15.app/Contents/Resources/Java MapEdit-MacOS11.0.app: dep MapEdit.jar mkdir -p MapEdit-MacOS11.0.app/Contents/MacOS mkdir -p MapEdit-MacOS11.0.app/Contents/Resources/Java cp -f dep/PkgInfo-ME MapEdit-MacOS11.0.app/Contents/PkgInfo cp -f dep/Info-ME.plist MapEdit-MacOS11.0.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-MacOS11.0 MapEdit-MacOS11.0.app/Contents/MacOS/MapEdit cp -f dep/mapedit*.icns MapEdit-MacOS11.0.app/Contents/Resources cp -f dep/ual.jar MapEdit-MacOS11.0.app/Contents/Resources/Java cp -f MapEdit.jar MapEdit-MacOS11.0.app/Contents/Resources/Java MapEdit.app.zip: MapEdit.app zip -r MapEdit.app.zip MapEdit*.app MapEdit.dmg: MapEdit.app mkdir -p dmgtmp cp -R MapEdit-Pre10.15.app dmgtmp cp -R MapEdit-MacOS10.15.app dmgtmp cp -R MapEdit-MacOS11.0.app dmgtmp cp MapEdit.jar dmgtmp hdiutil create -fs HFS+ -volname "MapEdit" -srcfolder dmgtmp MapEdit.dmg rm -rf dmgtmp MapEdit-src.tgz: src export COPYFILE_DISABLE=true find src -name .DS_Store -delete tar -czf MapEdit-src.tgz LICENSE src/com/kreative/unicode src/com/kreative/mapedit KeyEdit.jar: bin export COPYFILE_DISABLE=true find bin -name .DS_Store -delete jar cmf dep/MANIFEST-KE.MF KeyEdit.jar -C bin com/kreative/unicode -C bin com/kreative/keyedit chmod +x KeyEdit.jar KeyEdit.app: KeyEdit-Pre10.15.app KeyEdit-MacOS10.15.app KeyEdit-MacOS11.0.app KeyEdit-Pre10.15.app: dep KeyEdit.jar mkdir -p KeyEdit-Pre10.15.app/Contents/MacOS mkdir -p KeyEdit-Pre10.15.app/Contents/Resources/Java cp -f dep/PkgInfo-KE KeyEdit-Pre10.15.app/Contents/PkgInfo cp -f dep/Info-KE.plist KeyEdit-Pre10.15.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-Pre10.15 KeyEdit-Pre10.15.app/Contents/MacOS/KeyEdit cp -f dep/keyedit*.icns KeyEdit-Pre10.15.app/Contents/Resources cp -f dep/ual.jar KeyEdit-Pre10.15.app/Contents/Resources/Java cp -f KeyEdit.jar KeyEdit-Pre10.15.app/Contents/Resources/Java KeyEdit-MacOS10.15.app: dep KeyEdit.jar mkdir -p KeyEdit-MacOS10.15.app/Contents/MacOS mkdir -p KeyEdit-MacOS10.15.app/Contents/Resources/Java cp -f dep/PkgInfo-KE KeyEdit-MacOS10.15.app/Contents/PkgInfo cp -f dep/Info-KE.plist KeyEdit-MacOS10.15.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-MacOS10.15 KeyEdit-MacOS10.15.app/Contents/MacOS/KeyEdit cp -f dep/keyedit*.icns KeyEdit-MacOS10.15.app/Contents/Resources cp -f dep/ual.jar KeyEdit-MacOS10.15.app/Contents/Resources/Java cp -f KeyEdit.jar KeyEdit-MacOS10.15.app/Contents/Resources/Java KeyEdit-MacOS11.0.app: dep KeyEdit.jar mkdir -p KeyEdit-MacOS11.0.app/Contents/MacOS mkdir -p KeyEdit-MacOS11.0.app/Contents/Resources/Java cp -f dep/PkgInfo-KE KeyEdit-MacOS11.0.app/Contents/PkgInfo cp -f dep/Info-KE.plist KeyEdit-MacOS11.0.app/Contents/Info.plist cp -f dep/universalJavaApplicationStub-MacOS11.0 KeyEdit-MacOS11.0.app/Contents/MacOS/KeyEdit cp -f dep/keyedit*.icns KeyEdit-MacOS11.0.app/Contents/Resources cp -f dep/ual.jar KeyEdit-MacOS11.0.app/Contents/Resources/Java cp -f KeyEdit.jar KeyEdit-MacOS11.0.app/Contents/Resources/Java KeyEdit.app.zip: KeyEdit.app zip -r KeyEdit.app.zip KeyEdit*.app KeyEdit.dmg: KeyEdit.app mkdir -p dmgtmp cp -R KeyEdit-Pre10.15.app dmgtmp cp -R KeyEdit-MacOS10.15.app dmgtmp cp -R KeyEdit-MacOS11.0.app dmgtmp cp KeyEdit.jar dmgtmp hdiutil create -fs HFS+ -volname "KeyEdit" -srcfolder dmgtmp KeyEdit.dmg rm -rf dmgtmp KeyEdit-src.tgz: src export COPYFILE_DISABLE=true find src -name .DS_Store -delete tar -czf KeyEdit-src.tgz LICENSE src/com/kreative/unicode src/com/kreative/keyedit install: dep BitsNPicas.jar MapEdit.jar KeyEdit.jar sudo mkdir -p /usr/local/lib/ sudo cp -f BitsNPicas.jar /usr/local/lib/bitsnpicas.jar sudo cp -f MapEdit.jar /usr/local/lib/mapedit.jar sudo cp -f KeyEdit.jar /usr/local/lib/keyedit.jar sudo cp -f dep/ual.jar /usr/local/lib/ual.jar sudo chmod -f 644 /usr/local/lib/bitsnpicas.jar sudo chmod -f 644 /usr/local/lib/mapedit.jar sudo chmod -f 644 /usr/local/lib/keyedit.jar sudo chmod -f 644 /usr/local/lib/ual.jar sudo mkdir -p /usr/local/bin/ sudo cp -f dep/bitsnpicas /usr/local/bin/bitsnpicas sudo cp -f dep/mapedit /usr/local/bin/mapedit sudo cp -f dep/keyedit /usr/local/bin/keyedit sudo chmod -f 755 /usr/local/bin/bitsnpicas sudo chmod -f 755 /usr/local/bin/mapedit sudo chmod -f 755 /usr/local/bin/keyedit sudo mkdir -p /usr/share/icons/hicolor/128x128/apps/ sudo mkdir -p /usr/share/icons/hicolor/256x256/apps/ sudo mkdir -p /usr/share/icons/hicolor/512x512/apps/ sudo cp -f dep/bitsnpicas.png /usr/share/icons/hicolor/128x128/apps/bitsnpicas.png sudo cp -f dep/kbnp-icon.png /usr/share/icons/hicolor/512x512/apps/bitsnpicas.png sudo cp -f dep/mapedit-icon.png /usr/share/icons/hicolor/512x512/apps/mapedit.png sudo cp -f dep/keyedit-icon.png /usr/share/icons/hicolor/256x256/apps/keyedit.png sudo chmod -f 644 /usr/share/icons/hicolor/128x128/apps/bitsnpicas.png sudo chmod -f 644 /usr/share/icons/hicolor/512x512/apps/bitsnpicas.png sudo chmod -f 644 /usr/share/icons/hicolor/512x512/apps/mapedit.png sudo chmod -f 644 /usr/share/icons/hicolor/256x256/apps/keyedit.png sudo mkdir -p /usr/share/applications/ sudo cp -f dep/bitsnpicas.desktop /usr/share/applications/bitsnpicas.desktop sudo cp -f dep/mapedit.desktop /usr/share/applications/mapedit.desktop sudo cp -f dep/keyedit.desktop /usr/share/applications/keyedit.desktop sudo chmod -f 644 /usr/share/applications/bitsnpicas.desktop sudo chmod -f 644 /usr/share/applications/mapedit.desktop sudo chmod -f 644 /usr/share/applications/keyedit.desktop .PHONY: all eclipseall clean eclipseclean BitsNPicas.app MapEdit.app KeyEdit.app install bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/000077500000000000000000000000001506470510200206705ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/Info-KE.plist000066400000000000000000000051701506470510200231400ustar00rootroot00000000000000 CFBundleAllowMixedLocalizations true CFBundleDevelopmentRegion English CFBundleExecutable KeyEdit CFBundleGetInfoString KeyEdit © Kreative Software CFBundleIconFile keyedit-icon.icns CFBundleIdentifier com.kreative.keyedit CFBundleInfoDictionaryVersion 6.0 CFBundleName KeyEdit CFBundlePackageType APPL CFBundleShortVersionString 1.2.1 CFBundleSignature Bnjo CFBundleVersion 1.2.1 NSHighResolutionCapable JavaX ClassPath $JAVAROOT/KeyEdit.jar:$JAVAROOT/ual.jar JVMVersion 1.5+ MainClass com.kreative.keyedit.Main Properties apple.laf.useScreenMenuBar true com.apple.mrj.application.apple.menu.about.name KeyEdit VMOptions -Xmx1024M WorkingDirectory $APP_PACKAGE/.. CFBundleDocumentTypes CFBundleTypeExtensions kkbx CFBundleTypeName KeyEdit Keyboard Layout LSHandlerRank Owner CFBundleTypeIconFile keyedit-doc CFBundleTypeRole Editor CFBundleTypeExtensions keylayout CFBundleTypeName Mac OS X Keyboard Layout LSHandlerRank Default CFBundleTypeIconFile keyedit-doc CFBundleTypeRole Editor CFBundleTypeExtensions klc CFBundleTypeName Microsoft Keyboard Layout Creator Source LSHandlerRank Default CFBundleTypeIconFile keyedit-doc CFBundleTypeRole Editor bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/Info-ME.plist000066400000000000000000000036531506470510200231460ustar00rootroot00000000000000 CFBundleAllowMixedLocalizations true CFBundleDevelopmentRegion English CFBundleExecutable MapEdit CFBundleGetInfoString MapEdit © Kreative Software CFBundleIconFile mapedit-icon.icns CFBundleIdentifier com.kreative.mapedit CFBundleInfoDictionaryVersion 6.0 CFBundleName MapEdit CFBundlePackageType APPL CFBundleShortVersionString 1.2.1 CFBundleSignature ÇEEd CFBundleVersion 1.2.1 NSHighResolutionCapable JavaX ClassPath $JAVAROOT/MapEdit.jar:$JAVAROOT/ual.jar JVMVersion 1.5+ MainClass com.kreative.mapedit.Main Properties apple.laf.useScreenMenuBar true com.apple.mrj.application.apple.menu.about.name MapEdit VMOptions -Xmx1024M WorkingDirectory $APP_PACKAGE/.. CFBundleDocumentTypes CFBundleTypeExtensions txt text CFBundleTypeName Text CFBundleTypeOSTypes TEXT CFBundleTypeRole Editor LSHandlerRank Alternate bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/Info.plist000066400000000000000000000307541506470510200226510ustar00rootroot00000000000000 CFBundleAllowMixedLocalizations true CFBundleDevelopmentRegion English CFBundleExecutable BitsNPicas CFBundleGetInfoString Kreative Bits'n'Picas © Kreative Software CFBundleIconFile kbnp-icon.icns CFBundleIdentifier com.kreative.bitsnpicas CFBundleInfoDictionaryVersion 6.0 CFBundleName Bits'n'Picas CFBundlePackageType APPL CFBundleShortVersionString 2.1.1 CFBundleSignature KBnP CFBundleVersion 2.1.1 NSHighResolutionCapable JavaX ClassPath $JAVAROOT/BitsNPicas.jar:$JAVAROOT/ual.jar JVMVersion 1.5+ MainClass com.kreative.bitsnpicas.edit.Main Properties apple.laf.useScreenMenuBar true com.apple.mrj.application.apple.menu.about.name Bits'n'Picas VMOptions -Xmx1024M WorkingDirectory $APP_PACKAGE/.. CFBundleDocumentTypes CFBundleTypeExtensions kbitx kbits CFBundleTypeName Kreative Bits'n'Picas Bitmap Font CFBundleTypeOSTypes KBix KBit LSHandlerRank Owner CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions kpcax kpcas CFBundleTypeName Kreative Bits'n'Picas Vector Font CFBundleTypeOSTypes KPcx KPca LSHandlerRank Owner CFBundleTypeIconFile kbnp-doc-vector CFBundleTypeRole Editor CFBundleTypeExtensions bdf CFBundleTypeName Bitmap Distribution Format Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions psf CFBundleTypeName PC Screen Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions hex CFBundleTypeName Hex Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions cvt CFBundleTypeName GEOS Convert File LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions fzx CFBundleTypeName FZX Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions u8m CFBundleTypeName U8/M Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions fnt CFBundleTypeName Bitmap Font of Indeterminate Format LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions ftx CFBundleTypeName FONTX Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions rbf rb11 rb12 CFBundleTypeName Rockbox Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions cyf fntz fnty CFBundleTypeName Cybiko Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions hmzk CFBundleTypeName Mi Band 2 Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions dsf CFBundleTypeName DOSStart! Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions sbf CFBundleTypeName Sabriel Bitmap Font LSHandlerRank Default CFBundleTypeIconFile kbnp-doc-bitmap CFBundleTypeRole Editor CFBundleTypeExtensions suit dfont CFBundleTypeName Mac OS Classic Font Suitcase CFBundleTypeOSTypes FFIL LSHandlerRank Default CFBundleTypeIconFile dmov-ffil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Desk Accessory Suitcase CFBundleTypeOSTypes DFIL LSHandlerRank Default CFBundleTypeIconFile dmov-dfil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Bitmap Font CFBundleTypeOSTypes ffil LSHandlerRank Default CFBundleTypeIconFile movr-ffil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic TrueType Font CFBundleTypeOSTypes tfil LSHandlerRank Default CFBundleTypeIconFile movr-tfil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Desk Accessory CFBundleTypeOSTypes dfil LSHandlerRank Default CFBundleTypeIconFile movr-dfil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Script System CFBundleTypeOSTypes ifil LSHandlerRank Default CFBundleTypeIconFile movr-ifil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Keyboard Layout CFBundleTypeOSTypes kfil LSHandlerRank Default CFBundleTypeIconFile movr-kfil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Sound CFBundleTypeOSTypes sfil LSHandlerRank Default CFBundleTypeIconFile movr-sfil CFBundleTypeRole Editor CFBundleTypeName Mac OS Classic Function Key CFBundleTypeOSTypes fkey LSHandlerRank Default CFBundleTypeIconFile movr-fkey CFBundleTypeRole Editor CFBundleTypeExtensions sfd CFBundleTypeName FontForge Font LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions png CFBundleTypeName Portable Network Graphics Image LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions jpg jpeg CFBundleTypeName Joint Photography Experts Group Image LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions gif CFBundleTypeName Graphic Interchange Format Image LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions bmp CFBundleTypeName Bitmap Image LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions bin CFBundleTypeName Binary File LSHandlerRank None CFBundleTypeRole Editor CFBundleTypeExtensions rom CFBundleTypeName ROM Image LSHandlerRank None CFBundleTypeRole Editor bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/MANIFEST-KE.MF000066400000000000000000000002021506470510200226110ustar00rootroot00000000000000Manifest-Version: 1.0 Created-By: 1.2.1 (Kreative Software) Main-Class: com.kreative.keyedit.Main Class-Path: ual.jar dep/ual.jar bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/MANIFEST-ME.MF000066400000000000000000000002021506470510200226130ustar00rootroot00000000000000Manifest-Version: 1.0 Created-By: 1.2.1 (Kreative Software) Main-Class: com.kreative.mapedit.Main Class-Path: ual.jar dep/ual.jar bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/MANIFEST.MF000066400000000000000000000002121506470510200223150ustar00rootroot00000000000000Manifest-Version: 1.0 Created-By: 2.1.1 (Kreative Software) Main-Class: com.kreative.bitsnpicas.main.Main Class-Path: ual.jar dep/ual.jar bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/PkgInfo000077500000000000000000000000101506470510200221420ustar00rootroot00000000000000APPLKBnPbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/PkgInfo-KE000066400000000000000000000000101506470510200224340ustar00rootroot00000000000000APPLBnjobitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/PkgInfo-ME000066400000000000000000000000101506470510200224360ustar00rootroot00000000000000APPLEEdbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/bitsnpicas000077500000000000000000000001131506470510200227500ustar00rootroot00000000000000#!/usr/bin/env bash java -Xmx1024M -jar /usr/local/lib/bitsnpicas.jar "$@" bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/bitsnpicas.desktop000077500000000000000000000014101506470510200244210ustar00rootroot00000000000000#!/usr/bin/env xdg-open [Desktop Entry] Encoding=UTF-8 Name=Kreative Bits'n'Picas Comment=Create, edit, and convert bitmap fonts Exec=java -jar /usr/local/lib/bitsnpicas.jar edit %F Icon=/usr/share/icons/hicolor/512x512/apps/bitsnpicas.png Terminal=false Type=Application Categories=Development; MimeType=application/x-font-kbitx;application/x-font-kpcax;application/x-font-kbits;application/x-font-kpcas;application/x-font-bdf;application/x-font-cybiko;application/x-font-fnt;application/x-font-fontx;application/x-font-fzx;application/x-font-cvt;application/x-font-hex;application/x-font-psf;application/x-font-rbf;application/x-font-rb11;application/x-font-rb12;application/x-font-sbf;application/x-font-sfd;application/x-font-u8m;image/png;image/gif;image/jpeg;image/bmp; bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/bitsnpicas.png000066400000000000000000000360731506470510200235460ustar00rootroot00000000000000PNG  IHDR>atEXtSoftwareAdobe ImageReadyqe<;IDATx]|[my{8;!d@!@hKZfe頃]n @ d'$$m-k9W#;-)mn~/9>ljqb;ӑ}b7GBBbys~x_(ȿ^\rӚ̬˜j=10x6= VW% eGWkszOL)d2͏ ])j//~Y2 aTa\i@YF9aR%)҃W;j81P(/f k< L>y6I?Ly81>XsoHR2@P*8%!ni7@O<1!d:;ϗJ$\_L$k̦}hk}Uۼ>! )1I>h̽|E%e/ܱcwy123r^{DV[2|@%=ERTB43++pe**ӓS?Z H8h J~z Cٰ~$_D`H/,,̭,Q.#a祦4x{m܃++uZl;,3%685@ REPtc'o eN&!g̛7~$.hcuEɳPd]Hٿ?L@h>$?LM( 4q&%4ڼXkΥb7ٺtBB:999]`2YVPPڜI@K H * ;P mr>_*o> )+ŋOU0&ߟ V[\fS/rҵW`i΅88) laP+Xir jȰS:44!tu IDaV,1O9IKTrKѦ?i@nr;K6 [@n~NI (Js3S`>)Z )\ ^MXI#oT$h.\XJBf1is[[@kjzn7 +t$6e`8BnsfoFPud 25zRf K=c WZCRR<y N'X&^˸ AIifz! Zq͖1ZYЬdrEE$Ͳ'>z p{r5XY,={v*FSP&T,$SG# &D"e$+؁܋b h9-_dXYZP4i 9&<`:Sryϴ|V4}3 ~gm$ˮ{VFk3 ;l̀6Z5Zul<Dr1bBtݮmyO~UE\3?Dw翠K(#C =o|IU"+8gKV`XMH1 xH_zwbeND}3 <2hmfAkD2пlE68G1HPq mNGg8xKI]…R]; jʼnӏ~uH8cD,zn&-*Ah7HҰa;߂T5%mfSf@oh9߳IG>M*Mt8-UQ37VS $ R}a8Iw")yp~W B 3 $ kxNd ضm;bmf-E 4d[^t6K_6s["\kfg_gkؽ{8`6\Up;yOl$53">!|i9r`|*C u3x'wbfXfǧTU~gmf=َo6▁%^S@k²-?4T7'sx"אiH(FLa2*QE#$ p\ DYzl7sSôis271wYFT+Q`34yxjڨtDrJKSmv =8JS o!N_Fz8= w eQDݭVsӻ#:cԯ͖gCAnuM)'f8-׬Ysxju\@>80:d*bxex>.EG*~Zk)׫jA GV4s܅7oVh5\"% 32UGy\oԫt2|Wj6Pwtz ?~˖\@,"e(&>,2һ%rEdr[pizkQa\dh0,R/߈e hԑPi9WTη;{v@ EX1C6+q*Օwԏh M;HOϕɟLHo?/bVݕ;Ϊ;3\;x}}&o"o<P$+!W\qt* WFgκ-;R [TfMpos߁^^o qގSîã&igRȽFEqy\.}T\ ^ rVb^XÐ*RI5U m 1g`ɒmCW] 4+%dVJZ`DZ|u \uqn~ ̓HSI`u؂ꔨޫLU!>;4@|#ʗ)X?hIۍ6h'4K|m;xQB-?Tb>(RBT=˸|SbW:q7 MbȌ3@g#:>nC ?ni \ y|@d$0eZ26#:4 ,4^:|xGo76~ 㳗aEdp:PI/ L*PE>2eԒЛR)4. <5&lq~ͮ>ȋRd)H%rss4\.הxJ\Y$}ePv =2, $TNgu)HL:!* &)-@CPrUFI& PN4?k-XI`Wd{gT7~p;HYZgs9s \NN PXPBC◠FDvXok/i;>O>lwRp1|KLZ( J# 1:g2i\7c8$]uQPEKg m &(1D`pB2R≣9q_bOcw /\-WT= ]*ʢ2uҸ7π[L+ۗF^lu58AIeΜ9S]Gy24u'\ESRt2\碴 z^h?`7 ==i $Y2`潈:}ƁceOmlY5DPXU *B#r&@Q}$ DN'L~rCqمy(v$FC8RDM_&+'p>("b)h/-AJ 0]Գ  H:mWmqH4@~pd};a8Nl(*B}tQ(+++}  @x}71"Zڈ5Ndj5RRRB,dVNnrj谒Ԍp&໸xNl}T'y0BQfb^^^ E*CA` M!7w:;Al80!;itmzo?7Vr`7ODc6_w KX|:S=W+p?ѱ4Ub6^p:4@/^|Jz0/{=pȱUر\ՁLk; ~d48Q7`v .EFN D5DLVE:A%#lyE***ʧBBIj47$5`0Y\s49/)I"7Qυצͫz-~Qjbvf9ʗ1F8FVMS(>wh0E,2BESWGw~2PtwvqSuǓyHɔg5`B% `_ 0XϘo>dMZD^4`00d0 M[CfE~\*;g!=+CBOJJ:O3b#XBɲ䑢PD(v\E!519.::c4"gf(Td2ttP.@TEXh`fffbI F3##7i#16!!fн{ۄٟ*HSU䊚ʤ@vv.o蚲۹}]YBL% >DvjN8y?Sr=ú4)%P৲ **ڞ@q]FH( ː/>|VkJLHE rrDtYqBm?H@ k$("7{cM-.^Iz6 d?^pQ0J!mfwD,c*{*H54ahC( vܹ{@.cx@( zF 4 cQ(S ttQb. I < j<.(cx686{<Qr o Bzuї(*KE!SV Y-]NRpL9$3~P'J[_o3aoTCRXlTZ38V}>"9@! QC `hDW66$ȣxN7*G1Owu)m=t0^[QKJBf eF fdB38xOFͮ| ǜyNq-iBr'V 9~l֬qbLD%20AQk[]Z:Z>FO@)'JRW%W*KdrgeO=G2 Jh66$cxxXp&>1oTC畔V֕FkY a ;-(]QC!|6hPP>%^f͚n+_֫kkkZ k9B4x:Wz:wڹėSTTXSMHuQvv 5'sE=kl^ i:AJi((#5SchO0O ({EQ3g(@X7eS;dnM6ld',:-K[;X2=d4ΦP EeO7~yʕYVv̛7~{uߜ >XɃq2x.ixɋL&ʇ6(-)J溺:wy[ȕRމҽr|^\X Y]29})8[Q(OIsêU1+R,X8]iYYlɧ]~7H{|'|4xk?-LRGCdBy{ \[[+O7?CAˤ~[SᔕЧpVG- B.JuE!V:ŒtW~JD㰵k{m=Q*8< ;h8dereOOO7Gii)wH@p\6XLIӽ$"hu \(7zY^^iԼ}~\@m~ 3F{#|vz{`;dmonooդ2YOh0@3ZB /qv{w|X9|PpÇ?6.JDA^,LdYj  $DZe?0ـ?5LP&+IKK.uرc֬Xr \?^q$۞It僚Ok/C´y>. rr.2L, PQ#HtMpIz˭>`x08'\QB ͸aҴoLYatAbAe9( Y2,Tۋ>֭uJ~^,F hǁҋ/=M ; hmm/񓫪オgqټpù]}bHo|*Е'Ǖ 1>VbZ&hhDsVbݣn$'7Wb3!II'{je8(3uuu&@KKq6wiRo6'vr f˼>9Em,]B7PO9'hYO?999X1WBe~k8? CիWO_+FABg8 *r 8W{N^۵p{`E8X+\:mQ/ 1 7oBO\e']~6Ujuq_%|$qD9o&aZ[Zxe{~Wzyz&wǒ@E!.sQhi]R)Er~_o,φV￟,Zh\mP[S+Wu[ly=!?^ AT0"`b0P_?} 8%.@%ػ[4p8ӳ]4bY)鳧c֒ XMN Fm3q,{_bfϙ7xUW^k>>!q}OSa8R2sQ()K/4`搐GiV)zٕ䕳QXڝɷ2dq˽ןvcy k$_wSN=u¦QW(ӂjOcҥƑΨ.‹B;8-L+'(6k$r6k[rAEfv) u!!Y ΅3Wd~rRM"?jHF?ϑ=HPlC~'~aᬅΞ=;'i1ᆆU"ٿ k0tNf 1-C;EBzѺE<)U=ew}E᜷7Yqfci٢d6ڸBl|5\/ s(P~W~U<>6w"=={sYY(-E sP@=1(4ps >uFԚ˿ "8_> Ӳ,XrN#wrc!ѼJL; ɜP`('پL"'l6A ji)tM\f&z>'ہ};z2;,.A3ȼOC-[v [I7j2H87^|mex}FnfEf4^ȭ@Q_$M#D>+++-5Vn%e!D)clV7܂݌CF [.4vGWw/*5֯|Țꓓяb u58G(..… EGEUbj6yn*1UH'WWWӞ\\.>^iM>Wึ?0'ly_G Egh;w?g 截 [2SmA4ܚq  d(D9PQ3jx]|!YC~To{ha?B}[>7\xȥ.ڿ+T􊽄r.3 @B%E! cc2kњ|J@0lw|} os^Sv0 1BO{ .#⹻`(TWW(. 577a?bxYf3նP([[hll9P}$xmDkQAs޼yBNAnZui:Γ$FB 0DzN ڹ qQb=0͐;EHr]q/ Dh*x6|kOacɒ"fM(o3OT0܄~&h+&:XW gkF4)@'BQ<d߯\ ]]]xD{xg=[z'@~LƁ=QSoƲ 'tdDžo$EV yp&mmmC&CѬ|CO!3 ϗNA,-SW MdBl/ÓO-tTG:حuDb[+הڃԕf=RhS*@LY&000+g"`WΫYgAgEm8Rj#yw6V{&Jr@#|[їO\sBL??Hcb%O pR o/<Zd!`7˰O w:q`˱uòsY*U^]h3gNo9c.?(DOTk"vwۡM]Lq {\,LVFBJ-}'$gy&݋9O<8n-ïѩ֏"߁Tѕuj:7\FJm0RB|?EBWFJiD V-V.thxM&3{Kct5ckcW">p$X/0MNztFW?/Ev%K>W> X"g˖-3SNk"163bJ) P[A=+6}Lu} W{Q&fGKk+_Z1vpʚ}J6ѧtx= (^KnB{Ah^$ˑ’isrr*cp=+leV9}OL 0.lg_Bq9稕!m+=hGۡAU&op6D# [ N?L={k``gm}AvE [l|G +BINl6'\\TUHxjWY2z,ہ>?n}7YJW\YYz6SEU =vp3|2 &$bW#k~qqqL*, z"R d9"ps+,ɓ"1Ç*<:z+>a31^y#p6Y9o!Ը1SV`mcz5646+ n J!\Wsk+ f w*͛]bfV|_ KI /$>(o W+,̂_D澼&5~Lmv r[[jkkMH6 Xlv}Cs@ ~ 0 YKΚ5k\0jHv+q,tDG`~']xXެT8q5oI'&mY^]uKD{vFG{(n}8[96zKb,ޞ;}alb$ᛉpd]P6z؃n?/Ȼ]pmr !iB`(Y0Ȃ8s7]m71·  QZ^L}˙9{L*S@pWzMuG,\f7eRoaavĤ&!s"L=L=x8À:BϹg1EA98H-h a'R%7/Υa>:*PPP C&t}}xt:,^B56cY뮿ŃF)im,}>{N#&* mfM̓cyF $`WP{,̋# C}֩\C5R m$͙?^ƕ*n f/t(%m.#m.XȂ +5@o>ߟX& ַ .!A+)b/FVmm!@@,|e9?+L!m}3}O3:Fc51]zaGy*7td]hїɟIsdɑ-[ٔGms90́_nt{bHy{A[)D}z>twu1aD`6#7[5>Ɏ$pAn#hX?ɌX*Hb:K.r_;GԈ[A.kU#wy ^SA^xl9 \u70n1Ay>"k2!p={lOfI?>:oil6e2y749NwiqۂZ̦9 ? QeᶶA"Q0ao"kNbQg [ XU+`Ew~ /(|ug@`;^DӘ5%?',̼,xx,X*(,55*))IJz8K'QL=itA$7#=&~ߪ/|g I q`zk 30?%P!P˓,6$J m I+dO Ɉ,'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/dmov-dfil.icns000066400000000000000000010755211506470510200234420ustar00rootroot00000000000000icns{Qis32 !! (Ҳ#?ʗմ7Cٝv}}t:?sR}}Pt7?ݽ|a}{|{}_~7>ҁlxxj6=te}wzw~bv5?:ogwwdr39мe\umqluYg3dեfآ( '%&%' (       rqrq+z]o{}{n^z$+~_FLIKIMD`~%&{\E0oEqEn/F]} $scH4A@A@A4Hdt!jgG7i;f;i6Hgkc\=097879/>]d6\Y9.[4Y4\.:Y\VN3(1./.1'4OVIS4GTOROTF4TH     &    ESKQNPSPNPLSEC><>A@+A=<>EA><%&%&%&%<>B:2-6!7!6-1;4/,:,/5.,),,-)+/(%!"%( $"""""$ $!$ $ &&#'&'&'"'&  s8mkfff}b}util32A 260  ''  ("K *&%  "() SzѪҬvH|bԓق՗߂hk~єӂӗ΢hЍՂґщՁҁӍܓɃ͏ˇׁݗ;څߑӐ~jnjΒБϓg~ll҉wfjwebwhhwލq}ڕ:ww݋juɌΐΐΐoo܊frϐll܈`m̎9ffۆ\h̍̎̎̎bbڄWdˌ]]فS`ɈYYƿP]ŀŀVV{μ»LYÆRRƻzûJXÀ€QQm3\ERKKZ,%3gGVȆNN`3! #5VZU&,YXYX))WZU4"" <  8[QnrppM\0 Q=Y]b__RBBZc]b__eF~X][[~ny}~~|UZ~}~}~~XX~~zcxy{xvQVxTUTwSSwx|wbqzuw{yOT|URSR9U{QQ{zxs~]mwqtUJ@AK=RrPPsPPsQ=KAAKVup{YhsnpOE=>F:OMNMNMN9E==EQqlwUbokmpoDIqMK NpFFpomisQ(^lgigd?CfGIiIIhIIiIHeAAefjfoMYhdffd>eefbkITeacb_8=bD7`::`ac_hEOa]_^\5:^AB^BB^BB^BB]77]^_\dAK^Y[ZX16[?@@?@??Z33ZZ\X`=F[VXWU.3W=V00VWXU]:BXSUTR-1TS//STURZ6>UORQO,0QP..PQROV38RNPOM+/ON--OOPNS.4FKJH(,JI**IIKD4 "6NLK)-MLML++LLN4!!" !!"" b )@8^][NO\]JO_^_^_MK^[NN[^]7A#<.4GDFBCEEKIDEDEDIJEEBBFDG12/A7FHAAHHEFHFEHHAAHGID:0WDDB =>CBDCBCBBCBB==BBCBHFO>A@@A;L=>==<78=+=88=<@<G9::;;67;)();66;/9<8C7872-++.#'8''8''8'#-++.287:5?454/*)(+!$.!+)(+/4462;12122-.3##"#""##"##3--32213.7./.)).!!/!!/!!/! .))../.1+3+,'',,'',+.(.()$$))$$)(+%*&!!&&&&&!!&%'"&####"$#!" "!!"!#"""!$ #"#""#"#"#""#"$ $#$##$#$$#%"%#"##"##"##&&%&&" l8mk<1 <]J]: C8v ;@ h[$tzxwxxxxxxxxxxxxwzuit32x/9@CDEDCB>6+1=JLMNO NNMLJE9+#8FB=C@4*6" -:=/385% ,8:-153%,67- 122% *12*.//$   -22-    0/0' k`eScaba0b`eV_ϯԽϰy\hT_bac^fXZ>kcW]ecdcb4cdcdW]`կڿүwb[Yecdcbcdce[Z`~=Qkbedbcbdfefefeecbccdh_¸y`fdcfefefefdbcg`|<xμeifgfikfjfhfjf;x۞ltnqorvijٶntnqntn:x֕kqmomptӵ׬lrlolrl9 ЀיipknlosԽ0ְkqknkqk8LՙhpjmknqѾȼ¸Ż(ұjpjmjpj7xٔgmhkilqոԸʴٻ٬hnhkhnh6̀`֖elgjhkoһ̯Ѽ̯ծgmgjgmgρ 4xԗdlfigknпЯֽήѯflfiflf4xבdjehfinԷȰ̾δ٪ekeheke3͂N֓aicfdhlѼ̰ѼͰԫcicfcić͂2xԔ`hbecgjоҰ׾»аѭbhbebhb1x׏`fadbejԷȿĶŰبagadaga0΀́#Ր^e_b`dhѻ,Ԫ_e_b_e_̀/x}Ԓ\d^a_cfϾ¾¾Ь^d^a^d^.x~،\b]`^bfӶº¸ا]c]`]d]Ӿ--zԎ[b\_]aeѺԨ\c\_\b\͂ξ,LxԐX`Z][_cξ(ѪZaZ]ZaZ+xx׊X_Y\Z^bҶº̼¹إY`Y\Y`Yӻ* ù͂O֌V^X[Y]aѻϳϳԧX_X[X_X́ν)xrӍT\VYW[_ͽͰ¿һľɮШV]VYV]Vɾ(xsևT[UXVZ_ѵûƲ˽˴¹ףU\UXU\Uѷ'p͂̄dԉRZTWUY^кʰϻʱԥT[TWT[T͹&xmӊPXRUSW[ͽͰһľɮЧRYRURYSɼ%xmօPWQTRV[ѵüȱ¿ξεûעQXQTQXQѶ$j̀˃SԆOVPSQUZθ¿ĴƼŵӣPWPSPWPʁˀ̶#xg҈MUORPUX̽ĿûÿϥOVOROVPȹ"xhՃMTNQOSXеϾĿ½ĿĿ½½Ŀſýú֠NUNQNUNг!dʂʁӄKSMPNRW̸ÿ ½ҡMTMPMTMˁ˴ vaІJRLOMRVʺ͢LSLOLSMŴ vbпҀJQKNLPV͸ԝLRKNKRKͮ_ƀЂJQKNLQUԁҀ҄҃҆ԁϞLRKNKRKǁ Ȱv[̓HPJMKPTʠJQJMJQKñv\˽ƿ~HOILJNTњJPILIPIʪYʿŁāGNHKINRņ$͜IOHKHOIÁŀĀŪvVʽ́FMGJHMQĿɞGNGJGNHĿſſſſvVɺĿſĿĿſ|GMGJHMRƾƿƿƿƿſƿƿƿƿƿǿǿϙHNGJGNGɾƿǿȧTƽÿ}ELFIGLPāÀ˚GMFIFMG˿ÀçvPƾƿǿƿƿȺDKEHFKOʾƿƿƿǿȾǜFLEIELFο½½½½¼ƿvPǷĽ½ý¼¼¿zDJDGEJOû¼ýýýýüýĽĽýĽļļĽ̗EKDHDKEǼƽľŽžŽǤ-M{CJDGEJNÿ0ɘEKDHDKEȽÿvLǹļýļļŹ|BICFDIMǻýĽýľľĽĽľþĿÿĿĿÿÿŻřDJCGCJD˼ÿ½v=f[rxBHBECHM»»ʔCIBFBICĺϼ¼»êi__t3-HN:O}x@GADBGLǕBHAEAHBƹĮmGAY08v27LSDK=X¹ºöz?F@CAFJŸ»¹×AG@D@GAɺÙIDGK[8=t,309B?]VSu@F@CAFKȒAG@D@HA¸McIC>706t+04=??MW>qv?E?B@EJŒ@F?C?F@ĶWJZ@A>=/4t'--7:??>MHƵ´x=D>A?DHķ?F>B>E@ǷEJCHĎ?D=A=E>\=FB=:62(-v,$.47;7VRYu=C=@>CHŒ>E=A=E>ĸN_?<973+&*s )$+096OKFp8>8;9>B9?8;8?:@W<;6/)$,p"+))$((+Gm393649?ŋ4;272;4µ4,)'%**+o"/IIRE;TVWTVWTVVTVYD<9797<=SUVWTVVTWWTWVTVVTWWTVWTVWTWWTVWTVWTVWTVWTVWTVWTVWTUZK<;797;4.42!@9724*DTaYo^`WhZ-'(,L3!+((*t[]\fe\ 30146;<rCsllfaZQ]psmkpsqosnkotoOS\bhlng"bHmih^ZQZTHpssursvrtrvrtr F_LVYahjl5W/vgkWPNAVNAt`c``abc~`c`c`|}?_>ILR\lhpv@kgWOKHD0@EGLN\idu[h^OKH@7?1hr^`^__`a|^a^_^a^zT3<8CGKR`k#w p\\KI@HK/=r^`^__`a|^a^_^a^yz.:O>CGPZc X gYRAF6QU$uo]_]]^_ax]`]`]|Y.d8>ADU^w iOZL=>/&ep\^]_\^_y]_\_\_]xN"6=>=>>@BAA@)M\^rrvsrvWY[]Wr}owsqxgS]Z[]~sutruuXX\G@ABA @>>=>=>>?BACAPupusqusqutrtwt>surotsotsotsrl@9<::;:;2:;:<;:K[^~stottoWYZ\Wp}qqtsrfT\Z[\upsuotZW[D:<;:;:;:;:<;8Hrtprupqtpruouw=trqrq rqpskA:f=8:9:9 :9;7eA7MZ]}popVXZ[VpzmrposdS\YZ\{qp qWXZG4`J4<8:9:8<3]N2Mqqrqqrqqrqur<~upproproorpotiA:<9;:;;:;.:<9;LZ]rrurruWXZ\Us}ovrqweR\YY\rtsrttWW[E:<::;:;;:<:9Kqnrqnrqorqoqtp;~orpmqqmqqmrpokA<<=<=>=>==<>=K[[c[]Z\]ZQXYZXaa[[\USZYYZd]Z\]Z\RWZD=<<=<==>=>=<<=<>?>@AY_[aVKRUZXTWYVTUXYTVYYVN\h]]_S?@>?>@?R`\^`honoonpnnoonnroz9*yqmmplmommolmoloroosmsXEFCDCFHjtnrcR\YXXZYZXYZYXZY+W[Vj|oprbEFCECFE`tooqpoqnlonlonlonloqlz8(zkpnknnkonknnknmimmjkpSCCABADFgllp\QYWXYYXYYXWYYXYYXYX3YXYYXYXXWYSgzhlp]CDACADC_njojlnkmokmokmpklojoow8}xmml!mllmllmlmmllnkpUCCABADFgokp_QZWXXVUWXWUVXVUWXWZTgykmo_CDACADC^pkmllmmlmlokv6?yvnkjmjkmjjnjjmjjmjjninTAC@A@CEeohm_PYWXWadcdccdYVXWV[ccdcce_VXW`d0ccdYWWXTgwkkl^BC@B@CB\pjjmkjmlimkimkjmlilniu5xyvhmkhlkilkilkhkkhlkijnQAA?@?BDfjjn[PYVWZ~zzxzywVUWXSlxxzy{jPXVWX~|wy{vzZSWXSfyfko[AB?A?BA]limijmijmijlhjmijmhlkq4vsjjijij ijiijjijiikhmR@@>?>ACdlhl\OWVU[wfgfgQUVXRlqchffi\OXVVYvg fggRTVWRfvgil\@A>@>A@[mhjjiijjijji jiilhq3xsqjhhjhhjghjghjghjhgkglR?@=>=ABbmej]OXVUZyiilihkQTVWQmtemign^NXUUYwiljhkjQTVWRethij[?@=?=@?Ymhgjigjigjigjigjigjkep2xrrejheihfiieiieiifihfhkN>><=<@AcgglYOWUTZuhiehheQTUWQksffhhg\OVUUWwjehiehSSUVQevcglX>?<><@>Ziejfgjfgifgjfgjfgjejhl1ppfgfggffggfgejO==;<;?@aieiZNVUTYveggf4PSUWQkqchfei[MWUUWugfgefgPSUVQdtegiX=>;=;>=Xjehggffggfggfggffidm0xmnfeegdehddgdeheeheeichN<=:;:>?_jcgZMVUTYxffifehPSUVPlqbjfdk[LWTTXvfigehgPSTVRdreffX<=:<:=`ediWMVTSXn`a^aa^MSTUQfj^`;aVMUTTVoa^`b_aNRTUPdtaeiU<<9;9<;Wgcgcdgcegddfcdgcegcfci.jkcededeeddedeeddecgL::898<=^fbgXMVSTTOLKMTSMLMKPUTPLMTSVPdrbdgV;<8:8<;Vhcedededf`i.hjc#ebcebcfbcecceccfafL9:797;<]haeYMURSSTSTSTST+RUPcpccdV:;797;:Thbbedbedbedaedbedbef_h-*fi^dc`dcadcacc`ccaddabgI98676:<]cbfULURSSRSRSR,SRUOcr^cgS9:686:9Ueaeabdabdabeabdabdadae+cg_cabbabbababbabab`dI88676:;\d`eVLURSSTSTSTSSRUObo_beT9:686:9Se`bababbabbabbabac^d*ae`#c_`c``c``c``c`_c^dJ785759:Zd^bVKTQRRPRQOPQRP-RRQTNbn_abS8957598Qe``ba_ba_ba_ba_ba_bc[c*x`e[b`^a`^aa^aa^aa^a`__dG764548:[`_cSKSPRSknmlmmlSPRRO^qlmmlnaMSQRRjolmnlnUORSNao\`dQ7846487Rb^b_`a^_b^`b^_a^_a^`]`(]d[`^_^_K^`^bG6535379Ya]aSJRQPVudeddeeLOQSMipafedgYISPQTteddedeMOQRMam\_bQ6735376Pb]`_`Z_'v[a\]]`]]`]]_]]`]]`]]`[aF4524267Wb\_TJRQPUo[\^[[]KPQSMgfW`\Z`SJSQPTn[^\Z]\JPQRM`l]^`P5624265Nc]]_^\_^\_^\`^\_^\__W^&:ZaW_][^][^^[_^[^^[^^\]aD4313157X]\`PJRPOUo]_\^^\JOPRLfi\]^8TJQPPSp_\^`\^KNPRL`mY]aN4513154O^\_[\^\]^\]_\]_[]^[]Y[&W_X]\][_D3202046W^Z^QIQPOTo[\IOPRLfgY]\[^RIQPOSn\JNPQL_kY\_N3402043M`[]\]V[%vU]Y[Z]Z[]Z[]ZZ]ZZ]ZZ^Y^D22/1/35T_Y]RIPONTnZZ\ZZ\INOQKeeV^ZY^QHPOORlZ\ZY\ZHNOPK_iZ[]N23/1/32K`ZZ][Z]\Z]\Z]\Y][Y]\TZ#:T]T][Y\[Y\\Y\[Y[[Y[[ZZ_B10.0.24U[Z^OIPONTo\^[]][INOQKfiZ\]8SHQONRp^[]^[]KMOPK_kWZ_K12.0.21M]Y]Y[\ZZ\ZZ\YZ\Y[\Y[VW#Q[U[ZKY[X]A00-/-13T\X\OHQONQXLMLMMLEOOPMWRKLMLMGIPOOPXLLMMLLENOQK^iWZ]K01-/-10K]X[ZTV"+OZUYXZXXZXXZXXZXX[XX[W\A//,.,02S\W[OHQNONIJLOLIJNOJIJ,ILONQK^gWYZK/0,.,00I]XXZYXZYXZYWZYWZYWZZQU!*MYRZXWYYWYYWYYVYYWYYWX\?/.,.,02SXW[LGPMNNONOPONPPOOPO*NMPJ^hUX\I/0,.,0/JZVZWXYWXZWXYWXYWXYWXSRKXRXWXV[?.-+-+/1QYVYMHQNOONONOONOONOONQJ_gUXZI./+-+/.I[VXWXWQR+HVRWUXVVXUVXUVXUVXVUYTY?..+-+01PZTXMEMKLKKLKLLKLLKLKLKL)KMGZdUWXH//+-+//G[UVXWUXWUXWUXWUXWUXWOQ(GVNWVTVVTVWTVVTVVUWVUUY=.-+-+/1QVUXMMVST)SVPegQVZG//+-+/.HXTXTVWTUWTUWUUWUVWUVPNEUOVUVTX=-,*,*.0PWTVTbjhihiihihihihiihiihihihl[TTXG..*,*..GXTVUNNvBSOTSVSSVSTVSTVSTVSSWRV>-,*,*.0NXSTVRRTRQTRQTRQTQQTRQSRQTRQTRQTRQTRQTRQTSQTSQTQRWSVF..*,*..EYSSUTRVTSVTRUTSUTSUUMNvARLVTRUTRUTRTTRUTRTTSSW<.,*,*.0NTTURUUSUVSUUSUUSUVSUUSUVSUVSUVSUVSUVSUVTUVSUVSUUSRXE..*,*..GVRVRSURSURSUSSUSTUSSNK>QLTRS TRV<-+)+)-/MTRSRSSRSRSRSRSSRSQVE--)+)--EVRTRSTSLIvG -;NML MMKO7*(&(&+,GMLMLLMLMLMLMLMLKO?**&(&**?OKMLLML NK6(+U!! t!OKKLKKMKJLLKLNA#('-R#! u( FM)LKJKKJKLJLKJJN6*(&(&+,FKKLJKLJLKJKLJLLJKKJKKJKLJKKJKLJKLJKLJKLJKLJKLJKKJJO>**&(&**?MJMJKLJJLJKKLB0Y-&#  $% ?J"6KIKJJKKJKJJIM6)'%'%*+EKJKJKJJKKJKJKJKJJKKJKIN>))%'%))>MIKJKKJJKI,.S+$$% t!%! -,BMHJKIJKIILHL6)'%'%*+DMIIKIIKIIKIIKIHKIIKJIKJIKJIKIIKIIKIIKJIKIIKJIKIHKHK>))%'%))=NIIKJHKJHKIK<,)$#! v !%)" 7IHIGIIGIIHHL4)&$&$)*CHHIGIIGIIGIIGIIGIIGHIHIIGHIGHIGIIGHIGHIGHIGHIGHIHGL;)($&$((=?>=>?==A,"  "#9?>?=>>=?>=>?=??=>?=>?>>?=>?=>?=>?=>?=>?=>?=>>=>?>=A3"! !"4@=?=>?=>?=?887?1$ #$$#$$#$$"&!U $$##$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$%"%" ! #%#$#$#$$##$#$$ 8;93   85:&970   !"##$##"!    $!%'#!$  $!$'$!$ 2)'#&8x:D?IRAD:TN  ? %i D?AESDA?D ~&"#$&+2r4XLMGD;3>jonlnnknnlokRRQPOPRP_omnlnmnaWVWWVWanmolnolnnlnolnomnnlnoZWXUVYUfplnommoWPRPOPRPXmmomnolmokpd54?DILPN9LJIA@6FG,QPPRPPQPPRPRVRVSRRSUQQPQPPQTXYYXYXUQQPQPPQPPQQPQPPQPPQPPWYXYXWYSORQPQPQVSRRSRRSUQQPQQPQQPPSF1Q6;?DIKM,W*YIL=77(LP$RLNONNONNONNHFFEEFGFKONNONNOLJKJJKKLONNONNONNONNONNONNONNLKJLJJKMNOONONNJFFE FFIOONONNONQD.a.059@MIW1LI<6320%/JJKHJJHJKHJKGE5FJHJJHJKHKLJLLJLKHJKHJKHKJHJKIKKIJKIJKJKLJKLJJKHJKIJKHEIKIJKIJKHJJ%*0147@JFJHB641(") 9NHKKIJKIJJIJGD7EEIJJIJIIJIIJIIJIIKJIKJIJIIJJIJJIJJIKJIJIIJIIJJIKJIKJJHEDEGKIJIJJIKHL0#& -139CLa=C42)9>%HJHIJIIJIIJIIFD EHJHIJHHJIHJIHI$JIIJIIJIHJIIJIHJIHJIHJIHJIHJIHJIHJIIHDGJIHJIHJIHJHJB'E+-18?Ew W;7(1 HTAJFIIGIIGIIGIIEDCBBCCDHGIIGIIGIIGIIGIIGIIGIIGHIGIIGIIGIIGIIGHJGHIGHJGHIGHJFDCCBCCDGGHJGHJGHJGIHK0"d*(,+:Bw Z1G?&(7JFIGGHGGHGGHGHECBCEACCFHGGHGHHGGHGGHGGHGGHGGHGGHGGHGGHGGHGGHHGHGGIHGHGGHGGFCBBEBBCEHGGHGGHHGHHGGJ+#&,I6=w V)UO""8BABEHFFHFFHFFGFFGFFGFFGFFGGFHGFHGFHFFHGFGFFGGFGGFGGFHGFEBBA7ABBDHGFHGFHGFGGFHFH6!+a48w Y/,",4DHDHFDGGEGGEGGEGGCAB=5CABEEGGDGGDGGEGGDGGDFGEGGEFGEGGDFGDFGEFGEFGEFGEFGEFGEFHCBB@4@BAEEFGEFGEFGEFHDFGG@3'".7PQJEFIFDFEEFEEFEEFEEFEECA@AC?AADFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEDA@@D@@ACFEEFFDFEEFEEFE GHEK@fPwWJECDDEEDDEDDFDDEDDEDEB@?>=?@@CEDDFDDEDDEDDEDDEDDEDDEEDEEDEDDEEDEDDEEDEEDEEDEEDFDDC@@?=?@@BFDDEEDEEDEDDEEDFDCBJClSwUGEDDEDCDDCEDCEDCDECDD@?>?A=??CCDECDECDDCDDCDECDDCDDCDDCDECDECDECDECDDCDDCDECDECDEB?>>B>>?CDCECCECCECDECDECDEAJBgQUHDCDCDCCDCCDCCA>?;6?>?BCDCDCCDCDC DCCDCCDCCDC DCCB??>5>??AC DCCBI@hQBRGCBCBBCBBCBBCBBCBBCBC@=>93>=>ACBBCBBCBBCBBCBBCBBCBBCBBCBBCBBCBBCB/CCBCBBCBBCBBA>>=2=>>@CBBCBBCCBBCBCBBCBBAH?fOwREDBACBABBABBACBABBABC>=<=?;==AABCABBABBABBABCABBABBABBABCABCABCABBABCABCABCABBABC?==<@<==@ABCAACABCAACAACABC?H@dNPEBABABAABAABAABAA><;::;<<@A@ABABA@BA B?<<;9;<<;;=:<A@@AA@A@@A@@AA@A@@?F@@?@@<;;84;:;??@@??@>?@>?@>?@>?@>?@>@@>?@>?@>?@>?@>?@>?@>?@>?@??A=;;:3:;;>??A??@??@??@??@??A=E=`KMB@>?>?>?>>?>>? <::71:9;>?>?@?@A@?A@?@? =::909::=?>>?>?=D;`J]LA>>?=>?=>?>=?==?=>?=>;989;799=?=>>989889889889989889889889889989889989989889;=?>><998;899;?>=>=?>=?>==C9^IK??=<>><>><>><>><==<>>:9877899=T@2+D;>>;9987899<==><=><=><=><=><=>:B:\H'I?=<=<<=<<=<<=<<=<<=<=:8778788;=;?/# ! "!!"!""!"!!"!"!"!!"!!#1K:><:8878788:=<<==<=<<=< =<=<<;A8[GH?<;=;;<;;<;;=;;<;;<;<976877:=:>0#!! ! !!! !" ! ! " !! ! ! ! #1I9=;:776779=<;<<;<<;<<;<;;=<;;A6ZFG<=;:<;:;;:<;:<;:;<:<<775867:;:>."" #!!#!!# " #"!#!!#!" ""!#"!#" " !1I7<<8765669;:<:;<:;<:;<:;<;;<9?7XEF<;:;: ;::;::;:;875!669<9=."!  ! !!  "1H8<:9665678;::;:9?5WDE;:9:99:99:99:99:99:997548558;7;." !?DBBCBA#!.GABCBD4 !>EACCAC% "0G7:88554567:98:99:99::9::9::98>4VCD::989989989989:9::6648569:9<-!!#L?>>?>> !!>@2##K@=??=@# 0H6;:7554558::;9::89:89:89:99:6=5TB C:989889889866544510/8003536+!$F667768! "8C39669-! "E876768" !/B154300/00254469989989989987=3TAB98787788787786,+)*)*1((*#$G88987: !8E4:87;.  !F:9988:! &))+**)**)*)*+.878878878877<2R@ A787677677675+'+('('4('('+(*'#F786877!!9D48778-"#G967869!()*)'('(' ('('*)'-67677675;2P?~@7764*'h4#(&' &($f8$'$E546!7A16547,  D65 6 +!^F*%'%+ZK0464:0O>|>66565565565563+'/)'&/()&$H778779 !8E4976:. G879!)'-+&'(&-,&.5 6554:/O=z>46445545545443*)') ()+&*$%$% ')$%$$%! *%$%%$%&+'()'(*,45455455455380L<x<443434100/.,+*++-/-0(! !,;,/.-++* +,,/..00/24343438.K;v;342343V234234334341/.-.-//2525(     .D0532/.-.-.0144344343243 227-J9 t;1322332332O122122122//-,-,..1225'   .B.320.-,-,-.0212322322322322306-I9r91211211212..,..1214'.B.32/.-,-.032212112122112205+H8o8110100101.-+9*--/2/2'%+*)++)++)+**%&,)++)+  -@.20/-,+,-.20101101101 004*F6m8/1010 /00/11001,,*,,/0/2%ICBCB%6L?CBAE2GDACCBC -@,11.,+*+,.0010010010010 1.3*D5k6/0/0/00/0/00/0-,*),,.0/1&!@+,-5:(.,,.%@-,+--?,1/.,+*+,-0/0/00/0.3)D4i5././/./.././/./././,+)!(++-0-0%!A0010014=,30/3'@10 1-?,0.-+*)*+,0..//.//.//.//.//..2(C3g5-/./**(8**-/-0$A-.-.-.5;*/--/% @/-..-/->+/.,*)()*,/.-1(A2 e3,.-.-..-.-.--*)' &)),.-/$ @-.3:)/--/%?.- .->*.-+)('()+.-..- ..,1&?1 b2,-,-,,-,,-,-,--,-,-*)' &))+.+.# A-.4;)/-,/%@.- .,=).,+)('()*-,,--,--,--,--,--,,/&>0a1*-+,+,,+,((& ((+-+.#8()*03&*)(+!8)(*,=(-,)('&'(*,+/&=/_0),+((% $''*,*-")+<',+)'&%&'),+*.%<.]0)+*+*+*''$9#&&),),!+;',*('%$ %'(+**+**+**+*+*-$;-[.'*))**)*))**)*))**)**&'$9#&&(*)+!+:%+*'&%$%&(*)*)**)**))*))**)*(,#9,X-'*)()()%&#"%%(*(+ +:%*)'&$#$%&)()()(,"8+W,')()()()(%%"9!$$')'**9%*(&%#"#%&)('+!7*U+%)('( '(('(('(('()$$!' ##'('*7978878(;6886:+498*9$)(%$" ! "$%('( '((&*!5)R+%('#$! ##&(&)A.4;*0.-0#@/-. /*8#('%$"!"$$('&) 4(P)$'%&## ""%'%(9#$#%01 &##%9$ %*8"'&$#! !##'&%)3'N(#&%&!"!!$&$'<%&/'24"(&&(;'&&'%'*7!&%#"  "#&%&%&%&$'1&L'"%$%$$%$%$%$%!!' !#%#';$%$%$%12 &$$&:%$%)7 %$"!!"%$%$$%%$%$%$#'1%J&"$#$##$#$#$$#$#$!! "%#&8"#.1%#"%8# $)5 %#"!!!$$#$#$$#$$#$$##&0$H% $# @"$"%<$%$%$%34!&$$&<&$%%$&)5$#!  !$#"%.#F% #"#""#"#""!#!$"!#(5$"  #"#"#"!$-"C$"!"!"!"!!"!"H # #(4#""!!""!"!!"!"!$,!B#"!"!"!""!"!"@ " #(4#!"!"!"!#+ @#"!"! " #*4#!"!"!"!#*=#"!""!"B "!#'3"!"!"!"!"!#)<$#"#@ #!$"!! "! " "! "! "! " " "! "! "! "! " "46$"#"$);#"#  #"#!1:9:99:99:99:99:99:99:9:99:99:99:9:9>+!""#"#"!#)8##"# #"! ! !!#"##"#(6"#"#"#!#"#"#$##"##"#"#"#'4"#"#""#"# #" ##"#"#&2"#"# #"#" ##"#&0###"#"##"##"#$!#"#"##"#"##"# "$#"# "##"#%.# $#$!$# $$#$$," #$##$#$!$# $$#$$*"%#$!$# $$#$#(""#$!$# $$#"!"("#'#$#$!$#"# $$# $##$)#  !#"##$#$!$#$#$# $$#$#$# "#"  8D '$%"%$ #%%#$ %'S 6C$%$%"%$ #%%$ % P  ;G'#$%"%$ #%%#$ %! U   8F#$%"%$ #%%#$  R  !%$%$$%#%"%$ %%#$ %   $ #$$#$$#$%"$#$$#$$#$$#$$#$$#$$#$#$#$##%$#$#$#%  8E($% $&#&%&% $&  &$%&$&""Q :E$!"!!"!##!"!"!!""!"!!""!""!""!""!""!"!"!"!"#!!" !!#Q  2    !                !!        207(042-  96; &;81t8mk@ r` _3Cy w}~~~~~~~~~~~~~~~~|u& _-  d& _ & _  . e W}& _;||:Y}c) ;G[z( w|GX0_.i1[ _  `  ^ ` N*)((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((',&b- ` \ `  ^ ^ D7 c{S^c`aaaaab_eXg`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`d[|y\c`aaaaa`b_kР6Y_e!8ebG      ic08߭ jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 |X8џJ]qk Wn[mL?BEzh_Z0%,{Pj R|Tx\~ܸ=ץ@5h~ʄ\#.$yi`3?k'ҙ0?,t2MIXr}{ۮ|+9aܿЪ|\󟥬*UVB͝>9Čv ʳ40\IinC?/a.$zɗ*? ͍=82do X=tʲwl5̵;֟ѱFT.CR_=.3A껓9@6I{B_ j@<iY$^S>T($,>bR'B1*qr7")kiiAL[Pǧ{J&x%c9)Ӝ[(bĘ.Wi?ay}$T2ap>T5"|TԺ C(_\緩ariqoP/̎4sNW C FKXjq^!4rc^ed 4:H[@A-7ɚ]HC7*&lL=$ݽb3 pڡw }_rzyAmoټVM, 85G]ZRX7YK4y@^v=/&'U+Һ/:s#Oj5s)!:4]'ML옅Z_ZS0׀Zf]# lɉw}5۲eqJoH3j彭|WHtJ& :AT8PfӓYʋZ؋t*??BFz7&&N ! 1Yk+"- [558ohR1s/MS(j0{csg_*&"e&Xel!qY|^b[~ @еJd.w\~{xo Q"fE9EѤs9?: IA+E3'{3b͹@)=GwH[8 -J)OsN߶5*5] x@4`a.U:7L jtSBE/JvH<_F!v!-ƯjNՊ}p[ւ0-oJUv>X^ ٚJ 3dWmHvψyű:%tU\;yƛP7bQ0&x(x:H,rva{i(%!m yr>F3𽲄b{ĺڞ/\'QV$s Aw1=mG{uG'}x9XK!#JhQ$`IyƬ>?\A%dQQf3^Ԟnsb򼙔!zCeM¼ CZ|`(h!+a62KT:붒߳pbd#u# 1Vgmrf'%T|La*|_iC\tMU=5ȣ9.d1*D-{n->8efcFl(vWїY $"e3pա9Lx߮ṽK?,̢:rÞRY/ygw|`(J;9Ym=v`M45B]CG@9r +lsA=v GO:7"sub4̯D:|=L܁̻aNv=AA2Nlqb9z;}lj'OߤţYzlE,K_ v>dW_wʦꪪ#͕rC &/^+NHuhRh!CM-M@[⡵-s*!d*[v K?3tCx_ORuCt:q%jV@m( ?P@C:9^z%db0׵"6x>v r5a|!"civZ@|tNӗ#M0̹} _ k_keΝP  aQ+-XЕ[`CKgvyW>;CG  CٴNI:[ڙqdC(,aU.'Ag$*szX"ڇ?]cSX#M~N=/3:CQi!=by/ u֚!TUPm@ظ>}lHsqʾ<4]Т@hFIIrk7@-x\H5^t!f)%A@OJ3bp hLgUyփ` ŭd콩N`%t荷AqH"rd6WqCFN#|+=ӏ$Tl24yT ~;<(ܺ>Nj疤l]Y{,di]9qZ(!GcdflSR'z@X7(P]AT9OBSE~S8"K{]6K՜45)ޭA&ox*[E*) /ݿ\KykY&֏ft,}y sη #Klqw/PBshSF]W{@AA-D$wqiX2;:ւeGįotWXFtq][]ixPؿ9㽖(҉QxRT}Bz#psS޺9gyJDRbOnv42uW&,XAT('0ȁ;aW+őhvy:#QgkbSKÎylJ2J#FU;ߎ{RSE-Riѹ0dޟiFNd FʣɬoDYpޫ76"T/y{9 x̎B\E5JVx5=D:x`ZV}[u ENlo7p8|7q;n,Y/ï-^㏎91%ߋexS jFVv+k!@#TT⋪ά=hZ/1o3BZܪ' g|nٟZik_6,pˀAG ^ ]`6 EcgYT1О?῝zzms&sEܲt:p*PRRҫ(MՆbd:"Y YsX4.aHr.pq]ܢZP ۈO1W>wSpdDR|;V r{7 |0%'[ޥa˒Wfm;(|dO!Dv@&kҮC8oײ'˞-tO srT'e_<-J1^{t3wɡ! Hp!|94k> Ox dǿHꦿ xԘπ\UoH>{t~oW;"q}*UGA{_WWBg?:L vu]W*2bmvGN-G(yڃtvY\\TI"=[*QώZ[N-i.An?PɒuxDJQ|I4 NN=">,R}I}|9{KocQn>AFRews:x ҨBq+=<,!~D8b*`L;^FR;KNLO=k?b- ˕dR7&GQʬk˖ ')kI,,bmLL Ӏ@B̸p rtΐ"mwD 7j#osNwy1@t< s[úFY@|;ѩRAV\q9\cŷ(aH""ӂBIrIG푣t62\ho4uJINZUӜGКF$}(y$KOkRgT NJBd-h5cяyC>WhSȚi}.36|+G[zB'"5K)W*i/E.Yf2z>uC A BCF/rv;&˒Tٸn VE{k/r =J2?*bI}KKoQd?i&c" ݓsɧsVJ엑P)yYU^G`UA~ pePnm328@;[¹pvh ŐLSGltu 0:; q!Ui,CPuX쩿Ͱiv܌W*htg*VNdC !!mW;c{_J} W{܈G->o|  ^ů$ʆyX_mV3SC:͉Gj<% =V!'Ar[,A `yLP!NDI}GO BSWqZ1pc\_tE\oT| -@MmԂ7l?_An..6]T yQq[B*(id|u:eK"D.do(#[Y8)mH8kI1΀E|ΫXɸ,QZEHU %'Sr*$ RtP#D\i 'QTxǪg(!ۿx%nq<Ϩ_NͽҢ6g _y2NT"5 YX̹j$3ߎclau[65qQN+̾Iy utnn9l楺) _w=O8mPQhO7!^<2g(xq!x= K><1rHLzHC 0gx?eyY_qw덵f!ClP{.yc'~V_H֌N͞;du`Zϐ=<'}k(u 6ݛ:W)=o GЂtӿk~ȍe<=hPtcohXk㘰%G0_e4䀝+P$.w8tmX 55)lgW^/) {>*$xBHmSqkC3Iqlsa*Xʗ vG>G&2K0ȤTt6_A&!~r_5i˳+ {%C$EEߊ!6v$4< Rk|\u~ Uņ:P3ўðq;9&<.gL3+};6Ä^`;"9NeGv|XSBGnUdCÇ 8% W@W&_^)d!@eosƤ}ZޥڽܻM'^eiY/ȾYQfh;To 6J}h_X>&֯ʼoeřX9]'J#d}n_S&j 텥KʌlP1 Ek,#Rc~BB \1Kٮ&&"dYF!z3.B˳Ȓot ȏK Qñ7 a ; 8.YBg/doK =[,GsW'ZL8]7Kwh/9w6|[NkJӻ޻8!n6 Mmy%n`Y.1}5bw(9+UA6CNG{|zoUr~R /r4x}yKrM0AӞ򤺇6u=ۥ񰤞v*b$跕 |#^ ,zATa]jq="@|(Q'xkY,7_bMr;͌gU לsU[sCߜ9Z^ A黝DŽF!!{-dj+~9%bݕ:Q(|B+Lְ鎎фqXCOCp9RΣboʎ}Z <4щ}eD$H!k5ȢWeC$CS0GiVdE"{j^oe)2/?' 7T?cFYiѓ}؎Ʀ Kl&^0´۾z* ()Glj|G"sTc[I`X1BJ@uD<ȩ,.v9HJ]l!>6XݨA1,ȧB1 ` F 1EF^FѾ5SG_dwigؽB*o8֕0{Fzz9DRKqL?^7  "EƯ΋CNaJt_4&A/v*^45 0-ذ?z! %qh\3!\ Kt9 Ȫ@D&jkߡSnN*hV]S8C~wv":k4AmR=jz`M1ҵד_s!$5nňSއE.e0iNI!!E}tg6:rrZq- EQܼM} =>ׄǝnfӍܰJiIF^"? 0 n>Tk ̶ Um?=W!!bj\̥@8'.9!@ךl辳Ehf$6zlBp2gmLl"0AC6nc3+VFnĺv [BVdwX|5 qy)LIGnt{>T|qDi|<9G+L E9:Vat}(3'!n>}M29ʅG$Y^.DÌ䮚e}qw ƽJ*m䆙C f)0YW[v=yi3A@+~ z({{DscPz#al` d.jjDS A_a:!ժmկ3F/L{u'+־sl=3"c3RWhX*dNugi3ˤykT}]gq Dv!cn3v&Ro:2aj 8lS>j(%Eu}5-c&"W5*k;ek p6a/P}'O_\,U߮n1.:lj5n|d*Yݻς-t!ȄdJޯHrfw'N/g3qv0iC8=A ]ry`"b UfTfafq*Bp>`K6֡ H0M@Eit~L$^1 B{kRwS1מ+~b)'?$AqUb g uF[_2~1ñY7rګfH_<Fe•.XsWe{BN Fn7[y4Vu@^b ;kyF qz 2򏶋f=U -3R/JQwT-CAz}RPL-"l-YcQnNM0"*YY,8x.ѻ$;sv1j/XXp7nz/(J659j|SOŭXmՒrh:1G01}$N<&Ed0L:hq=tIRy ٱNtcKANs Zp`rP#76^qdpe65S#էu[; WlPjHw!ٯ(˫@Js9>wxK}%5hB@uGDZ DȦ B.*m,@ΊWV-ީV\$(,t( h8+Qc 1}y+t$e& VýnWYoVȟ;.3fWVoX ;]hMa)R5}Nk֤rV>N^˱XyPx3c8/wG8L HL}p 2[^^ *6=7Գ,Σ$:$?u]0_َub{o6ϒJ\`f&,Eak()fӔ ,> wbvɛ|dmմxX[vfs+3brf<]ۯԊ,NҝcN.׭1|CpPC{'yc<IV6tmb.ڤ{#c(,+U $ 5κB)JP} W46~ s2΢Zqƹx0cAf=TUB6Cąװbţ;`<͂h{ aFݾVGȒGQ,Veێ-u6t`h|h<ΐ n[+U7lk{0"u[m6` ʹVdyLdDwRlaN/-sK0^йL,nЖTƘYfn9%H8/Ϋ|V^a})V0T="#{nC2 &A65%VOH,W-?oi1R $ۛ}/]VS35JR4sރWPD%# \>:7U28C<*d'/pшwM[)xEYUztDCK3࿻ax6>7*fqRY0fBPL.Z1.-)@[ < YkhGZ 9/+S=Vhxؿ = .ffJO*,Zsn*@6UYie8hOlѿ1TE^UyJn>0V:Ų0Xͱ7B* ;.T۩>L[Z+J<3@b(J|D (/EsN]2ΣB "`^o\Pbͳ$2d_ XzIA:vF,,[l0C<텨xrUdJ a* DŽȷL LCB.NOR"ĕֹS$ɹo}C&c(Y2?CwXAGuByFxdI^튿x~V9n ?^$;GC `ߓe(n׳`2+KwXxdq1[; ^;v:6%08@T1 Ǻn5Rw ??da>6נ|ʺʰL[`(lڡZkLH*cS^ iܹSuX}T\~ȵ5^?Q UeZr_)FB#ur0^[Em$1'4Tr,ŷTε\2cgJ޺dZAͩ:NU|SzSGDlc~ГZZP ֖0HOT ikj7:~ EΠ`PwOΑ%f\Xt\ tdoYdZ=vQYR&Xߕ;A9rzpay#imsX5.0v{{MI-YԿSS1O=i0!#f_  9wF඙ Rba+WϠiژv3ffvv8,}Nu \}*"Q7s..Tt\ E:O2#qH@0'u Nq='γ& ȵ;zM~UmTVr|^ Gl_F[%dE8GHO_ES h'0!yBq&-)/^"䢈O?Q?@ֻJFz#Ҩmk䩑?+ l)؆ӿ诽UcK{zg4? AT*m%zJg"Qf_GZ^5r= N9wl'j%"gꪰ qۚÄ!`T' X~7t+{k'DLYVkgf٨Wi٨y+^ھZv! >f˪?G^Ar]4M 743jk6O!m)+!L?BU=~,K׌}w-:ż^T,$Lϒ ԩQ?b{pkv)chNt>_mX.*)DjI} (n:IJӽ`؝RҨa3(4= ۹y@AYY\YGaFHWR5i!&T^ͅo0y:kMLYV*9C'cN as/~.*xei)xz==[pJlƯ%kJoN,r^8Q.ܼH\J69Uw*~~OZfN53$kdtqח=Rg[":ʐm<#5(q=nJعB*3&jpw"V O$R̘E`D{zVTep]8}1 oa9s 1 셒sr,X62bo.gqzy?+Ăe[d*at©!3RxZ5]([$1ý~+OCsAS 72aWU{.j>T51m)d9g]lNIwA@w %\/s7s4qco%VQv޵@V3q'y'<4+jS{|3_޺}zٻføtrn[pzX/}U=2APBlu8@?PY B"B1(Tyǘu*3Jt qV5{`‚Vu2;}Yqj~879*Պ߸ WGpP)/P3iF4#.04-C\=@9Jp;5Nl_46Ui5f;.I)U77|7ˬ1~Ah2LSVFm RMx`~uZ08o>Ǖˬ{k%rS y_1q07jvM\_0kq'K%BdkDx Gp/NqJo1~W̽+{Dssr .=9;zlQGٽ]szԡa%6}ٴũUS{cJR򗔼^3€+W /c&BQ }~$m~f˦]%"|_rS9SM~.:{dkL'_s8vp?H Gi[(J108hn#ŏ0K 2el!j/B.a@21AqnqF)=l){DrApH}[|T$G%vS%%5fadI+SBZM:*ncxѯE~`[}  4{.&ȳ5tY ERt׍K@8`Ct:: V߷3D2:ȣHh|\LUGV@兩W} exDRivgRlC6k%oca%;fQ&{}j?oabr)w ;i;c)>K~v`[}oGKzrQFlϺnbL>\c9RSA ؜ʡw;U^ɈjRiX\*b/r$4>Մv%dQKt&oZJ+p֯m/QXP'Diu.80Ź5^YF!%ȝ$Ы֔H37jRNQ;섰;4+;SEiyR3`gƞڃ W@> HV2"G4"hy@ _)}Z zI5 Ct8W3V[Ym9ڂ]IX!6*Bp?wz`XEX ĊVw}C KtϹks+ "[D Gq$/RU ֶQ %ߗEccAe%p #0v.[L b6kL -H1l .Pg4vNF 5 |9 ,h`Xɘ)ΫjDxzT0 3yj[z#OךSW vcQ>++3?௣ѩߟl^).3zIWBl^N׿{6ׂq*1ocX.Ic0.h}1ʼne*ULp(UOŐ""Pta80bN$҈$ @4ಡ@ESOEZzvf,P>T:0ۅ8Kˀ-x k=e> \0QxDcJ!T-#L?7LH7?Kv :1YH#$VTdVOnqP{l(O`gB<,1sW31=1y/qSԬb*ղf3NwkXHoTk]uМW&olT /^sjYA 4iR'p-TW@Mpe!Ibnmr]\+%&QwgFb5c7ͱ*zwl]c-T哙^ ^z ps'>Xߙ?:;ܡN~ēpfE"L[)cSIWX L3l|I71v -D˝yZe!i! a#FJ*xy©"Àn ]O?<7֑U:9= '-H}|{㺃͘Oy7?!:MHgf'ƥf[$l6o QTӖƠZwBXPf֭ҭА%hyF{޴T+V=XhS鈎ٳ12]i,wo(a>]@ zxN)mQ3XiZ4៻cWִhs_12EwpVMvr?ئFq_O-/0T,&PZz U*pvI/I9p!٭!&"ZZ&q6!-C\m'<.*wINyPbi$|.X(ɢsmt8WGa\}xTGL6PDt[EtT1 `B~YBH[̊ aG0xm5zcQ)H(hPݹLxDDv4`b0Yĉ{áj]rA&_'y绌si%<DD5yZy?1K2lD%tj;a}H-))/Wm"#  5WJX3m9׼,[p_\YM?QGĺ €ȠYڷIqy݅](X(Nj,26QзA8U=XYJ^'x9+t*RH0>P̃ V,*>AnTR_IDnA׋rj?DBE.@BH(.]Tq I/r؄t%*:y겎/ ިѣBin/xlj_|1Z=k㫊U6Zw:{Oσ#mb"Z5~3BioH{$<`(_EޡRPopsPeo1=`PE~Id 7bF'  *`~‚nǕpZƐ^-dq;Ru]w@; kMfDp4X!TȑEI  `&j9*猵 ȧ7߱Ʌ+%;8C[fſzŸdzui-{Mcl8=*ވ ҂GY goI;5P&ѲM2-1#W S[eCoD &%W~pEiM5}3La$ΜĎ#NwA<`(X#t7y-iG#sk#|*,,k 4ĴT+ 1ㄕΊL+ ۡt+JmI{d2ʝ+րcpC+sc:\EbU_?5HCυ njoyVfd%=Ny-gARK?pj~=g«JRݛoʹGLQ드VC ŦUZt3WkM\e Zc`q!?;:W^?D99j r&lmQ)f?p F0(\gr3c:!j)VA f8 e[.5-oQ(qxĘf,lbnmw5vߚшMuNCoe*_,N\d>DBf v"u7`_݅Ћ/[ɜkޚHP@QQk ~񥛾oT휫/팱΄W YSm0fKrr0an H)nhLUPD!J8hI8;h 9>h&Q%?A"AeR!\F?#p?:%k+B(%޽N ,|,?]Y5/u ys(*˥nz,oq6 ( :@PښEqjT19X큙oqXbVMsɽ ^pGI/6KAG$C\PGIvx/ u&Z&=_Gґi!:M1/bƛ +l}A9wTƮM?:g>ެ~ܩ/F, ̉ CFbH0B"ok J1r2Yr˭h[xӐb"4l g0XR| P\nT}˂Ƴo3{mc[hvoO WGld(PAޓ/n܀-Pej_SQw!,XgH'ioQ6\ y25yD|; ^7A{7]m=m^Ki/1K&6øɨC _402q޿JcZۛSK5L Z'09KUkQ5au=7d؝Kt\tél%?Yr% -R{.iX:Oi*$> 4b 貭5Ҍ{wUI5 Їe^oM @wvZsڪo:? " lMR*\ `^d i[BrmO; ԀHeec'mЀoY釒 8hS\碯Cё4cn.#,Ҙ?Wsqrxi$)`g@|'yu e1 {_P?0^W5An-ɫ/,(4eBGrPNÞGڇO I FD n4P)dviċu;'ݻ0#ӢW0ӈT ;W7EQ𐌗ǍSY.#`װi=R< Oj)6yE- ˏ#QWq*9۬/o]v)!BCxOjl9QγԽ`v}E;#v]V©6-=C4e_M)8xHͰQ<*>~1VMH(|j|L:AiJҨjw8miZ^;PKҰwӿ 0O:kr_=VGCӳc *hT4@[v+I+ecw+f׹< g=ڼhAJ ݼFVɛV8BjL վ)Ƚ%PD'Q+{D r^&]]9)/N[ZO( ]Q7K֛]g:I54, -NԿQL*q`\l!kڬuַ%Q6jjeD.%IJzk|djjsGӕhZv"yc-wigkicZ@՞'Dgןtڳf2~<'қ==+n"Ov]v'Ckh!AKULgzMo %sGLڲ| B>Br]1$kf7)yާ`M!B&˘;oOu Ș/s{Xo41y,p"e|= &!O>3&a_io|VAaZgtqq@ޯVg;r[f/ t5BW!X< w\6xﭶcT1.t 83a/P؝'[B^߯Q> R$~z?aUfMyuBZhT\*%S ڃula5*4/mg4eUs/xlOY[BQ1%j[i2F"=3" W3E ۉ $^)bn{_n5XMS?́0 ߂1HH&VaZwM7nWx5BikGv砌8vecd!cS, A{J*φ :ou>~(Q=bR}_/$sV5L } :km/>MTɰrjO٦xKk߮o2Ւ:|Ej L@ۣY:dYv T$HPf1 M-%ʝ*ڋ'4!H1X6;U?KUJk!h*sQ%Y3WN:5t7XSOxJrQځv қUke46a Z=jI{ ɍuy$o\ Ln ARHRI?Htu% :e(6Yq`LI tJ]Hx'ײRNؚ1~if-)o 82,]wq)j7[D{7pͅ]\2R޼ᅞuP'g?";ښ3.SWq|ͪƗ3oFLdLṕYlNĜ]Qfq@r|Fj&hq}؃ږ8QFZb1 fHd 6GZx8VO,v 3uF` w gIuo-:`W /P6j HJntSqnӀ4fC BG }>]T!R)a*M2qm;5:$[ebdY*HeFt E7[~߉u44W;80w vyA*\m}_ϱSBry]8petߝcO;1rdMYכɰ㲰*2RȪmt9R$*iW'#ea}E{v,Flc&2!e&F\Q.xldchx zT.9Vv~މ!D~N{<+{Ϭz1/XKxU!J8Zיr$;y#WUE5B%CU1r@tTb\!(WI.F#dNzhQ% υOM灿_ι߂/|HWh~AOr )  =d&|-,gKFͿo9oK볏@X[b^n_hZ !_x`8DwP(nU"*ED4\at-pmwl,eYSpJqЉ^tBdN7q;l \gƁb i&uOlDD8v*K0 &\rݣy!^eԬUQ#o;mZ%f NnY2b;g-ly5vNKE-)z #ϴ4gyYhmi?wsڼ݇TԨ!& ڕ\,ą0`E7d,NJן&* 6 ZݧqQIE=Z7=O.R5ߨ~ꭡlMVFV1\2!|]^Ogۭ4)WDQu?PeCPǚ NO$R+"-PT뷱[{+t5AD /`!.W_@| 캹$(lrʎQJwK Ӭ"oM$l[Y9A6}ZcQI`6Z.n=ie+3MWp(0m] B]"=D${J%aD 6a,c4-#D1ע/I1k*lyэF>Z✮,c,:G߿w? KG+N&䂓 A;3N"Ef\2Ycet(0b{>+[̙+ &8 7d(g.0/~u@P%.޻ş/S<)t̀3#OXjIvFI<弒F̴ ςFps0slgfD, &0Ks opQH_gkSO:Ƹ "",<]euK=-fqu]e?J+fVxH!hc$yuwAË0xOm.Q:\;Ad`ZxiN'-D,gds}M\ =~V'dNFg"s JD9_=4q?}ew=p^3-ęhʭ]%iLV1wS4,~0QKnG! ;vH4nه▦N% ``pf\dAmC#"pTX'2wܦ)??e!޾O%}'>_*e-C/掾F} ԰.{K(cp{SCۅ)|TÐ ,U+gOo_6ZAV0V[mw??pKØ11 1|WNI΀ĂN(̆ǷBncD埀ݒȲ֘r rOI4 Z@]ƎAK>{T]Yo7$`bā_5 d׵SX,|$H=M)BBX$xqms=83w1]bѨts=VJEa̔}]R-eH|gx恌 99ONI;]G[#Rn*6fp66noV+/hsQRŝrhpƉw*[2~S3k Vtl^CZc' zͽiIrg%PʊM2$|N"tAͿp)73.zJ;}bHBR &]T}_IdK!(L2ҙr+CO| D҄$]D4e|Lo+3AҶ% ";D,i[y6VkSOK9z84'"S~N2x숭(6CAf0mT&>+ x sEjVv6{϶ᅳUe[ + f`U;|o yIAXٚGMC"oHUm7|9d={u RhT p/6C-$?ƣt)UBzl ߮1iK߮,T>Dfqd^gAw_R*e՞h;KLVL(5__Tn^Q(50#"Lk!zzfgͨ3jUHm[=ۈϓ F8YFJTO>_iD\lKx>k蕋RR9 [y*·|[Upp/ fV bi~.K}$ M,ݳi_\pu S(*ɦR 1NRF/<(EU#fx~|=*s 8xV1Y}s(Xb=BW~@G&>6_0qʾ5vt5ݻяtQ7M!m]L[Pp?ze+}@ c|?C%~Sh/O^p]*ds)u|T`P(wFb[B8@7iXa YT'@+b,{{]+'bF]V!@wZ`⻱2Ǽ#p?)h\ @{*ݷG<6'By{U5WƢ8?G+v7qDIehX1, X3gZt\pvȞ2I ʝ:n߫h[_zC tiZs#GQ"1(ڴA,պZq ԁ PX ȤZU(t`Pv/}>v& $f埜nAb%NqcUYg/vŁ~u>:ܐM)7})B{9 $+B۪]~S**p3dyhJZi>feK7<9l46K_­9RThz[^6v޷!$ȀZ[k8'LZםQ&S; =Ĉ[n "LrKɴ7s U4\#z] 8+soϥhh7G2 &N= QCѼ$LC[;D?xkC]#?}D?!N{yd:-OyH󬁟&u [7By;ʘ/!/g_NUZoltwjw&qo` {SC Px\..VUimjtia(t1}q=3-R0ͮXQk42O])3YHQh42* LRsi3"zTt PD@ lDPk~RSq0)P:A.0zKf.{vB1[sİpsf71G/*s1:b|Rҹz3SA !;#62t`5\yfk%0. =3$ʡ0:unφ/7;-+ۃZJE(rPS۞9M+{[DƊG?1&3o+顭QO͜>5 )Q'N/6?5{!S5r;g0U}}I^S&6)ΆֵƩLQl\eLR Ypi[*Vw/M_%B^kHpsFZ`4AkidqI,lHFu:HrP>SDS= 7ߎX*}ib="Z!aNͪȜ=v^gGo$bz죨%Se{CsW\[/P:E,qj؎x)+ImR _bMEjq}]ҹor -<`{SX >)sHGЏ شfSMyQ9e&i|zDVN W&.:]\ʉ\)V?Zzlޫ)0lUx[QuH1hSWm |ce rÛ?-mPhO wg`D ua*Zwz% `(k {|G_kXev$a%Jb ur7St%b$6bX#SXAy#RhÞo_7}FSNWQȊkIJ`9Tɸ1ZY&fl$: 6난NvxjZ%P_U-zAvEUq7`o.3𭓥̰"L8|+'bH((Sg 7u 1]9<K=xT(^b-([lw:[w u՚ @*oO@è=^+a2>ۃt)J+CW߭.Ȭ${9Rc3Y:m}? mv5<|z)b0?DWZf^f(sہ!с!%Ӟ=7b m!U/eH@ J7=K@?_003hFL} ŀg8vSNca7.jf P ԪKpIt}3* ~!ҝIRTvYJ'Aj@ni3 !&hAuYD5nz)vg{PT]߭3ktKF&@ 3҇h"ܶ2ԀmqG%R (rK&#N?aP6cioaxHLU]řb)Dg@@31dʅDzte=B#v\!uGksMmPC:U8|(\`\PoAB,{a1D//@xέ;V=GdeLe~H op]9zSY)L4u\71hoƒx3hVe ЍEf[/R8#_F?#a>=ZZX?=0IbN#SSw\׷@E@_\fbp11]e$U@^ +{mm9OjGW׾q"ٗ4T{}Þg}tr)KJ]c]bon>ܸ$Ԇ߾Rc0ԝh{oSc=LX#6ͅfͫbFe ~?ҍ|?sxqS|U52.ZKH/̶8 ່!Z#8ЧsU>L(h3_{P҅t?[tA/]DT. sc#4U&}'Cפn=p<*̶ I92׼o6#Asu\kW`M[1@[wWHPn28KjXAM8zg6sgCՁJ:2aJVs*,G40?}K2 wM(`3ě}`1;T_G5o)2L*N!*ƭiX.z..-m1KjC|‘Jcc7 MhdFЌ@,$Apk\9FHjl:׮/$zT98=i rkk?zsU ra*bFւ> ֆ| !KU  )S af]n4pVNN eYQ\">@/kiu37\CK},7E< 9U+Z pQFn—z! RYRB?Ԣ%1g/9 ~9Eb9LY)ZaeлmASдH4&v&(* sw=y`*}* g C9Xիm# ax!H><6D8ںɈzgQ50e*yt_5fz׻A3i!ȏ#/EY~ERrT̤ˆ/VrGg %Ј›}eiÐm=Gy~\JWqY3A]XkEv4MƇ6\Ü<;ns׶"ۨ41)L?\ˑ4qg+t`Έ)lp$Q[аUa-ńҴvB`'ɧR)s0SHS A/#\p|cVؽ]wʿ,e]'AntصF8Eĩ-sUSy^׶hFZ+|ZDL;m8@?H65#8Qż;Th;({pJ(ȣ̖~(yXZto9;Ws/BLqiib+JRP< 9tuBt>10'e;)`?F>IGZ}X V͍,&%T^Q!~20O M MKl$.Rpr35d b ى6T%}@gT_A+|;+^$ŗ53rq0&ZM(7^Ә$2cjt&֊/+rh1?ӄiK_? RVG.V 0{8&P),vœ|vh Bqr)jF'J0ONslql~(a7:1BޠAWVwb#%q\x'4LVvƺ<_ #Ck| &*`\KTz۱3O1`oƆhGKI|lٝsw5$ WJ)hc?!Rd܅r ? 6Bܶ\'տ bPUM0Ps%4.a +Iye}Xk0`FC3hn%Ԏ$xؕ4*>eᖞP ` Cb |ȝq7w#z>UGeQ?BvZF:s):Fרkwq*&N\獌E]6L47q{sO|oԟ~ݶZ $5((3|5IKYw"2fH\"l:ql%.;Ç;Ai/G,0`L$yHxˎO@c0Q5[VG?/ؾaٽRj5iHpo::hV╥FyVН{ CVW3, ^Q UT%DNh> T.iyFd:Z"x<Վ~޲kmNjc7|ϲN.?Emg}6,K;^a(,+$2Ǹq 41havfCTQ[X2:TfR3~LT$n/@%H&t,GnW>XpV,t2A;?sQ.csjܧwV51XL8ŗY& 6$]8Jkaތ+sX E~ɓY [EbǪ`B\DI W!qHnMA?@^ 9Q'MX)Oy6J:+#lqvAY6IVY8x@ۺR{g! `nxi_cޗ;\1';uQrԴ͉%dnЙ/VDkix;r{&'Lv$()jKہwܝ2g EߚOKBKoc^ٵ 񽒝݃=2^gIS_}/{py :B ?V 0C}>TN:Ƌ,8 ιW=T_!!n-&c֕AP~#ZҚLAq7 aJ1V4nwy(^9088=dFljuA;\ua?~]m<ߚY*-`hQz1M]&nsSę;X4#ӇE2lt~L\ǮaDrD5`"?6۠w?Ve1W?<]_ȂWkHJ#Gm*;zgtz"̫"=7#ZOY Pa]< lg-\rc; k T/dLutb']m]lA(<`>K{.n:lHW]P LMإ3+H.nTk48˖>6r=tk,d/#kA#_(y|"wqZX񽗤Hk`ND9-P _a}^m$f-dG卲 *-&:x-1ɘOe]-83;#5QuyR@ | MqXSڀx-|>r|1;xQEx^JBĿ_[0][+\K}-g&ȝ)6dU6apn? JS-91Y:`JܤVڞ&?3Wӎ)ΥI3G;RmB V2La9E y*7E"ӪG$k(Ȕd[Af켱q bǺU^ޮg)'z?;X;FrƮ,L༈O0uy/QUφrl=>R:d͓'WD Bi3!jx(oCErA XjCWvjDr!êrmskTJbO:V"OP:7#{.bӔ@$)&eѲP=Uh_ϕq! jK {7 >a]bb,g5GǷ\|e^_?;;<W |+CzŀhV~lSK̟fbڿe^hֈN+Y>.N>9m xfU<#p!Ά p- RI[4n SA"s&RG5@6uP X59r`tO&B6itA@;GMc ,D:kIpOlTeƜ,}QD}'JǘGd"1)Ha71UqEb(Sװ,Dž!ډ D:MH=[ )\I qXC[!m~i+iڮõIx: [0M:XMGC>H$z3n5HӱًD7 \cgϴ=@HOέr}_Y~5gbdjy Ψ,X JW7X6Uߺh7V>2N3s:f/ h72u2[.%{9Upᠩd5 vYM*,:{Oږ[U=Kh >}yRM/OP{85ڪ4*Ĺ,t \HZ%u.DQX3f 颀S:Pq3b%} xZ^ 袡…PHycc^8$ѹ> 7|=YTbf[|}ah>ڷols`c L \: ,̅LN"G-wx]g=hK&IJU-LU_5FXޣ !(fKK(+{ yu m>=F?~-%v-V}OHgZUYe\v %%>^ZTI9ޢ-O>ANm/Y|~ѧ' L(qҰ>4fg>X wPJ ͕=я'\隮`Xn L:-^vV_|*R}pQ71 mÉl{ξ$ܤ{x"3I}^u}jn0$ռҨ'&k`<Kt*VwzBw J~Y.Tu8qߪݩŦN"ć5-ƦlAg>C~#a8nm̬z`tͩ[)*aH_56 ;~LlzZ0繬Le3×fqZ1;Q{!>gVbbqMpæU1?"VXHw{t(RϚuѐc %B(:S:nKjY\YfnЦ7z=I9il)GȩDM6H ͪ;w Q>U<=ZQ^&cXȄlʈQyvB-m9h5LUk{#ȔHэnנ͇~ayRhwU]1?nJ@^4^nW@Na"S`Y-d%lُ;:]=8f 0.ՙTt " 57'D@ b@\GNNSV'|d'X6jQbyW]ғuCӦs%37$VE6:\"4 p{v[Ƅ7FLoͮ0} \M*n]䘢Pi&֧F\0RCrZ )~>YgT̳?N#Bӻx[!DYhuy=ntZ2sG ./u#vS{|v!9 K{,&N~/'k~>]C AEA#A5 T:+cMa(v.]%7.hzc0EEyko,SqߊVu-=RS|N1\4NI\{5\:e% m#tiq>!5&gr:*B)jH lF`2> V B_5< a@nEvhn|?؟=Κ;dfh&I ('A=?7S8>X?.|4;Kʹ''%'=,0fp@vʳ 8Y!AFZfxF`h d.ݤg-߷VӋ:Wl:r3s=Yw#븡,g+GD;KXyp5øBEx EB vmosL%E }+4 X,^1ߵzvsM֡3w\,כ=R{!gU32dh2ŽWd\J#rֳ4 :P_\q/@.0 RG̽?6!́&&LlFjy=$^xK%4*&NpfY'~sSseØri cӑMb9s&o=rox (I[tB.cl/m Rf՚'va#2ÿ2N9CcVۆaHgy"\xYq)뙬 6">¤vC~>)86Ty:F:؂&:KDt[?8 .BiNu.㟷2add{~62z2H`nd\ B~l"2$ tTX13PFA=yO }F )K2GZq ]څH֌=(i.]ǰ6gl!Tx]rOe7╞+0}&xu[ ~B~l^lmC +.CS HENϴL+K}DAG)5 1'PYfhQl/V̴iZ'%*)Lt4ZNFxf\ͻQ({Ul"+!Va 'xbr軏g1pfpd5h(_%]>;Hs9PVS2xVrŕ'C0"uyUU8<<ʺ`/xwu7qѸjDGwJ2?Na<}$JC4,p\Y|}d#a__WjfZ{R'\]u2VQnʵgT̻&T,}TV-3N0I?F޾oԙ9OCSpÄFZܟkzx3|??8fk#Fa缞(]Y)NbNU'%>+1پ_o(ǟZ)dx 2[#)W(V6EDV$3ϪvH\1P3Cjka=S4&,̤);)鈪xu&yɋLlG7sb|ctO E -iu >s} T\yDgSloAQN*H(yҹzcBt8H.rh:f~p9NKlZ47!j{G,&YFWBqPHo NJ"o,XmrD]*H!h45dRƆ,Cq)ZG.C2nfv&%)_`[Cx 9~ёt Si'ZB h$G03 %oCD{%킅e^ѓl\ 8x)섃moy=TTm.C]ST4`khL!Y-o^pSݑu^Qcz9v*p."y8S~ ؃b ,d-\QRbP5x=_6e|&dYR5ެ4k > EL eoبpk%&Def`v%f,'\A)ť+PmNTYIi5%p\5ZbA  5$yKodhD(Dj2*KM%KGk;,ˍ? sxcCfE* 7?G!zѵ42k(0mp>%cRNܿOnT) gJQyU~ǮaXL _R3{ȅPfeOzrQ3^Fҍ>\ω;s1K$QSʞV#Z^]Q'D?{};8^?JX8c' ylMVg̰u-EX)hG=+hEƐ]1St2k{WuKW{g1w]%n 4ktLc.J6s0iծoif495庯t֌meUԳA|Oʰ~ 7Ѡ|&նghLEmEi\H`x~ *0pz(#C:1w٩X[߁TѸQ͵nO./) KЩdMXgU[AV.~3O/_2j'zNoL;bDFqؤ:7[lThà QYI90&i}^ ݪ0baIxT'<&";@> %}IęU='$VDE9Y޸ w@7!rZ ;G+1q$b>NMy?k ~l i^JŌ _l`lq >ZVt|}SF螱.پ}IC0 Y90)_[{όym(ozt)#m-_5׵p^pIH k{mfV@C>>%a„S2&w fz ԊU|1R<|%O ]ROBNׅ} r︺흕; $Eh$hC،ΞgF'.qk+zknޣ7OD)TQ ۉUJ]sQfm@mNYHwr۔IOщHoU=69?:Fq٭{<-Tc֟3 ~!^Cz}|p4Eid0!d7MD9`{KPkpl rb  uPkFrANT[QܠcHңp ?W Jhx8nMk1S g4 naƜ2 7ǃ}:f+?a[@pU͝b:>. mgvC^K- N{0R Z.RNnME3G,WTa^VD" ~>?xY|q7ܗV8HjN{[AѰdkx$z)Axq7gJ'nu䚧!kD{G5RZ3`+Ɖ%"\yHR=ހYzd4}tF=µJѼTF3IU3t?;=g!X-{꡽J^)DFMBQ?mBɗEh֮Ձ,H[?dO>cƎeUY+Yf-/fq8zʉz$KB!L+y[>bnݴ: P6r*kX~$=W(\wv4K>!EJ bw~ 47Y{; Qw?FJ7JqmXh-;(\`MH>\}5c#X\ [4"FM,ZΜٿDI;.ESY٪|][eqNBd NfSKbD0.yQaa |wŜtHWW VMH43Tu8 'mgyx#q_{lsꞟ@;<ܫFmc ?y4!o7YKh'XN+,Usvir"7I :7!,kCq{8SLM;5h:;~GJ9[U286k<#AʻER#4sFxC^K34iv1Z[p)\*n66-iDK8wKicxs;J2j)8|WPJBK!`o2vYw>^GMf6WI^~. 2TϿE\Glao?o}-rL?zȊ0PK &Q[S՘?Uh3('ÁXt4S#S -w~T'G٤}5PXڇDh>?{.'\Bb uhUIg0-xwcýs#|PO2o'$F㲖. (}&O!r] tfH1)='GP&y ~i4^e$f\L8U>ָ_ 酎azDvFk^rP~b 4j555,ZjD~C}35cO] o'qS?&>fS٠/>0z.QqH_8}%`:e#F#]ZLEȩ0sK*zo0ˁ:Xzālje37hj6uI'ib=P9<{XYIRq_XA|c 3L|a`&k?Ӓ:@0•p=.5FxYbwLwC[cû,Ƽ)b4GvR5XzMF;) c}/W4vOxv3!T#Zg{4Z]SVi#?/Ԅ((+?8Z<\?[<[/L~(ɅO}U͇s >>c 򜵴&6C@ru+Db2P|a :r0ݪUT5z^mn8⠇ME5/v~w۾&(FmX _i$&W Q}7V^ت4XW?"k %;tӆ!?Ԫ8hXW.CCN8Dev*q]9JzA^bW0%s˯̥Jxʸ73ZDN?ls,kXj^nM$T4O:pk )yGŀϊ $ 7ri܆Uƒ?MCOqnǝe."beG pU92m+J|9q4k# $pVv7꾱<2Ad!i0!bOrCUxpS_hNPo =V铷ܩsUpT}!B'@7[E:9abk2B.d]"EoQ,Kg*C6zcd:FfY[/7pr>HpVN=ׯ1Ŏqieruc K C'+ip ;O HqSJ]w4qFjVD,M]T 1⺊]77O] ӨfQ6爓ܽmMϭD Ttؙ*-WZ o60lr}r.mJ!.:5i#$+Ҿ J%U-VMz\bpi4qo`}A.ki4Q}Ȇ% ar̳ LGO=q #S{۸ ok(Կ::h *SRcכDRiKu%VTyM#hP& Yqn}cu|GY78^cUSȹdGQڭsvQ<޹qD$P|<Ӡkw_7ݲoA69'i>{C){5wR_f'p%gkdʍ`U!O-sfȮqS?43(0E"/U{cqӑ϶^0CFR_PؘO H9eb6>5{gC@&24pַ"fLJT@3f7I_u3c"Vp )Afn\옲3jP҂)m$5 ŏq(?Fv|M~'dC/q$"ݣN (@[H6auW`k羚? $6|5q0Ƨs$ŤN(E[*{Dnx>*z+}5왯F1 6ם':SJkћMYdaQ'^)+RZmD+oۧK_nwo~/ߵO-5adFdu 4sGaLk 9aDl'P[v-H8 )j/->j:*sX.dtUe29= Ώ/?eL :F$w- kH:\7;P]_>ݻcdG\ m5|(ʴDPq-xa$=~;Et$\ -o] $*6YThp0[VrLܽj7ˣŹwB U'/Ŏ\^:?+pwPl X[NGs V;zw'~'<5KԦ鼌·R]N')uԁÁ 67F#@xP+鐁͊nhI!GqG|Teb?]jpL#ti Y|-! #ח5T;Y@⢵!}!r/V{V\knj/a~~~~>]:Ψkj1}-,'GXZ)vWcxr߸8Ahꁽ?t -5؊|g߉Do?I\ ւ@{Y=(g B*t נݿ_! ////]Qa#z] 5~>@sh}4]|OqyWU,+rb%E F0<9vM{3_!\-ˑ%&Mۂg7xBPRUœ( 2"&|8؉4Іc/-hHJP?((!Td5v3A}>s +?C!p8a)/v ɠ^`xX{>CpL 2O,C̽=Bf,LI.{#LWզ+{*I1/Vm # @oR[h kߙym[vh ׄO݀%Ve=z|b̅1*BsM~(/_#D[6$eO2UoA< "OF;@A:U1‘ӥ! c^ʘ4 pKSanrI!= k$lu/nNvڋ5|"le(|_PBdSK)I- ^c|j2o .녨YMϣPcbcqD{0&OqC/P-Jv.xrSq5$!B=%zbV3z[qF]= F2ТІ`9(}kM51W*|K|J$=[x~g|ȜޛãMFrSJ)^(Mw ;c 2MLI`MfZD7|R:!cwCvj)Ɇ=d fY0V;/utpHk1}S婨P4DI&Vz{>l3Mvk:͵Ds &ђt kEkjޗ4IFvyB& Pp#O()@߉hBvon Aek~9 D߈՟ &lI裭ɒ QAw ,|7FB0YQ^){D: bUԳP.䰺*փw8zd7$%?U1泭spL־cLo5mQ[U2 )ȇc~0a5Gw6閇91cEej`Wdxw`օHv JbmGb|lOVyI@;Yt 3 g ~umYy>o$ºMpg!T)})Y>=qX.8]`!5J2b43+~R(/bծR,R<_mF`ͧ!36+_BToDH.d* v`8@p+e+~[ڵy˻J%~ uz9֢خ _įiz뜛.SI1I8Oʗa"pgbރzz(wd4 N][t eJ1?Q*h ix &'9ш|Kqq߲}S_(ͱ3J,&"MU2MJP`hp&M6en LWGl~5h6:֎f-(Ꮄ YB?ƔwtkTЉ>XRZ%Z)`4~l՟\`ZEe0Ph+wMk?ud`#p^`ZoBoR+p&)L~)QjHcZX BDV$5jg{.K}svdm&v2I~BВ9cW8pf^C T$@iY}U~Zl7TVkR\tn@*m4%Q>( 0\Gv )MWFhjXq01[8Q?1 ,EJJɚ~ ;F[p}oFPB:.tN'aP8`{+(?s^G~}Ʉ- {w_QmmHZ0"wS@O;\ͯ(vdP$ѝ^>}k3;[ժ 'T`<-1GwXxhN'!/~FDG1iY$^ !O5fȁ|yw IS/7yJ&챒BijϖcD1"/1l@޽+zih:Jѐ>Ћ eϊw" bΣvټf[iaɌ:Q?(8`[FU7}Fr9rH# ܴ{ \a9h9+ Cj㰘twwRr^MKy[ɚ]HC7*&lL=$ݽڣ] y4n'Eq9QNc%J0>gw4jc+C/=˫I!\2حǪ{?'c6k$ ;pbmJwڤs I(dj5s8BtKcH/pjሹkm4icBq xG?nb]?:PEaW7`($Iev1@aIzSiJ΅Y1[E"8<;~l#bUנ0"(^S"7#o`"kaP#G .BgoyQ^1aYRV}>%qމjZz#k:y&O` gB!z4OGwG:`qNJf'=7u4LR*O z1V #$?Γ[𱠜 FZ@9 K׭^ 9Tb*!JX?CpOb6}-)=HY8;D-wq%Mk&V{yOJQ/sO3){}K۴õ&XTL??5 ͚b!5{VvkȒ'f T\Nǖ='"]0 CtAH .0;^z̼.j+_|xAR2nb1M;^v8b|۶0*ھޠ4 0L)m1 ΔMfG7iBU|czcJ_dcNOzB!7svq[r}bVJII}>ss)(7?Eb0-n'!t+'>QqYnL],i\tng?nuR3 0e,ա#:`Z-~j*.blbqHh8Ʌ"QWaUk) kb0DĹ^ZNjE/:I}p@ܖ(2H}Jx27y\2ogsS\ʻ>:SUYb_^S=lm@O wuC[=ϤԻbp>&fGg#Gz"Q^UOR6t2"֮@;le8aIhLog%ΘeB5j 'd(Nt#ulo>4+hqj鏈~!c@TrKx_'3nk\״~ S G\C\tL °z f##ma)T^@MaFKslF>s1-ędbWkǔwU*ۯxlO_0P EB/) IIwS"["y2Ms|#GceMKyZn5KŒ(yŤ)KʛI&-W!>&䨼۫ hŰbZC,x;+LVFa_e`ngΊW#fj(X"q#gǻ;:8`;}VW[~;ˣu{]N%#|1^įތ'UiC 8l>E֕ve{+j((p]I lXMOEujV@,m( ?P@C:9^܌XD_M71O/bId .٫L%WZ~cLB@ eSw fݥamu`[7dG~%L3ڛ*Zw>Ŵ?Ԝ ȝ/pc1pv2ˎ n Kg#‰xR/Qϊf!6x8NP: O!n&x=j.)#)7C[#Sj 8 q#λdeɦGTu0u]noWW_V[M.*Ia_M$VA\U5XIѱAFd?0TZf8i64FϽcd`~!}$W$-[TQq3J93ğ-$Ո/Gmg!Fd:}EgP\R6ǎ%axzm6*8138B.=C*_@SDoqb=7jDw@!W"׈Rx-tRS<npi*" E "~+ֳ>Pp%u@m7湷*$vy](TLcG_7L_Q4fA&fNM\Tc݌(>}lhs:Rf08ϧ;oGmiw?Nyv\vnuY)T)̴[ 79#-R R1,uK~U+y@eUd2lyu<{i˷R}gNe aҾ-ZB^_hƈwXgws@)elb<`^F:MbCqGPBᙆ)ߝu6Oh=)w~>|VdVd L~b$pA3/)ܴ l$Qu;CaaK. SU0#V%z}a¾~mL^&"/ge񲫑'nսfFeP&3Iɓј#MP=ۍrYlBOO{4_;1 K-qYDV$ %:a^vU Ś7M~IጰRz:,+̪ Ip╔AD!;-U0Q9C=-+OXG܁&Ob`EK-ӎHPD)|y#JMuH8ᷣ'*;.p[Q* iAoִ$oDHmd߭-j|pnXT8)xT)$~lA S? i DU3%i0,(-T^f%;3˭) V|M_2Ϳ v-3; bcVS. Zs1wp<۴"~H-tu|Äb杠t_{j|y"n!)o~OvH-8U?au4#`f?Kr /.hS0i-,@1hhn5?JXlq]@T%[8tqA[4Bk}F`2Rc ODžsuWwZHQ bV<`IIKSozGV{⭦ 17ۈT'?kgdxYt&qYun˒Ws6@C5פeXU,jRsѱ vW9%T.nX6X,a$ u#[M?=N4ev,Ҭh *XȖSP im *r;,5P ^ Dv @!-Hq0kNE+km f e^΁"{rr|Vs2g(y1CCP>.3En <០@'11W57T R.QdA'QLjLhҚ?4V'fJuw3o`;n~v: 3|l;@[A4nsQocaM`.9h( QGcnO6CܣQɒ\@`sL d, 絊]μy }|@PY[HyWÆ++㈐oB"D}WIS^~F܀<ÿH Uhv{ *TZ݄[]ދtb4y-NB.0Ʉ ^d5c pHPX"L+]Q =, XN>.CP\K0`O,RvKg,ATt"?(zw]@kiHsk@yE,h.]h@,*i Adf =i" k®3m?vEč!oPI%bU5B}dD,z!(I{tghrR{C`\ S%{&ʋPS4?ħY-g?|w '1֬iArgEVfGNk"hna{LtH*Tޒ6'cp!0{{&pz2HhǛRu+}Q]UZq|M.)*}~+k5dw:zs-INZN|Vt(K+۠6:z߃&CBjT@zI klsEw%6Kv(Ʀu0nMqkik;bk8)P֠Ld{v؂z n2% F|߿1eCrb>o[ j3`[ ?] WOM>*WKdiņQx )Yx0R\!Y:ǁrxv&=g//\ "k7UT^㼆{{_YUc2:(h%&0FSZ :~9%{ܟD?eFxU6(P6> #0]"*#Az}ՠKow 1.J~/>b"| Ρ:_v6 fJӈopNZ#Ǭ3dQ1ݹZVEMumS[YE$c3A7$^xޛls쇈ɘ,U>^'D7rZiL?ǯZ ]Ulm ]Jx_R?RhÏS)&FgEsLz`F~ ۠~֨Sw xnRZ&w>zLPL <:KFfWj2(<6V#l}tC?8?pN&Z@Qє#vd7lvxa=D$N ~h铏FI0HdԲ3 FIR.OyOrz`|, ٬<䞸pӷUjg/m}b1I)G;qaԁuu4OՎ1aN2nQT0+2+ݧ͝l~X#k~ N~z<4AdZ=Y;FO󼑞qE^p?T`z|# k[[Nr;Vapc]vK0m3jF:+]~RuG$diKl}|ԘqPKvY9G!YEcR$:L>B:GW6mg4ڥ*OHq%&hĖOۓ2KșKQk۩Tq'Tl /UÊ#V0#Q\IiZ )j˼>CgG#V :u0ܺXsw%Љ ӧ= #wuD-{%CIN>hL2얇 <|Z}DHI.~p?BnЉa'G nmJbh3.rk#p@|*蝗ʹa߈2zUJ,%v ϼp1b4?xp*&ѣX&_rMykPov2>jƣ)6?'֩ӗ-DדARJ$%32c_iEڭo6ަ]x>΋֎ iưJ7J1U? mb1e.4QĺTo}u^𗸟=;.2l_LJ Ts}OMþ➳XY6Zϙ=GxAxp͈bjȦ `{80t2O70?>#9^dYGz\;syOe| P4tp$mrI L ˻t l&zF֙-"JQ7qLGL-BLnΰ|p8_t K_bK@2h|0]jjs }6%] ~gn^VT6u-axPWӧs/O”l¤hK* >U64pZ۷g-XW.x[b ܧ pȎg8b_(]gOSK.k?`D-BUzG^?WF%{sf8$W||kfbut2-cQhTPC 䬜F,kn]9X6G ׎`tܽ.fZWZĬL&~/*ieDœ'FcÍ7y:!ZCy ]< i0ֶu9*-10 .qzi(?ՈN<#|M]0hP4ԥNv8GV ^d#-Ys6QZx%NNkH>猴F'JecEqᷴϗ\UnSO Ix ӿ,'kLF cPpb5 xq(x[GF -H G0ILǡT9|S-{[4 =vi'z3Az@|&^J& ںKBVfM{9v㴨ub{E֓8g,G=kq; qNRO{hq*1,d@ml[eل#&9PE_FXAC"T.8ɋC"7 PdKHƝ`/ -?(4NM<:>n7`瀻`!6UUs*PP!挀!0<*L~QBvYV| NiwoJy ~C=\ggja r:V% URڏU*G+@3f0*Gfq x\ /hk|sQN̜j{gIq256yCVh&KH]-42&*#=rW؛+(ekdk8Ӭ:Oquq9CPTCw@Hqg00 R5͟~U=UZ NCuGeF74Ir*wCk]WX }չ}[Hs# i_zM`tu ri Io7iE%z7d+wfE%;w8REx "fcB B͗lcqQ=o]^^ǔE۱:(:g!]#Mg;@>4̃Wi`oU7t]N"{Nyt Hnk$Ýn;(5Wd_VV9`Uh|o#θ{@^:]bs QN_hEcƍzZ7zvl=Is 7S?VgzE˥TAC?:0=Prn^0jȶiA640ff$ĎqE@r lSWW_Qz-P`C ʱpC2Y R]jUOf[L)& 'CY.h)Tfݤ-CZRO81ƕp>t[HhS|ҪIYȎY5w܊LWr*b'ܖFo}c]+UBh{p2?yZ|;70>G#N"5;LjqҀ'B2ѡB' (Ӹ T8 * .ưDa$咐NV`XRjsB4s"xkzfcKe7!6&6x;-la)n`Us;v` QAQ/GK,T8 5o0ݻP`#leG^}/2N;rp3]uulҸi+S(;HAW1OvxYkőѽد%fbm;F=\#ol%SGZ9fn*˧|lt${9Hݯq!g|؆irh=OA^!-&:>rԫ0s%X6v="KłƤ*_ɛ(da5A{JUzon,ҥ]@t(4o/U:-h7R$!o}+ 9-_Gd@E>R2EhDij$ R/o*}s}'SAK߷4)FP;%1_ q&zU~?$(gi[ ~H5&%-I(KHs =b(:YPXt\g'8!%xs O:A]7B%S [BRT)vx)!rBt}ۻl:ڛ([^3~V?F03ƾ1X10:+j8nQ5`P@X\Hۏ}ؿfwkqtx u =}c{C%P[#gьn1g,; &]s==ƉUݚI~wU-r+24q8KD.}i)1\jn$no'hK3KeKLC<+DnF%¡TV]s]ONA۹-]dVAJpoYg6?"):w${ʹX7K3o OώD.n乄)y'X6@\b~66+9g9$D?^X |PN1=P ʗ@>^3)k8u~[rY:ˋD ^HxG%Gi}gPvAIƋC ̵tdӾ%#m7,3*z`2|'I+П8=ο-ws)mf= |@"2cD'E{R#tὢ_>[&% k_Qĥڗ;'1[ "=hkL==d1]E =ɼp"* pr)$WAEQ>]WdQ"7ݚJ\i,ޏJ;HxM! gmK".8/l[ A% ڎbS¸Kd'_Fh[jd|X5 JAMV76zDۋ"D=CsZY3?*`Jq ._Ʉ:SH'EE 405PJRdboa~ MB0FcՆ1J Q )f6% PM꾄sgg0\A @@:jdIQgvtӼg|ij0~>ogـ{]\Qv͂hǭ b H肬œ\l@?g9FVL({9<;Y|3NJ/9vt(N?VRv.٤P &e:Zak ` %jifL D6Bo/ MVi~*Wb@ !0v1:pq\ra@T:T|xLD\tW:6lVL~@$pv.9@;nyԲbѳ%p O"zJU ը֭}Ax*>ce3n/ٶuw^a>!{6+jJu+/Nrd :JcX,Yg\KK>9Y,a,q,t2&i- սOL%E+WB/ԏuf_5ceo93Ghk5B%yUk qbm&IF0!Z("Sw'LLVADÐ+yf)Boi|~uԳ,Ï#cRΌS_E4cpŝ=ں_nͦM_,0%׬x CT` ;99H)΋?[Kkb0gz9ͩmȸj2w%ӿrz+ e  VuabvXc$5=[gsoe.Q?#s@*Ry`.7igI2Gfh6JÔ뷃n nuЛ҈W1{>:B?]Sį#Gha)eq=]qE.]{kޙ9 XHf'rX7~hA, 5<ڻ!F[Y lZF?qu,Řԡ w3 ܍i,:Xu%@He "]OO,1 !jZd=6."$&P̄|sTfByTVm9W,H-O̶h3mer O(צ‚lf S?{[?Ҋ=s:*M~ C4kyW C)o5J]jNJ "lϑZX] 6_n#,Mn]"eI^aMrfcp.U ݘtgز9JicۊJr4$άN^DJvFu?U1t1Z/;%NIn=L5֦;h|&J9= ϴ%6:V(bjÂMr6m#RsK0^йL,߫v[~;TShчj.D z)%:h@B4Y' 2T*v*t#Xf׹pR-Y)zlc c![{ 7:k{$"jpGhKya3ٍvOLE/x}$gbWsx{/`,+TCn"'pF\-ZКX)fAaS-ȸ_Ȁd]{.i6ys7)N#!݃a-~+გ%>t hhOXPSR#?D}(UZ @%S>u'6 zL_wFO\?AOՔ0\@K-5괛5/(+PCEH o?![z E8^O>S.7 KŪQoCK"0"`49 Įٯ9Ĩe0BȌz g\25݆vN0B%l O*O4!7̟9nBn `p13\zYt shpHt[蝢vҳNLlbƔ eq칷C#\(^63 M `)!+FոEV^QZu`6Zv:g2ćM}ϘE/yd6/bSHjR]v:(Jx'6$:.*;30^-\s5_5bw?ӳ9!L:hyzPb2s!>$׎%(z'=!3A\j=G꓅J?5Mь$JId˩s5ʋ6`N*pU~ A-p~/*O[EIFFWM-o-wvpAĪMvdSLfȖ~+PwGك0] 8DٍD?UCԩb1Be,g,Gam[=3S?n[/9乄ޘLY֫!~\ğ\ĩl/Qp uj so0HƊAj)qɲ=$XP+G,FN}v|J$LAFg;t|&.dPyz081(u%%0(r0+eQ\jkqw&uwHjĆg0E$CHP]i%9sJ(" b{&cOUh ZC' VO+4^խwD>$S)zv,3; 0J Ⱥj%k7-RSyOnK"gPzW=J&-r$$i(`CDOYa;MElr1K) y5(v}Ҏ,?؜jYKnl[[{\WlC_ug13'Ge5@N;f!g>5hU^]/OTp P3:uPx-56ygU2P%ÁI'\kr0zKyT%h~Zk >k: oO=)2u#p&΂!<̓A0œ8敏Yl;5"*\l:GYKœC]&~l@,{h;];nyEېV u>LZt:i&ƥH l|npnhL>}cxûJw7g|5R 'HA[]H=h z;VPw&fjFPHe ~I~ѳsZh壅IZS1N@0TQUzM3wOʖr 8Y+wqz9s h˺hSJ9Cm#r淚<{ںXDw=mSg~c1d_+L5W#-N(.>ٻ_}g@N.6ܯ ~v6p\ޔ)v4 a8\ż:rS'/0 lv{!U?JYRŁÝa ^ro\'hppHܿ[|*D͘'|O뒥6|ꮅ` Xvthb}xPbb;xk2?v?$h ؓ&Im%^O]1ٯ_ M/azvyi ]HxЧ/&6#wf[n*<8Ӗ-_7w]༥ΐWr6 DIC4w2ߪ_1q KUnoABCzERhY@{yլ~X;#}UP rRiBvp]L^ *W+S5Xl<ҷ(7Ǡ=z+o.$c<>ZF4;{4] |D.QdB GE))rdm C J)wܘeCca:HMp~+s&0ឆU6ڬT n6x?R,jKN wvөuc˄[,㲩PV e5pOf_G8YgӚr1DKf;-Zʼb.Eʞ4c,Sᙖ`[`Prك, y V K};)5K&mfJ=wS@8%UlB qUYk*DF;6? xQ|]=;BNbTBOLDRZa-,W镯`2g4/Jul#uKB1!i0e-Y~z6D1/`yQTA6hg |t8)a45 wAAؿY4f5o X#,Cs "޼,j'k ᖿ UL3[ eK{r6\O^ m U`𦛶LxDRſ6ϴcQGA 44ihO1% hZ x{>nd{7ov;=%=>\Bvw_3!̎%Ŷ EѠ !q=>lSJ˝. S}b:CeЮS ׹h. J<х%XCQ87/Y{=oSfQu76ty[T ' h2kdE ;(j5Y^ 7t/?oBn57.34${4EG?=RY lpF+jwAG&`GK+"yp:+f$4􁳚Y_aȏIg'tɥR)@8 Cě48y,ϻp)~wų,H)%9Px"WP x9rqGn5%lػ%(\je7ELUӼw|5do@5Te'TWr]"sIvJD KȎbEF{un9ah+>v+c ޏp5̭^43˗[h1wIǠxKd1A޶ezۆY26$s cӏlm+dosHxi-C#u7kM`Х1Ƙʵnu[X_c8mLPKg.22P'W+ƥdԏnblof)E2mD@lHL\\`(Rgac1""N2^Z#J;& -Y,֑'5LGuZ1¥,L*D)>6z쫲4z2&Ɠ5 E,";:;41f+cw/g7EBX3+Ρ PA'FELAH~l[ 7yoam&)3It$ m!7Z{7jܖ:n֐m/&ܣ^y6j -/![FV/"rl[1^[|X^-l:z!2(Zn3EIpdeA`FǜU,9 Nփڜwh X&Gx9zR$"Lɽ8OPWJapO7S3~ҫ/%pdg㓳nҟod7Ȁ]JטD'rzǞ ?//FFd3Dg7W&!7Ϯm.=-,px Z *zrgVQ`COV[$ө4˳8n;PNq:M{A-mC.iD_Mu_כ$/E>&w巻{9rG0ѳji6L~к@̀Ɔ%-2Z(Db U}"9گK^ _-!dQ @ţwhc̿9ɓ9؞ˎ6dpz92`,6j[ǹ6Kn;+V+=4+ǿn<~ [f6*"q&sΐImn!h৸ȣթsfuJ+in*}^5)v'#>S<(HtP8--ʙZz T|Y~ kH%s%\^ ﹉dnF<'2M*'`7Xmv;eNq1|kqSf.68I{ 7T%6pLv*VR_xƳ\?O!/qs%L.\ip?Ǎ繼=^],:JeRZw~{t~w yI #KM΅sŕgTzX%+^ v'%JÏe2n+L5}KuE+!BeG$SaJ@V!bχD۬8Gjǻ^E>$/.I[a+wI.UXS미q&sȕRO0'p՚F _I= `Gؠ sАL#e_DA利x1G51x9jeܑxnA=ﱁ#FG LX<ίdЂRˈ5 :zBUᏁ+?A9ԥC\\Sntw~Txb r)lRSWg5j9Ptu1N(RagWЩD$ˢ)8Zthaa".Ї !/}ZoDk=;ŕOT0τ 'Wp=& .]x|T?JdT-2-!>K2[3Mu($kWЦ*dg$Ĺ@Gtd"kK&!h`>2ah~99;HgCXֈ[]1YmiªdbQp(ĪBgN#Ea|R11*FVwe#P@I݀zhN^R:!CA7­/zjDm}`/nG󱶛h4jzW WA;-j q=r~Itt ԅhl+'lviUҡ/#ݳ@HVDYǏkP]-H/Ol;WN))-7|˯KJ51r.G^ P3'YpZuENO E ]R.?҃aQ[ybP`+!js2+9HRfF`70!m q0.JͧAZ#JǔL({Հn DtƤ,#$uf~ b}5!eT/-?&2nT,_/h`NYmK1$SW!{Б=w-Zr,M4t7/İ,]JSuK7Z=+j$5+GzXtXnDD+ D@'bs9IJY27c؋NT[ԁ45tV߁ր |_;NisGpP)Q\k aaTJ{ޛ~:ոzUuZURa P"v *Ńc/kVg4۠FL (͈ _pؓ§7?%<0VM1N /ͻjSxe=uLt?=¥o}?Jɬi!/vsұmoqWҔF-EɊ&gw`m#63Ixnj+ =zRAmup!9>MmgX Ѝ6K̡넬Fc& Wo>wxesZ~2&'ШyVc ]CsUoZ ObPNl~vwjŃ^"%X ڌ1GgM=g!!}RC:~I'Ю {[.F}.E^[UABK깧AJ `Gd5 Cb+EΥdQ|t͊FV-b/qB&.#3 iwNpRgQ 'EED&3oBjߣ*Q3Pq.ȇDƹ Kp9 plw),n]V0(4 2fvطM-rV{P1<5-dL6]X Xh'#&̌~J`P ei2Х ZݦC] aMmOPN7Ph\=9Ob\b&Ck@ss(zYnV#a@p7N7Fz-eV%`̟9An{&[HXP[lMpOhݫd|^6]?Z;[1X] l_^֓Naҟ'hIB[HhʧgRSSɱ籽_g5z9ruXC:afdleiQDcVCZlχJ$D(cF>IeCYPP 3RK!mY bLjա93:)NyC3}=pZt(a%Tϼcu4Э; >ڤ_xsZ<@KQȳX%Pxy(n߷x/Xw? JonѦS_n~/+߈'-{H&j a c 4N(ojRӢGwvvx&-_Gd$~ vo&T.P(%Ã:ު`*2ME 6zh6h.-%LnvJBnn^ >}]‹P -@T4q7hD@^1 @ZL I:E&NvnĞQ8‹ I"3B~-IO%RE@lJ2Na^֙àE럝Il v/3~y@H BF](6{ҭdI l +^CkJ$^Z2!/|] 1&%"dP^ J04!A2lgz# 7Hb K/'TB%[@t8=9VY3:.b8yc{2O`srXX|+Ϯ^e ű~Xݲ,0hrs -qp=6΂BV$JV&h/76-0R'>k9FW}wΙoTBk:3*tܘ67R7kRvHN ǟ/ZCX |d5*JFAɍ|.+g-CR]^JP }PՂ0{}H%;ow@ YKk4IBOׇTQ`Itљ?Ra$^XF #'qz6Ϧ\&>zd XSK$-}+CIjmVA~v&DM?We)dThEφ6jGY8a<{)i(hAgIܭ ht63K_;;ʪIĿ-\crՆ 7/AC@rBgY %U},d ݱ7'ʔMvbԎ% j^*o~׿~*+AV2s)UݤSy:RVwnq%i.Ɉ]UW;yC[d9W4H/TmF8r} )F?3±MږGԖ>i\vރшZx dd>C[8\gw g 2!ɉM5lS%u_VJg Q {a(/A9n49cmH S&=]}GWwGl|%>!} yJ:8t%q~$ sY@p3ҙF'ԣ |Dgt*/zm'zq8(7 O0ƒ0|Kt(W!iji{WHZCSSdb30/ Vu8o)ʊV_k,} ("AsG2BE5Ӎ)&ޚ?}Ş7뫕d7PHX(>Xec!*VuafdJwPsxBkFZi0&gkxHœ5BM`F\DTh/YKg;VȹFlߎݯO -nt2̚1=:< 6co&2`/<q*]bm71v7VWuK~Xk澜0N"ͯ.glw }Aλ "DϥVw*a5ǚ"1M:.zEa3ٲ#V0` ٖuY5Xw|0ݶ:U%djQ$nPE2sXq;* 3j Hߓ"3zޫƭa/8" Ҩ0Wl,H/R<hOggifjTz&S@ndmV;k˱y۷B,ceE6F.(j(v M= ޳fzS'f:jL4Q8' !iLlECeasbEdJ.=^Y5IvkGR`Ka0d}h%` jCXܽ}|9gb4v!z ۸2ζc]߃&qgҫJ(K"Hl%+3>쎷B5<Ơ06IKtc6<[eKW 6%[Gsoݗh˴DYn1AK~_&{aFw͞y9 BzIИe`IHI@Ro2"5DNn,q=V3~1(*y򧦥#%y1vc6:}/O%׷ҭ'BF/Ow $*l黈 `Gq= xa}@N^!?ǐ}LɎm TQx99m)gD"S(ϥynUBa>uB 71PQ1yG.㪃sP,BK q[N{Ok+?d,~ C$(.ȣYϸx]X*Jlbt(CTM<P92D{$m/`ԛ9LQ+ev\V_`7:fKޛOrف)R4lX#{m FCK~O aO@v5!TmN@$=bcvALhn^@? $<%g(@Ll'A ~.K!P((yReNehTcg1OUNm}f"5ari8= `,2Ng[e;Fܘi#Q[(d(k M1j={܅j>p>3- &5$}% "ec9ք6gx}4dTSjy^T-aSzHixIB5P3u I Ե2HHrĘYs~µQRX Zlc.o# ɬ9wQ_+C9/v†_* `7s8 ,~#"8"[J4g2xdiN:v&O {E,ͤ-Y1/h(0U \2a/PŞN)Wzt|WpCvLM*zd9L~ WiNX345DT1Ұ h#Pf/vꮾ[7~#${)g::xT<ō8n\),XD*ˣs7O"_e){/'ݮ@E09%&w夥f$Q: (o bĢi:% ͬUr9T!,:~L,\;=$$#^M9@j290erNpa5e|'έ0:7ff.c/jCģo| ]ç:vVh 'י:YGݲA𙨪]ܤ $l5J0>e!ɓT#=%)}?'9j7Zޞ!Q "j*ِ>& lP,*Q7=  1$$)-- B,(\l>utX?;>k g.@H? HB%R^tFNXfgvn6MLҲ? xu33Va8Kڒ"ݴ[l6l.N{+$=xڃ[BrI^UNa<4%el7+i(sC<ցm:\ڸ~P~^Ku>fi ﺣ#y:,0nDpQ 6BPjN.IHfJdsS^&-aFRJ}}vR_t P7ZQ ,c?4n6ujXfn$ٟog}vxO~[&y&ܯ=4w௹k脤Z 8ɒ>p$c$b̚q UˮPS3J/fkOX1.l1DᱝrMrfЖ4HW(2(d'(f|XG̀|h(]eR)P(Ydư7?wZRo8ݣP\X8FzuBYNq$1o K*U:z "(aLInA*'TK|4b8uj/\Fxu[즤,0:B('+ۅuoىBtȣ 9l`jZvN>9{6H,G0RFYxFF yb`|(,}%E8ؚw>KT,F!pDH0~9&w"jam l9%+,L0 -fBb>aa$|s){߶ GBPjsRkk{˝(L.9mTdhĖ.3ބ7ݾ#u'xt Jnmnd]ے s*~Fɛ,%oc`P@Q<<sIxOcbh9aqyKsaL.$ҤʵeZZ2E;6T^@QK/^g jMyOpB\Aa^nvެKla'Eª#<ߒ /ɇ`d}wi y =ks %/A8n *.²:İw>}ǦP%)YF&r,,b nI*x}=N2; ӉAِ7~ aNj{td]Z9G8g}:B4&{ B Ŗz˄..;_CcmA=( &y5E=-FY(U쇐Ra8SZJf\v Rv\>)۴R%'<__I*f7{yޑgYm Lqn#A&5dCS>"Pb6%0 l<漴?m#K)KL]|}7'^V ;Exc*zi`0zT {Rӟ<0%YxZOfxWN)k Y} _gn|Q g࡫`)B0K3^T/qMB\FОvdN,~<]ߩhp4'ʆӡ> ޭڊ;ɪ oEYL&(z8M.o~Q>ٕz%͒->;iFuh$`4rlڄC@֩Fe)ܱe6HA.&QWJ8+$*9bt=~-ZBJxCtB¢ +@~: 7`^4FwT$>)g/@xAS* 05x(}[*`ru zy j8na^YB `PB ll`lxX臁"kf1úB1,*CT-2Hž׃ܖ Qim.*/ʢpFU]CAQ]L8X{l!x{B=Q 6!u. oW}17GI.m) "ǯ[ < EX.|2r \i>T(u"$kf{XgH폎0SG; W D#vWSa0.~$tP5 m`ŜohD&!-Cx~-Ѭ4u P{jAc7#$%ymQ6ej@ç/\uilm^ޡsG0EEUN^ɺpFQI/0$$"do\TےyZE>1=>h%C0i/TlȳIKTc]3bjCW]7t PEO \±l/U!Kʛb%|!'SaM!5+ڏ!"_Ć M".8nםQ;OQ` α\R >vݖirsƵ/4X2BxCA|8tDJֺ8={NA nURQo_ȫG B|$KCRb}ڴ)օ9oJ\-?4PTn~'\SzNY*`q<:$(rmh\pZga%=tTp^FNP~qC*I,X>XQ_yjݦ* ]bm*~S?B[v~72`~n?ڿKOqlԼ "&/.M2CF]v|*s`dZP5nӕD+7鎥YXcfj7x5鵁Q_+97$L-0|fD^\e]v4>$W#{4u5g Y^ 7LAG;pЦ__?T0!]8*Ѿwr3Ainr 4e!@N-Rdj<|A񘱝@½TE⟏MP4 Jt5 ɁTc)voD9ʜ9ϢxA}׊Djv=kL8 K -o/@\mnMEͪaHWGKM L5x5>v_U߼XC,aO)4Px J×mv1iC}Iyi*Fj2;#09b 9y.ݼ"Ƶ!}pJqC'SbW `%>}w* MҌۚtNޮgX6 ^"!d5RwD] }q~"Y .jsvԎO̪N%j9V˾N&[EJ*m+5}hDa ݱbb<b|bc)&*ج_I%1 ~6sAjn_u{z'd>٧Ku7f `#h.IAkfy|GR㐡 ErTh%L|E('Ԩ0ӭįDy8\mXFMY\-ت %of\/k|qP;DҮ*;nƫ)"yD43[> n/7Ւqаנ?o k0Ľ)!,f{|I"/dq-"M 7(ԞȹMw"`LuhIJMQs5|쑹QHuqC UFOj]6&LRzL':ua~wr^/ws.+ؤhJce>_A8{2q3_6DBpʹ3T.wm.ms)r6Zh̴0$%)^X݈my; sFZ5Ƒ(p4YY gQ#P훹9$;Kad4@pw Cވ6ZͿ߅aҺLa $[o>IT O+$񨧡!:K(t戝F@2_kN)i3=4sR3  [w05N^^9+Hz zAP9m*-]N [iKDRFdQ]KsH7eHe^쥙d@Z+qʁyjM.]CKF!<q3pO{o"VFMuf2lz#a TU‘Xied*G1?n3ӫ42P N:4\'>[uf%iQ&)L럋x"f9< GcjNK%i2Uצ)0^sf#vX8L`hP\m٧Cnd9n$VK]W%J$ ^װSZ+"trt[wɥ*wL +cnLbbfRDk飍ҺDag]HK^7TuX |dz#$JUx7/ x?&H?Bމ2$k+$y H[dy/Q&pcp㆕ INmŒ&&J;܍8VgJez_U2ޝxt+rfDfTd8=|j;׿H6?ބdFY2hiezÊ;eZVVj݃A]|+=yz꼹Vb:U{6XFmR$zf=K|ֻ7wF"%k~ ̕2:IY]hݹ d*R /T`(n/d1e)Oī;s?ߺ9 yLq+i͍w-(V*5&-BA.o*iRep]vޔFR ,םɬu}jx@`% vJX@r [$/˪k`%UUnM9G-CjamcNɝ㱺y؜[v_/NZXX̺i7*],e3Fsg'~2Qϟ޺bjm 1uN$d@pi&_I}yLh{7zZj ABBFr*ru 6ҝOa:% 7 #quV@=g?!|mxd@CTGlz5E&|dm_U W7 ~؛|=dk$ݔEdm+q-膹j7[yPIedy/ۜ f.Vd4Nb7RQ\jp;O XHO!"0*#R?/9͞*raV^݆NZ>%R'zҡR`۠A>7ӽ\aK?S1 3~'-{ehoOgB=yԟZɯyv;zZcẈCrv ΛP(LyXV89m[JBcKVszr3[OlyDYNvܞ UՋYgQ=kf.4BOw;cMj*V#zU^K{2U 9/k{FWyxk@=-[km9i^?!ӻB7Ip kъ䳹!\1:6ۖhY[S髢DR)HUq ECGp53yPvb!HHcEL\ÝOՐFΎ.eLp$Z^}B)Hq!_+ 584ɈixO<(@0;fΖE.TGk]zTIw2EĴ*ח9$`W,[FV+6HJ 9tnjÛy@A8][9ujyد_0<`_GYaNNWѪ6N H-}ZCUQ}s9 LK[EI}ɷjI{;{) F%i(i ƶF=QR`$72# B!X , X1Z4pm9$5|\k+X03)IN?D{?Lub˄hJF2_[Chʏ40Ah_0 ?\"Ӟ\V&dnMe <ǿW#fP6j޻Ɣ (7ACO oY@Z PNjj6gdFaL|ԇ!Je* Oy㍁ uK_@pYV uõ?9?dRzȸ·}ĸ=5g(%ф.h!{o"ǁI }S>M=gBͅ%IےTSz  3@'ػWlOGc R 1=^>rՌ؋v磺 E b LOLzG2s9ڜ؊Fy>fi @+Xt%Z!lq N,t+5 \CJFg/> BwYyg&!] 隂+<(7Jaε="r?r=h̖p>;QKVq+ɽfJqE-5eZj qn%հE,fPFpl`V*Z '[Os{4pgΕң=cap;B 4O#,f `jq+k;%:f{:p3'{|bOa@vTshY#v`<ϣFۺʫ_ؚOqHyZ mPsp)_U*Vh@FxNwfl$P0d4fg@>% Wu/>?:fz9mXY<;@NpPL#T76V(Ӑ*&ia'1WrHN2?Jjp"LpB$=G|~ha;=+S*EY.UdIsY?~‚9 {aNVa)[䰚pg Lv.Olh:d}ֹ M",6ցrLқN$(~ '#CԂ O(P0븧]I#YtEH~_w]! 3l"2 6羃G2f:kZ72A0#[h=F2R+ ]nBHrUحJպ#wbd5 p2+Bz+_#; c  j0RS2"v[3>Pl^ÀƐvm ܵ˨f`aK4yNwlbOHJiv-QbhA Kjߦ. UD롴lKLEUy.? G_L(.2mR?W2}H,UAf4RFdP~d*3&x-1(\(bhOyVRx)-5ϙsIѷ*i*L;֌7a<,> .!̲k[f܎&7/R;<QV3}tRsnY_y=Y?x [.lAC Jv3, @Wݏ@2#>7ye>7 \rCz7 T'P|sjK>)SNC[=\K ~fndn>HizԷa]2>[6 wR-s?ӀpmZPr _ ϥC2㳻Ln$+JT[YwSg>ιH!W JuਟwZ8ڶ>RD *dPcц&(Yj~IZv,4$CʽCn{u"1WYS=R/G25JBy@ }NK%A᷷zxV #IrK)maFͦXEx'JT5 _=^O[ՔGYJUw׫yuIIMWu 92R0濋+ S ò #2%M׳%/ha*xG{cU>f,^0DF>00bT06g2%Vs/܏g@Ҙ#kF6gVG|>}wY ѝnץ+&?9>ݤFߥ>UoT&y\.UkV!7Qvtwb#W'~tU'C?Wp>3ME>"5%oaӆ&й^B)d|[iQ ztŔAKuU7= ʛp*hW0aɢCW!2#uF0#lioM\RTexd$k P(y򄪩VѶY;)pvGRjѱzXww1 )u#Q}R`3$/OWh+D&7F  #Џ2/FD<#{Dokl81LUoU>UzB+xXҀj/(h dMй]˄X;ztfΚ͇3t"p3в?d;Y7JWICEE76pLck|}ZPfQSψqm ovY%s #zRO2 +Z\_84 l2̈;.M\悻/f)4_\ MiSvH(?TꯔTVwF"g/,P+WvJ^wGI7zsj\+ Ưl,]Z(P+5 ON+k}Co|˔kօ8>v)M:U,?&I 3!!s5 p?j}|p(DzCc^Rb_Z.e{܈ɻץ=tѤ$uaܷLccEz=fGum9!n[䭻kL6ْK'y݊mg8^fr`p6" *>Nl+rR HyY!++Ŕ3}6,kA/H#؏eT_7~*36$G P0tW^QY5CEߕ`Fȟwvr$ppzGs`JH5X$@1 W>i Ue (E>iMFr7 tB&0=z-Bz(-JMr,`@AH6 6sZZ\nbCxF8<ܛxW=) :%TܷuA14J}sCpj\byVR)R.veܶ[,0,imv@O.AyX[!G⽱CO/a"dlԓ\l/ugVy^+fFJ2TI:&p"b <'?m{;Qfd(#j oluazD*eqd-ؿw R3? q#{& j*pPt>wķI%pyKo B%ELHS0~ݳiS嗮DM2 m$)Po bf 2#LV(oq}AmK[SK,PXDg/3;T|x#{,$ L򚱓/ ''Dge}6THsf}{u|nPvbA۳Ȋa%sigrfI`bp[z{DR *'ob@v~q@-MjOK܎? ^NEQ_kCVaI!?]y2v'2&,~_kmVF BǮ{ ^|9 m"7rCN^T"#tA,J߄pj7M RBHd słqPR[,cgU= ۘwFյD.5@"~· 7Z?6Q5'?؋_d6IZfHWeJ.&3 6՘@6@P[&^[xA%llK{kQ @2R>c יtD#!eb``=Pa(BsԿeKkW~b#;{ cYhIr3N؀Qu511e?&Qby%f6i)"=[fi OKkqNz J5!GT Հtf($R)[DdDbWE%'NfNuSlK9Iیle@܉6չctGYw Pq:K8NMxHkSw\ Z1Ӫ-rJRV/xf 4Zk4E 9Ep'Hm>Bm'p 8;&\(,8H)ч}`uNַ?r:p 4!wm)m/!bK9& XaeD%65NN(c[ Yb\UR{ׁ 'XUB4hrHwpZ^]}9|[ƹb_fJţAlV t=2Y.P;̱"4;.aLU'QCPΔCQو/}^ud ICzE"2oOI >7&annȖq1jNΎ LPZ(ZOMw~|g!{H01h0g# Nw*➼3B邞 mdI=PXs,bU`| 8ŸUK$+!CH7L$D7\L:jcrsR 2w^hh+_[@҂pCwLXJyeO雏^TBigcmWiG ھi#fHZi)?yѽ7wF8DGDmJ#s\=I3 NxB+ Yj8l3V]m+ƘpX$$P9ͪa(9'Q,gŸŒM{V,)7V`D{b4,~4_6OQ,/͝}ʱV*R>vE\'dn7i6?;u)lӅ,oW˹HQP%A@ԨF#,p$|;|hɍ嚅o-֬GS(Lr ʊ*P@HC+%M_ձdhT~`E8^(Mz0-ਭ|&ȥ}[1AcbeٝCTtxCScG1&_ ԚI;V𡗍ioaIqUAPdȻ }㖽sE$1JR0d'}L(qW( 65]n[Ko!f[Xse98-[MQ3gRB;joun`W|HwUTm8yTtlp-GX _ |v+ZX+0A]"N [~v/6[347ت:8$?3LCnM#BTm?=vD+O@_Vk$Rz oX>MGϕeI'H?g eylEG1gN[捻9:knf'0rw%Yw9BP3XpK$"e?@A$yTޥYEgX|#6zjwBcbOsUFWB63dYc-!=%mS8zG:|?i5ܛeR&Yztdc]l?Wk?oMz]W3u #˶ٶ:$fk?Մn05^Z̗тަAWcrtɡ rعY+ۉgnsDD_"aCe{mˉ2HвJW]nzD25=ŐL3\ ҈kVPI& #OӱB1gOz^$#Oy6= q//*)EA3$J,y-s+p ;s1S].P.Aiw:U fjXx~UA\Ǚ5گR36܂)\K]:D9HpnDUAbyV:s, %|↠,2Y)% ;1{8o8IbhGrK)z8r~e2j-Do6ҟc\I*F^] +!W1*; 26:h%1F_do-`I@ _CCl$hϞW+M+ƲJŋdUí^Z+[ޥ7<-dJjp|2~skJLeQ`rLF6YȪG&a:RBQ1op6ln4qςp{=~Å29_צ5j>L,82n=im_1防ʜ wwPWIX{i`^gٰ r0S؉ZI#7o`O_d̋LӠcU^RPLhڙbJ,7VxmnM?F u)W (q/yUۭBJ~﬒lEoWw24V+%ňTRI9"noMJX\n5xQA@l]NV%Bw7cG+geX*s4t(:(4@hA Q'ձAƌjI^sQ k>8yQ} S(] u|)K+M$4i柎4BNd{?S x'd ;XAQn2QH^M){aOCNn5zThؤ]^mRè92۟hd`(ۡaYx,rd.noXT,T许1&Mu2f~5)~b4/_kdfdx\/q#w5܆::q L0#ј(Х˜hGp@mrX!⾉>36 Zd?.E vk$Z|!ˇu2TfʳnuPuh//}_{zn(e<tY/\ a;b;!8Bݿz%w՗eI@Rxnl;%/dBLke6ĈzyL&~aqї 4WGjtoZ:%'cM axȧs B=ś<Ζ/K/#|I (a- R%M4%%@ς_X9?EãⓣPPoEv,9YWvSϙn5٧vH3di 6l 0"\p\-ĸql$B>3 oG*w-3d=tœ 4KBL;H|Y̹{WhlfǗQC 5(1GL"LZ ,O8Xk]Kcg2C ˢe88^ͪ =AK 3ǝ5rzâWҺxҭb %3 OA .*b' &" p_|y#0>~ 448zbcfg]WE57z>&8m{=BUQ4#,Eă #7OfA:G'w37at|usz2_lfvԧѥӊ() |Z=uhԥi'!d *;5Gh6Nw~<Ԋυy^ٔw۹59^.h4g}{2#Οf1g;b\`7lT.b%MDՇ밀ޭ-Ħk:]`rk+gnוNنNLhJMAEz)A,U!m%1~eA##"6SbB3K'd=;?E 77ab;*#tt2(ن}(g_hMeҕe!Y8m$W;6ҳ%(pׇ0%v lآr'@JAa2x rw.uYM[wh+E,TPLqգJ(ӱDT@n/;qnciJe{1ThO S&qqmءcM͞`Y]4Msz AHV`"sC<=?ډ:2ILz}?pKyFVWNÔw> j@( Vq+34Kgb]\0T{i)sXg -f `;Aj)\D#Helś]N<~J.f}x M XlW}x@~pJODO2xqzS2lW)+[ɀ{G:i&0dJJP>-JsTˊ1"Iz2Is,`?y{] T^ eƯ5+Z~׈™43*İ #S4KңZ79VvhۈYLY|FVnɲbB8QQ˃0T=/!(Q)U_]?4#>_닗<>fQ:ٍ8fI3/De$N-D~O4붭i/Ly٥]燜zE+I=n.Qc-x¡ U|=RZg̫ocUBuhXuη'sP-;5{v95J( DHEAl0F+y,۱On#nm& -hP{mӰඖ$<-gr᱄ iC|a$A&o8Ƅr o؟mm5<_1}j9AR Uld.@s-]MQTM!40j$cgS,ۖ|؛'u$ /datHdup xeӪ#Kҙ;x 0u_w-(hac"6Ӑ/b<^of@)Kـ&<"kx\=sGCpHՂ3@6\FK]Y`Uvu"5g0?eo"f^I;WCn` Y}9M./H'H;={[p Qg[RklG,m3/Q e~iarv _4]}?hN Q*3 Jٌ2<ڜ1F r͙ZpnH[:Y45>,RL'feh'_yľ>O 0_z)x>**^%30XE~%uLY#Ɏ ز\h%Qq~ޭ~OvuR¢ZM~\Kl9[KS<F./SPPN/>$Ex"f4s.zF/W9JPzd;C/V[~"t !]s}4N\cn~glvG95my(@1<_8WA-5ȀOi]jmZ?eX" tʃivLq 0yIWp>bp/UKSto Wr0M^ v)I]BImCM{ ;2xI^M[u P-$J퐤RE/ t,e2z$t-dM+~~kHv <[J m$@C1zvјs G{*RM,tu_Q4bxhxǤh: 7`/8dj+˖Jbߏ}9s:|* z~uO){àlZ!dAa0E8LfQov@6>gu._hPLdD]/''.ZTs [NM[^My;]׍7||> ^3 [Bk@1 ko`\@fd^\eGhiIݗe MPU0$;LPYH /Rc'|rÔN)0=>SV)׆FRT+Ui!zqݯY5H^dr\踟rK'TѪ.npkEf+h!vtO>z:dR?gn\l>`gHo;Ḱ+wTdjk^K:{H#f] 4Yp%x5MI7֍r)#B)CqN? rp'iDZ"%\Wn8|R=Be: P U4Q &_aFy౪Ce!8shSq ̉  k;l =G#X)?_cd 䐮s [c ~ܗA2{{Dz&WTђ`NUN̷O;a[z%K u!qcѼhdS)ǣ87؆< \A?y<<אKM*H8=`P3,&߫z訚DCh(Jx?(sHGQB:Kt9\-[Z,B؅xO&Y%$UPCZiTaf<%sPanlh<ї;.vwzUK,eNƓ^C>^<˹-&+aw?$-oc)&,AO`t͚`?,T%Xi< gH/ba.4͒0Q O R~WWt[70:sK ׹+NvɩB^{x$ׅZ^C{ithDvz NR)Xh η% r`@ **w1\Uέע_%g,D2!7qzIEf7u"k!$܎5{@UdLtHmM D.F!V:i?ÆROPkGG8:X~( 7@ !-v*`8ZA=訕Tiر af[Ͽ jjhIz.ħ2g6 ll_-E"B4`pKЌ{IwXGIZ f $6CեVm-6Zq^p)Ig1F(Lt|@P'j=T_9-Љbla癓 (Ljdy71@Om_åܒ]gxsZ鴣 9U6cţ. X~$fğ;֣SOr xnjP:F̥ԴAc@IlJuF8@1ʦ'YX4iT>;Q.1JY[/jhƽ´o,V6Xww.j̉o8gYig3, %?J*oApB|1V_2"5l:O9Јah Lit"c9|֜p3#5/:}齗#=~zgT ~QE-sOp(ui0G5DҗJ'lTv1xY.Nzג6gr7su1EHx VȘEUUp%`op։Jk3+X +ha:: (ILF]_gDe=֡޸Ža5A ,f9*pԯ"le =6!GO۾'@O*%C` !&x?uR^ ʈµ0σ N`S6cOazFG(]ɚ$/;oN-L6TjنXC tEAm]dg78a34VBș;vc7}4"Mk4t(w *sG܅b>ЂH[1zyVeuXiUV)A =[]`M/,-b&JfK ,~ dΝ5,>ʤ֏ 3\DsCvEk!Ecz΋4<m{tP`?4/[/Lf xb* 1z<곃hThݺýK>0jχkw5 JPN&KrmN0-,/ p^Vs] TY7_ڐT\=TWm]A|'ǜ0l>sE:|.[f +qj2F>*(ҿ Y}:9#l&8H:xFeuk]I m\)2҇Ҫy͂tS* ҔmGۛӞ?}'NhR"6&/f@]-5sgY'~O~,I=$~#&νQٙqz ̸՛"pcOsY\.t1*x)kҬ!p')8DYdEe]-:dV|fa"{q ]@09,JhJN(1d wd<Ԝ@$n7$\sgLIIqF O]BWz4[;X@+2RLi{ѯ%V ~U7{kM'S#'JB Sl9[=a1@491 r5Cۊ0@l&#M GVS^t]*c%^p)n";UǼ)w1G2kI:N 6NG"euCp)s} OKO0xA2| pK5 ؠPT JӹG={!WSڦW鯏<[QTԗ~ d9L2^.]!x6Ώ!)ᦐ-.$« TZT':M{-~Qcwݲ?ZB$$܊9{)~59c}0AC>2T Zcٱ'N4)lkP64_~PQ ]?bV8V4$y-IMI\U R19 RJi$Q3D;j6:tMbm UxWRxO\4g!ot7 Gݨ7Xg~m!]@-?D. h0C!E%mAD#FV}] /hp^z{HYsmW~bӁI]MVq$7պ7I'7RBU@kwJ&;ߔ>B)W.Z3FktźQ; g"u#eI &hig6>~[(D 9gj,{"E3J34^30J1Nj\Z][#Ky&6`3- 9Mgm 8bs8y杔Oi~K b2w[YYabԞt#R5{  !F;Pvƣ4=btc=}p`geiH]\Dr~@f( 7?d6?_Ͷg=OG K2[p4/ebw"4_,# TTh0[8;m=r[՛m-Z|1[ېƐ3ډHMD-p$y'0?'N&pw"I4}5n!~y.FnΥh0=kdlaȗ2*p.^3`&RNҹݿtSLлĎkb*08 VUWJ{0*_j'Lkʀr~qȼsMKfg{ιѼ %}w? UA5èEҧζ3Ȅ$Wb Ps7m`Ʋou{eN4]5U~5Q9=GN$LW L9'JUċ%,AZ w)E$pʌy.t_͡ڥIo{w6.0#K( xVfҁ\eH:4>4G}WVEyn`6Ŗh$B]M^4> mM@RHsg|!۽zI% =jww8Mrv|xH43ByTQn ANc#fkeyP!0W/u\:q1`OS@<+Hj}NBS-vFiܨHI'b&g)d wv7 %TD'pSF5& d%B`,[T>,r̉(rf7K.:#C=WrRx:6 !~a!4R \4P;L*'n }rEu?xD }L$0;衿0qQ I#H ZO]( -:'4FWmhU$);Mk @Zly43|H3 ^`TU! 3nf+OT"Gz,W߉t[Zhw-<^D$`8 A%Z] )#3m4'RQʠT#Dz}ԍt/̕[F4cTMU2G3?? {[)C ~3nՙGT [cv@*'-0THտ1bA8yNpGb=B]A۩U/&S@>CzMLl9> dZFJ1.P}sbhrb@c[-kJu>UJ5uAkp2(l.:_ vD֚+m%y!Ap^24<ɶ{Yax-?Ѷ|&n?| zڟ?٦|4|}a=X|*4>,_Ы?ƌ>ZF#$$х,XzI4m`tl+ѮPj5u7&T1Ñ ֡V-zIJpv"zdn\+"/0 A+#zSQHu*l57IQܸL)~6xr /dgB3i)#y*,YW yiፍszK+ $|sAp̆YB4 .= 5 DžgxYtyC1NR5´Y/ոɺ8lh_|LֺObaf1/ !iup=pƪoS0bQ*s]U'(^ 1h10Zc ,QOpeA3]+Hb֒I(|{{'3ػ_NLXJM ?0ZK ?/ K^T&gӻ,6d3})^ZJϾ_- 2>>L42uMSe:^_9%g$]J Q B._0ƧZ+vɒV~uw Y17f3[GCkf̻5G}*_g gNIDcnfMF,Hk2r\š$o#Kx;}qn۵$ίYzW?,:54S=83I0<] (Ξh@JZٍ,hrc=mL8,Z}1j?ق*EZ ] kA%;;=ND }R-V`ѻ *P*q^f|O-46~3́(2K6~(y<.Z{*jWم]Ĥy Y`;Ok_N>%wd3UȈO6bTRM`<}{Y\R2`9chL@>" Dc@#*IJqf?6C[xHbjnSs6}0"t}}fbu:y{'[9݁؆Lv`ͰO*GB5{pum="%['f< 0ϫ|*] лQ-P:(\Wm4k60sXfDʧC,d%aw`=^ga{R1稵TYh7PN,y|8s3Ǫ#v_DO]zlVQcy<\r  Kd@X;E+W$&)BTn=`azMa^GmfBzK8e%mtX NMr, ,B$: ̟MZXt)4,dfQ/VLF;@ی&Z'H8Q;;֡UB?|hp֭jW翼˺[㗌 $]DtU ́. 02īknK_c /˱(#W X-u.jpkˏVw0sjx2!-.AXH!^=a4,xBwwxH ӿ%E R .B2{CӳK[cz>ѮV3-(ЬbY 2&wvጘY0fSoR,XOEھpf0lq=\o{Wc9cNMP`_r W<|+du=6Ѓ~%/)wBW= K1CE{| / ѩ翃P/:PRr%(H3:eH QOoղ^^ǖvvжΚ5U(1d gk #GRh6l;|] P{hIǚ6Qґkߨjsg?*Tc_EV_D}Ak?|[Y(o952VTB{Rop6'̳c{ce{ 2rvj=kqI~R-9cI]𨪛ov 8݋o=](o&Y5bmYQD8zhzFQʺH˕fFD P7-dܖmhfa6i$8hU4S 72z$C~J(IFI?_ Ğ;} jZbCP3,= -Wm*_?6 d/^zؽ7cijʽې?̃Lp"Z{mC"jm^[2t)Ꮔ4|q;*u{l~!?jaZ"DHP{}w^UJA"}&n0Yj)ސH}B; 9K,rTqO}@X_-I%IT3ޕ͞^z& x7@e& ToPj=%#uړ_[58cRxu<~;"@X7f \kC, I7/Z: q|*o^~d$0bnKEbBf\Ⱦ^nfl ĥ\/f49f!|?29 fz s6|!_ng2D'6FzXO.۵Xy!z79I^١9L2ɣu6ݔ)[)?[fmF-QTD zszѲ"8M7\K7ocw7obDR#Jz_vaYϮ[%$~#vٷ^y@NOmN }肋>/[܎^]>`)O-h <DƭHUUxx+%~b!*eԑs3 4aݵ,.-А/>~`b]nwC0 dyaI}23K3[fQWA%ҵGv"y 7|5.r ZDNk'jGVmAf;M/㾒LN#sTT+xyi?rđAuʚ`Z}WCef1c-xSQX| |`.f2H]/yQ'==գ-xZ;+ eF)I4`3vwKaHnɐRZJWy:uhi/ƒe.¿fQRߥv}$,oN sǫmT7duQanTWl^fFp?M9r<4?X)IQ# dhDJ w@u bp5ܝfׇ1w,bX$;):R q];^2>,RlQui&A ȓ)%?S*y\Ht0Vۖ&6+I4Z# s/GCI2_lA}:L^qDXψ,f([*/`U"SIݵ"Ჿ#_xvXH! ; c(z}IwZcG4"PM֤5I.pgOBVV2,DSm:PcLzAO"򨈗#D p]s IBY^rdIcܔ@+8_6k)utɃn~1q &d¾ #a7kj5X[@i1YhwuV|#K0J\h]ʭr!J4 b=|R!I\YQz6,gZm2)Ԣasp]n ;_KN ܹ#:dB\"ұ`ye#Y[iU f1jp4&N-',b)#hǠTS^B!UKk9}2Ѽt3Fzr 3NWX5Lv<4Z~!ǦP܄{qр +F%&QTM맿J$IARyTvv"o%qA K1iZaVbϲ*,#ɹ>W/=Wl:.a+^VF&C0~aacW?pq j Er-b3 ͫPA_1W=Vh3+рv~\?!X;T+POΩM ,o^?Waea^xZcsO=kQI#b$U|EVlחiK S0J T%Nqg똆 y 2@#EAKag 9nH; v^eAja7FϦ,t\@fۏB`4ٰ8,j_NNFlq+'U >`Ox̡=e]ud `inBǏ-qb?Q!̕~-CXE}h!OkqףF &H FR⦄JW ؽQe[n&4o8 ] EѱeE8EKm;F[4舁@jw6[~p/1Sfa1YH1;FXdS2X i޻J|0w xFR8xQ-blW9yՕZdĦ++#gIxVеcgܿ)jcXA Q]KQ1 ׺9 #|*Ael& 1sD DFڒL[n:_ɺ̣IĄYʒ[tT8-WЋa]ȨrB(\^9R>3^G|Qrlʏ:tWe9@[V0d%(-1 S3& 1R^դhb;":_( ;} K66mH0kƶ)[]l>>n00Ĥwo QˎJ8Yi5wo(cokAtَ֗r)DQrMh/p'@eNrFjPTߪN '-N J;v‘F3*.'KZޔ>Zu̲4Й\>E?&-]>h"8ȎB_*½)ާ>p% X$nU!<Zǫ(*iuR\|B"Q9LWUQw̶'[ dۢ\tR\,Yy627MsܗIIfZ ,Оp"V>W8#c;ŢvGKlc8 iIȶB,ciA$5aWoOyLʎcHhl}Y[j< :ӬیܜxDRAm{ULar{|; U`3μqphvpљ;p}EJ݌|b3/!'4Sh]l~fW+Z8Zs=^{rDL>*aڈ߳$.AN8V8x뇗RޜgYoRUXCf&:eU x@ d O췬dUpMȉ }?/Al3jJJ;?[OW{ZaNm)hchy1<Ϧ0%2]fktc Ğْ;c2x5A>楇Dͧw3} a'nF2z?Q;BxZVU_*8H'"deycYCX)Swlvw6Ȃ\֒ dalT8k.QBLf8+Um1G͑xŒO 0"rŹ!j4 n?-)td>_;KH2ْԏ$j{,]a,8#N Y6<[I {^t*"X*ldU-dE횠4s![C3',`[^&i/zO8 ~EDX-˻rҮÚ#⥫`Y Ewe3]> J=9SlK#D"l:JqĊb{e-N𺚜{YDW~SK6a >%4e-UblP /^&.1gOxD5>$QL{ 䬘Qoi]q4ܪvlQv{$r$8rwǯ:D?Ԫ8o-B4!K݀g"jÖoz8bo_jEVEyGws9_4H6jFG1oCVwJK@h~N3 (yݲb,Ӛp^\|ȵMD,ǐ{&"N/Ʒ)7GFUrW%hnLs}7ש-ϫxzXRBdD|h>B䴬DAnk8[IQ'^+nfqۚwΫ a↺"X |{%=4/M #"3ѼՈIwL,5tMω| T(ڶ&|!k㣣bv2>spSGђw1_"jUAGxRiuOn 45 r% 0.,"* ʰGVӢ2Ѥw÷,D[2&K9nU eO|y2kJ8Аy1&Ieg5P~ݜ=3j '!h,62UuiF@ 5\mF Ļ|[hgK;X-ut@53%L&ނ9{<ڮvX3 rhhTv neL " %&fr]2P{HIcݨ+RF7L'LK@9AVucR^ֿTɵUEb0<ʓ/0fVOq}3uG^gV* fQ(Yʶuء~V)O@, *~t "ZdAsS^Wu[bC"B葬]mEĿą즽Sc2>rX,_i L cÛ>“)Z֔԰ Z9k.<+x\]+Vu?cӼ)`>e誽Ћgq !Ι}9{y&_uGo%[+:+$iY&$~ë~,DbDɥir.>{ͯ"g2ĵR~&CU7; 2OD49I 5/DZ,Sբ~M=)Ay|j"|kP4$BB7C1y#+Cv$e}[]+XUnmqf dvnlihal2\@&`R+/W7e٫If e9 륈OȤR^E>0 U2@xH(pyK'%:' m\6O:S6rq 4_qOڠ}d'.%L\LgiR$jIq{YIv%}}<䊉JT Z!?8}\|\^Ҙ^/IY ܒZ^Uwk_&Ӷk&l_ f 3 Ud%+]|ۡ0L :wj En͈%9Vb(Bo}xHE7y!'@!v=>پ-T&6޸M{#Dfc{0[?;,U[`e~YgGZE!Li e%$ԙ 6|8GV|ACvh\%ܻԽ(*i^j:LZW""Å~:8Ux$*uBKE*N~Χz"*ގ<@/et?B%5*o2Ѐ_y柄^1{뵚 `W閣 ĖUj[ eáN a$9ɸh:H^Q ^?e"&-L*ߎr^_q '"GQ]L1V NsAdKfAW(eaN W:cբa0?M~@ k@[ BڠKϲQK&ƴlUa QrYy-Խ;ru*VUבRcR'esUCVf.xyUv-j7-Y?cC۠"#K@ /E_C_z"ATs"RLʑy|AݸL* n"[aGҷ氯c|+6`BwbG'7246bvѣs`Ӟ%d+9p"bw`sPΉ3,8#^4r%B& M&Fg)ij@V?/bƒMQ迚6/i;6Jj?"F,DY4ګ[n}ʺa|:,_o*d2rHaM|# H q,K"r5rMt_chR8.c㝩Q%4i}.c2F hk(]V c =c~/-SڳKri0Q!3:;պEz#C 7EX"1ہ8f#yQ#gO="lAOpvZ'm;f6 h -x龢M3w}>8.s(&>Bair(yOkplo/@q t{B)*yl\f^_o ʹPFo[>im#Z,JIxG +# okQiceA/!Hf.}<;'g" tizk( 9 8)5{}]AVb3Sb3I:iS;F<".9Cې){AjvAru,l@qV6@ҷ-gZzK>Z]h>EyxwپF9@'n3,)׫FrB4!>dֱD(&:?^M2=,[\0]G\M wyTHsxSWP4@tQk JX gI&w<˳O5yz0ƹ4HN%,&$c,>AOF~{#-c#X4[z%}ve}f>.ց oLFĘ`|.?H]^Vʷuooʼnq| Q|b0BŽU_KE7QE Hض gQKu2jv\|[S?;Fwa1r =`j(DR$}$CDH:}q~k4nOơ]dxD^^x-ǏRXdhFT.ԡ #Dޣ \䕼N a5*0mڵgketMY \ am/z53t(Fe'IET<؇:^t)Vt'$N{WR𔘂[#?tr ֥pai _]j(Fث?r0ڿ<堜«U=Rkj 0Y<S+iTW]_z$k"?&o){mn(7KL$CW'j+"!KV)yXv=#F= Ob+q>DCOVߝ;q(@19!փ>(б:S]Wqx8~\'aE^#3drzY`  )AWP cIN\ < Jj hcuĜpñ)=© Lg%JL:qy+\tW-H-Mm\ގɹUGbA 4-GYtq=3cq97iࠖ5][.1UJb0? /Lf.8n2Z !vGp;jye'}~ D7Nv΃ñh+&GS" 4^<>?gGŶ)ewxo)ڔM< >_(i>>-j>AqFPЃR\|]JZk{($%1snŒp!>w:>kk8Q~jUB? Sgt$Bi_%&Ec-/w\[[u":v.τ 6eYcW'(_wb .n,P}=!\/$'2ڦ**j9WYGF&7;7B* tY<mh_Tz9!PM*.mV cޯ>ZYg"X7N2j!ЇZ!$Z=Ƿn܀159gYfa? r(wA_#d$bk;?'w}+6#.U.@C{CR˥!JRNU( Fvwu^;WKn&x/׶0ցd|("I@U-63 6O[B2mEuF,);A.z+2(ؖ. x^iv7^!*c, h Vڛnl=ڢm+ 7 (G&ʎfVQ)Q9 x+4cejLqb٬[#H>؀"nI8Y?ɵt' >l$#Tɲ2a#w_X=՟.lS?ZQZ;IAՖ+Yȗ6yDN?t0XV5ЍTdGuT!HХ88TalgFan {T:;!S^HGDCG5I.okơ\ϣ%Εm}y= F2 #Z *N."D:{`(^ĐtBH1wq/(aFk G7ɢݯ1J(P8 +|(RxA7s ΏZ% UHP΃Um螛GjWlC4gI[mpÅԜb3ݎv4y缸@)NX:o\0~f!j F]9)fch-]eD2@Pi/Yֿwrd3dav~f-偔rA0z8`PVat5F`l;hʹȴ̾im~:UB+H cOL^v?ߏET͹EGTAIv5A7]:t,^gd[e%2?fMҙª-H4/P3.lKrX( -Ff%#VWyFbw: Xhŭ6\-D}ǰpKWbo/@`օ| jd/E={EVj`uTj:RTi!+@X k13#N ܙ @֋r@ ~՟# uᬪlU u'oڪ7l>P*BEHؾ}S6)Z8-wH?1p[o GɢkL`tr~ONCѱ֔M,=+‰O\ߓCSQdgX老#k!0?ڡ-:+r סAdpR܎o,LY+!1l"@vKK`"S' m e9/>M>X Y-{! :O֧[;vOՔ%᪥na5T{w"|ӛټ@MIOY<1R!EYq?Iچ)h|d$3I&+hGx eK*QI$ \ CF ߪl۳_0VD Ԉ{+"%[4.{e {O2X}Ȫ$T`=a PUrbaZX] d_1G_2сMAcCUkn.*C Ch0/6Fdcv'~!k<&uq GpsDFqܚLHJC>w_\kCC-b4 WHg@`!8ot aT>wD`'et./$1RRB;HPf߶(kU'~--E,ˮtoG;>fJ C ,{ni\VZHm_Ur2X:Sdc][3N ݊ʪ-1P '1~ |3LUevW%"wZj\qwB25xՃPӡAYh.r$Fަc4Z*~4@ܗYRL&;oKZjC* "RAW(։iJA U(`[iNNƃ 10+< NTҤ'^ 7;q@0\ogH=&HA"uoW9ylKKxk[7aQQGgT:"AwQRqm =Qk[v(j=:bpu$٠ 6eU)t!EU y6C)E@Rꥋ9Az]rY÷c{A {$93Cb@rA6;p `C}ְHkh0IͦCMyܖ*Q2)zɵ~݂^>ܽz p~rKheK j| *zJq]뗛h&TJK$̭H 8?{)Q, E' t'm o(clGaBV̼i .n z+wtj"niC:~!{(Yȱ"`>;mB bH"ܜn 62jc?LH,lEhaIG7"?ټ K,҂u])m=v4NI.=&s IzȱQ8={qmH1e+ey!|~#͆)oWvh`Nf`W,Χw:T>ΨJ[o,"!Ns\N7E,)% P؅͞K>S`JӐ@5`I/`yw]J*p#^r@KշWt)P&Іn_)tpD%^pR3)%/[tg&'UL=8ѷY&H*Jcͬ>!`j8ﲳWI-&[vCbvrESrlG Aڇ}k٬u#[}9q;.췰F>7$Ċ5$i;hrOVq5ч8Tם [ jQed+ Pepˈ,`dʀHcQғ ="}"~=7%O[tؾR"Su| MN2hegcD󾎆 s /=xh1Z 11I~ O18JA|]XwzXݏ;{Y cU!\NJb $E"wdҮ(K M Ѷ@/~޻Xpŀ ]G.T'EOJo!:>:1* qoOOt<|w[+yf-l0k}؈vqP捗 Ze iN6gQO vqSV_z gz;ýɉ)]d2Ow8cz~tZ@pmKB~,7 ]kJ2>Z_\=e59z3@2r&"ޮ)遮|QYN^-;_M K:3RMlKvy"z1*T8)qѮ&*m-~q/оh4Ud{[DuvLY}U8]m{92mgf ]-}j@%HPRak'El_PDj~K?2YFN͌@,q77^~=GZ1Wd*U՟)|(.`5y0ʍ2BP6yƞue2/?MpycŻ:;wĞ"cǣPlތը8Vu73{Ri!NyV!Pm+Wǃl2!G 2Ov Etee滢wnMdADw񖫉0A(+a{b> jPʿDcÅz{\*R=gS9z1LW,r;`7؟2t PrK{*FH^ݶ҉ 6扯kv9lhCR[\FP~{N* &- pr(LSw ~X\ݫ<PSonnqXY'D=<țgo\f* zq.ts+N RKӋ1s*j>{c>rBߏ$!8a϶֓"Rdzj:P.'Yļ r!ݱzf W'IRdf+Ǹ Y|Q95PRs ߦm}YLuYF<W;tw]ʱcq@ )JmZx}L3"L8*GT' P3wA fyPWOeFh a(&R/4Ps*DcԆ7#֐KG .s=S^!b@NE/(9#i(ƱLޣ Wd%41,Qj|ubja-JŮEe{8BNz(}Rc-2ATsF\8pW *rI'hV~P}6f=ОͫYjZ Dd ^UGᚒ%P##Ix N8>:߬z+Dwr UَO.*La!3KUr^湵l sg3Qn^/l?x$X``zQž6ԗ>878m;$w)23)A8:EjI{p$l@ɋ-%)B[\ WQQ5'$2<_5p/0qKQL촩/{6 £Z3US)&d} k"s> pprќ/+zGndzP9zpmw*FX8_v$%$i:8R5$;"qUU*>DW9qzD8$5< b$cQÐxf+I'gU(VA\@V{pLǩx!m Ȓ ơ[B>A{'ۙze!94DXUI!e±MXe a_ĵsТ+\/* ޟ?UƦ}wUbl_p0΀4Nz6޿2ܹe`hLUaXj`yE!(I"9Ҹ>$0b0C{Jvm2HG\SH{ls=W(4F7 O;R0<&F| 62htx%%t#sGVq.ZK\:6H3`(h8./:lP6WB!ܐĜ `쯿H]j*>fB7J{]LUueӳ nR(lÉ]YY(n@ISU}^Da@`tb!HFY7YVQB|4(4+!|gTΟCUĿGWtVaZπ 3\BvN2],A3iEг&]Ti&=G_H"2P8:G|+~(K_":^5h LǸ!eR|Dbc8}麡 }*1&fʐ=oj!]j aeLh^}OA[CHFz\amLȷ2kk pZ!Y0#.5czƷIbިw Қ7 U۸K-o@\)'ӟ#ࠣH/- {!n&ޔ8* CT]ӄzrCMyF}t&f;$ r.zH `)`="N8 D̡1Ǻ@_D<:.}t;_~] {dQEU ~XA)8T鸐>SlV3F##7зT9]:M^BdMvX#x\82SOrw!,z렱vaUDbo%_̡;KvG7fȅ->xHkΌc|yO4@La%QTE@'WBjLu*T"U3:ɰ&9isg5" Zd6MwO ^yzCP&"NR"+u'HSCdL$n,(xuB~I4li7IE%dQ55[:4>Q>o\j\.ejL0 BU0ڎs,5]8Yh, 6֥$mHL"-B-_Gć]1ۭw؛J> =O*[|9|u +5ýɘ&O3mŝ};'? XvzK7zO|xB [ $ RÚszoDǬԙ6݇bRi/#߿9=`境1ƍH\+q9M߫Ή {l :h(tI50" BGTcIfXgSN^kEg5퇴9/M`[Fsw,Pqbo灬Վ\}^sMI(}]+Lz9Ȑ,zYC^LlTz*7.jlbw!.h2n9\Qӣf,GMO+`uNWJ\=l!n\To@ %+ x{ k԰ؿÙ/_/j穮2p@pz?ŹGcz&G"/ @s tkv6C;Y jS矷$qݗ._LN $zt6ڐᙃ$JY!}Z+ KfI'h*m`ܐ0mWelt "%r4?V793b5Tc,E RUZhm=ƷYAC6 8ҽ6o0.`' =`1 ^#OgLo}o޸,iTݡk]tO$y6)&oԑLN&*#IS?q> *\Pq{-7:5%~vh"8A޾~::5CoyJzs!xWUy1@O5|.7pO5 ˒-Gj鐾3LɊ7Y_ZS D[׺E] g'tx $O7ۯ\B徭Q qؤމ̀dZmw_,pѲt f} gT敲 U _kDD%ugY%vB&DzyDNH0tl|UPio}W\%/BAFȺn^+b]_g ׬yL"(,СK +4tɊU<0X3Xs Q7ix=I璂n:G|(;_K}eMC:x'+!z֯.C3#KC ~Rt{&CZ`V kxXZ& R6 ?XCL -s^Ϙ%0G|`GF[#Ь٢ w`U[y=~G#i b#W,dh&&OFRjMQ]'3@Hm@M͇JNzRyI}&? { T3xW;uKf>-X2'|ceCۇuQ"U2GA<w;ܗ"%Tc'|Ja(zσQ鴟,BrnZjGll5ӈ/Gi( Ds|ͭl8AR#%*j[}8lP~=.+*&4Gm>Zg`8zrK' \~!SX,*#IǽF^E-& {O;[J]kh MH38zNLH&['IRBl;@*x4OhVlUt@jؑpCXr5MruSC!"(/ aI Qk.2jANUnߞ굚i:qxs-Rb%czUXᅽpV=ĩ_rPs$5\P,E+Ȣ&|>alMF9yEr} eh$60G*T"ξŞ8UBÜzL,F.8S&l pGB[_:gu^+P[^{W \|P"Ը%;Wl?@i=#P6MpZۺAN-4"lyZ im8CHلGp4QxK!B:Yeqb(\3N]$ q6X^|kκU^Y(R;7PPSˊ4,'+x0xd5{͡axжNM2̌V_)(s{㞱8O}V"fmvh(\=1V=t+7|üPV~0 Hu'22Lc:fcz|b +X~N+̓B(h/{l*"˱(r]#%/Gu'DL!U rP@^Mi+ xLBoT(`'=̔A$H(EK&tk)5٬OV{|5ȯbʋ'?^gtOJګ.sJԶS2څaI |Rj`u1 ~ۿVάnQEV;Fΰ0rwG/K>J>D<|ᕎdݥυ | :QɥW+~d8?qh'[BF>O"BPcPK)PL<Ʌw@2y.WK25I5bIQu(rohΔ,V+lJq쨢Hahqz并*/RZ=?Q<ƳcLSB*7lGXov^|H$Fnf׷ ub}jHۤG|d$s\[M+Mћeń*!gTi_r0M9ë;M B!;xu-|@=1 qͤ]U1s|F[ݮbg3h[Eb9dVZL !Qq8&d-,cT.юcIoSJvNyc:)VNI^L gKo/˭;x%UԪnZPMp~cFБP-Xa5y#Tf47%w Rȼiy7&6Ѷ@?튶Df/3/}CZ1=VdnzAÚ|+zsm6&EbOu6ΓZ´{ :a_ZgC :/w5mDT?_!+"Y{})Dέ pHG <6_3vSA3:ryOV=7fRPJŜ:|+4_9!yDiD>H@P̰AC5i(.Bj t0qO &C;J-ZǑFL nT@ GjuARoT_e2~޻Йtu9C%3o+@A!x; 4PUV}Ψ+omN5"E.^`>>ByqwƟn9V򩶟`&sQqTM^7|GlÌI%V<#c V?6!x*(7?ZV$H̲e^zOJ-]dS+?@#Rj ZSY`Ȼj ms~QǸT!9rj~"_:x]qu-Fzֻ@s’5V]axgoI|yiXo5 L>[d6xb)&C24w۵+q10bIHq kH(qg&Xqk')[l}o %ٖܼAIo Aʞ%?1I_IT- Rl:8 P1qf4#h{Bj>h-Z #'Ԃ+%;΂‘ٮ [2d&W:g= DqbQƹvtLH !L-'VOwke*@?I>%.Q9P^ޕ|8G^m{wJ(G ѥ/TPD50dT,(2G$IAe Z'p^jay|b"eAe:NPPLZ\|zMTX. y1!0X;Zp2s0l1á"u_t0a.mC=2JM26ˇonnٺ|z"kIHv Z0G a5b4?'Kx ||M&BіMCP4ed0D)D/gb F~LBS٤sa7uL~):gl';k0Ӷa]@sOqzwaǴZ(;}iLe O0hZL!I*jr F!_4ۚ}e3Uy\{P͵Ul7b#~bm`3(M?pȦ3~MԈ-)DFVPwrگ0r~H5iϣ@aFPr (OLV'zλXH9vkXu %ɝ}zʘɫMyFeXoZ@MZp(ט݃7v{%<'XzYUѓQtڌi7ϽkAƞXkx߬hʼu>Ċ%xz/,sb .V~sЩ.u%a&7sS}Al \[(S\ۓu Gc4!L>s|z; n ȗR^ o^>ӌ)[ȳxȗF]/~ z)r黉Y_k'(öT`@v )<~ˇU?\}re ld| F= 1ZH.Z;XkɈPj}K|ܭ?E%!b)ژĴ(/p@>b1%R2LX2m?vl[`[pOp%<|zIӉ`nv6Ү>0@Z2Ϲjp>s7]?c֫k5֎(WUsJ|RwW^LDLS1EF*ﶗիޖ8[#|-$a)8DLji7@L "S)V]8%=UYIlT&ޡ(URax@ ڬn%}!.L0biO/J.k"H^RV{0ΠϨJ* 0 YZ*[XJ2VgR6 ծ'T?8$*Ou 6LY9!4wi,@l~Ӯlbx|gǦp<96|]"0\*hzC}ʜ,xr ꦆ+Nsׄ4/ij!U4t7̉ oOCSFU-|1i}^sCyW^ :קR =:EȨ/h[$"vP,:ؑ`_ GB0>c rrMY2ݖ\RpcOUEDY@=LmU+y4j4qYAP 8q-2LBD'm Q }˵wQJBL1mZvlbj>M]``W/yӎ r<]Z[xƐKNag4f tǥT[rhiשT{rp(A UÛ{s^dWg&d2|̸ "]|箖|UXRk5.sq8x2I?(2QIq^S5(2nߙ? 3!$—5PO!<ߎNw}Y[il5Bn}YIGhb jk6ׇbڼ+I&oYkUMq/O woAkU8H%vU&:ι%UeE=y>@|y-?"Ev/ST $ʔ 8$^Wk鋬na?6%v%"wx(vBnue4CgH/mƉ_>[` /V$ [9E}ÙwyEtTfCRˡ@\Do=g9=IlH,v21y4ZJ1R?phһo'z'0'@GtdpW{f򮇠a{25IfsG%I >}5cg(DCFJ#N+6Fja{Z_qy^ۋy%hK蛃<RfhʇuU. pd)T:QL8C?-?LX`CBIŹf<(c/'u[ V?6K;A{c>NĨ,TٖX%mM^YO,&S2q/=7ZMh1K]^yX]*COH쇤4'y|yf{3HD7AA+PU>LJgYί9AJINwG#@ J`p@빯/'mR7 O@ԪYOq 27GtDм78 y>/^ASVr؅#.8(0C]w\PaC?JȂv]!cHyLHNrhjH27WL דcX*_ßQNkqw3BFMH'M=81"}SX =*=k0ujS^{PbL芷\?l|/cԖ%.;s$Urlc (}(=$%麪{t˩;]q֭5QVoFFjLfpнR$^D#ˤ!;X`L!)MB%̘E@J-%AC \D.)*fVJuPH׮qMDžtBākw_'Jn^.rC-";Wϯӓn()L-.gsM|Jwe_+X㫓QjzNfQ)$S촺gNs< SJTI (5Sq6 ҟ.CoJ2,n|[JOnRl#lE̷wrh}V;\O= 12MUwˢUKI\;xAZbS`^l5.>D3gz`o/VuRt`U>ҋەHQ;DBsb<wxNABzbI+\83xˆFP-Z0Փߡ?ʀmF?Ji(C C}~@a&$2eYA-yglR+fc-.}N%U'N/f/q꡹L(Igd kߚqxi 7ZꬫM(8uĔO'4'R#8myNAUڔkIXj޵/$+NUk#aeyݧf#79zW&B~P8g8u/km? 5)KlQ;Wm*̎@PEU2y XQVS2 EP;6T|+ >̹Q/+lMŨ3=3qfv@k5kzjœBO0 86sUi{'1BcTsA vuFa<ˠ (i]OMظ4OM:l. %"J$}ZEXHVciuGΙδǖ'oINIr1°A?^ e)azD+@Fsa8t^RC_b\i4uDft&٬$Q'_z̖X< lP+cw&OV1 sag޳ EB O-b;`ܫ L|06`OI[ƒ¦N _)K1=JRP73l\u7EcٙLEڶjT*d7ta{T=eR/r4Ӧ G+Ghk_)O jFr, J R(iI;P=P fv2 4 lr. }2[@ 0JTN۾N u[i8`vڈyQ"#2F9HHY||q#ֵ5cܰKS!f'N hq"(K%3Dr9y7ɒ_S=|֭S|:)܏)jMhM3>P4yk'xA}TLYKuG츆u]RH{MwOF5S Pfrϲ_jѥqjգX\1` ÕR42 6x{oܲd!Qj&Q5;^&H6GŠc'RieNѢӅf +IhI* q 5/3җ?:.Y5޵^єo,oi2t26#qԥ8cAJ;MX2Z;&(=#pኛF,wYvgqҐZH ;CW.l1 sKZDeध;p}wM)M~ހf_-T2֐/p]J櫛O"w_[]A2e G-cDg"tx~+2 }C%<0#7 (a5氘4{_@Y{}`ı"͡ ['2- *j6h iva7Wpcמҡ{c7LxS7uU#>]|zVÄށ!6 _?VI3f"8l .E+?+M褬Fi43NFjSSXY_ϯA/ɟP99&*ksZGl{Z-0rHdgA?*UKdr|7~*hd4ྒྷW{Gj^\-2EF",PEGB4?[fQ.꯳mq}\b]M~QK凵Qa[ĂPngW_dCE;pv۰)R; Bf%WZ5XHdj5RuneԿI7feDJDѐW-aJu2uW"{؜z/ֽnA0/)_@Ohc3?JYJ)݈"Ĩ4e[~YBc}B)uwsY#7a,鑊x!!fE큛ji*\Kȫ@AQJgߔ(>zHnPijzFvo͋GrXBc:U&λK.^۸fwR@KT,q&cr)YMҫ'ܑͪRT}4x o4}8JmJL~s֡X*Z &Q4"b(,a1Vyd 7`VvQ~㙞% ջfS_ b*mڔ>RI,l94M3OEAjz,Nh\s¯ PCU6=ݫu0 j>3.5(_)S~H_bwQ_qMT1]CbO7٦DyCYԸA74LxujĪHeXWR-'I!e'@tUjgNDi5 !T")Z<83@|xVY*.ɞ 7e \P#+@rQuYUhHFc˾i\Hu;wh8ͨr¢NT>1& X&Y1.e"i7~iZ`מ`v|em!%ZKN^7Kw3Tx80}Q9|iV]Aw _9x%tZ~}Тcqr5ګts )-6Qɨ늉K_86? n!|#\UEtNx$CBm{#39nmGth#/%96DK!jkj{Z}:0Gj VZILVg٩={$*¼*!Ns .AAS^gU`L*़nlkbposU|1Sj"KF~tSŦ'dI#ڃÃ% `z ՝byX{ guSq%?c[ߣy3M^31obyv֘dKXR%\G?A@pk+pYM>@lgKtO*C¯"Yz~DLBՆ{g&l[ӳ%?룿}SpJ{%2&Wo3=lV)HۡMPl_dUNEzi:)lJ>R^QM9E<v4Nw8KLj˃2wg9$۬ w|۴2t`*AuZ.*ċa,1C f=x52uб.dLfzjCP:#pbhb^$9ϘX,U/P AH8Dx,M4KOsO HUghaフzđ]m3yoPk"6Z,XHŇex;'9Nf]N,ze lgaOΟ'Њ>ޏ A =_?{' |:G]~G//#}(7_'?{XO`@φ #?CO'_}I~O|?r??ZŌ8t?,*%>QaY[JnF@V?!*~TF<-^9q;((y^ ? 5J#8eJMq43.}2Ls=oS@$1RT S7:|w-'dm3iIrc·YMG(4iokS~Gpt'2@b#T=k[P:Ye<]#Dp2@Ȁ!U\";0ng lUrMdY탲=bnvlѴB[@^h= K{nFw<7E! a;0ȼc+Oo>6OIf.;CFog Y_aӬto^*F0bΚCaNCgHŨ+OgpX;k@N͹ UۅYbmvy3Y%dapmMkhw ;U7tBc.Z#;3ow^C'8:]$Qʀ%D]SsR(#yz3]B̋щn~ ռfNl q/!d9xv maL$=I2}Az EuDBgvyU OQïppQ`rowٕ҉UR P WxqxF%Ԝ1]1 I~UNPb답?i70XSm l?mcƤD>w :“1R@wAzJe֬E;3qݦ2:&ߊ׳o}]D†40J:<8O62x fwYrGnEKDueLUN^_d4bM?y>i$8aI݈, i<4\ۼ\&M`ŲNdAkV }i{,}c}ʽ?Y(,y@E1]Xp=z[oX_Ji>E IQFY`Rj⮇?u,^c;pGwE&@^/ 0 ZKf0CL^BƟ{!y%Z$^PUVJR{L+$f ɫcN KVns+R_$gcXR\xwDH*j9 ^捝鶰Ifm%t8rx&]1-]O(#c. 61IqyDntiewlKX3>\J$4xc & WSgr#up)ll`%A7fc^Bs(K߃ҫ1x^QCeˮA"O"4XrS6fyϬ%wII s2jˎҪ5{4PwaV7CH ),@EPK`xaa;rPSv 댖.\V/L\(߻Xv~קxm3f\ԫ65r&cFIb,dޱ-9A{w&Z"Bm5ZQqː@3z%J{C6?36YHs|N͕ln.zzq|2k(A%6č@ae\ :l2 쓌 nWz%m=1BMx76BR&aݥҜm&iu%^~i,Ef̽ك]cHR ΠD7L/J ~ׁug.XxqL^b`$>@'?"* .e$6$`!EC?UHu6>iX%DWY3o"(@uPuoostn=:6>'Ϫo\1:SM@-Sݲ N|.x^.uR/}¡La4L`PyzQ_u!Ҿ_o;߹*0Jß*HFCKs1i=z:[gߎD?:rȐ .CPUnxM87a&X9~ّ$>ew e3B5LQ8O`O"V)Z]R)Yio.Z@/A aSQ?}X#f5~=Sez^٦c ,"ERa;/TZ @};i,{hnl_R ˆ +noےh?//ԧ 8'YhBd`H٧yx<3ן5`CO`uS`,JuV0=<9HMM ] 'ˆ$lWpbwD,>+(q.{2Fw֑s",Eqae.UD(K<.% 2#DL- etw="ĵok4{-;B0_hJq%S7XkO[PoKV),'c@u,y lKT( ym ˕Oa9W6cWҠ߅~%1%hAkNGδ)x>~]\CP̧ÅWX'\Lcvq@E$pFP%7@Ğe4V*2Lܜu71 FC[.DC51b>v6G^ω7K,m 82qT+nzYzZԥp 8x/㺦tVY=ќvS{% =w)\rݵJPb0<+^rMbF/C[p+l=EPFԵW*.D((Zkf"鲼B88{5{Lq1c)Ixz^8B߄r^3=aF#N >s#su]F+S|<#0igݜW-vz^+B5ة5oT!.K}ZȹP^P ,선qAm?K7rj `h4ChO&o#~. nIセ}^B_,V@!. S48/|7NŲ+I m.q53ƞ.H$ t?A/TxVg%Rle[{Q"[Tr0|JsՑP>V:Lkxw w@ݰf=.jQ缠/%Q 3}r{N"PO %dK />H(T(k~ }^(q fF$QqS؟k!zl&/y.TSJ 5*M#B:@#ĈsQ$M>Ii'yƜ%; оЉPQ Y LEXTMIxSB3ҟ`u5q.n%If$+f =k = f%X72j㸀kƲc_+ S4\^6VY{w(; MuwԿAWɜ9*q-MlT?YHg"oƖ35k5[9om;jCLu0׫޷!}i| _CP_7.&<VOb+:<24a]D!ns*=9{LxXit禬%di\U(,6eCrAHVy#3Zn\9H6Џ~i67\ 2UkuwpqXGd5hc`*c³4@2 }'S:O4Uާ^DH) D/ O/Z{~W7݂ԕҥ6H(fl^Qպ='Św.G̹m9+?>dH.#˹V@cW)iчYeHnlGDCY r}Jl Կ[]KyʸJ=db V'y=Py5jة"-lo,꺙 ']/Y~TłyA l$wk3yV%3BoBFkuD^>pjBlOövckjau[xN{4_ft~ao94P qGy"Qb񩱢#Ӽz;VzU.V0a:ǃ\0'sJ^6ÒKLAcXz~ .AyBsҧơ^"j;6 n4 >u+nZ0Ǽ08'rUxƥiڢJL KJj'vkRB΂$.-=MI(c"@PVGp,T~$yTƞ=4UY{rtK<|b^(ױ)e=A'cL<˧ z@m3a|U,6”]/aPҡ/QKS Dl[@ZK!ݜC5L^/(࢞Lp4g5Ge΀q[>/bB ?Ip]\KvuKj7ΐQC L0V!ۢ.ME]F}lQnT?Ӡ, ƶ4sMނc8.1Z;5p*(S뎢]s4A6J_,|$=+#}a'1Lػԩ?ޅ綋X=qnБ\:P'W1>gFUԵ@ckYC~uA` (d?#?ӓo3W)v:Qs|qU>U7iAP5!I|q^ɞ:"x,t\q$k}2ase:{ƒ`yv*A4\AuDs6>1 ee'υ!Ys`EhRGLa=L2 q|ҒLd=X`.JGOBO2lCre' }0jLP|4w_'jڞYlL"NfPUu D:*} &w<BZ: eFS6$xB$S| ;W1r{áׂ2mHnN^@QXoȴN|z/~Bw83{7ɛ 昙TL1GjaL.ZHQ3( DUAw=%D#QFO ٔ=]{:3 9AՁTqc\SiB x*,  `"Ò|'^GLWQ Fo7A*Z{"Pس߂]!ڭ}qd: 4usX784rW>Dw@a 4 ʞR5Jt9 I]1 T#uYT٨c@xNciC4{Mv'U P-"SڪYͰړ@TG9F6vdqު0\p,a%4Y+V^Av0SH*SCuޣgo@a Զdh8]3آwSRΤ24_iXMG4@#is.F.'~Wә9TOr&CD/1-@)VD)hT -u4BR 1[0H3ڲHjƨ,u@j /kсc|8YR~:h6%(jf`s!dHJ^I[E -A?f`#6yu5y -BS?( , 7=܆77Bpی΍~g'?XejbeZg[x+qawnކk={ V6t.lJ ƛ@V+'XpcopPGp״0 }_^㿏#2,fNŲt`\B9VN2,K[ DIq:0a:oG>v6NP(hM36$r(1$gb3m"zRAzâz7c|=]O^" j+]uMC*4tHO0ʅ9FC4aQ TR5hpG3i a86ii6ffU{ܡOoB?b>=A&uzoZrҀkv0fƸ+]b׌6tfd')1kY$4K1z OJp0^Ar@G͌u!mt{VҘSWz\Կcd!㉬ Mˌg6c.c郯_*@¯!(:Fpւs&F|Sc)c֢=5i^gwe D4` & ^ :f {`%AF]B0$njZfb)\q݅q5T^WMkUN:h?ܻ/jhѻέHʢ1_F9Qʧ[RJ`.K&h8Pr[8t:7 ǹ+WPn#:>i-?͎|li KAs \"+^s7SyI,DD`% a3"E[BJsV7V:2N66,7eQe bbc*OFdV[uhKB`zSISҘxBxk3ٚ(0/Cܣb 2uf4MgIH! K[ oMObU)~nEp`0$,tGVC +iwE%sA߰ASnƭ^ELr?~"'gScnerMaUGJL:nJ1\9]Evܪ+I$nf,_`Q@YudJ "kgv\uC$WIUuA9R99.*Vvfs[ /H cᘯ6&!tЃYV7tMiN }d v@C慤^t M!:*D$A[+EW4+SZ5Phe#ixr4-o cCS?Su2nf𨺘YO4>m0soχ'h*A L 85[ u/7ꍖ$ TCf14CJ-@Z_=!D4uqB;Bx\9's1 8`;w>E\ȁ2'QrDa$1kxq!?:91[Jc*̺g KA'%{UcmB.=v2 t)910?w'ͻkMزVmҤy%Ht-3VeVU'E=^ (x!ԒFV*ys]zP]W+2^pf'cTfS"N][iEfvdgO8v0t+<O?$yd>s:|S|C.0naAڐ9dopdP+Suy<~4ojĘ|?~b^mI"KhMlNjkQ2=A@Oww$^e j)^_UZķ^Tq0EZrseRD&N7% 5WB_Z9jK"Kz[2bDYo:tfl t"fhyȬI}?/ P*5(aXa.DS˯L*+EEZE! ^ @ouȌpb=گ#h _v! 5- 1A6GXlƵAͮ&)qzE,K4^VY#ߕrd Y~w}\wf8~Jgp$ WgIwJ&ւH\E~鱯ʒ^;>j\XOр#(TIh +nk7Bfq2 $A1E~r\1aX6kGB#ۯŃ|QQYO#W'P7t)l|3\6^ɁPG E;`j6F]V\?v5*[>VafM}9vĻajeܠh*Z qMHVLXPl R01yFE . ^EWǺw_ F36yb#/.mKy,=lډ!?}!͒(Ei} rC%?f`3ޠt Vz2ߴN$x(Ij; D"asa%*H.lA"q^EVeYC1?vݧ J{0F xAIS/29TJ URlB!c=Wޯ]`ppv vȴHҙjϒzc9HÆ 4@DW-|bvَ\ٷ{ffG5eN8^9py:>U|'G*<!Q]A)7ty7MA9%ȆVĮ_4|5ffbU)[^к>"piZbÛŕ+y 0҃q9UR#c!@N4cU:.<HAm~J,sa1ߖSjo*QAuvyٴB{p+:]W!\֥զJ=Gl+^վaR`eShi t5h}F?Qe ҤM*p Yh;[X'U[q w"Ӕ)ij1CA:;ѯZCڜ Fsq աF;^AsAP 8zN_Ii~̟Z|TA!}a?O6ZYvXl)0$A=%Hl'r;ULk~h^e=t"$7!0] A36Hn"j I&*Xs=N|[Xt")hKIGZjUa~qa 4@Y=4&-kOU\i2I9ZCCbd.8 ~Tjv>rV)QM`?)B*7RթH;lmVvPa~aM>cVe34ԅaC&oj/4eXpmY#lj=GUI?edajH"b6Kѧr{i/AvCYs1Y&%;C.c(4 2!ElsPE Ux%2ZȮ4P2VWWA'<ߪqaXWV- zο@b(#;BI5OUܬw)$^i]_T-IL>S_xkKZk&DK )+":`=Rpnk3F=H78-|J|mT =;AYȝݑ-sA_#ցCW؇Ɲlhg"=m5f~Ws+@4W[ (w!l(6vSqeӬ2Ӌ!x!mngL):K=z,~n jG? xJ&G*Hd0<&TP{!FԳi Ũ#no;Z^㴨EGc:S y'Zd.{CE[.in7mެ,W;Z(-ϰD2xa{NW2S^u0J~HJ`Z7'|yMPGG*1^`_情 hQ+ N">9Lw3dE+)XJ< I^h> l|H T(}-6I ,^q;}N'K̩|4ۘJlۗu ^iqF?ClϬ~P>7ڍhlSs@}RA|jp\BIɈ$։<:4 [݆kpfH!?Y۴ l g;SO"'վ|v`R#Lc8/7=Lԍ<;7Oq-=]-f(!ORN!t,r{#{_ + QeiC0UOݧ#; V^Ɏ_ރnrMLWD'jެJρ3 ,rY w[еh{fJSt(;htҨDk;"IMa=#(`|>Ux:nEC*S~&fĴ@H͍H-0ZShO> e'$rr Z8ދA|I zV-g9tgF g[t7;#,$#2̑Ym9xvDm]*K*ވn4V)ZRZ=yTqBLGT.FEx6氰R;Edy7"bHR>Zvc85E;5MIzBi'y+z3[D{$ғBo(8J[X6W!Dr FԔ+Pk?;XD,&Igm`LFxfs.Y.%V5tO>͏.3 7cv,ft:TN=cj'QgcNv d399X$aQN̑LcIH1Ll쏯@$5Cq?dhlBtO cQq|Vb;/斟PB[Ll g,3h(T035uvٵ5z$Z^l˺6I =b,gjU( SPSR\ŵ'ylxv"|ɹ#ر] z=P)GÚ?7$\l9 61j cjJsmHO _lttsPl)cY>o70VH2\:;oΧi(N[e7\ύj'ԣW۟ nϐ"$&{)YJH$ag׈xܗV&ID/Gim17hTmj~A> RB&A Od.óYTN uXuuavȃ cK2at;X=JLTjԖ%A9f$L'Y⻤{kɽYZ׍PxaJ=xv]FZ$DwkhjF5~}=A7dmQFֵuw=:C r&%=n G(cԏC\Mb,%qpRD{UtĉW7#j^.OCюi=HT (`;NQ`obm;,Х2mi$ǪgX0[4.2xa]9˧Iϒqph|/esWȰU;& PgFCC`(,GS%8~03. ʶ[&c$$e0uO#h>ɒ!}1-+֬&Wa:1 l| Hwfp{Szk;rè3q20N 3,7ҥ7+IC9`h o) & tv#Zw,Ӎʴ^5b-'dUd8V]GX./VqUJۤM}Yd3Jy{dUSЀZa@10Hp双5doa`h;TpPe%i[ 7?zţfb^&VmZy\N}Ȕ(y/1籘p4 ܮ*9?N'n=zz'?4u5qTi`|c_* Tղ0£r6#MzRDwL$Cs Xga1&m|KP3W- 9# jgtL}i7F'?է6_ccj4o|f6Hɺ {)PVzڶGVNJ6#˹?'^K*5U^ħ 1?`YoS5% rɓ,fq_|Ȋ<[:qqf쩜wjqOMx nmq56LZ*[6ً?:<9Ȋm蟹<hom FW&k@dDٗT6NZ {+ ȊQbҀUS@<`la(B-` Ob.!Ï9cRwB3|KQ4?[564b:r)ocJW% *Dbclϱ4Gvwe.C/57 ~S_ t#;Ⱦk^ԥFbOLo7wZ?RJzX8w@ҩA Xp5i{ (YUo_ ȸ~N3"D~4[wNătߩfџN<%aOEv=މ7jy5Ԫb_/1dFW,v!~ 2$B8[0goK?!5*n ULSÍ#E-QLNcWVm2-\vUq\]WJƏMy)o(]}iod|Xþ0' eJ+D vYQAAv^,L> x@bͯ]K~`!(}ݸ[zOh [%皿zqWCZQVM=a|^ڕb|[D$ۻr E: %C/ii XI;qόYp>s9ֲ{8\VrlflD~'[A8b ɿqD$Z4jbx[==L yx |94?o}/BMS fv*)OU ̣7g构(EA{Ny@aM`s)R8Hz̍D_YٳCO{tQIm,PEwp_]r#s8%  ªxejv87Q=X9Q$h[q( ,x)S2`[R5:od>b*qO= _:2yc lV#phyw&ryE|ѷLZ=O 0͓)<҄뙲ͺ3X[5wDyC#8!1\>[ƻh0֐/y&Dqǰ Fu_Ev=-}CϊD:տl"b_jR*{0M׹V,F>vK^'~]',xQvѲ<4$n 7k'mnjEIV"YO}]/C5&0?6͟HLvmb)9\5 _;KJ0D%*rs|cG, V<:h;['Օ#tԄIGNhkJ J{{ѽ?>©R_h~r2C:#Y5r<>q@edr*=#L7n8$X)S@u? >NW SWBd&fC{b j/M1gwsIaIh*>LTsӢ~t?ң+C<ʫl\bI62bWfoC7B H9KL=R!߹#1īen1ٲ=qb 06[k/cP p9SHyT)Ĵ:N%nfnV`a5!!iLPgp|f ./Ec*O$υ.oN? ]l |E>Y٭JDs+%_=h9`DY`8r5wT;n>M l#q|kYooiƪ-ByzHE!DOJfx [=4M^C` M..[!]sy bW[YH`&"~Az(KFC@H-sL'Ե'W8:]hw 3jmZ&»wνVz!׿xdVW+* Q"vI;~^Tir=Ƶ%wngZrݾVa >v-[+PjҤzKps l"=ZWd/ܓ2֏PA QYP_ ] ]'9%X쓶yV}HDQwԦbkˡ}W+X*_A3Baif7~Wd@ l~T'm 򋾣0[]m$CJEw}xt.Xs \6xGHK5`ë?~!}[=9T]VdG\^K+³O_ĶyXL~1pHPRo: 0sЂ;ìTqTmM:ke]-axVQ'#,auQ„aE:g#9i [wْgdVI1?@4$A/\$HCo݄'8@ǽwH^FkBmש?a+v]-[u7>m(* ܒ+0nѳJi&3 E^' T9z!seRJ1N]g qQ "jƣx }+f%T@";S]x[ 2̖;BRupWuB*vuOLQx{}u",jo A0ޚjZɑ!y^FnOG:-N .)xb}Mg Oso%</_! n6p]#*HIѧhMVd=T#,eK'0[#FiWCZta|X?YTAmƋ6< jQ?}&B9 <3o(QCf3œ#P$̨ qS$27pT/r~$`'*f{ߺQ~yA dJ!+6\B)PrL=0Bެ#kQckaW1f3e8lzGF݋Al6 W/ތ0<U_@<V.M%'p?¥Y3sF0>h_05|5oYcjSB;})FW醦g ZJSZƴ"˴lOMßdW^,Ӱ s\Z~qٱ}W4ǻ&2WIk=ukGTdE* a! ۷Qhb~V,;$4x}(jxâVvrHfE< ;w'vE>c=|)["M/ Jbnr[p3 k9H-L<ٻ"OV|TPGJr_|=8_<2j*H:e]Ms]YxZ5,eKi3nJ"+OLXH(-IaO5Z!^n=-N/2PWA{϶ 9! WY^ghͱGg}0l-ݱ6M퉶DRʺ[ /ٽD(0m&`$_}>Ìu!`JSf| {&& ,jR 9]<|4B!eqY>l_h)_܃Sְe@Ki4 -BP7+Jcuݥ{eQS|Rj xRJ+OTy 1"W*k2 (M {%,-K8%oѩ\L7. 4 r#6\*#%W#qm!9#2AS?f*lER>k20I*"o\Ftf/M -̳4} I:-jܶWLpyܒڽPH:a_EN0BZn^U~8]@Wp,p0RY|`\[չڮ-i)hjDC|`yV;BbӬq Ca=r$yPd+)c!趾vt]]T\WUӵKBU&5<0t]4 xmt(t]AhN acj :=&Lo[(Xm58nS}I4Y[/p\ V+iP\B;d@E9G|gI1^״T e]bXw]U18dIAh]7 r̭V?A*bmI^>NZ.̱Ո,B!r|>Hg;![G/cj Ḽp \x>1ļKl"M _%>Np=づ9?7 Fe\X3p&:~rBɁm )m΁i9Jcm cmUPO$MmP}3,ys|6Nkܒ? o?CZ<\~S,䐈)U $#ۭp+ 5lg7#doJZe%)~AsZd%ǿ 5x؁N4Xk5Ԍvs.9~~y9Ξ hw>bi WWnTn7ؗKL~yrĜ ;`83bgį3CAc k)ՀWEֲ팿WYK ;Wyiyn&?5 D3u(q51ިCnjH,% oq$GC(P`\qb`T%\:M8mQ*aܳ>KJ_Fc fj8 ЅGot 3Kkp5q1SŮjN\ܒSd7`N<#B2yH~pNM ǔޞE7oB;즮ZCw0XJ(?P=j'jz4S_(Às-lߙ }9uAlyL-(j<ֲ۹505[l= ttAKWNQ/Yx'9Um34T6^d듣ӀZW.icCLMQmˁ^I.cĩUR0㍩ۤ;x<=H8 =\N#&p}3 s5_q|DC$E/#,#eP;f彇*& 04-5\ޒ I2GqhR3)2& r.B iņk h`L&=C楋%CZ^'LҨ40,q?vB\ =Yļ4Is7/砙'*2/zjUhN`?xu{}R`:XP})MpqaXarvvh1#m6d{ +y"i q]en_OVl&*2Á0RwaQdv7Ģw)˕qN`J)YIC;LecUyzWSd3jd( /z1VL_GJW%3ԝ_Ne=xqg/MH1dP|W^}ټ xkgW$^ɚ1~v$ ٧K Ê =̪o .> RO6A]U_̟ kPw\/;s&{v.ecT߹[~`ZTˬƧQ{pnTVɇHM1 u zM3s] wɫj:^MKWS{l\;)P.0iXSo=%[3„*[s QC͹%S`~c&R-{%Cz[,x ӒW f FI4QCX RUd; 'h[+tiOs?CHRenoQqrM2z( i wqK(_bjP`Blzc \*.W P!KZO6'" $@ɳlH~ #HJĴZk+@[, M0)@?6TSS;jMŢ?&`G\P_}VJJrxg bFQq, x:]d 蠛 & nj$ T")) ?Y6DtixbZ􊈭IJ{5 ^u8kم@ĬeKmWl+\YvY̒xפ_P ~tź*NIqhA!X)Д^u-6H+nC;_Fkha~%20C&>0/fuqRⁿi2)~Ō*1&34p"I>,_QO eڽ0caY81erAWROxp!ȸ:ؿHq9M_/l㒉+;'8hz9וbq;mL :rG$KxIuKt$1Bݛ'I{7 qO.mY Qo>DB_"cnaf ac>oJũ"jy+ Pt~I͞,*of?ʊ^$ٙaZ`~pǗ&vlL6 !н9E?toXaV!>8t;\t)MЍZ% !O~Ѹ}f [ϑ43h7s&җÅ7FDS+K䓔LqH _`1b6GHgN 8rX |%z{=U.-(.A%@d`kB_t\:G")@;˟>`_OCVewxo5`Rx!t%/$lWzV[(G؆\g9h Y~P#tH=(z +[s~Ùtn3yMBĦ1?<}^A'X%/ ĨN_`.K$()iaMywd_ 5ffV2CT-7·4c2YI`7+n9f`kEQq:[[i üAx*p9 {' u$0 +dCS + [1dvjQ#A{b!SeL[Swe2qh܋^# sΏͦԊ9nȨ) ~f oI(kqf9B]y!43/O&ͿET Ҿth=Z# "|iۧ8|cHZ,z&H#: +(UO RXITXU!̀ ˊH \%֔w^ݳB؛.lP@LR2Tp TZٱQ x];t9Xeݪ靮L8a@J}8CH&5#iW.:Y_#+t-z>& w4Lnd0^;ZI>z9B]M=x0SW8Z1ЌP\yETƂ刓ry "KRxq_[0J,4ƌiX4E98&GߡaN714se#%X~.+N8nŅFS R7ML0z͋r=R|c׮nG#_` 6-Qm-NXg!])7u`=i,X|'fʰC=S"]63p+HNPYtHHbQ@u tAg|o҃wyܜHlrccYu%2X++nȵ_Ak eZ%#DJ{pϙDD񟦬Cl*sKF%N4im8CyqfSy/MNVy|\` Ɉ ԫTH&͆)FȲ  S_Gi2s'z3;fkwr̋q1aUbY:ؘ7?GlD15ObLJ?m]QϺAT`m i,ȃg5華O%T/vR+,](6/ڏX}A̻9)dqmDERh ~E`HV'07tR*DWLTNYaR (XSIǡ REؑtو2ZSYNEd2>]ѯx[[{Ո#9Mߍahv؋:7ʼngfN[-)c}^qd}x.4SG_z(F'ۈat.ÌL͓C&Ba.1[Q*jΕcNː\2C]nғ^ _M AVbԹtKLb0 ȆU ǹiE@. ;M j[c$uɥUJ5.>QJWІi#ւq z+71CDib4?mmWov Ha` .0_ Mq r/Mv>*nEm[t3h{kOG7?L}b*0)l!*p('t!n;5 ew^5϶!n8(v} <7Y2UvW܈w,U8T[YyZ<\",p{iӧt`^b/aұ}z;k|^=Ic,z{vH%"?bSLl*dTINW}E*nt9oWY'dV*PQaIqC6A A{7XL۰%[ ɼÞVI} YS3Ŷ,Rő5 "Ak#* g_ٕW˃mxlݞW&A‰ ``7ɞ2SV0Vܯt'ۏͯO|IF3;~ϲ9G}T@;_#bd}!8xSY2І ˪[íhϾ*>[yTBO~IHTo.ZZ!g+vӾE[SR[Lu9с1΂(Q*h8K%ʓFފ{?a>` ,xdž|2?ٺNEh$~1y()#k\FS h1QLL!g В;)/IR gCoy뫳\@f̝̬rh 'd6 LJ:iHXa,Oe*3>gPfN9a'wEF oeӴ,`ɜ1P\&.R`?3Wlgjg [7ih"C?/C9=Jv<|v7N m( -u{[? 'q#;y@&Y3Iv?{IR|j6_mG{C?.tɬFĴߥyk6Wu]Xz%M>aJuZzmUnUcŝc`snT 8vd fAX֔vS Ķ]w-$P1w`jk]]zá"|\f&qy[Ț!!)pq: {uo'&:$(l eC%`i\71fň/F&K ' ݟ7Q*J+HeRcĐwCk=7Ty79oY@[xV} TA@) YrSKiJL1s{҆Gau}0q[Xe,`oWlNdl3%$+t6ZRN&{BX_cY랷kłP ҮֽDݤ 3n<`Kޖ%5uߌʤELSm@i B|$4""|oJ[V=͗yAeظ; AX6,ˆv0R_$ @zFbtTY7e\.U f0BD .B& +jpQ{DogΡOr}nHh=z9p1p5ҽy}ӷKS{'o#ي! n>'*I,B/h@RRduQYez^ (}T9r W҄o#cZ4O+؀ޥqE* z~ g~m!Pr]K2oBpdƪAt.XldTMI9}ڑa1_>8aAW.Jib%>@096)moy^k՘q|G F-3hgVoK5Fo."K@ǢϮb UO\SRn[+'総Q"P ;A&w*L3-WܦۡcA4M9C\'Lga W v,Hp:$NY`D1gw$MTj>b]=RNm}H#K. eLgTW$C%ٱn$C_@1}9G9(8^0!CplX2|Tj0&Ah+"CTb/_?>hhv=C.uڲ4"nh#P1qȦ5֯%Qe/Hi>?MC"ΔeA4zԻ~ز˽,m+ J|6c0*#w 0=Lg~u3x~mN>kl0籨 a;/N V<̓3D[;kp kpGM !&K?|$ѼZiJ*z'1>P{/)W'P~o #HsG(Ś&xŨP⎒ojƓy b b(B+Z`t!R?>DţɌ,A/sD1ktL\NEuM0)Csp=A-ahk QYUF֠6N 8CB_Zx@*ߋ|-:mb΂+EZ|bjL{fJx=)$myl}$DfqLf7B_tSsb8$䭏W&ʯh CZ3FnJ{9W7G?|snbACHA*HtxF5Ae_L 2mxmA:16qCP=AMVewgcOkӻ^pRԙ )3ņg4?`K:ew{'@MqTORźA F{=ji2\,A0*IzҢ),5W(U'_dI,u9_,PKZ64,naeljSbMk dMk\AlϦ{( b]6ϒE-;%uگ3}A 5T,lSp/nQ7;W`| ~:ȦNW̊3'5(V}(=Iۡy}!k -!;VS+w~{CAҢx *vWj<Ǥ(t.1Z/UXD<߽&N 5(g{PE}A M^9k=p?f~ӛL/6LϮF.?T:DKsF5֩ bv-O-P7]N2'Ð7qFRFDj碿 ŌNQxܑ+?f ߈׍R|ؖB绋ӖF Z6A&\]#ĮSGfK&>S d.%|O1KUI9"UvBwmGKbOёtaRլO}ٖ*/\n<-uZ1:}:2"Q6{RD9k}eb3 \6j}m63&_> Cʥ,ߢMԄ}\c.x5fgpW8h Sgʵuv38P"3,ˢ$9LSiժlS;qZz.uL gyBa MurRܐNMbkXp`^bMQA6~E < z _f5&*EQ&2Fix4UY 2Dw'5HI͊g2rtrؗ P 3 HVi#ݹ/k6R%Mj,ȴukĩ봌uib$tV"F^yX nVx\ìJ݁wVwtiX\zo 8Ֆ,4HLUa;3ŕk(+(>'NouR5r'L'`r_D C< P LEk͐+7/k8)ۿʉ)VV,i8; a8n=:}9Թ ú τׇ!pZ-lMy;yU^70Ptt*X̆cF̚$WRJ 'O,13#`!e5 LUɻ7Ϋ(A#p(mF"[yiO %Ӡu&)2öۉ|4!qMn:bhSL W9Fw,hۘVQ wU C .#\tB%8V4%lJ(4{ht Nv7Rnc5kQ}[ȓ0 .JSvrAT5QBZ ֦K3k(ϒfdUP,Z7V%%z@xY@u1j{B06T۶Ub<yQW$$8|meo ;so*M@b#U>uxxI?}-%N?Ìo.+31:߫CHUӳLE(Je+r89GCz IbP3(w-̫̕ª"-&N?B&W.D}g@6LPS4m+zR"\ŵKŚ& 9CDA,6r qodmLj1Ǔ~gh WB}hpDEo棇N!FzW3i6T2OD*2mO%1Ys\S[1zV+V-\q)UBwM03҉~ئQ+C2EL0X@TM4E}yP0rnj~F ts%ZePn0"wHK-0ክ2-cN=ڷ=k؎x… s!^݋{KEy:ŗóˆ 9ZHn]_Yø)^;$<. Y‚יdA˝7:&3j2T5:\ʳׁMӾWn W5zo،;(ZTC|)4B$ԣͶnBd-TlܢXtzGm*upY)t~ Vѻ.Yd%_ *)k#,B謯WKA8P17 yW&lܶbmIzrR!e=v\ qK>KzL;=O?? Wp ((i+{zuϓϓ>OL'Ӿ|OSX=^g\b16Pp:tHw`W_Ԉq\W?ȯ{}RKǗFQ`%Q ,{*vm"kOKt||Bb1 ` gIRѯKS-c'y!cjȕ<}m=fl(*\4x:)(x9T?Tj̤ОSVM(Š9zx`Z<vk%Q1:7L-o!7⎜c(ҽ AB,Ydu5V-XfwysFg_ay/`Ux6 t(g X#6`i 2)HIPoi##\;woRS*7aХ]Z:7V`q*rK(= Țn#K`cPg z\eb7-Chga-C<,C&/J02h?7&YVZXxnQv:#9g\} ZiGM{l׊UM4j݁l>U.D^ AٜGĮzPcGʧa4_ |ψB,< q xR gD\/3q1j U~AJxHSϳƤ\[Wf\÷ 7W;~Wyٷi~KYCfL@sbS=FK, @T%PCkqw,?$y<ߤ3 Q*sC禖Vj!:8=;MI_M]]`@*jŒCpp|}4#K=S+CWuL9 +ˉ2 yawOk|J=µoI[kX{szoĦ9-u%LµݓC7zdsuf`}S o~_WWkl0y2<|(6_R%D%ǚ<Ʊ=̏`ӁCM8>Qj-g.%^VC孏˧"ù|G"}= S {p+UA1;c.>&A Y IHgV9IZUI@'t,TyH{iJh= 7T &eS#iUn,p8I3s)9 4 : Wũ%'6F_+ۚEYXQb{1FaX4oH&! \I$=^d"a*].{jO{9@Bl:AKkJN4C5/@BuJ6 F^H)慢(8 f u\\yg}m̌Rya+) 4YlN c î*~F٥YGB ǵ7@ȧ7zꩾؼRt<TyCݻzcbjL@[Μiz"HޏܬH.v+Ф0>e^N{Xrf]t@|#xo "^ūE&'IIU~b̴>6f"«OI)ӎLԧ4@5IU$ ͊~@ylN>Z fh[Qա;ۃ0eEI!@'6 Qɂq`lҭ}kR>; 16T(R{m4e{{ߵ~n$KʰBwg~gL@Po7IԧrWtW-or RHei5ާ˸D]Jb3L!VӿEW?2|YS&rOWPLؽv&s.$8 |1"]1^ Z hx| mMHRkrȬ8s . c'G<"<:i!тOޛD 5La:VOtl#X,'vAGé9At+=Z.%Y1јeT&P4r4E=-Z(eu.!7֦b|ق!?ɋI Ww9DOdOs(۪': |P}Y]R9@?@5xLzW b!EzF{|O.l(\ÁM k0њ^4(֦Z.[ly!NH.!p' v.Gd2<쮶@5bŹagYq⠂<5N847eS @bh^ԖT>P 2 s̵ghNB멵҃LٔXݟ&,r#F$bҖJ DdU'$5 T#Bgn&*_ΞR0O1r[sZW4mR[?pYO%?R}$C&~ϐ&͙TdlHِS /DwMjRe*``yO_ޚj?QJ.`K"|lxh +P  ]݇˺n.Ua&cn m^A6Yq_XuFa"#+7`7v<* |غ jL_s wWi[]!wRGiva@L`k~c Fvŝ&8/A2Iu sk cQ*XY,W6l@s1Dyi&9Zk6+_U =SI:f^RdanQ3 IF` ȶHgvj:kQo%w⣍k1IZ8;jzG+;UOgh{]X7TVf`)bt7aKL .$d~ϙkdO!`nVׄ2jG)@)!*EpVtR V2r\2eXܰ/ U?6b?/+#|Lf0ht|fZ %ǫo3<azECCvQhX`/K?Z}Bu;u(PKHq]) G!"mޒ-l67XڍkV(}%lM,PkGʵi1>@6&4ì6e)S˪@[u**nz\* C-Y-zM_ϭΑc{oTAxJɬ{=M"X8C<;4f`ޅo6 ù&D盩8vD^ gudQ,]^ .]3wȤĬU̳!>Tw* 5UmR,w{;wPF!yA-81J gע]V98(sorϳIObXLkKKZN:A %U" "=y5BH=I$*Ϳ/n*>Xg'T\thPyI-ޏc=3??τ*uOIx%#߉v E*6ۊgD95IBׯျBgźwuEZW\лw(P?.ɫT)Xwn|; Ŗ:׬u9ZcC"B2^|@`B^Y(ZZǩ_ Z=¢lJ:wrNjDRAՙ 7cqCq @aW?2'NPF^}&n=;B֔ufPP`l=aSx>''#6r[;`?{oJ˓2q|j[>+L ΢tA}>MP/$88ezK5&M^*kiLm}986}wng-'qZZo EI"L[.H6IT5 [FAh:+#d> -G&sї(F\ڝ{Iw3?Cꗟ4) 3)2BKXUkc{X8@[_ m>3W" 7OB'Zҡ>(W+hC%SRJ u\ UՋp*_0BioICFGbFQ`1dU`9.cA|-Ro ,Ÿo9p`X5$P7wq 7,N,T%@<+?1(ab6mLXxk.ؿ"TPzBҰ5]@. nM%aȵ&$Kksu0RY2HmUi!7 hu\Dݪ% tP\i ]։y| ix⳱T Ic/E%ښ[H|d\Ϟqbk)cgyWUl,dpP"ذ;5JByxpCeEMa-FhYW}Ign8'<8Ǧ\F;ם J.l]%O 6wnkVTzxQeaC҉Oʷ s$wm$>eʭsb_> w֟|'9IiΙhO,+Vҏ&t%RW%dTmf|QfJ ̯{^Ppz!5}MGت.]Ycz^1L ULVp((2#3|f!, 88)C6cB O7#]N)FOtW{~h{Nȝ͵{]uu ۋև*"Q5j Fͼ2y.O:4IPrM67'[e; n"hfy%Ls0iJ,5mUy)k" ƁRxbZȠZ]wHҗha~f6QUm1 w (GlhHy,NAEPffrQ OQWOv م*{6;|߫B<흫JW<7rp<4)+⠧ ҼsY~? [[#ȹ\ 'T]xKLW̍)3;x(kkU[2C|:%sZFVF a]"jOCKsEm%ꧨ@fc6iHR*VN@zs8 ">׆ ] Ne9F.+5&,oe8 ٷP0E7`q*遂fb@&UME!oq _ʱ41mɇL%k}x:υBAu/!a =ʜlX#٠}CΟTtP0m~.~* 㢈Ddi%{O<t+t(Xpg T QT8s0#. (>OG>@C/(ԲΈ Q pi>C_j^CاoKӇ%'6iq "I+Nih.҈ Ót 6VM:8i\=KWg*A6x1EA+nj)Tapo:;?P"V '$#LaNhF[+ 2'Zڇ{ՐLN tѕw轅rFPu|snnJ\A0lUBSF~Z5t$s;"@7e@hebE 9ƕ̺;V5y>L筈:C; .k,킜;Is" }O[&4,ѿ@sJ<eGtX:Cg FEACڛ6a6$ɘnsqfbxxHRr\)u| \0!CJxdn#gGܓκ^Vk bA`"b8g [R/m71H-Ų{>0[AoSzNcG3g\ю"@i7^ a<%5]#@jIDY7 _D 4) mI'x܍ٔߌIz|sOp  #Y֕xȿX΀TҤ]#TGjbI*Ŵ:|>V}a>\%]LXYهUA _\ y6rk2s _S6ZU lW ^`I6zr!/iSԊvpWX9ӡT`(*Ecx67,Ըe˗.EmoS*"B2/y]^0bbQc=e' * xf:r$)ntϞPM]v|>%@p:Rn7:+Yplm cdߩ \u֬g;Td]d=9[꣞QKErOçկ$=+w8/5 \r?lqnQWِK/rv%e0g:'u9Fɟ!8?# =)nyV`~4ΑpfA_ýy?-swk$c&mot>0`yi6WX߁y[- NyAc;?3bYUxD#ѥEJpwz .g5fEY9$Ruf?(F{յ?߄(PcA?*~+-%cmJ0Z>=i5E2z&/<dBT 1suV;0ֽ"hnYS[?ޮ _[!.uo`sp37J⬗?5R؋7Ԉ TI~$gM*f}G{N" f%-~Q )\-J~q2fNt );XѰrtTN.MOh P2s޲rUɟF!5:F=d QƎrjϺv &_. ]Z[۞i%v%`<VVPT^ȉ/Oq).<RR%\}QTB£;`-Er+?}Љb6pnOUݯ[S-mŜ-c%k/IH7wu1l\G-1w:ğ(؅p o;Uq` B *PI+bMQaDMc暰B()"8e\uf[z;*G+ kJRAHPod#Bd6nYuBRq˜٪P^1cM1ӺCX0=`7Mْy+0O!ʗ0O[w0ʶ%CS1=6cXMܡQOAZ>0 ZWz\ 2zl)P&6Du܉,WEwǂacˇi׆}N2mkN8P@yxUk4ޥ12I4uq`bX xaFZ=joNy\/Ttae @u}_kUT- 6 $P|=W&~AXzLsU|]=2;T7*ŋ !#?jt>KX\]Jk2^ kg/4фXa@&:8xft-ҫ7M̾P~Wjg^/:XYEqhFE,Rm"K&|Y Q9Χwu3)_TgLotN0 w2"n0*=ל??ˍ:5yhryߏT}1Vc'2-*ӔT:DuLyAWz{BQZlVH~`ih?>哅h:F_*0<i?7<`'=NÅ|1ݖSyi;}bvUp7.?֘!R`D#H>rN|H1˔Z#%FGBOs?4z1Mp) AS¿Ӄ̦%v5ǩp/PM=W$()vnti /LTZRh8f`~%BJX/c8ۚd@7S̎80#޲TZI金'ZX#Ea18_!xB'G,)Ff_o[ui`S ;E4M}2s؟"G$z#>eAm:p{_5{bj0C=jot%STwH˭d׶]ehcsQʫPbZ_yBrM`Uc%k"5s8SmWN= cP0mnVQ¡͈Q: 6" z8- /&!|>d@@;rru0GE.GeiNX 2Vbd=mVlaX0dAD^̵P4Rm Oj \vAaixNN{ gilhT2,#Y-<{+QI'TyFU$BĢt/T$)&ZxRXNԫU.a=)Kza7I8(NLV]|dPq6P"N,a7#{ Sn+ՐMvfk(L$bcm{ITWT]|#(%lM8^oPJo4jjq{`C;;  ޻9*|m<!^gǛg@ ִO5dٗY>2KuB&>ӎSdR pY"uفAwQd nW+=ع@kV&i^`H'bl[e^i/eO1rgu=Oh6 <ƕHak)-7,儫97`Ϥ 0dN$ljt8QA`QMO4:Rոq%o}[: 7KM< _RF[IuR4٤Di>KN&LĞLJ۰j|x}US:dXT`.Cn?wFRzʴhqWFʶ⼴+Y1n6}`Ҭa ;8r޳O!XnE 4FDoFb='6.kAZB0X728D $zuӢgW[DHmn=HoM]C}^.t:A, ҈n~3]w*~-joPڢqP됤0L>Z%so_ں+RfNϑsstYndɚ;e;e>%5QײLU \0s#AHîೆǷ}+R1*Qxt5l6!Ρa?}55PmS<0uWjps+v0Y?S't, tPX;h᪊9g,0 S)'nG^| =ܖd\VFslͽXE :J{<~ G+yjdZ3'֜trXdkq54 KlA)v"Yarc}F0uj-qxP18.pۃ.-ߛ}woR,8k1A CߧF-i (S(, sc2ͷ{ϻIG`MڐT\qx/N)dV-'u[PKU;IMq3Zctr\s&w H%YyXB]}̖o4m-:}mp00iCsЁRpI~10}IGXgA_%.3NF@SӲzyf}JK/]vU2ȴlnOHUa*RCƝB n.~6+[($'z͋*xf:vС|DeNm(V)8˧hC>0Dp8DI/ XVI C9b T%pAx9BJ6 .ٞ?<-+8q<;#)uaFoS#rm@a]~~KÎ/^ ;G'W7⹲Uĕ%_hW8pJ*pHĄMP}jZ~qr'04L\pBq;䀇toKnRTO+|taDdP}Mtq0./Q6ōktm^`Yq{ԚG~H~k~ jV4"CKhiN) gOc#.Ʒ@~+0. ŐZ*[?4뒨i$%{Cx@LZ+l` qa1Ic6lTfdy,, ,QeIPO=6Whߩ")<'NPNj?*U,Wd>},Rf ӧڗN}ScHWk0Xo5_)ub«Vlpv(\ `&}27Ҙ&CLZx!AA1JQV #3<"Z暰n':Z.,rDW]>|/ O[_Uw7|W% ;MpC,̄55suqbYI!1ʋ_4.Adz,,7CULmww&)b~O6-DTj,If]dw #SWR4E] brt  EľZ)j>;nj%pM?g/6Z8=GB~V F񦕾犮ȔCbG馗Y2 dz[eW= r:@Љiꦁ-)1NZ)s_CǠ9I)'aה̐:eWc8hg7d÷&D`ږ 43FhrɇHW#U0E۩b0 ŪXv`nqMg:~U-KnqH۟N)1z] G@^G6A Hs4&gڛ476v\Gߓj7V[&{k&MыjQ/cS"Ux@!9|1[F#J }vG[Z& 3&qTcC 6/yxv8($ZUJ]G"1Q+r=P@RYn󤬣l?$XՌz2& AMY!5>i;}#QQO5HBe'b(Rֹsf`7t2/6c@#u\3Z -$p zl6N0sB\ 䫨*N٩C{"y9p~֗#y 2Krs=-P;Id)Ndhݛwep%G+/MuS^tBs\C^qN8֠ C%LiΊg\wҩ6`@ݨwUY u]x޵&+-KH{I<|WWHZ1krc0WIFxˀҴwjgs1sO48Y&>`X[-  ql% Vn'#*v&ǪLprG٢zy3+$(SdK GxGK73%3(<"]u*5iU8PClB!@`yM :i5(z ClZz!U>缇do0u6rX 4 ={w8E6;IʽO8wM,Ȱ[RlfHdvqpIMy|uM_IN"b'X>3I1l-f-iw|V\80-5s>XMxGc^q0/Y kpkE2>{?],=wvs_(9bz/SJz/={Ja34nj =,ɰWfTiI%@HX@lk3ȃe/ix^O\o5u.S麡IbCmiH a->pJ3ZB2y :[ #*"7쮿zH Spx OgujNJ)j`8q>K(G qTD,+snǧs&:Ƙ]?zCl,mEޫ{=cYo|?MS1"  qZ SJE =8"cGJ.}fǠt2?NcHNTw╠0!.yrD{ZŔ.}0K骲gg[ϵD䁜<&6ϟ4-xlТmg8 ɲ6(.o|Uh24$/FLSٵ(ě_[6ҳcCA*Di: v7p+m1e^Fxsu!}ҳTU3E 3:U=^6h({TA ƪW>9}0_<]i nx 1D|.|W>m͒JKZ{Y%?KYU/uGIVcћabH~J +_'SZbgpr#ŗVr0ٮ bCBeUќ_fNqzxuéiٮ;OZ5?v}^}>{#hgRFc0 $,$m= 74KH=9Ԟ O~ZByBHv [pCfIj'Cʣj"0c"Ngw׿uRf$h!@[ bI+'F\"(AL!˺ӻ N7CjY[3h4z̀ dxid \ģ+/mIn)-LFfR [$_WcW`]VO dj;vhpaJËU-PSřw` 7z:S-),q(:@_*/,W±,XKcT{_׫/רy?d~VPWW[@q-/yGsLʫ%+Aؒ0;] Lq KCzڶIq̂)['7a+~tJxٞ'ʘOzuJ>FխF#>?'-$+\ 9 С3͌ -yy>g׾0v&@YyuKFBIP? *>'Yd7b}>UX:-T3KSȔ/P}𡀐gS ou| M<i׉3pj"@<>#Q/,׈'^Nԋׁ+ _-3LHiBR2|JBzuqf Gr37``## @i{ȷLv<н4u׳ɲorI9EcG=E#p%롿 zs$ҧTLjh H˿ ԼuѯiGl˻X?#h1Ve/흜ucbHSp;3X@!R_ʛ{dX }y' )_Z@xC

sr|97}xO"L]HK ^nW&5s c8b Pk҆y~׿:r W5Sz;},^ Jvul2>Or9Fކ*LyE&hIu71RUP+rjBh&ohdwF(߆#5M"ph Xc]`۟*ɦ^G!?>?b (ct tAΝ_d}*~%̋mJ*#$LlD=$2/]]>~}8ǎD5{ma%A= Voa3[[f+uoӨW`[`:)6zRB*V/WwZJANeSPc1+(EFv u,8 2`$a4-|t}6 Vt6ӀjKZU}$T>B ̄3kΝ&3Ss8ĥdا.d$=_3r'x,])"mlL&t\5m(O;ڵGO]{SR8G-m}V4l2>@ž+g+23$qW,em@Q?M Wd-̋N٢C_B>S1)j੦>xUVش,@ {/C2-F&=hhRRVsW+@A1'|^fU s>p3Z|g/g L8w,^ kQmv1t㏣0V_B]=2f;' !>OBhTcAts]6>8 J50#m-7{64Z0`׹֊Q*MV`^-RG+e a@̵=' ,= Fpu,>}pܠ ,`sݰq;yvC6[.LFacU+<+ohkQ4no^%6X; ۥg<7}HY`@؅:ǪM >w$@JCSpC"l9k(]S:Gf r F~(Puox8^AojeZS{OE1nP?/Y@̚ep3NjA\Eݧn@ ʃnt uxtnh/|!XuK7nM$&AF mL0"Ԓ@镱? %.iզӅd[;'ϲ:k!P# 2 9 \NdY"HToF }ͬ>'1Y KU6~ 170LyC^WwЗhjpln(; <T@dKdv9Ogp=wn wt6Gy=&MP )@!՗))s,Z^O಩1J?ZQ1W FZ k՝*.5D Zrxr_f!')b̼7_~Q{=Ɩ鎗GuNh#N}$M'qĿ4ݚ%4^Mz|bT(l-y_Y\L'W\ znŒW%ju u w8ڔ]1*r2Ҡ8ta0t_hپM‹Icypӛrߊd4e;uV5ԉ|7iZ['״4Z 1 $W[^z#76qxobc`sO~Vظ)حfy_\8Z쐽#O% EmehQo@ oԻٵ%(F;%1anLDKH11NfooN*R}70Z^AGiitm2k0N7pI+]Vb9a/?ě'2t&҃(pzbi? 4 J}a“ ́!`cGSn15Uk2%gA(]Bz .7 =K~&>4!cjX"xnDV- wlF 7_ԭߨ x`an\jN^/慯-"n3"Lݶ ;^eq*s/٭1|!}#++R/rwxJl{pmW&-EMGh՞!ee jDi6#|\J!ߜ4y 4Ah^+%[ vCǦqG<[C)hERj kÛw@6J\B}Tg~eH,JoygqJb(UfLq5"4!t򙅼}А҅a58;c}Uċ |S`b2ЃxGe/x!Ro~ FÖ3q 7MmFG S(;Eu g*D3vH`^oc6MFo:{Ihtk/4lLr-g^GvKSыLpԋgйlpijO΄[Moϫqs\Ƥv.*~]ud+t=HlqN{3ط`x[2JG*#1n8AG4&(!ЉIL!-,.~6QSDͤEn 6$7[icU^rN9St#)ZYEQ8!O.6lQǵRd<2oLPL4[K)b(9.Ow/2S;l}JnjFօ'RaAPDX,D-':1{j4B~cZx¢}vh~JÀRX+h閄ռ Pρ <in9*XhJ:NjF^$Ev^)^@/{İoIJ8ds ~Gh. #2S.7@&, k>^e1%VC^F0HaKM[>%.KS&`_}LPʎM4nR4ޗZZOKk1eyVӬ.$}r'd`q82X3{&!l;YG Or)gSL~$%n5b8lh\{L9;314r0`A+*p$K%C}5toŇ6W&巉q :UEU v?|pZfdi+Y83Υao(Z@!1j:څմ :Hrhof&WR{z\{wK#'8'<>?yq"Xlْn }2(&\tWk["@L3ݞm$)&"-uEi`xlCl-b7T1Yj!<r.PʲȺǨM}/}ٱlj_06);vg%23k3gW5:qv}l^j>_"E#-4R`+y^ONj? n QGMgz'^u?Lo,үt{- )٪Kw6,)K(/|k 1|O?yN#?t\XLi<~zB_k9;(A ZIE:e^-^5嚭@.g/ eB쑎NOIq#?twC1Ԅh 0WA☩ Wp&ۡBvuV[/X-j5vYH|RpjNxB9pƔpX>pJuOWS:g@ө[pΈTS"[_LN;q@GHH՞P AI0Y$O$`̄o{q?ʴLf8B@\ ` #AUt Яyk+kk.*;ێ5Jl! ~3{#ǂ,ݞ9MD/$ r?H6UcSYHZ 3Dҏ^ ןZ~w6,7k`H޳iR-0]%;t_W=<9r:CsX{ 9gzcD{g6.dq4յ2zp7p}"nkDa+!n}zIhq´p5I Oɵ(T[U*7EfNzшFwz A`zɬ!i]zQB&DsC=}OEZE:>IJW{"i_;wj) %#KU4&=91n$~o?~Mz97U7!_T$]Qrx?ZE7#M뎅! ud3]ApK˻|W쉹o Դ3~&΂1/8%ZnZ:L .ouקh,,[g׾;x09NOEIW#t:Rz&!LH zdtGw7e( +syyt/x GWT>L0DuLLF6/t25;vbg)6 F\m~-Z腕Q[K{A5!|%^Ef$FOu:i ͙0lLaƛ-QK&1',5쩙,D7~2+}oB"_3*r7<( 78{8@ph G(NY\Ju-[mі{{n5zV82k^` ucaBv^<g"<' 8#0!x[^mgav"Sܒ/N_O[%IW$ώp 6!21In&U9DDN}Rv| kt,8OBphJ3\/O۴Չ}0=MEuT)'Ppbbk3~Y@Ҝ*ě& Z'E<0ouWgh=L#=Ž=`!.EIiu 8wppTN |[buE5"||W ¾w-/\ȝWU`.LϜL?8jwޠb CЕ)O/TMTX14Ǹ.׼lv6>Tc\f-cUqog+m"X3 :董^R^Ds0زϟA9}ǛE;=-`cO_Z (kV#Vz\jhv6u)+krŃ "b_f z4PdbPGm\b%5"rg9%xp*R'/(>Ȃ6ժ-В5 f_u2 y?T(Fߞ{W8$Ӛ+Bd VKs0漪aY&Gt0<s3ICz5SSȡS/R( @sBGx3>ބZ fs8Yd~h]y6!l Qڃs HNSFo|LgogP)kuhNYE pʡwχj-{h{q".'IF|\Qwf1"{ZB@%txӭ^&: ")D5Ă@n2gڼetإ15ݽlkH*z֧"LPl1R/u:•.^i9' =ؾXb ѯE>+dYƪsnhIXgHC1 ݕzAO9"nmғ}C]1ѺADFabxɒM&ohH>D(z;h>cuϺ8(r7FcJ2OziFׂƺ$vs"<t-PBȡ19К'(pǸ.3fRŏ>j6M +sЮep̨%qɐT<.x boy~?>Lq1?c z-+m'R ny9z[ARY'(( 4*׳s)NuQ.ԯ4$҄<{2#lMQ ܑ  BYpĦN2w?__pjhCN@ȁwH>Xe#.b%< aN<`.0N[/a1a M.TE)[KC?MQ96Ogc֧V߬$ SA_n-|j/b 7E+I1]\O%2:MҬ?4/+u%쳯"nӪ8TEA ~_zAw9Em [l-ŷj\%ư5sȨhmDt mD C]aF^ի}˻%^k o<;wHyג?`/cˬ!Ӳ('[j{OY/s{x<ꩀP/0a1i<" ZYQ. ,G*"wOb1s QVO4gp 88Rcȡ(+[ܱRd/ɳP/[qhY>h.!;RZ*pk@LMOhHp*Qed0ةY`x/|]̆gV^AnCARqKKqᐏa&s^FG$39ևts~w2k/cAb9g}[ؓ3MK yə Q* jM]R0Zx /%nf&Q&L%=ErT_(j[?Ds4`I?qHy_aZ2ỮՕ'}]CMPl%mF Sn򵭞#nZ0ӛ d8_FyOR8<ϷM+x1X<%v:-n{իYɞ8o׍; EQI0`$mBu: 7m@̟s{{D?w9Qެg^[ܰ?=S{Y(KH.ei~I;SW/W&6B/twk`_=_Vo-R VdɒtTTpAqlmڅ}KD9$$(7,SDnP-՛մ;zJ}bHWTC@Egr(k([ɚ&695BL%eTIy0EϧTg9P]؈7JDRSTäjux6Ca2C` ;O'",b%&`֢{E7 -{IJBzCkO" CպeIg>ϟɽ(uOcL!SPk 鳪ץUrC+N-HT=:䵪l5Ʈd#F,!!e J%O>mHMin/P_FUM*((mP`ht:lD& i!8N: }P4 ctfT1KRnh 6\* _U7\d̮}H[ukGAS<eE!-A>٥j{較U0lzh-=!}Vz90OrFQwMU6<ٽ]VSM!gV|ӝI~ T[(K??_g벟hq2x)r7pξ'Plh݂# ~ܱ[t>) dz|K橓@s8c[ĵX\g&70$b/ i4a}[[!kEfi)U%nB~Pݍ F%;̋ uɞ3‰ Mn`eRQVDG#|q54+>'.ݞ{)# ir[W1-~Ȕrz@EŖ 6&3f|a{|8g͸Tgf(Y. Ѭ5=d3#VWAe4X=^ *ٖ,&pO2=Ddr8.J#ݻ- !&&G|W 1r2GW hHhEe?(5ǝC@9 !Ν̲xPɋSyOr3x#5ġcGyj^fdK{D 0L;|V[P2p1v|r2("b0g-0=Dt;mAߣ`@f_r(Njw^柎) pWs:Br"(L"*2 J8vpN"daJNx- D\ *X!]_VWǽdy쥰+9(i+"߿^SxS҄_hS<5(F@BD#)-o+"TGiZxUHRJlݗΟR^3T@D~hDA_oֶۭQ4H_b se8_ao MnUy0`UE6qAxlhrSf"_,LE] cZw`wʀ%"~0*΋ԟ?)!6ӥjL>Xw@s1#s'wԹre4f 76Xeh홍 ,wºPϠO}81і.ZcϢ05kߴ%꺏} db&d ˪IēN|xT WW ?|!1ZJZ X.. I&HQbiR\<H<_j~d8}-â|GkX:e.=f+c:^/81I,)*5S@/5`/i?8&vU,fAOHCP:P Hf_"Ӧyh7>YR J."J.Y 1h.8_RMͼNwXbw Yl7K4B3|S ͡ SQ]'\Q'"gq7YrّS0_qoXJ-]O)>xM9?6TVQubﳁ;]$\B~U^z_AјkՔY#%[uﳱMĐ'A+IS/ڈ"ֿ?Tt D,|Rp2cJfhm3nޡl@ŠWX,MZdݡ&5s\fP(IVBrTLY)_8^ Z" v"4J_@)ئFC4Vaz"i3hYl|T'uHD"wh,ciׄ 6nR;!CK>aK*``i$ܶiո7P/i#N0pDͶJyu _C3ض fe5(qP(-yYz۠.'sU15L )9mO?@z,.+İ z Q#AqۄBVn4ʩa+V̿2$ufI (V` LW9B\|@Vd;P$;g)D GCVaPCy-ʍ4&憺Za^%i-.dN/\4+Y>OS s]3HCL$?`~iWm,nM,s#rb\(bEFcRT1Ȕ/1uc~p;.i^Q67@[W_B _D81mۢ Dϸ{R"@m-zvUlW*8JVζIa`5)MB\‚4WT=t) hu:/ eRlY}܎感qP2FF&D>{ߋ)Y%(8W>GQ>Pl=⒁vsTUbÏM$U"E7 r\x}Bl*l2zȨi#D $;r*"))X Af z&eꅧf;#lQ}(&0Θ5{5Cn> tfpvO'l DSI v>]E;`53U Gu$geDYΗmYiG#Ch}(3qȑG}8?Һ22=Bt{HY5I\t6 nOi}Jm!ph ?^LAnȵ飾ZyZvD*l[fP A%_{j#&;sAid%[ţJia!Qҫgb65OӸgLeP[6HҵԽ( {}(ԓ&M8g4h>KW4y~`(XV8;NӉ%hb(kx7n^FM n7ci d2aZ+;OCCaR!>R {nr߼'z(iHD JH3exkl<'.bb-3%~%6e*H`Y(W0\uXe'YVi\U(:i0[W5a׵<$ *%v wzt"llKiQW8I,oEn9hV~*yzȿ{CkE3?Xv+6kVQyP*-ͫLN̄px?IK%Z^ƱIy%Q"(n%x~k!(Ee)݃ao?$:dBg^ܸ~Y2BXoF|dz:d\>ߜCwYM hC}j=pR9W%66A^|lA#ƞL͊&l9PkSu8"4%ӂhkW]A`Xڬ0I=4+dkx=<AMOH'N{*_feZCVc~YeV&= zpBF @;<憙 WS?K'2m]wV∯kjkr \[KG^TW`1 =QC]䗺x9<25S5DIAC մ=ؓZٱ-,Ծ4>K6x[_x8oLm ]dAKd'+5;c#Y}XQlԚ >p[IZ ÷kSEMߤ~DR& :E[.q֪mꝍS Iif׬Ӷ՗i-ƞ- _Sʷ NGlMI~3| =uMf͋[7򡷽(4%Uӡja2Rz*m)?seL{zSK#4>6C< }Ԯ2ũ;]vk]9A1@{Zw]fAi[($ aqH>:mq[˕ TSl~JBqd8@,rП͔7Y}^G/B>]0'3 ѬVlRTd#=ϛ3@ #̳%H}è$S-9?Ls W|/C|wFSF9ݚH2H@GƝO|TiV  5pTtRgT$VQh)MeY5?d_K~G!(d.J|-g]U3Zu,R澢||MjURw{"S:˹ yWn#'3ߚ#*?Vnhyn<)Kb3tθgѱ'|@?iI/5kE MYG"|QGuF{,nS2́E3gMF'*e7"@ LuwdnQ|s0W W2w-0`qg!'.d^euUOҧ#`h8!'(T w9F!%NdQ RhӣJvqJR}A?wYW̋8Uf\TWW3d uG{9$e% m&', `0u;E4ؙ pǤMA! ~(D7kr{!OяA+#hes/FP۬LIg95$w!MĒAfT֦#\R?  !N}؝0|O-}Nxox ul(Z6PZZ3r%_k|p0;taaS`L*u!Ħ)')WC'h脯7~_XUT''`=6 pZ|ƔwcNFkNXq|r)3^Hxs;N2{s8YG+|=W ";\2}z&)rM?2J7GɗAvG5X&M<Չ O~i M?Pyo<`]Dm>;NjD޿Q)a|}Ɵ8dz}D1GRD[ e.IluU[?:DM=Az2?!w/?46`n 4{.29A=#\wӎБ_g`}KuQ=&vI; %.ʚ]0;+jUT-^>?*0E w kP~"TP1/YoU+YjCQlj3Rkg{>R"-$v,FhL[Tf>9;%:Yˢ*忄XDd-tOD:pFE`3w&K/ fu-p(jm睧{sbhL܋?b|JBT~2(u{R %nmNn6E)P _tOPHFrWJ)7N+ 2ـ&iqHy."+w(uLڍ( 9RN0ܙ`AMWwK E[z2­ov^`'"z; V愉x̦ijE^f %\3f"k(جA v,ikS얎8>Og rY ;7d2Agie$~Jw.9܋ :AaDߖt&9OhW/6a{99f 6TXNR95!R'JV]X3rH: 4ɭz۱W0 2p8u>oA^kE_kğ 3iWJ{J?i9Q/'B?j߲ü!>~>Ǝi\n!H%/lѐbBAɎ +Gr*|f M)Upfga?sttt~zxD՛8\Nٜ%\қĨfT,gغ`uDÀT8o]kyfK'ˋ5u1Ȑls2CZSjqA&B$Q [AN=24k+`.*9"h< ΀mLo-jg·9mdʚ یd12{Rt=z2%X#(yP橀u}{Th۪'Z'u}UT @HꂃFZ&[ ?':[X|5mG2(N4\p2ʶ>* Yٳ/) $#`a!#'yuŀ0|1 $$d]l"{_e^3 (ozQV_zc(-nY32VqŵXC `GP7AC s;B3!okoO-g V ұvc:#^W&vYL~mZzxQ7PN:7쀭P%B >ɮm{2d/&2A!d+l#*'Lu_Y}5ڨٚTB&W-&v\)EF1 U:Mګ[ƂH~# Nc29$FTɵCelRKD>Jn]) ZI-l>Q3>؇Bh$ńŔd H%@›3g'$a3o%.*KʲMhʑJ<;\zC >qZ& US(L#)36pGһ|ݓ@zԇsJ8uҕ{ZJ~ u#ndDŽAhBڴn:=Ϋ~q[*" PrGoEhmMia -俫 rTW!;lrqoDž$' qV%;գh`C<| ɹ*:hT%=ArYh}v%FCޗ9y'G2'^# &0Pu89MwUaf5 ;hAL /5Q%@%"@ NR νsd]]@S@}=]lHEP"ۇBAǣm ~||B({Ek貄?*;p '޿4W+0 +g?G9\)LzȮ>:FrJa+Yըf\x[7m]`"? & hͭ&lƊzń)!!S& H"F bJQ!Aߖ%BBze0joEN0E(G ]<2炣wך;{"2p?A[ؓ(7{T` j&CB+4ؖGvb9/@"Beߩ-G&:X@_:@t^Xu;H,g[V_G4 - o-Iƛb}H,BRqeѳT&˧wXTyL<#_2 Pf:#;~?< ^)򝕂gbLvA6>icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/dmov-ffil.icns000066400000000000000000011020641506470510200234350ustar00rootroot00000000000000icns4is32 !! (Ҳ#?ʗմ7CٝЄž:?s}wt7?ݽ||}~7>ҁx}x6=t}~v5?:ogwwdr39мeŸŘg3dեfآ( '%&%' (       rqrq+z]o{}{n^z$+~_tz}zMr`~%&{\EPosqEBOF]} $scHXlkAkAWHdt!jgG\i;=;?ZHgkc\=Q9\^\9O>]d6\Y9.74Y47.:Y\VN3DRMPMRC4OVIS4GTOROTF4TH     &    ESKQNPSPNPLSEC><>A@EA><>?>?>&><>B:2-/677! /-1;4/,.111.,/5.,)+,,+)+/(%!$%&%#"%( $"""$ $!"!%" $ &&#'&'&'"'&  s8mkfff}b}util32r 260  ''  ("K *&%  "() SzѪҬvH|bԓق՗߂hk~єӂӗ΢hЍՂґщՁҁӍܓɃӄˇׁلXڅߑӐ~jnВ~ll҉wfjwϐАwhhwލq}ր ΐϐww݋juΐoo܊fr͏ll܈`m͏̏ffۆ\hʎˀbbڄWdˌ̃]]فSCɂYYƿP]ŀŀVV{μ»LYÆRRƻzûJXÀ€QQm3\ERKKZ,%3gGVȆNN`3! #5VZU&,YXYX))WZU4"" <  8[QnrppM\0 Q=Y]b__RBBZc]b__eF~X][[~ny}~~|UZ~}~}~~XX~~zcxy{xvQVxxzUxwSSwx|wbqzuw{yOT|zvwvRRz{QQ{zxs~]mwqtUJ@AKXurs9PPQWKAAKVup{YhsnpOE=>FSqnpooMpMNQE==EQqlwUbokmpoDIqolKllKKppFFpomisQ(^lgigd?CffiihIhihIIgeAAefjfoMYhdffd>eefbkITeacb_8=babDbDDa`::`ac_hEOa]_^\5:^]B^BB^]77]^_\dAK^Y[ZX16[?[[Z[[@?ZZ33ZZ\X`=F[VXWU.$=W=<00VWXU]:BXSUTR-1TS//STURZ6>UORQO,0QP..PQROV38RNPOM+/ON--OOPNS.4FKJH(,JI**IIKD4 "6NLK)-MLML++LLN4!!" !!"" b )@8^][NO\]JO_^_^_MK^[NN[^]7A#<.4GDFBCEEKIDEDEDIJEEBBFDG12/A7FHAAHHEFHFEHHAAHGID:0WDDB =>CBDCBCBBCBB==BBCBHFO>A@@A;L=>==<78=+==88=<@<G9::;;67;;:((;;66;9<8C7872-++.28'2-++.287:5?454/*)(+/42$4$$/+)(+/4462;12122-.322121"22"#23--32213.7./.))./!/!!..))../.1+3+,'',,,'',+.(.()$$))))$$)(+%*&!!&&&&&!!&%'"&######"$#!! !!"!#"""!$ #"#""#"#"#""#"$ $#$##$#$$#%"%#"##"##"##&&%&&" l8mk<1 <]J]: C8v ;@ h[$tzxwxxxxxxxxxxxxwzuit32x$/9@CDEDCB>6+1=JLMNO NNMLJE9+#8FB=C@4*6" -:=/385% ,8:-153%,67- 122% *12*.//$   -22-    0/0' k`eScaba0b`dW]տ[iT`bac^fXZ>kcW]ecdcb4cdcdW^_¸~a\Xecdcbcdce[Z`~="kbedbcbdfefefeecbc+h^Я^gdcfefefefdbcg`|<xμeifgfikտdzfjfhfjf;x۞ltnqorv¡įٶntnqntn:x֕kqmomptֽ׬lrlolrl9 Ѐ$יipknlos΀Bսװkqknkqk8xՙhpjmknqîӱjpjmjpj7xٔgmhkilqֽ٬hnhkhnh6̀!֖elgjhkoρ:Ӽծgmgjgmgρ 4xԗdlfigknүflfiflf4xבdjehfinӿؾ٪ekeheke3͂֓aicfdhlͅ7ҽʷԫcicfcić͂2xԔ`hbecgjҭbhbebhb1x׏`fadbejӾ¼¼½¼بagadaga0΀́Ր^e_b`dh΃ ҼԪ_e_b_e_̀/x}Ԓ\d^a_cfиѬ^d^a^d^.x~،\b]`^bfӾֽú٧]c]`]d]Ӿ-&zԎ[b\_]aè Ѽށ%Ͼը\c\_\b\͂ξ,xxԐX`Z][_cο±ѪZaZ]ZaZ+xx׊X_Y\Z^bҾӻúإY`Y\Y`Yӻ* ù͂֌V^X[Y]à Ѽ˃̈́!ϾէX_X[X_X́ν)xrӍT\VYW[_ͿѨV]VYV]Vɾ(xsևT[UXVZ_ѽҺĻºףU\UXU\Uѷ'p͂̄ԉRZTWUY^к̃>Ͼ¾ԥT[TWT[T͹&xmӊPXRUSW[̿ѧRYRURYSɼ%xmօPWQTRV[ҽҺżúآQXQTQXQѶ$j̀˃ԆOVPSQUZι˂ˀ,ͽ¾ӣPWPSPWPʁˀ̶#xg҈MUORPUY̽ÿѥOVOROVPȹ"xhՃMTNQOSW½ô˯ļüȢMUNQNUNг!dʂʁӄKSMPNRV ȃìҨKULPMTMˁ˴ vaІJRLOMRVƽľÿɿÿ¾¾¿ƹҪJTKPLSMŴ vbпҀJQKNLPUþþü½Ů½þþþ½٦ISJOKRKͮ_ƀЂJQKNLQUԁ҇ݢKSKOKRKǁ Ȱv[̓HPJMKPTʠJQJMJQKñv\˽ƿ~HOILJNTҚJPILIPIʪYʿŁāGNHKINRłŀŀ"͜IOHKHOIÁŀĀŪvVʽ́FMGJHMQĿɞGNGJGNHĿſſſſvVɺĿſĿĿſ|GMGJHMRƾƿƿƿƿſƿƿƿƿƿǿǿϙHNGJGNGɾƿǿȧTƽÿ}ELFIGLPāÀ˚GMFIFMG˿ÀçvPƾƿǿƿƿȺDKEHFKOʾƿƿƿǿȾǜFLEIELFο½½½½¼ƿvPǷĽ½ý¼¼¿zDJDGEJOû¼ýýýýüýĽĽýĽļļĽ̗EKDHDKEǼƽľŽžŽǤ-M{CJDGEJNÿ0ɘEKDHDKEȽÿvLǹļýļļŹ|BICFDIMǻýĽýľľĽĽľþĿÿĿĿÿÿŻřDJCGCJD˼ÿ½v=f[rxBHBECHM»»ʔCIBFBICĺϼ¼»êi__t3-HN:O}x@GADBGLǕBHAEAHBƹĮmGAY08v27LSDK=X¹ºöz?F@CAFJŸ»¹×AG@D@GAɺÙIDGK[8=t,309B?]VSu@F@CAFKȒAG@D@HA¸McIC>706t+04=??MW>qv?E?B@EJŒ@F?C?F@ĶWJZ@A>=/4t'--7:??>MHƵ´x=D>A?DHķ?F>B>E@ǷEJCHĎ?D=A=E>\=FB=:62(-v,$.47;7VRYu=C=@>CHŒ>E=A=E>ĸN_?<973+&*s )$+096OKFp8>8;9>B9?8;8?:@W<;6/)$,p"+))$((+Gm393649?ŋ4;272;4µ4,)'%**+o"/IIRE;TVWTVWTVVTVYD<9797<=SUVWTVVTWWTWVTVVTWWTVWTVWTWWTVWTVWTVWTVWTVWTVWTVWTUZK<;797;4.42!@9724*DTaYo^`WhZ-'(,L3!+((*t[]\fe\ 30146;<rCsllfaZQ]psmkpsqosnkotoOS\bhlng"bHmih^ZQZTHpssursvrtrvrtr F_LVYahjl5W/vgkWPNAVNAt`c``abc~`c`c`|}?_>ILR\lhpv@kgWOKHD0@EGLN\idu[h^OKH@7?1hr^`^__`a|^a^_^a^zT3<8CGKR`k#w p\\KI@HK/=r^`^__`a|^a^_^a^yz.:O>CGPZc X gYRAF6QU$uo]_]]^_ax]`]`]|Y.d8>ADU^w iOZL=>/&ep\^]_\^_y]_\_\_]xN"6=>=>>@BA!D@[vpvrrurrurrurrurrurqusqvqtjMY[Z[\YaTAC@BAA@>>=>=>>?BACAPupusqusqutrtwt>surotsotsotsrl@9<::;:;2:;:<;8SwrpstostostpstpstpstpsunuiLY[Z[[ZZ\Y_K7=;:;:;:;:<;8Hrtprupqtpruouw=trqrq rqpskA:f=8:9:9 :9;7dB6Wtorq rqqrqqrrqrqotgMYZZYYZ [X^N2aI4<8:9:8<3]N2Mqqrqqrqqrqur<~upproproorpotiA:<9;:;;:;#:<:9VsnsoosoorporporporposnrgLYZZX`YZ[X_L8=:;:;;:<:9Kqnrqnrqorqoqtp;~orpmqqmqqmrpokA<<=<=>=>==<.=;>;StonpqmpqmqqmpqnpqmprlrfKYX\Tn{P\XZ[W_K:=<=<==>=>=<<=<>?>@AY_\_``ajononnonnonoono'nnpmreKXX[UifQ[XYZW`s`a^_\`S?@>?>@?R`\^`honoonpnnoonnroz9wyqmmplmommolmoloroosmsXEFCDCFHjsoprooqmmplmpmlomlpmlpmlpkoeKWWZTjpcQYXXYW_}ppnrorbEFCECFE`tooqpoqnlonlonlonloqlz8xzkpnknnkonknnknmimmjkpSCCABADFgkmnimmjnojnoknnknoknnkmoipdJWWZSjmqbPZWXYV_|immkkq]CDACADC_njojlnkmokmokmpklojoow8}xmml*mllmllmlmmllnkpUCCABADFgolmmlmmllmllmllmllml'mjpbJWWZSinkobPYWXYV^{knlnlp^CDACADC^pkmllmmlmlokv6wyvnkjmjkmjjnjjmjjmjjninTAC@A@CEeoijmjjmjjmjjmkjmjjmjinilcJVWYSijmkkcOYWWXV^xklinjm^BC@B@CB\pjjmkjmlimkimkjmlilniu5xyvhmkhlkilkilkhkkhlkijnQAA?@?BDfjklhllhlkhklhkliklhkmgnbHVVXShlkiio_OYVWXU]zgkliio[AB?A?BA]limijmijmijlhjmijmhlkq4vsjjijijijiijjijiikhmR@@>?>ACdkijijiijiijjijiijjhl_IUVYRhkj#l`OXUVWT]yhjijhm\@A>@>A@[mhjjiijjijji jiilhq3xsqjhhjhhjghjghjghjhgkglR?@=>=ABblghkhgkhgjhgjhgjggkfiaHTVWOggihejfh`NWUVWT]vhifkgj[?@=?=@?Ymhgjigjigjigjigjigjkep2xrrejheihfiieiieiifihfhkN>><=<@Acghiehifiiehiehiehjdk_GTUUTklkiilhjn^MWTUVS\xdhiffmX>?<><@>Ziejfgjfgifgjfgjfgjejhl1ppfgfggffggfgejO==;<;?@ahffgfg;=;>=Xjehggffggfggfggffidm0xmnfeegdehddgdeheeheeichN<=:;:>?_idegeeheehedhedhcg^GSUSTUSLOONONNONNPTTUTUS[uegdhdgX<=:<:=`eefcffcffcffcegbh\FSTUVUXWVWVT-UR[vbffdcjU<<9;9<;Wgcgcdgcegddfcdgcegcfci.jkcededeeddedeeddecgL::898<=^fceed ecf[FSTUQQRQQRQRQRTUR[tcfdecgV;<8:8<;Vhcedededf`i.hjcqebcebcfbcecceccfafL9:797;<]gbcecbeccecbfbe\ESSUOdvorpqqppqqprpsgOTSSTQZscdafbeU:;797;:Thbbedbedbedaedbedbef_h-xfi^dc`dcadcacc`ccaddabgI98676:<]bcd`cdadd`cd_eZDRRUNeiheghegheghefj[KURSTQZt_cdaagS9:686:9Ueaeabdabdabeabdabdadae+cg_cabbabbababbabab`dI88676:;\cabbab `dYERRUNdb^a`_bXKURSTQZr`cab`eT9:686:9Se`bababbabbabbabac^d*ae`qc_`c``c``c``c`_c^dJ785759:Zd_`b`_b`_c_bYDQQTNd`bb`ca`ca`ca`d`bYKTQRSPYq`b_c_cS8957598Qe``ba_ba_ba_ba_ba_bc[c*x`e[b`^a`^aa^aa^aa^a`__dG764548:[``a^aa^`a]cXCQQTLca`^_a^`a^`a^`a^_bVJSQQROXr\`a__dP7846487Rb^b_`a^_b^`b^_a^_a^`]`(]d[`^_^_^`^bG6535379Ya^_ ]aVCQPSLc`^_^_^aVISPQROXp]`^`^bQ6735376Pb]`_`Z_'v[a\]]`]]`]]_]]`]]`]]`[aF4524267Wa]]_]\`\_VBPPSLc]_^\`]\`^]`^]`^]`]_VISPQROXo]_\`]`P5624265Nc]]_^\_^\_^\`^\_^\__W^&vZaW_][^][^^[_^[^^[^^\]aD4313157X]]^[]^Z`VBPORKb_^\\^[^^[]^[^^\^^\\`SHRPPQNWpZ^^\\bM4513154O^\_[\^\]^\]_\]_[]^[]Y[&W_X]\ ][_D3202046W^[\ [^SBOORKa\[][\[^THQOOQNWnZ][\[_M3402043M`[]\]V[%vU]Y[Z]Z[]Z[]ZZ]ZZ]ZZ^Y^D22/1/35U_Z[^Y\UANNRJb~[]\Y^ZZ^[Z][Z][Z][Z^Z\UHPNOPMVm[\Y^Z]M23/1/32K`ZZ][Z]\Z]\Z]\Y][Y]\TZ#vT]T][Y\[Y\\Y\[Y[[Y[[ZZ_B10.0.24V[[]X^S@NORJa~\\Z[\Y[\Y[[X[\Y[\Z\\Z[^RGQNOPMVnX\\ZY`K12.0.21M]Y]Y[\ZZ\ZZ\YZ\Y[\Y[VW#Q[U[ZY[X]A00-/-13S[YY\QANOPI`~ZYZYZYZYZY[RHPNOPMVkWZXZX]K01-/-10K]X[ZTV"vOZUYXZXXZXXZXXZXX[XX[W\A//,.,02S]X[QANOOMc}[[ZY[XXZXW[XX[YWZYX[ZY\Y[RGQNNPMVmY[Y\Y\J00,.,00I]XXZYXZYXZYWZYWZYWZZQU!vMYRZXWYYWYYWYYVYYWYYWX\?/.,.,01EIHIAMOMOMZJGIHJVYXWYYVYYWXYVYXIHIHHJDHOMNNMPQGIHIFSK/0,.,0/JZVZWXYWXZWXYWXYWXYWXSRKXRXWXV[?.-+-+/1GLKKNNMNGKKJKLgXVWXWXTBKNMJKKJMF^V+0*-+/.I[VXWXWQR'HVRWUXVVXUVXUVXUVXVUYTY?..+-+/1JPNOMMNMONOjWUXVUXVUXVUXWSFNM(ONOMQIaW+0*-+//G[UVXWUXWUXWUXWUXWUXWOQ#GVNWVTVVTVWTVVTVVUWVUUY=.-+-+/0IOMNMNMPkWWTVWUVVTVWTWTDN%MQHdW*0*-+/.HXTXTVWTUWTUWUUWUVWUVPNEUOVUVTX=-,*,*.1`kghihihhigkiTVU#TUTXhhihhihhihhihhihgjfqO,/),*..GXTVUNNvBSOTSVSSVSTVSTVSTVSSWRV>-,*,*.0OYUUWUUWUUWUUWUTTSSVTSVSSVTSVTSWUUWUTWUUWVUWVTWVTWTVF..*,*..EYSSUTRVTSVTRUTSUTSUUMNvARLVTRUTRUTRTTRUTRTTSSW<.,*,*.0NTTURTTRTTRTTRTTSTURTTSTURTURTURTTRTTRTTRTTRTURSTRRXE..*,*..GVRVRSURSURSUSSUSTUSSNK>QLTRS TRV<-+)+)-/NTSTSRSTSSTSTRVD--)+)--EVRTRSTSLIvG -;NML MMKO7*(&(&+,GMLMLLMLMLMLMLMLKO?**&(&**?OKMLLML NK6(+U!! t!OKKLKKMKJLLKLNA#('-R#! u( FM)LKJKKJKLJLKJJN6*(&(&+,FKKLJKLJLKJKLJLLJKKJKKJKLJKKJKLJKLJKLJKLJKLJKLJKKJJO>**&(&**?MJMJKLJJLJKKLB0Y-&#  $% ?J"6KIKJJKKJKJJIM6)'%'%*+EKJKJKJJKKJKJKJKJJKKJKIN>))%'%))>MIKJKKJJKI,.S+$$% t!%! -,BMHJKIJKIILHL6)'%'%*+DMIIKIIKIIKIIKIHKIIKJIKJIKJIKIIKIIKIIKJIKIIKJIKIHKHK>))%'%))=NIIKJHKJHKIK<,)$#! v !%)" 7IHIGIIGIIHHL4)&$&$)*CHHIGIIGIIGIIGIIGIIGHIHIIGHIGHIGIIGHIGHIGHIGHIGHIHGL;)($&$((=?>=>?==A,"  "#9?>?=>>=?>=>?=??=>?=>?>>?=>?=>?=>?=>?=>?=>?=>>=>?>=A3"! !"4@=?=>?=>?=?887?1$ #$$#$$#$$"&!U $$##$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$%"%" ! #%#$#$#$$##$#$$ 8;93   85:&970   !"##$##"!    $!%'#!$  $!$'$!$ 2)'#&8x:D?IRAD:TN  ? %i D?AESDA?D ~&"#$&+2r4XLMGD;3>jonlnnknnlokRRQPOPRP_omnlnmnaWVWWVWanmolnolnnlnolnomnnlnoZWXUVYUfplnommoWPRPOPRPXmmomnolmokpd54?DILPN9LJIA@6FG,QPPRPPQPPRPRVRVSRRSUQQPQPPQTXYYXYXUQQPQPPQPPQQPQPPQPPQPPWYXYXWYSORQPQPQVSRRSRRSUQQPQQPQQPPSF1Q6;?DIKM,W*YIL=77(LP$RLNONNONNONNHFFEEFGFKONNONNOLJKJJKKLONNONNONNONNONNONNONNLKJLJJKMNOONONNJFFE FFIOONONNONQD.a.059@MIW1LI<6320%/JJKHJJHJKHJKGE5FJHJJHJKHKLJLLJLKHJKHJKHKJHJKIKKIJKIJKJKLJKLJJKHJKIJKHEIKIJKIJKHJJ%*0147@JFJHB641(") 9NHKKIJKIJJIJGD7EEIJJIJIIJIIJIIJIIKJIKJIJIIJJIJJIJJIKJIJIIJIIJJIKJIKJJHEDEGKIJIJJIKHL0#& -139CLa=C42)9>%HJHIJIIJIIJIIFD EHJHIJHHJIHJIHI$JIIJIIJIHJIIJIHJIHJIHJIHJIHJIHJIHJIIHDGJIHJIHJIHJHJB'E+-18?Ew W;7(1 HTAJFIIGIIGIIGIIEDCBBCCDHGIIGIIGIIGIIGIIGIIGIIGHIGIIGIIGIIGIIGHJGHIGHJGHIGHJFDCCBCCDGGHJGHJGHJGIHK0"d*(,+:Bw Z1G?&(7JFIGGHGGHGGHGHECBCEACCFHGGHGHHGGHGGHGGHGGHGGHGGHGGHGGHGGHGGHHGHGGIHGHGGHGGFCBBEBBCEHGGHGGHHGHHGGJ+#&,I6=w V)UO""8BABEHFFHFFHFFGFFGFFGFFGFFGGFHGFHGFHFFHGFGFFGGFGGFGGFHGFEBBA7ABBDHGFHGFHGFGGFHFH6!+a48w Y/,",4DHDHFDGGEGGEGGEGGCAB=5CABEEGGDGGDGGEGGDGGDFGEGGEFGEGGDFGDFGEFGEFGEFGEFGEFGEFHCBB@4@BAEEFGEFGEFGEFHDFGG@3'".7PQJEFIFDFEEFEEFEEFEEFEECA@AC?AADFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEDA@@D@@ACFEEFFDFEEFEEFE GHEK@fPwWJECDDEEDDEDDFDDEDDEDEB@?>=?@@CEDDFDDEDDEDDEDDEDDEDDEEDEEDEDDEEDEDDEEDEEDEEDEEDFDDC@@?=?@@BFDDEEDEEDEDDEEDFDCBJClSwUGEDDEDCDDCEDCEDCDECDD@?>?A=??CCDECDECDDCDDCDECDDCDDCDDCDECDECDECDECDDCDDCDECDECDEB?>>B>>?CDCECCECCECDECDECDEAJBgQUHDCDCDCCDCCDCCA>?;6?>?BCDCDCCDCDC DCCDCCDCCDC DCCB??>5>??AC DCCBI@hQBRGCBCBBCBBCBBCBBCBBCBC@=>93>=>ACBBCBBCBBCBBCBBCBBCBBCBBCBBCBBCBBCB/CCBCBBCBBCBBA>>=2=>>@CBBCBBCCBBCBCBBCBBAH?fOwREDBACBABBABBACBABBABC>=<=?;==AABCABBABBABBABCABBABBABBABCABCABCABBABCABCABCABBABC?==<@<==@ABCAACABCAACAACABC?H@dNPEBABABAABAABAABAA><;::;<<@ABABAABAABA B?<<;9;<<;;=:<A@@AA@A@@A@@AA@A@@?F@@?@@<;;84;:;??@@>@@>@@?@@?@@?@@?@@>@@?@@?@@?@@?@A?@@?@A>?A??@??A=;;:3:;;>??A??@??@??@??@??A=E=`KMB@>?>?>?>>?>>?<::71:9;>?>??>>??>?>?>>?>?>?>@==? =::909::=?>>?>?=D;`J/LA>>?=>?=>?>=?==?=>?=>;989;799=?==?==>==?>>?>=>?==?==?>=?>>?>=>?>=?=@6!A?>=?>><998;899;?>=>=?>=?>==C9^IwK??=<>><>><>><>><==<>>:9877899=<=><=><=><>><=><>><=><=><>><=>=>><=><=?;>8$M;>>==>;9987899<==><=><=><=><=><=>:B:\H(I?=<=<<=<<=<<=<<=<<=<=:8778788;==<=<==<=<=<=<<=<<=<<==<==<=;>5)K<=<=<<:8878788:=<<==<=<<=< =<=<<;A8[GH?<;=;;<;;<;;=;;<;;<;<976877:<;;<<;=;;=;;=;;=;;<;;<;;<<;<<;<;;<<;=;=5 'K;<;<;<:776779=<;<<;<<;<<;<;;=<;;A6ZFG<=;:<;:;;:<;:<;:;<:<<775867::;;:;<:<;:;<:<<:;<:;<:;<:;<:;<:;<:;<9=5!(J9<<:;<8765669;:<:;<:;<:;<:;<;;<9?7XEF<;:;: ;::;::;:;875669;::;:;::;:;::;:;9<3! 'J9;:;::9665678;::;:9?5WDE;:9:99:99:99:99:99:997548558:89:99:99:99:99:99:99:99:99:99:99;8:4 "&I8:8:998554567:98:99:99::9::9::98>4VCD::989989989989:9::6645699::9::89989989989989:989:89:89:7;2 &I8::99;7554558::;9::89:89:89:99:6=5TB C:989889889866544510/00354469889889889889889889889897:2! !'I575445200/00254469989989989987=3TAB98787788787786,+)*)*.)+*1978778778778788788778879692!!%3**)*)*)*)*+.878878878877<2R@ A787677677675+'+('('('('+('/8767767767677677678580! ! #.&*)'('(' ('('*)'-67677675;2P?~@7764*'h4#(&'&($f8#16570 "2^F*%'%+ZK0464:0O>|>66565565565563+'/)'.&/)'065655655655655655655647/ $ #/&.+&'(&-,&.5 6554:/O=z>46445545545443*)'),')*.5545545545545545545636/#4F #.)(()'(*,45455455455380L<x<443434100/.,+*++-/./0343435. /[0 %B.1//..-++* +,,/..00/24343438.K;v;342343234234334341/.-.-//243<433423432433432433424- 0X6*  %F2434332/.-.-.0144344343243 227-J9 t;13223323329122122122//-,-,..122323313313322322322322314-!/Y43,$D032 30.-,-,-.0212322322322322306-I9r91211211212..,..1212%112121213, /X404)$D031212/.-,-.032212112122112205+H8o8110100101.-+ *--/200100101101100110102+ /X21*$C/20101/-,+,-.20101101101 004*F6m8/1010 /00/11001,,*,,/0101001001011.2+ .W2/1.3)$B.101.,+*+,.0010010010010 1.3*D5k6/0/0/00/0/00/0-,* ),,.0//0//0+/00//00/00/1* /W1/1/02)#B.0/0/0-,+*+,-0/0/00/0.3)D4i5././/./.././/./././,+)9(++-/../../..//./..//.0./*-U0-/,/-/'$A-0././-+*)*+,0..//.//.//.//.//..2(C3g5-/./**(**-././-0)2X2/1/1002)#A,/./,*)()*,/.-1(A2 e3,.-.-..-.-.--*)'&)),.-.-".--..-/(4#" ! ! "#A,.-.+)('()+.-..- ..,1&?1 b2,-,-,,-,,-,-,--,-,-*)' &))+-,,-,,-+,,--,-,.(#A+.,-,-+)('()*-,,--,--,--,--,--,,/&>0a1*-+,+,,+,((&((+, -+-&"?*-,-)('&'(*,+/&=/_0),+((%$''*+ ,*,&"?),+,)'&%&'),+*.%<.]0)+*+*+*''$#&&)+*,+**+),%+B9::;:;;:;;::>."?)+*+*+('%$ %'(+**+**+**+*+*-$;-[.'*))**)*))**)*))**)**&'$#&&())*)**)**))*(+%-S2/ .1&!>'*)*'&%$%&(*)*)**)**))*))**)*(,#9,X-'*)()()%&#"%%()() (*$-S+%('("!='*()(*'&$#$%&)()()(,"8+W,')()()()(%%"!$$'()')#,S*'*()(+#!>&)')()&%#"#%&)('+!7*U+%)('( '(('(('(('()$$! ##'($'(('((')#,S)'('(''(''('(('')!!<%)( )%$" ! "$%('( '((&*!5)R+%('#$! ##&' &(",R(&(&' &(!!<%('($$"!"$$('&) 4(P)$'%&## ""%&'%'",R'&'%& %' !<$'&'$#! !##'&%)3'N(#&%&!"!!$%&$&!+Q'$&$&%%&% & !;#&% &""  "#&%&%&%&$'1&L'"%$%$$%$%$%$%!! !#%$%$%$& +Q&$%$%$%$%$%$%$& ;"&$%"!!"%$%$$%%$%$%$#'1%J&"$#$##$#$#$$#$#$!! "$##$#% *P%#%#$##$#$$#$#% :!$#$#$!!!!$$#$#$$#$$#$$##&0$H% $# "##$"$*P$#$"#$##%:!$# $  !$#"%.#F% #"#""#"#""!"#*O#!#!#"#"#"#"!#8 #!""#  #"#"#"!$-"C$"!"!"!"!!"!"!$#$,N%"$""!"!"!!""# "$ ; $#"!!""!"!!"!"!$,!B#"!"!"!""!"!" ' "!""!!"!"!"!#+ @#"!"! 4#!"!!"! (/"!"!"!#*=#"!""!" 7$!"!"" -0"!"!"!"!#)<$#"#=$"#"!/2#"$);#"# 5:899899889:7<:!#"#!&98:98988998998:7A*#"#"!#)8##"#"%$!"$ ##"#(6"#"#"# "!"!"#" !##"#"#"#'4"#"#""#"#!#""#"#""#""#"#"# ""#"##""#""#" #"##"#"#&2"#"# #" ##"#&0###"#"##"##"#$!#"#"##"#"##"# "$#"# "##"#%.# $#$!$# $$#$$," #$##$#$!$# $$#$$*"%#$!$# $$#$#(""#$!$# $$#"!"("#'#$#$!$#"# $$# $##$)#  !#"##$#$!$#$#$# $$#$#$# "#"  8D '$%"%$ #%%#$ %'S 6C$%$%"%$ #%%$ % P  ;G'#$%"%$ #%%#$ %! U   8F#$%"%$ #%%#$  R  !%$%$$%#%"%$ %%#$ %   $ #$$#$$#$%"$#$$#$$#$$#$$#$$#$$#$#$#$##%$#$#$#%  8E($% $&#&%&% $&  &$%&$&""Q :E$!"!!"!##!"!"!!""!"!!""!""!""!""!""!"!"!"!"#!!" !!#Q  2    !                !!        207(042-  96; &;81t8mk@ r` _3Cy w}~~~~~~~~~~~~~~~~|u& _-  d& _ & _  . e W}& _;||:Y}c) ;G[z( w|GX0_.i1[ _  `  ^ ` N*)((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((',&b- ` \ `  ^ ^ D7 c{S^c`aaaaab_eXg`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`d[|y\c`aaaaa`b_kР6Y_e!8ebG      ic08? jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 R|X8џJ\oot3QoᢥY/aʻ7J\7qb0R&:\~ܸ=ץ@5h@xi`f3edL|O˻=?k'ҙ0?,t2MIXr}},H[CB*t|\󟥬*UVB͝>9Čv ʳ40\IinC?0e/$z#ԃNXDV %q ,8wqUD:{N&l5̵;V̧O1yMz5]+@y8;xxD@eRm{Z.-sC-c6|£ f\ӜH&Av}T($ă5k1+,o'}gsXlf}x=o}xfT؁YU>ǑM9#x,Rctb ]3mSKQ>T5"|TԺ C(_\緩ariqm!LXzh{.u۪փ[$Ϥ1H( %)vJ1CB?{DUݔJ=SQ@K'=ɚ]HC [ՀN0!SX8Uf"As.MGlL1 ņ(e,_^ox-$#eeupһ}8ij5s)!:4]'KYUg#fqPYoc'B'!bpo,G#`c7HJgb+ YPe?R.G,6$3PYc?-!!ёqO Nd?H~ #bUנ0"(^S"7#Df厣 WT-L#%kV9vkN,Ԃ큷r{T4K:-?\L)m,efL K7eX 8Hg6o n.7zZ%]B3ʺa}!ؑB:7&I7=0i4qHݝ2}Ҭ/ả_*1Ts':=NT4`>L옅Z_ZS0׀Zf]# lɉw8}۲eqJoH3j彭|WHtJ& :A%#H AVŸX+L )J6iɤΔg$EoSӧ0a&PDV2j5d/92ۨ+_^H Xh:/no'y$}=8)=%R hqYTy#|;Vc^ѭEUfm"6sAɊG& pib 8jnk6A]'巼FNӍͬl)O3m+t>FN}POB#KOwo~j?Ȑ{qʭd^c5Le;|Pz+. G5v-%L8SrXa]#du[`I-q8*l̛#OnصX.&J+l؈-8GRDVcG\#al>B2ٶ1}Y 6:g; mRU}oIS 7jBgV  xHZ1C\tMU=5ȣ9.d1*n.q=L띲>6|r4 65.#N?.@t}!,m@rVB f9Y(K:B 5mKh'{RL/L(6R@x/ĔY 6Vm ] 3V?6\ 4?mB}8,8O9ع̇05ȝCŇ%aopvBYU& :In̷%ɹ[V\d/)3;(>M};=A0<&[qNq]yvV7"1!h~aC"Rxsܑ'ܘV !Uww{~L<ڝzKma0pjLVm( ?P@C:9^z%d[WNrԕ6 r7jI;N8 sBOyAvy'@΋qgMT~;Zj%! DqdC.TrjJܞ`(/'""JXjْY2GڼO ?+⒢aIqq3֩:gCn@֑ rGzٙ{CK$~jMF'""ӣ~rhΊӹdnډ?wg+/Eiw~i ;vf+dC7g܋X mpvFyꭶZnM&ABPJX4La.+g[">m科?XZςoB{QhxC+Tel KhZ'b=?%g>D+`xI 6zoVD#@x@i>Tƻf6 dGMK/;&Y۔`lcp*4{] Xߏ[)홙̄xؾ |hqlxsqʾ<4]Т@hFIIrk7@-x\W2$dл9XOmК;Eav\ה4,ݯs w=ZsWnaؑMN˶w A@(Am*iI>L}A@nFf 3g.vb)td[bLGDt/C%2xr Ӯ"2@Dd:JC=GG N sײT:sywV7[\7&Ζ.xQ nG3,Tl4|1LGH, _q.0Ԣ7L;t$ 7 KA@@Zkre8.e5/`: #KOR1m=pEGb4h ksgl]O@v̀PaǗ3<#jk{UWc!DdU%yQ`bIO\z#@,8v!uKͪvbBItvܖăY(t. ;<@j)4w")ds# xԗjf$sWy  haCC=E?&:bi.㯟crj  A|7z`^s弇#|h)-cĦ;>Rݗ, bfLrnlb'`G&<Ɋ{i ,Fo=^G)#E9:Bk  }}-O 5i7۳vGrL;jkE'^e D6y8Bj^U(A6݉5qHNMJ\亥|/WH6r]IC*GY9dB g!GSh7$L}phFFJ\ޯV̹a6 Aw!Fzi(iq39s8jS℉oͭ5 Q!n2SZ3|13(BmF(Ơ4l37@fG5%f9F?=Fޫe#HY88j~{l)%IømhbGbC𥀘EAO"@H$iX g1a괌˴}mr ed@([ukf'I79Q-6A1bnD ^8;6G#My}>]ܢZP ۈO1W>wSpdDR|;V r{7 |0%'[ޥa˒Wfm;(|dO!Dv@&kҮC8oײ'˞-tO srT'e_<-J1^{t3wɡ! Hp!|94k> Ox dǿHꦿ xԘπ\UoH>{toW;"q}*UGA{_Wd==j%,j7%H׋ ?<^AU 咑+nHKl`ߢU~]CxAȍX.2S3Qx_"3|Y{{T fHa7,p<]\n5Iݽ 'YODk흽j6ͳM[e[㘹 K 6-|{c\;^FC4W U _uz8b)ål`Y#\TmRn=D٤< 1c")>-Cn"-(s@{\~oQ<<+'g\lb(x>*&OO h)cj%yUOyHZ# <'Z<.SPRpr.3 TI/[wQG[O :^) ^=8I{'៦vqr<$`w|Ł1QgzBnDzJ WX뎟y^)'5h 7]=QfnNfۼ0lFodE}" . a.%^:l-A-E N@ JA|qLU\ ?Fd*NHj4M'sZ#DBI9w$ c~/9UVfK^e!GTVAƴRΫQb!ۂ#]5iK1Sb$3"Q: / 1'3Z5G4O-<٥+:m&O<] g*ҘR9PsS&10Dsic A{NX/wYt%V5׷TOh RR%:.#qȽDfl &Xe I:>@w*D[דKHbY_%YPവndP<"wqd[6{[ jM!?-B[s/#p ҖBqYǑw='ȏʳkl W6r&&Nt9 47>4:u@M@șSxac(<ꑚN\:F$f0Dl>] mPtb<km&T2R*kE=\aFc )lS\ʢꚜTm-$=c?P [W(š?CVa7E;. ڍCjh?qLS2 {mWnj_9$bPaϩ[xDsDx@ZH7{Tb㾤>-(C|$Aş'I(8e$$ҷ 7(L:Jz ?(9B(/_泐&kHIu .y;+h>i ]wQֿIDŖ-WҪ`d v}\Y'Ƀ+nCT,'FcP>Tj40qPaHq%qj\ oM)1םRKmA2uԯ-0ޒ 8Q 3su?F''l#OVLA *_:I~UvIӕ)O]4 WVG>IiiOٳ"#]Қ$bAxm8M~I$Jqbk/df % f6paH(vp~*Ȑ"S*eeM/Y`p8!C#d4 ʕx{˅bPj\hA>|r9ߕ-h,v̒ҡ+IOxEK WqZ1pc\_tEe v Z"V]devR'GMLk?:Nf~+i3=wȑ'C¿_XT9d(`4B(/ftYR(vV~>|cѼ|)%2A/pc-lDjH#̻2@˘{چ~/9c ҵv_h1 [̰6H>sތ$laKAN=tV_y@9l179 Mqg*D[I@hm`H+}Q Ma!7j-۵MA*Y%,H.TT/܍! %wc^Ε&FY@~Y^(k|fQ/5O+1@"uӕ 1%&w:%3WCVߦF ilXSz?SOGyt;)Ԭe߶w*F/dGE9W(в(+'BvW|YCɞǒ?" E2NmҐ̿6[V,W>ҫ NrzOﰟԔFټEn<«xv :dщca(})Bbc( ř7EIH:f^Me75)ezt+JRى2H9m}oD9oe~ 80t^(퇡QXDCp>k@1 .N8 (p'a vrT=z+z@^H÷ .`rsqaNyh!IKYФ 9> SU ?jQXCX5[1:}n gJp"w|y? goQަ P@IB͍d-WJns3!z$bۨ`Idݓk|A`lNh\NCb[b? NŤ(L:_UPJD"Ôfv*|l }.G5hFmrL M#71o %܊RՌ$!y(~ -W7F(ܽE(.i@ Վw+`ٿ]ClnT/9jl^Ïgy3$ tR8Y_ Fl ;cSs*S#~m-Jׯjt &sp(L^ic+&:׌=3 :0K;ޛGWrt*[ :Kw7"8:Z\~M_ k?xrظO"XCTsЯ'OޣiRt=ϗ|`;y.$B5W@q AC6[d={˷E?^>0@XYQk͡`^^OB}RRcMV8@ș9?6밅mZ>Oݽxdp={܌&D@6=Ic:>NŒ$ZAYA)-K)~`/}ɳ9xkK~^ eO Rsʔ||g _l|T{#nnͮl1X Zq{޹ C6.2v?|i5cqfQg2%K Ж\T.$Hk /=^|]7Dm?pYXC@vVzdɧCCDAIOA) HGqÙ,e h0 ?$6 A\ė`@)-3=yICV}+TBLSl)bi*#WOdEBpG`/&O1bh ,7_bMr;͌gU לs}f(8r@w;L笌BCf[UɤW rJ5s8@Jh;_vS*yF!X/ hz?AqQL-?)^FѾ5MF(`4a %ٖbWfo].zt]bQ~&"[4yqcQظiF^3rDx2(gBz_R67g7L2=p0'R8gVbN-$9f'))+VK\B2NN*ë#+z~TQ ӻw]5E`ȪBPP+їq.JlK {u#UdT,<Xcn'٭xmId|-Lj䰌? S$Z%V e0]0?{%{L(͙1A2G˵ |<ywd[E_!vPQS43d /BiWɘNz$1C"m/RsL>BIN#PS0HG?եEhf$6z%BVfnPM)V qvm*)Mi9S# ާ~~/jSu'*rϼ.j:K9 6 ByQW?QCaƈs5V^Nf)PG|0!PS,}EuiOIHI~(sOq~g-.+ )ae}E`'O• q.#,}YIe*\~}[ 4}S1 jsnQ_*}!x[_IbႪ_$*VahzWj:8c!o}2V@µ*S:׹$x[YIΞ>*Na 7ubs3JPΗ@n1p:ۋG7siN#wYL8x8'lU?"R6¹|{If/"崢HnvXFl"1P򄂽8t5N/eʛI:/Wm2TzXSQxĩI8he bѿ BIv/i>4D.LK#xKQ2gAK#t  |.M#O𮻓vzCud*dy4 &Bi þ6Gx 1*2u^0KQVGiЬZ1Ѣ_c"7)>:aVeݞռj\'MG?xNEu;p͐;f PFvHo-"rFsCcO{(YtUfywZ=lXZncXc7@! u +kZVMKB|,hWdmFI&6)P*R?w6ѷO]1\eek͵,M}N;̤ rzJ5 %>Q16$WFLec(=}=J AluNkfP7կ8v+&~= p۞bQNA{w}vAH rS$[3D 'w&e %m_hz"/="B/I1)1V5LD HG'VƥZ (^"8cbH>}RPL-"l-YcQnNM0"*YY,8x.ѻ$;sv1j/%Q.'cVoGݶ_HP]mkѲr_7ۋZ$0'/nA/P_B(dO3 CIs̳HF=LMB)uD BnvL0_!Q:EQRHxq^> * L.3s֚UЂmNܾ>"OH1m`Gz_Ʊay$ 7)QECbdZ@u]W-LNu$TG:zhwp\2f3I䂦w5H"G(:05q#UzM0Elmc8FZM[ ad[|d6 [!qQNVӅFgza۠%G~ZQ4뉳&zDht_ m1 oߊ҇ Y&Ӝjq%!Ej50 K]c0^'KBE/f,aς2ZFqe?Hi[OrsD_LH@ޚw4b1sM\37lae6FӚ5JBf-Ԝ. H^^%o TOp6>tv&^>yf+>ּ/a.K2Ȟ󯘻=P'ȿ(f]w6&b yZA8n JD//-Z˟8# 嵸&hs?' }،܀g\"{GRBi/\yM|^QАn*94xgjKU3 gnzDg*> ׍]^\lM ŚQJӱ:4ؾFӓJH=ah|46~ s2΢Zqƹx0cAf=TU[2b,?BtNv-nuP`չrhx+/LU8Z-Ǿ i-!J+ocSa!8H-j8ƚG!Z\lUTjh\2<&2"ΩZ6u0)R sK0^йL,nЖTƘYfn9%H8/Ϋ|V^a})V0T="#{nCn_CT:Ɠo@?G|ښR^HAr%ƒU(Y K:``*Z>߬Aj"gkFi[;%DK^p8Sx%?~ ڨ`` S0\fP~ >\#3H#IL8ҥ#p `iid !-#Ix襴-bAUDd/sх_ %ΠTAWgg#d&%ŤnlA@AJ9d=;PTP t5f$ļl %Ӏ0:"N[9Ūgk4}9Ka" }ҍx\⢖oCzP@FT-.GL)[#(~1@%whUjK栜uIpixMLjc A!9] 'q:X72k5:!;NiB{) > $Lf8,N>nT}dq+a(Oz붳PnxU|@/ xiܾ h1 `u53ҌVb珠+`t`KE~uVk=[PAuMԑɞXi켠ӣpRg㾏ʕcn,Nō]buGW?i6@9H ӧHc nbIv**A b^ ~e0rj?QPni#|"+)5BdܽjT ssZ`"e:=ZF}IIV A -uMFTpߒ` p!x gŋcBvZK;|r kCХNBZY4by(̜Xb#r_ȑp!c5S՝K:ju?f)\ǻ&2=_ oƒudU05Q!f3!1O7/JbRX2y(cqj#,8.|Cbȼ}ZC~,a"nSzuQA~Qk-!k CQCd^ɂBqt%Z>Z(Ҳ\P5&Xw B%hSvrCV"NKgNgT[e9cߤgg%3_B9x Ӆ/Z }_-wn`r_KW8:~AԈ0/x Z8Hj&>" џaU>K'Gc WZ:'< «,Sdf%:9 iEnd]ke0{- &~:AճQhe3槼f7 45MGSA󒥇G|ͶuPRp|W!l S7ae; ҨĝBr-*gbBwXY{eGYI&D&ߠ``ǁ!*MS2Hd@{Ma ч@iWU܅z *+؀zNKHKu%ٮlz h-ge.o:*7 kJeH6^W:5`y!\3 $V׋x3R0 fEu6IUIh J0Ĥy\wXHEODYc?um91^$~[KQ(2n9~/RW 7).Ew~KXKO)a&k]a=c b=5\b Uy}Lzcz6}SAyeLjnhe`pFmw'39H7`*h2S*y^.|/dc@c|s {upDHBd?J-8L eĶ.u/WИQmRi$PZ$L c9/as.%m$6LuT d1f>dzfMut wp\N݂$s!sy/n3% L|H'n"g!5=mv,l:߽>Yb$˅=$[J('<ܺUc҇&a3[@- z$aceT1KE(#H%kPٖ Uk>Q}{~nyǘu*3Jt qV5{`‚Vu2k]Rqj~879*Պ߸ WGpP)/P3iF4#.04-C\=@9Jp;5Nl_46Ui5f;.I)U77|7ˬ1~Ah2LSVFm RMx`~uZ08o>Ǖˬ{k%rS y_1q07jvM\_0kq'K%BdkDx Gp/NqJo1~W̽+{Dssr .=9;zlQGٽ]szԡa%6}ٴũUS{cJR򗔼^3€+W /c&BQ }~$m~f˦]%"|_rS9SM~.:{dkL'_s8vp?H Gi[(J108hn#ŏ0K 2el!j/B.a@21AqnqF)=l){DrApH}[|T$G%vS%Jye<1A#XcVe}8*0jLRdڑr}PO}]EX5e3yCqy:ёhH(SU4jv;"=(,'cWA tLY1;hvh|\LUGV@兩W} e(' 'e FgNdg5+G5E K,=J][0Ճ1|z䵵]`e5Ku` i+Ёq-i;Yr"iӔs19P( eZ fl.jhU<[ÙYXw[LYû[h-XGf6՛O]R)G*/1vRbq>/s0ɵ\ۊu rp/yQRD$CC<]4\٣%-ž5Mi+ 'bbV2ݕk>{%0/N^Rp8Ц&@[y@6 e/41G_>mѧ7Km+t=T:\@-j73y->v;]8b\誓Lz.-{m7X-pQ̐G]HaE>u}'as;֝|7^qWrf!vrs %ȝ$ЫVH>1,S*RyXaV-Q% pm!{J-Luhر^c67x412}ȀNSǦL0pJz +~TP㍂ыGx>[b08 l~P{@~gm֪`ȯw+Ob_;ZY;HI@9>rQEj(J@a1?#Ť|)t1|UJB>}@RX0kr*٥Q85,~=[ˆӲ?qAB> 눨3s ,8 U2(+ }7 ap sWvۿ4,l\ /4EUU)Go&HY~Oo![7ȩך9Z*#+g8(Vzi(> %nu vXדm<#'qM$H9j-PZSÑ/A2/O `>Da>\$W`©5zcf*ov@9qqd#rw 0bN$҈$ @4ಜz]Iova"X(EKDq 7U̩xThretH:!sVdpٱ瑿nwnIVh) RKLH[V<[*-͑״2 ּrUYkSs٬@)JpF:[Db64f{6E05WD{q-$|8hBRQ{V9R8qɑE$F9 uwZws 2G洧c* Ie2 ![ñ,{\NXXrZr?+<|5+ EppBIaй3вY%Sb<*3UŎ#"!vY=gz5Z IlgӱCt# to^Fm8dW'""`pc_c фȕ7PNR -6grd* 3ۆ `F쁁Iu.2W 0([.U텩y}%- fm;#Uс| Vm%SG*Ơ>J ^<>F{ ˸©p5Q>haX6 ݘ[){0f/^]Nڷ" EyNlz)S՚yΆ OZ;KEvM>?S&5Hҹ_QAI|*&qi,(%0HN 3y1yJD09RpEbcei`kíҵHGBaW ͉-⏞V2P@3s'f OI``x&!;7{z8*: J?.hKrTlQ>*\4C2Wd% 6Kl2H!G lQ苩dd0q ;]~/E^6?4?z~~6x8t0cSfws^J ttzWt޴()D->}Wݐ^Fa^^^#ϟ`D"/Dc2뵳[&N;Ǖ%:NtN&uuФ"Hā.`u;pkip>_s ]^3q̈́oUbj|Uɚ# 9ӑ'LC/љHMtۙ@.+ƹj9[op;нZݺ۷@am*S`B )?;،ՠ٬4,Eȕ 2PV5qzs?Yr=mn\ZM[*\MJL>,H gb\V| =[^7VT5vg;m .)BӖXOӌ/έ]~c[cIzkluJQarM P?3Fv33Q[k2#OhV5Ec'=T 4]Y[{ :F]d%:+EV b?OANȻU,w#381U |~ PltZQ K,J ewdpbQ =-35grM܁ ZY0MT)6&&V5 ]/6L.j]b Ґ-hC*C$$'*Z~*!$Pz eŨ/wVFR}y]t rxbXGb~{NFljw<.oOmEw+ vNo/*CIѢv$ l;3I-D̒b½y%_9ӿL˙w@ t^%p1sx!yleD ox Ų |Dy'{$򠹈Yj OXfxmOڍYZo H. P('5ˋSNE %~sJ@gU4A,1N /{Qt I{RCF8XW`:Dem0qHvWՒ+`08dh_o"Oe:(o {I$*kG.Ajfv K/{f~ɫ5ljP~V)3.RDm G'sd: PR7{5IUT_#: :ȫӠCSez%LS2+3>]Sz%_~d anlloB5Rl> Ҋ&Rƹ+̂CK9!O`I:oޓXwWJ2Kw}Us\j $9"gNBt|}z ufgI[D;U3CF]@Q,l*[9Y A7L2w& 5X̼5^󊛤X}D#w@]e|I)"C2/ϰQP^:yn%cj$ o䈜Mz䋸f^%_lkç|;7*5u(k4\!LlM[ o%y=f }ZPC7={v4!ɑ'j4P`QTlLV[ ,~lY}oTlet$Jbʟ&i7fB]' po2GMw<+O.tRB' f_ Fc@6@VD3&5.xּ-q@4M|MaӍ9Bn'̟CmwMb/IיG5 'pZ] `gӸ) f 5{+[ ȸjIyd_c7ϐtҞޓG{uOJ~06i=Wo%U} v^AMƣX@DQH}Py&&KNPr )?/S%ӊ|ױܑD5n`zmVSܲxҧfe#3lpos(mӸҰ75=[/Od r tUFO(xEƊZqh7j,g킙 pO/,] *v=Y 6᪼t' ]6K.f(oD O`'NJHIrH]?>>Tt0u~n)8fiBnб_!J˃@ZUYlYm1Qª8& 1#鸕lsMzBYe}Ot@wnr77rK|oz)~i {)-xu ) a$tr0_CېڈVNP,H2.둨29F=K(tĞV2tIE`Ĵ#L,`-j{"xKlY它g=S/5;1VşGI2Kfo0X] <7}Ue?˼`Efs8;"_Mxm-89L۔>A ~7NB;tOe% mrw"j_*Q _ӰNrILf.=}Ģh{ Mm;<~pDKm]#·u-`m87EqFO9b*rҤ~I`aGFlTYb]AybڈG@Pmz E+(!t rY|?h;jExG5崛$ŶSFiRs_JpD$@F6w"߄[Oz=Lf~lL3o2i:~4p@ p36XEDY:xxqģ˟;mF5Ppf`u|}FO<[mId:PdOl(.w6p0+g/VxF<6d&tGQ1m 9iVs3%TMrϤEWu ~;K0>B/ʣx; 6Ghn _Df2V i3#XDƒLa$Dz#9=pNQSB4xH{~a!cIi z ӬqVY4ڸȤ]W`kL#|<J?nW\2ƚtzfڳ]+v}YSqy`{VT,H2][-E *`\VGBo=`"AJaWOk#hAEzqNz!1/,mNʼF׺Mr3mU%m١5 ASĩqo@.vuL+{aVILD:)<~C>,ӗ9bhgꜢ3q tFoi)suH+Yľ%VLt=ʷ- ~(<ˉ'oמ]?#ovRqDJ4|U=$h8w] 69dmpbRn1f2I3&a_io|VAaZgtqq@ޯVg;r[f/ t5BW!X< wwmtZY1__7:-z lEJз+7awM{ 쏆"_*ۺYj":[ci7d +};KF ab:]"3D峚jo;D PG}mq¾?pG(ȵb-L@qJ )3T~n?YaT0 - u"gƇ秞!("d4E"9T@f}G$u^Yd(8̳*0OTWNm6>҈E?G˔j[,2Rݰoό^䉌 I^M,!4S incby8UD'9p33|(\{f*}d{/ZHE߸cg.q2S#C-CBfkm!nQ. ap>|PDY.Ug#VmKt1yϚ$nSí(~e?RYnG$~;u ~.+u~맑-5w3ATe)o= }osz#kUקi,̿PoD}v+1$%:L!k~RJsО> Q^&kr}& eLwї@^jC 0[.(pP~k)Eg8oԡ+a*6O6']&]oA DAΤh۸ԍ_ Wa&?GYhwu ZE*AnFwP}אBF _F S ^6Ɋ4z~$Dڭ>$<"@?,V>%Ӿ$3j7|F{Xm^ʃ>xbJ)Ws EVyϜZKmzK_e2kK|x |>gB 钧!LV4 #:3T5?|eaRD K7bߊB fylϋ .aI~7l"%3M 3/T ĮM="}':x.1U/KKՕP7]1Z~a3ٟ3!Hr!>ž&Pzձ_3?Dgʼn͈k [ %|tUSޥTa0s4{/X *wD?3Hoʏ6[Iffo@U1}>|zh0^UwtեP7 _b ISr+o0ҙ 8`DGlNaO}7pgXk{UۃEF#4ѓ]~d4+۞%ȑA y%Oue4yu;O]C+M#VL:xE("s }<Ǟڇ8ďn0&}y`t.ݤ5Ym)U~%˧ :A1!.T%jS* C}lzyO. t1*eZ@DV 2XbX|o!긚AS!e:'42XRHFdIҤ$s/Z&:?-p#S"`G} 6;uzGU3@)'k)Zf%0+G}>Rf.+~ܐILL|jG0Y0aܔ?z4Kƺr+ɺXS@ Lpo>o'K,Ǚ,&; /zpqPl|+\HP207` wdұfe܉2g*Q?a : Ah~;z h өJu;AY]7ѐXӏytVIسIt8#i&<h;ѨRٔ'>xn1Ȗ Bv >6p=9A+u<"`d<0cwE"Y14dely#7z%Y? JI>E0e)SɍEݰ6E)UQ)_bsr |4]}O#bHIԮľRʍ>†rXpX93 ?.Weu{ PM3t"g!qyu6 0M`^΢ڲZ T{+ s1cA@P-/-vzVK6^"jX ]7{2i;v̖tzkPU]"{ tE].X~:jkYDFɃ~6uX,%Sg3~qUc "0A]>5ұSF8CV<obL;Oo e2 x40ӶW&%Eo6@>-s>pFzPBB`) [Chs߽m1USxɋaqDZeb:e5WDy\rAwp* Q2 Blnf?5BۮN j8Qo;Č\ +K_fhrLHo!6nwG?ۑ.#[xrۥp0R״0)դlӮz#[˕̓-hd|P\a\J’b k?T ؾO-}pW>Je-C/掾F} ԰.{K(cp{SMub/PGx7F8h)!=1aRl"xG}W~ 9˜n+ٙ]A+ΔJR+_tM$xv~^#2Oҗy[%_E*0Xץ唒ɒ^kxXM〼 '|4uȍ'D97,?Hρ͂UH{1*LܽkuaSUf'km < 鞿aqhU)DN)j B)Į$ֆP&iKeAI煒< bSz=3Njt4.r(ؒvt5ɝn&g:gk jlH, S݇no8?Vżw8hֺ"*Tl9wDK+Ii(=nH}O۶ɅvC4=;\tq.8HsШal^m ?:ZHmFbS 2A^jђ{ٕ5\'7&5O<:๝(>LI͕xj8a:wxkaሃ_ %(2@CEHBe"8ynBd? z7"}tMjٻ͔.J9B}.MɉN&o}[Ue C5DJvD̯JQbnu AwU//"H+>IY$gS (煶iNϳ'!d0n 03bq}\GvEp}q,*|H#$xV? x 繊XT:orj>gc*[P33 ]ɍ8H^!ݓ| CFhҜ)xOh:( Ĥ[|XE qyf&b6zq^casL]X|4L{gTjU.@)`eDgNv$v,3lS]om;' ?%CJ7Lh@o<$OhSm'YSeNs[Q>A9FyG r,ӹ㾪{U;[11ɰ+kUw̓)I9MNF/NLD%;V_ 3-@Ka2xuՉlk 7lmEp[L 1A =bwjr?"rna* w-G r!.%;zΒ'H BPƦ={MX;\;oS7LYaKcA{q!lzĆ|e/C+ʴ4o=R1f55k^6@_'DҶǮ?  DDu'ҰMa]{ՇHsgg+$L0LɌ{P$|AWfFcTC}_\yy. 2g&*#/E]cs y_pVCy% ,adlspJL/Zb"[190P&4O,P.Y)UYg/sD}?]diI`}ւXC ~ K 9Q${VViI'S[v!U+La}WXxʼg{GZܡRDcU(F[; ߟUIX0x-W*@svיxf9"lzňa K˯($A_pW>GhųhV/odA>h*\;oo\v1(iC)DtOS O8D BpxQˠ6߉<:%(R$IBp`ڿ@CQ5c͜΂Qj`ޘlcφ"D `ɳL8oL))EmRb&hJL]G6axZ^ qf'hI1Ma^hHn.Y=L*N! 1}}I!y%W6բOKYPD u,=~M$MW<h8ēy%P ~ngnGyMQW#yo 2#9BKVKE5d\" hYRĴ_ܪ gZVP?=9)?O㛎V !ŮHU9J* Ţ!}] s[(1 y/rg&R,Iɱ/߄Bߎ@V3˙BMJ4Wr.ĥ!@>π>{v}ܕ`RI>?˻LFO~P)r}#v4k:e֛RcEco< X>4·Yh<=ŽCud\msx6L. *#<~qžrv{wldPcch!"Q|L۰mD% #VFo),-ډ6W@ d^Ⴌ돶+K$NgTa:d*Nk>ordwҨ~֨1ib}Z 6){pj*3" 65L~ZqM)sOxd e)D # D&xPI܁}:oh Jt])R7~}NIz…_T #%sOk{ q- !Q(d]wa4iqg)# D!NtJLǯybs&Ǫ9`E8ϱZEM)/y-E#[HK gu^ӥ @AaEq"ngyI@gx=xޫSq{I+t3XOO* *t@(Cs/ j"emX R?KEHj)f;$iHJd =TSG%$^[.fyD3"f4[Hܪw往8z/!٭Z7w$Oա8T.=$rNz-h!Z,'Df05`0XF'3^˗ꦄS) " Qވw|$6Jʪj3l#t J CH?Ѹew'V'l&yT9ͳʹR e?;m&!wB?q0vy+DIEEt _2q^ *3x62KO Pf%vPMgp!K4ZP!u}K N ۋ>_2_ATjQ|FR[z\j y]ncm%'iq'dSlS'r3\B8MlE`#eYC[ރX6Иv8D81;톧NJ9#V뻖_ ~sT} 6o |f!4g0:mQu#NY8na//Osva,=hچ<WСbw?c$;'Y 9K.풷p4X7VW\۠c oTڦOuFhg8e^$9Pb#up\U:E)kWyDZCLZ4HU`%*D|4ay h[A|akG =+EYK=Pa"MgMAz5L+hx!3'c\պ"^΀]x0Q;;Vxe*`EjÂ^RC%,8;N q0w4̪/'-oegW l\?W{z8z<_Nn]a}gS_E7·寪d\ akIcg9u%I=QI2ubⷅ@ Y<E(nF9@1DKdzJ&R4s? y\u8J &5TY9EIkäK?Bm8`|($Z /@di}"H TվYnb2=NMCdg(PD3m!h1xűgDPBV$ΆV'埤RZ-CX S3 ,xţjLTu t& ͍,)ETw#O6$ X<eHosH5zܵe!d9Fjn}d0lT39``_|wKZD6c i =l, =AyM+n^{KD`)KwGf ¿P#ܿ Rcx5K*X MDm8uAhwYIh.1SR_{b.1?8Uazk:oRG-|N/YK}J\_&s`.#!C:̼p*44d*X3'mCDPiOUbS6UpE#? Ḡ۸eo׸2`A7texSyAUO.dҒQLjpD>Z0 F$(^[QT) 6a[5Z'.T lncX|hK ;F2Ppo8Az4KAұ\s>e82uSRN/o$V4 WtȬwCn49Er/?wJS56**4s.X ~vǮ+'4zp?\kX0ԠCI=kukVq@-WQbZ|= nHOjfRرlAaȸA};RJe FH /t]V&faj'@Wa!+ďDrE>_T}t ī4zAeq&'9u}:X} VgDĞNu׀Bwv*u9<] }+F錸FtD1fr O|oS?O־qؑrzk=k-zp? 0 ՒQV!`tvY]#/<ψ*AÓ+ Ay%#M2DSH"crhIj:aZdcuIeg`^0,.]pt#,ڑڞS `%ȳv03S MOFx%',+!0=nI$;b쀊mē>'|;dgztMWaZf ::3'i4p.%K`jZ}M[E%7j g8y=b+L4T<=̴_ p̃tJ`KQWB˕:[IJ boe FY@;A^U%MvԿ8љ(軟OUm<4hTW2#3oiMsCW1OwS^AsEhTC9hZ sv}JSQV,QB}iybc2J9~-vg DN*gNv#SvԧSs99GKbf1N,oUO#8n;ⲮS.0C4Y7+{0hkiK$*t[;5k_[MJK&\pi9 KgjRiC% oE|4hS8n^Po8v:mnayD|VԮ84ሗ7ơأ( ]MM3ew3hrvnhMa%JX3~`hS)Μ[&sTDUg&"λY|<̤F+#V]fDWEIXʏIXnz붹@EjlgXSNٸ|? iD 2czaaX|Q^8_?-IO%T1X)K}b^^m]`)ᬦSN) /_(uE]xHMD{bV|Hf6:o"- !Íhד-Dد8%KUE K~BI~T1`jv VAQ3aJn-@#iPy4jڙ8Ea(<WJwpO(L4̙;){JSwR2w }ClIZMK k7iıO~161:dߌwm @2JS{}#qyk6=Cgl P0so/'̼>'zFO u(h58GÅ5 {2 ؤ< T at1yv_"ڒh}LxaU ֓3[U(:]pA/6-!DR&/#݅eԛ)բ}ǜG/z7KAVe`Ӿfk0Rnyd\5iת۟$=PY/&]`܈Rh%|؈CfCA;4[v@qVT'{k>^Or~zL|:%F-7^Z AyzoEǜHS׻WQ7*3yFjOrgecy%ꐃqdqRCC+yLJ#yt5MWY>F|#t$|aߥX5i+XIet+!J_mRg~a-Y,;-g+[J\U)+3ЋɌY@3A,7]*R-M?-qo(t|hB0ɶ e)g_!: 4r_é&l6Orߍ1GS+:fv9ofd>;Iΐ*ݰBdFuϲz@k§/b}r^q1hxaޤ'о L 340D{o!PH|C(TճCJp-[wc6hSݹR`[{\bJ^B+UUtH4T4;ط1 'S@,  V,2B4ICD]~a|ϖ13UkWJDx(8nQ'Ro Єkt' rţ;g»Ϻ[&cONmA'Yr@}!?oOT20{[d^1#f$D^fv' :dn>\7ٿQ2IW? UO^eG'LZGO}JCX`Ψ;63Vp3#B3OR`|ICr"7}wA1*KƜ{pgs?Yœ; tT;z]saRZ1N")rWӉ*&1CF`x,fLM\? .pwα\Wvx#gE+Jy"6wXZ4{_W ce_xb/gtwǯ1:/OP9ԃ'<߱74/ o-h#O ᥦM}y¯71Ӫu@ Y7 ˌ;7_0!vC>zIT*Bpdweܣfه=df[,- 3A߅b MhnMp7UU/<*~q|2luoƿWqSo{p̓z#. oꭱQf;sȜmK8|qfcU6Shq˪AE& UBo0Wo5!s8&F jʷ#{_oi*(6؁*{[coyZf4شjubVMw@ h ,~B%MY]9$⌫JUr='l 0 jYkw'L+%e{F̥IXV#DhnAe {Qqlаd qICt\Ĭ6Ubq H,Bɘ:l5ҷM V,-cA0iR'e@_md*v=1Wwu?CW6cyol|W3d1y 6+=PtPU(=[o cAAĽ3x5Sop` $ɀZF)]s8;zΠ5yMqO~EȂ(ӄp3LB("G#Xb%N4UoVN#/a º2標>rCaH/fp_^̥-'Hb>v{w$y@\L"Ħҵr(3` v#*+4"D2ΨiB XAN+÷ @,Hoayf'= D!N*B#o͖1 ůVx{ \TgK"AR]M>MsX/yjHGLfrnv%YC~9*U)qZ47E6hwW߀teunё):cm=B㠞iw_d,A e>j%\zKCaRTky\+2~~IcRr}ܿEB}~D|^Uү(W7vqlsMfslStOA%LOaQm{{x:yDss-鶚z  Kp~tW"p!l>ə}=_huT}?o1f{TګbRZ}vcm#$c..kY# 8>aç`Q',mVN2n:@ak;w믮]150h<牝]nI(9 [[TAWS~FFNqRQ02qs4r̵_)Mm"v?;KP&kmS⡻Xu7 f >8ayP}S@?k`FT\X.Qj?C<Ux*|J\D*]%;%0U&_$ۋ)Xޕt\]n^Z9/2!3F< jdJS;a@Fg_͸U3uECL䨦.(v%s ɋNjFZ4 D ]QBV՗oDvrMI"u9Qw?bD :P_\q/@.0 RG̽?6!́׭, %&FTv~U#;z꾺4*&NpfY'~sSseØri cӑMbBPY׬ TTeBQR%fXqNU=/T̥ q`H\_J1׶:ʮ;138Sjt=7iqeW}S.Wlǜz6٢>P_+ztA2%P>S΋5֟|ˆpi273/W'&i8!Xڅ󁓵BQ0Bzew׍Z*?+o[抣Z͔k1-^)_0/S>kRg–o%BH{;e-x'Z=vnҀD4fC~-}n/r_2uc'CZ?( x2eHZ y!v$Ѡ6b *ݸK:uBqoeUYu+;uCA6#, jޅ DjQ(k\G2z Q2?㓵Bb2octqڗхFA=yO }F )K2GZq ]څH֌=(i.*A&8<>sP+/,sZT A ,*LJO46O?Ufrs718-"Vr; ǫ^E_-0(2r)g"%<^(83AI` '5zUDnAa(+2Ui 4s G8GX%tSaSkңs5~_Vo*H: >`*.\vcvu"|13k1Gl&3U,I"j0Dm[S vw`]yOJ-a]>[8Tf  Rk, V[g)рW {:CKb/aUq<sjh ^yaXG?e_3y&VъZfHNXV} 0T 37,X1x#فeQ8S"":~$lߣm^rHe VAyե-ddŻg2aLJz8+,O4yCh`g@]hO+<al[4Ǽd7!k)_EA%]YK)8&"c*H'n1ځ&J_ڍ_u|<_Qeg^@]#`v%f,'\A)ť+PlNTYIi5*Au|R(73C6uڇ#ɭHDk~Jhlxl )E*a@~1ÊlCcrMo^k9TfsE,Zzx^~A:P-;Nvlo#,+(0NoY?K(AړkXPh(b\h%ٷq[%)Ga|J{[Lh\ ($ctB˖)_k dPk)dG.Sdd©VЎm(rF^V5=Rj`ip vij:8ϧCMUH@|_##6^ʮ^z6Wc:j"9ejX3^ߤߪEKW4.t2OJ,5:,4H|F_k%Kj{8oe<_lSI|N |3rËU=+=?RDf`bM.jxhHf#Gz x"IznZNzeNYQ2-M^ψJł%pmO8"tZ Þdķy)grY>]c(GϽOYݛ{'9Mmƅ6msUnwHo%-;C"*eD뷹K:dío7yCpd/I+L.=(ƮetW8zGr6VsVQD־{)@HuT?6՚H;,=olw<ϣ)'Z|4x"zQ#rˀ~x? /^C]6$ܚed*ˮHՄo%'(¯cǙ5좖4OdKEuՏ@YnQf}?mDh{|0_pVUTӳu7w_NZ񚏇xqVgG{`ZMbK;ff8q%'#J)`gAx`縀M$;lwPdBtkfNrpw۟~i;">#-&.V|qSu캿G9E* vq_A#O*<˵|K97K?pA33BI]yĚHGWFTр^`g@`a߹P)iyM.yQaa |t?Eml%1=immu3Rdp@ !LaɔV[69ȃkOiqeP:?8%UzK:/DZ{AR7h+2]pjN@_bʢ855^oA #gdb-Zt!Fc2eiT0ÇWd56:TJt ʌϽW:H3=lifOqH_b|"֎l9W+y⺳#%(GnM[#j+_s A2rx #\؈GU-Z2KDxQ!Hh*6B3=_8%^<\صI[V\9(Jo^gz&=3CT}ltލ mĩ 8V'o#|]wyMCVz+ JP lbof9DB=bzxs'~n_~ՠ}j䅴 F\HI)zcGO_T1@5^S[Ef{x$Ȍ!8`]G|&Uj/^i'ڷ"TMjX>ۄzDb0lNi^/a M&.Hr6݋69Btuڜ'?o;%/Vai8.Zgi9hOޏ6GlǞ_ABYntiPہp;r5?$z {4% X'-n*XbzE1+`XJ5 kYZ 0/;ܢ]a"K_IQ/Q'*H] ش]4i92 ߼ ":Ĵf2IJo>b, 11^GD4zdZ RoFA˚a;⡋0Ҟn,oKSf^m˽0Uٸvx,u"]$ɾyyӆG lvEʘ.Nޒd!!I?b"u%e:u(8 4A(})gz;CAlu#jӃ,Pqݹ¶ F\/O>"s:lZn㓩+ KgLPG$Ї&֭5/ZlDxis 1Nad씪şq2#/cA\ʞ*ocfzzd0 ռ-hIbI Yh-?;:Az[Q~EB[$m-'ԧ[yhp |T%EA$9L]|FoZȕ297x_3.p-'rMR#x9R.-cg"W;!Rt՘'}y%_jqG1^FjonƒOMC 25T%Hm&?zMxF}N[ ޏ/ROnTTcQ=sgq#JuןO!o(( P KN9KA0PBħ%ډN6aJ$x]d5vJ4+gnЪ`1j3pR^jlĵՌVd1U"&&8h*d]Ƀ;<02} 9SΜ56ZJha`!2{I#MܦuZw!zqPr(h (/ hJz67UMm%z@u yİ AU4|i ۭd8 d puuxj)\qjTbrA_IDwpO+}!$<2 E0/2]8IC#I.%Kxv:Jf{}W$uaM]G;ܞ[',I pڸ6q!_*Hd&@'2:p_.VtK"o=zOaj[1`˙ihT,JOR|U^r[@fpPc$5$ YzS0%(x+p>y .v/Mx+mmؘ'MtLP2DpϱϻYK1eW_^kWHm <.{FQH=XU892ikqoȺIJs.xT("B2A14 һK]Kv/^A GBq[9(ZL: X7l y|' zYbrt'{(DJP"3}[: 7lQ?Kxa"c1hZ32IO2?.=ML؛K:bzjj< TAjs1Weoj0BV\2EШfLR Xr<"_ٰKLku/S^8M#ͰJCRDeic |H۩o?ļ<g)`D9rl۝'~{ZgiIVvڑwR5[d ,}xfjk@R!g` @ξv}6J)Bhd}p?d/T)^! 3q#Pj2HazeV#AZ񢧢^! k{)ET"j]S_nwo~/ߵO-5adFdu 4sGaLk 9aDl'P[v-H8 )j/->j:*sX.dtUe29= Ώ/?eL :F$w- kH:\7;P]_>ݻcdG\ m5|(ʴDPq-xa$=~;Et$\ -o] $*6YThp0[VrLܽj7ˣŹwB U'/Ŏ\^:?+pwPl X[NGs V;zw'~'<5KԦ鼌·R]N')uԁÁ 67F#@xP+鐁͊nhI!GqG|Teb?]jpL#ti Y|-! #ח5T;Y@⢵!}!r/V{V\knj/a~~~~>]:Ψkj1}-,'GXZ)vWcxr߸8Ahꁽ?t -5؊|g߉Do?I\ ւ@{Y=(g B*t נݿ_! ////]Qa#z] 5~>@sh}4]|OqyWU,+rb%E F0<9vM{3_!\-ˑ%&Mۂg7xBPRUœ( 2"&|8؉4Іc/-hHJP?((!Td5v3A}>s +?C!p8a)/v ɠ^`xX{>CpL 2O,C̽=Bf,LI.{#LWզ+{*I1/Vm # @oR[h kߙym[vh ׄO݀%Ve=z|b̅1*BsM~(/_#D[6$eO2UoA< "OF;@A:U1‘ӥ! c^ʘ4 pKSanrI!= k$lu/nNvڋ5|"le(|_PBdSK)I- ^c|j2o .녨YMϣPcbcqD{0&OqC/P-Jv.xrSq5$!B=%zbV3z[qF]= F2ТІ`9(}kM51W*|K|J$=[x~g|ȜޛãMFrSJ)^(Mw ;c 2MLI`MfZD7|R:!cwCvj)Ɇ=d fY0V;/utpHk1}S婨P4DI&Vz{>l3Mvk:͵Ds &ђt kEkjޗ4IFvyB& Pp#O()@߉hBvon Aek~9 4^{Z4@kۖ!*<&LMbA|zv=xbs]}L7Ch3(>SUrxi~cCrxÊ͆+3'kLo5mQ[U2 )ȇc~0qxGw6閇91$4k`Wdxo`PJ|"`w=RgC L$.76{"SVP>Q1Q)d빡[ 'd¹Mpg!T)})Y>=qX.8]`!5~eٕ) ?gAt-hBu3=5jR/b AY9o?yt6gbރzz(wd4 N][t eJ1?Q*h ix &'9ш|Kqq߲}S_(ͱ3J,&"MU2MJP h&M6en qʔ/H5ǀ(\?:t4v/@“}4nɘ-te})2`CN@OF΋k#blX@bᡴ7DJl=(T/w.z0-n%ga soR+p&)Ln"Qsf>!GkCgl1gXQ >j>Nv_6m-XtKZ܍[ȋ4"RDE\^{e R4դ3/lfxCLoՋ4Ŵnt"j5vB: <ѝhYrcM> {ϜGJo"7\aS3/;"zDl"  F=xNvny@J.[c?Hrݚ4ib/E><|f !=6zN$Q}y1]`TD07o\̜byo[bnCiz]0×@crFA޼0Ðah;Ro(4tAGN<s^G~}Ʉ- {w_QmmI9.aHkw<=O+Ƴ= ܷCؕ=i_o#sM?#T fgu!XBc iY$^ !܅WL5lz9,#w.0:♧9uOlΩxa"|~DZD3][p!> eϊw" bΣvټf[iaɌ:Q?:ܶ)>&T#> `^UE29O\a9ېow%j/%_NqT>vZ`/Kt?(eɚ]HC [%qމjZz#k:y&O` gB!z4OGwG:`qNJf'=7u4LR*O z1V #$?Γ[𱠜 FZ@9 K׭^ 9Tb*!JX?CpOb6}-)=HY8;D-wq%Mk&V{yOJQ/sO3){}'۴@õ&XTL??5>?&q : 2眊_w/e@c&b!^4snhlU[D\ap[c̐N$jmn؆OX"Ah duc%I5nphM3fiUyp=Z n# B끉T0fND!,,b2s']g+ Wì8NYLcs'םtFW }c`"D%BCDqc&ED4*ķ왬=׷!;ri7t8NɰAqW]Orf#,U6؟qvx8eȊhD& %b 0-n'!t+'>O %$wƅS֔ ]R UN](N,BG".Zbo\-͞4}E,~5TdĒ'.%ʎ& PJa)^KA),'{{V~҆y]XkWz'j {j@KRh>v{ei=(CAΫcW[MԮ5zX]eaa/t!?EGm([0$q9Nc;$c$W2Tpi #Cn HNbLk`Y_NX4S.zaw!wd yUZTt]iQf^DzFNC<v! ie3"O3/f[@@K%=g1@<'?/ykrܸl<ąJo& c#8CL+3HMnhxJYsv"8a!Cv2GHz&Nݺ!E4p j 뢗!UR. _Zi3ujDqS;žExka1:-܊x=fQ0,2)]1bG&La8'B }. ސ֟d%qc8{bYOfmm6ݍ`\:yqM.|jNnN+N+T.:n$Itef>s,mls:Rf0:|6D.XH= {!)4z<ݢxLHQԭ7L#Z"6DbJSep ĭU/*0dWlݹ`>b<6ZX2L"v$w+ /󍡸J+^HYH3ql7͖2SJ^ tW@>Bj_h88SKb8r]:ye>^sǯ}8o:RF1w?7?On3.+\}lolW4H[̋ w˩;CpÓ 8OlgFȅ1L{Sɿ։s?{:E /hhƐpWc.%Gf $k6*[>@)elb<`^F:MbCqGPBᙆR1Wv?@v9Űv6EpE o;{p(d!UJ]Л"pIr ]QVYjHŧ4G| jU2;|i55լP6 mem٪oOUV[bڛ=݀†uI Gs%݃wNy>`c.4zX`6[+2]/7yYڬ$|:嘚8h /'J[L6JRLZ4G&1)=Sb̶ݗJV؍)0fT4ǯU 6WڇPB>hBׇj[Ղ>ݪg+gFZ@fhUƇowKs[%s,Qu ⩨8Q뼐I6t4 T r6llsGh?^eqov`f?Kr /.hS0i-,@1hhn5?JXlq]@T%[8tqA[4Bk}F`2Rc ODžsuWwZHQ bV<`IIKSozGV{⭦ 17ۈT'?kgdxYt&qYun˒Ws6@C5פeXU,jRsѱ vW9%T.nX6X,a$ u#[M?=N4ev,Ҭh *XȖSP im *r;,5P ^ Dv @!-Hq0kNE+km f e^΁"{rr|Vs2g(y1CCP>.3En <០@'11W57T R.QdA'QLjLhҚ?4V'fJuw-o;n~v: 3|l;@[A7.8N02Vk&ye؅Nԛ$Qf﷞g׻N sڸ='=&p?Q^ Hs@@?fZqj(%vEh5T{5t/WxŢ8vTWK7- b|FЪN)Ըۛ>V`"DϖgO%ޓn!bPX j_2JQZyzƇYvk:m76QGa7+z+]@"Sc4&{ 퉔-xOE.g*mزH홹 dc7k<+a`A?gŖ7^=!UHPإ"r}y*r؊@}ʾ0ݏ䐧7Ge@”;o5L~HtX̰04H>H!1+Js;MY7/MT6w +! oUM7[S;_wU yoilZd iW y.A237:%/Jo$W kM]6 , 2%9"kd|z6? 3*010>CR#U@j3@D@:+gbݜU ݬQ2z~ }t%!.M^q'cdx GR5 |JLjJhfбz1B'>,TY#oBU 嗒s}CL|{+Pe+EJ!_s{C|\«S\ |f{-Wx,ʹTݺ෹ Ꝛ#YUǟby֯IwD+1&"G2)56z7Vi;\N`:Fu]JlJe@>G4JH`nJI __Tu.ϾKԨmi(nRP%88ɏmץxá'kJi[춛GRg8AbM6˦գ'0\ː]e, BOŏaFI9l_tW;m(C8]R&0Om.i}kAB}ُ޹˟ 'Uz8CuRwzx^PP/ *: <]Kñ19y|7:@ph]:4e{][<\: \zE?8E֬;)cv Z>O/Y@ %ٲ8V:K~["(;qC2Tku4# f@OcW}p/1>O#u8#a0)-a?ȈC2J6싶I;$*mSl?̠Q|B|Y[nȻ#[ 3!R =ӞY-lu4ݟōEl_q-8J[*Bzr ^'jht2w3 h{$qb#NbݱUP8: (c([v%N:Urh6הkO;qXq%^>n̊]b\|GK<{ oc^~HnǬ3dQ0ߞ? -fdy[\d t`d{AE4)E~_-H$YA: h;s.'?.瘯5eC`^ \\R*J5+y)R; &UmIFWeQV (w'F5g?X!OcUx8֙gs%mzlC[+xCi0ЪfAಅ~m݃gC_]4%ڦ>IlO;#OVoi# +3I w#wu|zP#돶pENeHa׆+U8tG 7ZCFL*ov_^GVE'B-[1rᢁܰzi:^f\Gͬi8f.#:bL)2%@` O&1teKƆw͟dI X';G7@P,y<^H6*/\gOo:yjC#G<&Afr5eT Q/ 2`[ޫs^lB! z#;݀C"Fi K_iaɋe$ E9uw-Ey7SP%/uŧHȊ@}V}v2@e*H ToVB_ԘɄ EcjW13н 2r@F~[n۲F܈Z #e=גR՗x}Z ΏSFutatYCB&vqVeYHn:kI}ee*<~d@l]4{V2F&}q"`)bvK;LI ^!7yoj t"Gy_q D`IӲɦN͓7>gb* ,FT<-Kι^U|HyxX_bĸliEimb΃0pY5PbBϼҭ$pAz'; 1Mv­ZjTfjIloV<#fF MR5'k`^頲չjEk0VbᚯC3*H] `%\'6irДnQH 2h`"\  8-?CwcZ9B*:X\IG)0ߖIc@vKeP +X?,6ĥ\'Z0W}sc5խV_'T-N-v3L"cĢHlv1Pzه-k0F (K3xIu-A|`@S#N`v9(vIpEe)O*s7-8yπ(,#)wdHYiJ`ÖJCaMtdt=nj u3$%0F'L%M-~þJs.<?3^eKIH?Bi}W?FTj:nq]cq\Emq1ݏm 6x'':ay@$#Y.SV&ZKx qǸ'syt7a0e1]U {DgÁ0@2Z,,\37 ڕ B|?6$qP8f0ovdfE MZ=Ey.7CCIoMO57&nj]m349vɯs|8J9 f X6:ElA߹@&$5b(VD'@ <.GH2GMJZcumݟlyŧGm TP] r9]lnltl)ZڏΌpV hм)uww86 Y&!\jDIv3XpC6ٰU\|jr_~pԧ>CAڕo2e5 ~8W/3 ^<+_ e#q`#UDeHr6a"j(a<&dX>G-6,Z[y͎oC^6DLfv=JLN%wRmN`OeMi<{!&<1X:$s- \z"(7)G'vJVAaPrD4.XQ2C) y=OѧtONh˾>oh|T < %f,AHpe]Vrg::iwd ZM Đj=nH5+Sd)I9$V?zoЦϐz D~܊ o<_d TYF63Ct$h=r(hCu $"ߍ`p9ބKIJoL)mr͡|sP)?tiv> Rhy: tNJgE<9Ar"~|+`oM w~:G0[Q X9# Jo 936:[0E4砰l"Wt< 81n`q жNH: 6}-T։<*;rqZLR`\ed;- 즂kGpY)/r %4t{FM(ًoFPQs#޾àS{XP}#-G*:|.iܪ_ őY8Y]p~4#[l\)Cڌj͇Nùt䛿ҕo=9v`~'l(C K'3 ⭒sK)P~T(əKEY(#gzd:W+;lzD3k}HT* y ӏYظ_MYY&-\<]u(y[JV#94/6\-{ xtv ɺ6,;b3}ĒJ;#F몏ЕVEhDij$ R/oQq%Mn# Bqq{! Ь k*/uW0&4s',EHL)(lXWq"ѢIRN JEնC$P2BH StYd"4jv^B\6h'ξ'Bp#FeYֱ.oOӴ/nږ*;Xr ZhN^_^~۸A?$:A{7FX޾ɤ0J05v aJcz}ZHI9Z^m0SRz(.xDQ''|w њdlkӻR|y!ù6%͊j̒So]h>9x/sQ9Zɿ.p/5<[Xjx &ܒk|q6 rF!GԃwPUsr˘Q&v<A-N"5-KQlSGcakcf`I0+}K6jo(reuTnj_rcr:-PiS`>^%E=3Ha_lR&WΟ"ꓒyÙ.t@y92PL]}j>ɶ M/$^qA{F[fmnʰr[Ck-4نfHz`q!˽`J`ˊٶu1[Ou?.5aU]Nê_1g2c?$rN+!iPO=y*/4S%⚒_NQtDa^7WI"\o JHpuiC׳VQžԳqHKִֿ[ЂNVƣu16Ә9V8 . ~,OLFbf>:Ѫڬ:'A0YOFD#OIǑ@;h$wD(*RV^g SoEL p/iahQdzsGmfe>$z֟WAPB2.i|!pS}ZIW 0%E8RH /k) GQQB. 6|T3NJ?9.!Falƍ!ԅJ  uflO_Y,([gΤ$QxYS֏OnW-Tʈ.Wb*E{H6cBbfߩ]I5+Qk{Z\'H肬œ\l@?g9FVL({9<;Y|3NJ/9vt(N?VRv.٤P &e:Zak E0M;I\TifJsK"1S gXТW:n<[S3Z'pYA_N oY˾n ):e&0TE zE_"F@*K4[-SGPNv֐A/"W@љ D!!iۢCCx#?RU~}p\ G n!gRNi0[**ͺv&?8OjR;^bJ:W;f@N{KbqqR8 "4 z 2'\WB/ԏfB~h`vdJT׎ݽhS׫zTS~By⻢Z7%s EJ[>fk۝@y$m>cɪnfS55gp.0!K A'U rqhۿ|KA@tkɥl"ba94$ћXscw /vdc1C)nV|Wa>MI>dE2Ma a4uՕְgr3rAߋy0^굚0 IjIEu2];Wa8J*&ϛ9?0xQȰ2"$D\ݦ(Äe2P:2- ":mo7L:J,XHp=CRڃa÷ ]+C[Dc Ԗ9Ne^,·Kx~;\fo"LzdX9t4RT'&qPv^zGUZKR3 ,I}ihkd AL2FκydjPe_Sꦝ/lqyu7>")m q>oFx-|" M&?h,8<_4-aM&q)ZCWHZ{i$dj ثz sK5;gK»>m»>u~icL/0%f /  pKHĬХ+0~ǍR{HRHOpbj{Du.Zc_d6gȭ,.ԛ}m/2rM%02,{.fRmqɻwWPU7z~g(xp}3PpC;ӫ isۋ9<%Ǘ , 燗f6r [!}K'1`ղ*+U1|qmnC@كa&|b^6(sK0^йL,߫v[qoF`֐n/0~!t$ϫPƀ ؑ=ڪҝJ}#ͮ dFzb>Y qnT3< Jp (RR@*u6̖ b8n0M-8x]Nz#I"['.ħAK,$ؐL!>٫E}ka%ko>g#q{7Q&lUDl2wDC}maSK]~pJVoZ-3# X!CzߘAZ]ڭ7/դf~ $0fA*+daWT$ZHW#n'M>iQ5 W.۾JG&A])K+UO5P( o cqO"ն2ags[ xP/E-F oI_ah0J^IyK]ĈTӒQq֫%}]]ǁ]֪e$8ZF('m/j#$HGH0 KyJ*4؍j֯wՁUE2fӁ-}dWs ;WI@$HG-NvZoW+(}~@=G_\]Jه ¨$WIpm摳W_&a*^Vŵ|1Պrƽ @2n1Zpa1nD4)S|[N'ӄ}Z]Zʪ74!/V6s,n/:>L!ƥ_x0so=E;"&W- J+?qA,p9a~d3 Ɨh0}g@QM>D)]jS͘lނ4g! j+ 3-bZ .J ک6wCObx" ʲ.nyVo\~DKxig8+?s Mp| Z/vp>dk.1[P};>dfeĘ3&m`LIzImD}C?{XLJ`]m2@=T!?bԓrB*CҮ/U臮L઺--D@ϋwa0EegGkC㺔` f7+I~ܶ^sKs 1߭WB%( ?{2q7cTE ljLV޸k5 Sv(ZI+s dX}iU5 v:+-@9P$Bfyfpe24kWa*/qw&(8QXԕsD8])IDgsI&q/ڇ gJhك1 #Wr h7MvVAAXyN04ܐH:dqȩhSdkP>Dĉ Kl;ג* mѪtD6@,7|hv X54J2l"+xLzKiynƯ}wFvzqٗv:;^}Er6d l0Iʈ}'}(3b3{@Z<c';mfz{(8W꡾2n +p!#}5:IE.h y`4̞NeJr:{/3֏~Ҏhf-yb˳sF&Znju6-&zPUb_rQ2#P%EDNߥn12v`v!8t.#Fv,󌐛.mbqÆCMO 56H٢IuúXCX-cF-gB2>b>Qf yû9rKXXS]uW{)w00ufY2T{ 舦9}v&2+^)VcGA>}A拱%Ǡhòq}gYNqk3Ƭ9{3@̝@){v-`x$I6)TN:ʵy>ᚄ#̨]n!+/ k,$L+gxֽaI%L{]wPP6.n)5og\ͿlS wUJQ JtBDPlp>Jlnm'nWX;BlX877 Dtrl `fB1L᱐;;?K\iq}H^{e\',jGV}6R]В(5 l4}wSJl@C2dt)o?PKPF^an^>0LS>[MF&-]է"d)0٢ s+;5ǀ!k? 쇜GIU#4x"&f9u%kkK]FhnT>_ M/azvyi ]HxЧ/&6#wf[n*<8Ӗ-_7w]༥ΐWr6 DIC4w2ߪ_1q KUnoABCzERhY@{yլ~X;#}UP rRiBvp]L^ *W+S5Xl<ҷ(7Ǡ=z+o.$c<>ZF4;{4] |D.QdB GE))rdm C J)wܘeCca:HMp~+s&0ឆU6ڬT n6x?R,jKN wvөuc˄[,㲩PV e5pOf_G8YgӚr1DKf;-Zʼb.Eʞ4c,Sᙖ`[`Prك, y V K};)5K&mfJ=wS@8%UlB qUYk*DF;6? xQ|]=;BNbTBOLDRZa-,W镯`2g4/Jul#uKB1!i0e-Y~z6D1/`yQTA6hg |t8)a45 wAAؿY4f5o X#,Cs "޼,j'k ᖿ UL3[ eK{r6\O^ m U`𦛶LxDRſ6ϴcQGA 44ihO1% hZ x{>nd{2_oEcvq;ꉏA=>_ Bvw_3!̎%Ŷ EѠ !qј!{xbiUsR)I]ȳY+,P[1 v@bOU 2 8/nBJ{`4]^뤰NJZ-u zfq ӵ p47'`&  QuRXm@5^؋Z̊MjE-Jׂ)J^ÛOgbāOߺ\ JO҉/y9.[-y`3!x]~ގ&i?Pswp8VýNW c ]no3;p?\ȄhujACXT+@s>;blof)E2mD@lHL\\q'.9*xýTI $YnCrnVv3\UC03D(2t\R7xv_"iUHYjl8(6}sY_AGNv0v4Kߩl[N.7xd`)Le'$vSq` */c+J!BWkkD3Luh[(I'+Mm5{^)9ٰ$'E&S,޾ߠM~ۏR3ZCl6{ P=QBH#\xUNi+%^ɕ_ryEci7"!]:I-sϘlZ=F܆IN"> @@xPΪ3aH`}%'$U J39VG M5,T4dNrM@n8hB !, }'H*SaA35oC?j*(w7q0ʚэ_yrNY% kB ƭ p>+pP`]BxgpՊ_MoML|H q CaTOر ǖRu-Sril&1E5Y)-ybY.A51}ϧ0kO7 {q-^Jܥ.ys[]@r|[ &⦲\Zy",[@ l:rx?PBkZAuBp4:)ͽS &e辑_}S`iI0:^RDٹ+P&,%2J̗hj*T6 =𥰲f ?ވ&ZkΟuޖC.I%+ncb]`2\fۓ~ ʶA tߥKӇ;h_JHfBV@$=Q>}tA6J6=Ľ p{e ߘK @(#/VD}Gؠl@nt74>HsWp$@[޺ӛy:&s5 C(D֮yd&̖6CYSE 3~[qt9|@\?4嚦mf.WNGё[` I%BTá'XߏةtЅٝSm|Ny(]gW\k$}5uO>9DpUlo8(5$Ƥ`ڊRl_T/ GLR5h'e$A !)cE7iQg XL|Q]Q)SAz|5S&v䌑$[zȃ> }?>oY=攉rv[_;k-<1lvfUh.8@h!_/n߅7 N z_H,xhVF(." Dh6 ѻcl #,@u3v +B1ƒ S2M[}4="Rj/>ľ~S6lhgBg/'j|NƓxkIgœ.4)0 Kg˞рT)EY?F X(u6=hMP4#jĵ;RArHٱFEE>0}/0Z-Q:RH?ЀC9Bb} 'WsX]R`ny`,s~{3AIn'g?1*#kSd4 ?ZIn^]Ca,FލxDGz P48>H Xd>;,8YEb6=]3 0M H44eBO-j#Lق_]v5J iCp25Ǘ<ݯ%RHiëjU΀+@T# jb|.JͧAZ#Jǎms>|%n DtƤ,#$uf~ b}5!eT/-?&2nT,_/h`NYmK1$S Dex-^M)M,5.*>){x,^Dˉ@ө5s\h@xnP_( (TqnJ u5I xuim2$n f&}.i;J0_N2DH |QJe16?[Asڤ윞GAٽA*%DC/ қ1qxfqiR'}0]:$ TA?4y&b,` ;v"JX!QuB ߂SLpv!υT%??/v`MG&MslnK^sՆeTo=@F|%Ly(7gYR۩22! (_aG@$.~Ƥo"B#ƽs j T^#^kjϿ⒊Ӳ]k9g#oٜỒV95Cx [J?+ڔ<5\N?q0E)뾣W,x/kiP߹bWͤji)i`NixVo"~I+ Ư j;_zD⡽x{;ubϕ4CgKz@Pe*+Mtl,;*O}}ZOWz+J5 L!| Nޡ7EXlej"`ƪ#-֜C,#ʒa~oT7`Z 1N /ͻjSxe=uLt?=¥o}?Jɬi!/vsұmoqWҔF-EɊ&g:30/C9Za^::K?v*;(4 4v͌.~+^ԃJ1?PnIm  ?ȲR]M^hE!n:m&E4 ˈkl#!ÛA=%bQ5^Uk)Y|d ͝ P34kI$>uB*"uqA8Pk|Q$ld>ٮ$`er?hT&)/{Q"v[ ̧Z%d#or6E%xdQGrĜ2v RQ@>#RlC>'U~\[CO_fmOӷ2j&N9Wݔ+N}YH%k٪_]/s>OXВѕNVcc{cU鎿ժ#I uk20:scL갆 tW@) 6ҢwE`1Uxs$? \ǁ%Ki,/x}Ŏ^3{(s(y'74!m%GGjtWPzb0@+OvF〬Qt;/Ys!✹~طCՒX%YQd0uY$(M(=,qޏ:؛x3X\!cj?)䇀5ȭpGEž a!K/vdɬNni<4kK ~zg<ġ[prr ?8yR&C0o;†[{>Op#y]Ҋ@¯ys~ݷ v>:b ½LeYGjZS$'р9=3O9l)Mʿ^Jm&ԏmfi 3`]ln,C^O޷]U}l *L5-p%`cҶb"THW%Д[]WGi=#*N?Y@aC]{2dVD}=> vئEZ￾*ҏ<^ tS 9?wHIBaok}/ C5a&%-5h6Ά@QTbZ3?m9";_?J4nK_yhȄP.3Jf87匐-򐂛{#MUQ0Hd5V?Ap4yF5\8iwVV]=}ZN?&fPxSgae/&sUA)!y̴W}46+EQ?N`=64$h_L0H瀊uImdkDa^kW;9xD W؀?3 w"4gݵFJU 6_^RX% qՒq& /o=uihySEfx 6c-05$Qĭ~Z߃UVdZe "yUi{03-*<`1"lp{;cud&qI: O_^ rLm%.'*=[@^9F@PEN{'ɻM|4KCkR䁕||P/ KVnjj:TLAW[R p\`Z۹d 75uysFQ֋Zwl+(LH@~VDrO*V˭!iO~iC쓈nVJXz4F?WPm\!jF }|&f }mٹj $F uѿmDM{R{̾\^"?p#,=X꽛@O(4%k<>)@vjRaΏVer㥪,9Gq<geqyF. (zHKp QK?Þ!\mVMg"U2@R ,F e%zEjǭDf]6wC}RX&-<8"ۂ% ]Z]ʧ.),;{,$(\N0G6+{֠Zƕ2-l52>($ug,źAC+`=0?=?PfHfʨohŴ[*)pXLz֮ zK1viM.!>]K*ݮ.h(b$cgS]kmbl HFGGfΛ"iAzh6u<γw[vNoTfk?іt((с9 Wq60mf [È{sf 0ߓ"3zޫƭa/8" Ҩ0Wl,H/R={&,<&XB0c6H8.z}OYڕITA^>XG$Zi4kO:[{K{|YY%!^n>pk׎x/aP +9;] M^Ë2PU1E%؛DdMZ\v 84{%ViTd,!+P@L 3pItQ284Z˿%"y BY:>Rpܰ*ӎQnB[pɛ/M hҊ31RȒ>I| ϻ#ЬO91$ R+ p/<*Y+@&gz/Iaxپ`WhC>enji[,I[A ǕH @#HY=dt9vD;.8> 9idAiK`KXMaRӸ"7\iwTPz/B'G_qULUce֓SFX?Z=kTA T3Tl%eOl\[ lx"d1GөĊCaX/?jh N+cbFK|X>k苆5Ϋ6ﹹK92T&Ȝ~nBLF{,s_XJӆru8]u# dl##)0qն>=ŃHr"ƃj;%'k'\/U`g݆} ըsc$f2>%WGA̒ z e=%0tNs]/őW$]݃QL2o%d տ(Klg̤nO8(t* |! omc"gU;] 'PݻS0J(xCS,C&$ˏlJ-lbXKDeAIc:CjT?Z)@|.p9BJфn{|ƃ)cDӿ~K]bPTh*.و>!(r&| Tځߜf 80r4y4d09x(:Lh"qkihPd Vl6"!s=N+1wM b|:t?ΦbHi`s5WGT 4GB\*CdzHiFǫ޾&f犨)?+u;?Z5BX.ZGcPeM1w$()cŽ;E $|(bfJM9D[\ص"[Vx?Ⱥ/aמe^N#lr/LK琕,%DkiGZ-ޡ#|S=wQ)Ia*?0*Uտ]I Iho N N@YNJsT:h {P_X6mYo nys{vHH|Wnӭ9B" Ye xb˫'Qp*#rTDgQwCk Cj\8B1/iDU$bt9L'%ZRxY"lZo jA<;Z,sb 2L)ٵBׂ9OV/4pu]x^8t=qveMx@7M^6P1bkˍv:o.gWvguk,ƋVq&aSU( Ao&{x|uGxԶR7[i6$25 8)Oš/;H#xî$6e=ZE\„W YU߂<Fag ~ut62)U3ljXA@;qmUO'UZCf5S1c?l)*gѝU羘"1|@!8pZ\,hpƅh-u.>- 5sՒY7ihj;63|1}sr&ϟJYIAN:8 +OMJ>]٦9h,n05s uXUV#oМpRiyj%3Dpx㔸{k_g(SW ,C!g"K  zVGwS|yUIGu7l16]^rKB+8? 2}4_5uBRt[v&4daLGD Q2ŸE7Xg1dᒙFAnzIÿ}b}'IOXk=3D ЏE{O =\փ ~d~V5Ĺ,d-CBi>YȎ^nnt喬K0e%{ >Bz,3-Iu ?2kq;p5$+'̻ :ܾz:Hg"r*G'г^$1.5f 1]BcsK+MQ2{9'?ď2ۭKx6,NwGܯqĴ[;D9$j(F[mr2t]awȉ%g76B˄t&@Bg؄#(Q!IRWδr݂n۹-@KE1]ْު1e)s;{7^3 2k3%L΂6CsL7 %MNVPђtp$4C4$TMxeEQXͰ<ٻVnBf nh9"=7!AoCMWnn 0soIW_ CFZ]%:U3Il.,,d/&{LoìSp$gSfcOcu׀ZKU^de`WC!.>O15ӌ pC3m\`϶$M:i!h(Gų!̠l?9_ݗtIUјm|;cQsOa}pA|Lg \+mIC%S@HMKH8FToYtɇOysDצo(-۔ 0u^559949,x]dYY>~EQޕ1QmѢv]9ARyQ⴯Sz+|pTtHQ3F(й` _Jz7ԍH1@TYk԰|LջLTȹ9Oi~QO3???O??O[N8KOqlԼ "&/.M2CF]v|*s`dZP5nӕD+7IѱΧpx҇s*ܼ`Mx|Psܑ02^~Wgir@sXE)zAiE>MDƽh&{ @@xǏ5Nxfm5#]6N:{l6`ijܷO#hX7׮:*_˹%m n1jRqA@bq @K~@uɠ? _FkފIմv|Ҩxx#$yGnEtl/[EnM& _x &JL) Hi_| f`ÑN"Ң"&dohƊ2vOO' sˀ^Gmv1iC}Iyi*Fj2;#09b AGs6oeBlߜ 6kuA &| C\m6.RZb<Ө78-ݼlnZ 34NEȭ_?>6fxl?ȉHDiM1"FGeY9Ž83eMr/毼!kW4W1=G:>nlJ#Sߦ y{ CK7MP]{{OU{RPum"3z/l0н'>IDBdflZ&rD3|(h]гϸF}-Hx dBPX%{Ďgb3P-H/pփn}zl:cSmdδ ozG՘Ӿ/wi}hQ"FtM] EȨv =w7dɌܐR$m[Bx/ʗ4;`7x@9q6oEylv?jU=3ϾTajbSzOFU2՛"WQ%7NQEUaz 5`-b w;zmWr DmC, G†ȱ<\֟onbl!ʃ!}n׭sS?Ucp~ u|'G5f4.׿n[kzqcS=2 U/Njy$&vyAˍ]-4C {M)Woe6?nLbbfRDk飍Һ6,U {Ԅ/E "'GrXm/>@r>c) W`sk&dzKS}>Θ\fYxf,o:7f 9h>`x 8ȴsbsX5,xEY 7 ͏Zdq *[ia_jX%@RLGl =NiO%>ѫ=ql0G|neKaЉ#YTUǢ$*;кo9~9\pc8Anp/c&YD~K|M`~ ' "tN4܆_x kk}M\7Sa,q4|*oN;ۜjBۑ1.>>F|/ &jH紟O1+CXdtL&NJ$sr"kdhG>Oդ|ʛc+,NB*ˤX)w¹ώWf~jxpHw|~=p{0iRnؒS{lU\*#p$xX7V@m?;#,ag%29@w~ґbPFFI0ЭCD.{iy%`PbxZAvZKy" S8~.  3?H7XĽOq94|hSIgIRХ^ͅBQ{`垎f'ٿl|U=OI+HγCn\~(Pp>W ,!x3L y,\r:݉aFvX/P79=\ue%+'85ZS, O e~I,+O c(~\[U-!b \%J07"+|s"иB]KCDL#q2檇>*raVȞL\-vКu"nQ>B)ÇFS|IfZNY|.lQL5S/xخIߥ{?JX*Vq\97t r>!cq@ϔ6BD1"@TzrF /ϖH!uFCO ~cey|BƓN1] uzUA['d̡Ffs~\1_NZdUq1u8vϰZPP^"+$xIz ^W ΀kk c]Z^;̱,Td0jg}3yPvb!HHcEL\ÝOՐF΅Td~o'k_ `&S<4ɈixO<(@0;fΖE.TGk]}5%q_ûv焊g}˩% <1> PÛy@ϋ0eo#CHXnj*׍ySKeEϨcD߫WVP\;3]vu^q2u[]tdD+79G.Qlϩgֽ͕ZQߔ͏iZ @j: }Si:?>p~CmE@f)WIX/ݪŻez| ZhJ^]4ȥt"cQnr?vҞ Hr?VnSvbo8h+WWtVLFA{15aaekˬǼPE\?G+(EP<`Yy5wbuH(eڽ2܊07"0:$^R)J\XjkLK xl "s:\&lc밂aq.tP\/(,Nv+5Z"P̽7%?CmؐcD4kr]-rZg@L&8dr?^W?9n@R&,-K&$x3'V3[f ob,!z)4yԇ~WTk΃su~e.3^S >fi @+Xt%Z!(592HR=Œ(6$vۍq'kS &tbo1"ykR:;`5Q >x3=8K~qmA9F+Է&W+VpSٕBzY#go~ ON4r" ÂT_6!Zc䑄ԨrqC%ܸ`i5T닻pu5HJ^1-~?b6 ips%[X7XAT Ii4M ڃ ,*H_ 0b4B/i o6?lڇr=9p7S2f{tY ճwe(EG?w0,p~|_QE%Yk|SXc)y "nJO"4EhP(Lsf7vgHbB(@I"ЎF4_F-fBP/6}a RWyFf0*3' aqR\S>$  4uIo yeV H v=b^@JP"rU6܍I*$àI= ղf\$JHB9-"~"Mt@$wTn<EZyq ܣL? %L8Z1ײ\ {9Q:0,nH+W/>kI1ټ3),qX >B0Q| {ݘ;njQlY|[GXZQ@i[_9\gfEUTgwnkўPp۞*w"B_8|͙Sw>npL?8_Ts#vOp{…1M *[xUs )-5ϙsIѷ*i*L;֌7a<,=tiM[hZf:M:Nzw.L[G/7W+s]%5B^M.b1*G-]j2\!c(NGۓ|.}WP2L,qy/1UTCoZh.=G?Fź>$EPmr?  cd\@&E(2O(iR^ n%y|~PFasf%ϛ7 3>ffy z%KGޔ;j-#ĸ`|aM爝Iv3VMS* ,mr)Z-I@.{uK-ģ>ق6TS_@aݏ.s J'&Wj_U1G: -N(l8&bde5^\Y,dW(Ǒ Vy'F~CzӻUջFl*{me$tO؉lób Xe]Bjpx[_FBN'& 2(ߡ2Y̠y cl#w5DzF+/ 5Qۄ([g mQS6vZǍb1V'2Zᲃ-3`Ӭr'h*Dlx Az-^ȅ~ce+4 U9>RʱmV5<5=i;[pG$9h@"U5ŭ"晭!IIcCɮ7#*o/PM8iޥrvWo|;Ծ'o/tu^2W "zE-`cjm P|Bmby.61ΉuOa7 "&ǴZ)Ml[U#Qhn3-tt FBXxX"/sy F>PR@r򍥣X;ztfΚ͇3t"p3в?d;Y7JWICEE76pLck|}ZPfQSψqm ovY%s #zRO2 +Z\_83Q e@^J(?^%M D-ILWPܤQ]"k`۹Ey!:!+nAXb@A{k}Jkh`wGNǃ8&jMgt1 4 J#cV9glcWDo7C5KGZ{0EoV%Z異je+uDwF 0 MFsOڠr mGi ˾~Y emQ|S*ЯzPRi Y8ݑـGvfeWouu;f3}nw ZuBoC+G~Й„Cn5U}Ȱ ؗi<0ӘR)VŔ3}6,kA/H#؏eT_7~*36$G P0t|O5dW~Hva(*3@dWLЧOm֍>T!k*@ceXA@r:4ѳ<\%+<*J ~G4-TmLZTmpD{)Mrm0l'X@lZcfc#h*ݮ.;h]qHy7SaE/zRtJK nWbh~ )R\%ڗTΚۅdgnƐ? LL;%JɅgP!v/a"dlԓ\l/ugVy^+fFJ2> ^7T)_6ƲT? ܑ,Gat1lFb)59YQ,!bhu]\%fxeʼGN)A厔.C'nzXVśůpW\]ן(cBf<$;_6%gٽl-=>v" '" -,V2 ]0D.F^ooв޲ce EI䡯ck/Y s -6Ft/0:!ah!Gz ƌuy]~cbO$"S ?"WzpN\ȴZk xH< ?_k1BgF^l#!2\"1*K:ЦuS3#h_@R1Ǵ556_ [VrvĶzs*#]':Drm.h_tV>o`dE;/ghmW$62۩(їLQ+hn­NAhZTnlҗòLvƔ3;d^!ՒΫCT9۴<j-F9=`#d Ʒ)[2"~JEDž^/C1"E:miYkÃIKC)?ߺd6IZfHWeJ.&3 6՘@6@P[&^[xA%llK{kQ @2R>cq|Nypn()Y{Lɋ.C(!qkD,Ыoܗ aڨj(Q`d|$(>#tJfJTV£"Kr̸ [ޢ@ "6?xD^07 \ )p'/r;))tB-l.,TNi/C% rc*{մ8[6",r|v֊$#g+<7@pdBRǷ{ ;%!CG uEuUpW.oF OMΪ6@sC뎿k8ENћ`^a{x2*WoDB'x?% ]$5PfHrI#{utbECIa*E^D:xG{`TW0+: N,3m3ŀT]N\ (7?Ev60ta)e'hHt({HLA_VM#lbh.\4Es, ]9 D g^>0,9]217vTƬZsmy:8,58 \nܾ,[uvզ i=߻k]H'D97\)C8%lʷ'"J{ߜq&%VE=rzcy4]e Mel%vlI~V`f$&l=&O$|cnXƒi~^A/FnI\Uu&UUR8|PXW 0aDp)Ahû;!3.!uZ2cryfr[˞4__a_qγf䵲J6@,by\{hQI0P/_0̛h|sc5i] ܃U@a!J!%?)RW8xo?KwAyV|%~FgCB8gtt|SX E`;DDfUL+E7CR6/QJ?r]20MjL 1(~B c?Nla3(ظaWݚgh$+,ୱZe?mj~JO$$v/3gЏm-^q)_Y$huH*rrJF**DA EF9gTb3zkFDEG{w"/˺Xaӱ~\>/\ȋVN7nd]5C"n,4Z% .7OȈks>bF fg!,k#pd| ,~ܕj^ ,gwM L|& ۸9fn |. '7V$$-߄饣a1GԮ> % y؋ys{?m̴BOZeǤHeWy􏠱9y,[n¢b[T; 1qS7YZie +э\\(m x/wGUg^vG.s_K\h'˜zpl8 6 +. <rΑjw}'9S>'Mq"A&. `8] ,v)yr(V=>KN,Rz *"F|wctTTb[28ښ\hm)8(_9+Lf$S&޵XVlX1)mn,neg&k2)^~tɀ1@6YȪG&a:RBQ1op6)&$[JBb7\KbQP[qocYc2BK'cBP5~0~`i :'wGyּuQ"+ՂԶŌ5lnxB1f, QHHݚUJ脦ci!l9³DVE <َs|`-ѵwXu 6!xoT?G ]c؝K?L*V}j˃i}31b!̏JBR'}'z`v<c/}N.pJ^mc.0u2ɬdXSs5X, ޙx VȘu7U=/ ~%@KV~»N1\ðePj*B,Da2ϝ.:GE!!vR:*!cdLPh4m[,ad"{/eI+ &.BzWO[e)o]yR=m@#AB d;&{pOV`%M<]B)Dءtczr7{缨L;4G^σ6~_A[!3<ݟ x^&0EiK.r]c:wmb!" ! =&u_h=DғCy%U@ߒ[߂“A6ʲEȃY  Y n}1I`ʇЁ9gd͠ 7 հ@ȆhlfS}vvЂeme6pFU?uG/X鿆8gDn?ݓ/ԜO^Cܣەх> Y,U|ZkyF-ᯤGhד)zT;l8w:t쒸e^sp^NM|nri8 L12;ՎN +(7j9{Rw!#UD X~iPO Zu&Nr(}c \1,(F"Jj2۟ۀ"5r,3<[E\;48QCEv2eJM)tҧo1rBAA7kv1fa,tIAUEJq;M_אu, k*Z%,cnZ՗ƈ:&2j< 6Ň(K&@4HZx)-$V9Z "PT. /*%^ Qn5r6 #W%NQjsE7u^Ygl|MOBaBץ ~w؂Mwv-(.Fݻ#);2l1pY+u8I7يw _v("+nFI$D[,D&v]pG}L¶U HrVۗl KXN, roE'K'd/Trcq֏ZckM21d`@3_vo)Ĺݾk8@}1yu4לv,9}v2_ISU6{6^j>|yP"}DǾ S>|ʚeXe S߭Qx /OE0.ݯ3IEG܍%7l4Œ]_;yyn8nUH8ld.@s-]MQTM!40j$cgS,K䈁YӞ +ЦieՕTs0 'M|ڑ+[֢zmvI/*ـΉsV4ElN璈S͍~|}kw䣻ہV~Yrk]d&=ĀFƕ63,%ͶЬ۞!owԅ/_QUVHSZ4*>Hiy]Wi*7 kp#6:L{d}:1 DESJi m3d`gAd j<zg luukyi[1o &5C3B -`/vRg5Ę~zcdעcdHzA&f*F]ʸ, +ܲ=beyyQϬ/}ǬO%奨%2K%7O} M41Ќ8nn[C9ZJi1"y^Zl#NTp+Y9OuUjyo\*JbIVOc L@ių $sXX[’/Ԣ 2܄{Q)`Hc8Cjm'%tyu<,/JMn%8-3=1+. !D)nGRO<-(JTp};Z>vn.yȏYqx>z B06N6rIiR]S;mGKEya$ZPm_z82<X um$\)cPc6DO"!Ѕ<_f J0OmGsy qPmσ:"VP?+Dd zE." Q;5Pv~PN.6fDg4CNz%ٓĿ[az5. b#_$2G0^avK!WȴeOX?ݳ~Fv݋[)ˤ9x;MoQ,>R!9t'+z*!{NI4 &ng8,t1P0۵I'yc@BUG@!rj#=I7n* )e_ Vxyԫ?Azh tɋwL?gWlI 6 h,*"n#z .oߨ'C1-ؙh f]&[Rv7>ډ$ZD̶S(]Fylb?I m4pRm23`l)̱ϿX bAq^4@y=B#E-X)1HK8ruⰊϧ ; &/j6p &QIhқof[`U@hRPR`FѪxE49¦P YWwaĴn}}\u[$wCe6֏B5b؂8i˝(rKkpܼ w%y{u]4Z,_w0|-!k)uM]F`?߇Ɨs¯و+ekBκ6"e9&cTl+!$*Ֆ, |؆]l:΀ƒ]zL~2Ez}1zIIj7Qo]ԽS( =HA\bdkLM4œ7%*^}FpT(ɧ=,L;ܟEob["&ZXmcJO LaObu~(s}{K.KhoTsz6Rw^U?AkUOl^Y87{Kg!H$@ɏ^0Z `lV1t89LwNhmP⊖&zt8hn_5WVz < Ց! R*{'5T7 }R NfeP?#zH#:ʆ e<$6t:bq|I7 (U/6u V{# Nڶw4B, ߤYP[l>Z* h m96jBjSXi< gH/ba.4͒0Q O R~WWt[70:r 2ځ/RgWL&Ok h|UsSHžh|=S6'÷T[vO$"W!}Qm]())p1w#vW9=SbBAG`R|f0yf(4O5nеxf_o0_e/)qƕIw/'! Fft"QJw$9__!lbfgES;gto`i&1.7iQP,xuU^j,Ίc)А*E[+J^,#78gg j %C C;=c0W|+!6g=V_OQv55 //: tFuRpBnFSڒZ4@$rf=͜E 9Hh .S%g1axqP=wdwV]XF&n9RBvCPK?ik!BꋡQ!w<;+RդQRA?}Y]|%d9G$:O_[9.֫/r|fwASU#3Yb7|oD2JSV5t2@TU<8xc r[aEkKCY9̉l#s:2@HT00l D=}<+GrAzE$^7 ǣ8-,ZE8@.F!V:i?ÆROPkGG8:X~( 7@ !-v*`8ZA=訕Tiر af[Ͽ jjhIOHKu7mj]g\gR1 cjzu4&+#mxVU 晇"-oLcqK1 U ed7Pl 0r$mH>nė'M EQ]x0zQϛ0C~ޭE&gbF6{N -FL蛷]_J:!bE7Js, RQR#$қGVrD\nx[+Q6 kUnO8yy|IĮ]d68cg&u>J&-/ukT/:V5H"´Qv Vd%Oc ]%zCx^&OA'8MiBo:t]9Mvfyf5 MTMuFIA LY,͇ۜ&(N.*kp6ܘbMdQ>W4 smj|!_bPL(7xzu?(z$ Ҷ.NdD j(W 7-HC!c c,|^ÆMЏE8_n45{iSXl\ՙptgXJ:Ufރ8bq1Sھ( xJpn11tPBbZQ;J8[f0Tܝ?2 wOJήjuD ݷ#A0-{U Od'QN XLZKTMd9[E7T'_669XMr8DׯVv >c3#,t)~iď(z^(W03!Hzx|a&Jcm4Ŕ'<89)zu{1K\ءuA#o0іImj?>{":nm7wҸ,?)wZ\RG;d!vEXW\g$`5=&G1&Ty T|;̃B# `eo[O_54uEh4yH q>jf];yelvEpmP~Eet|/C( эE2>S)n=s+oJ6掮LEԼX f"U^8`XFR}&QmbĻ7"uޞFű*IH;6/p_j1 N֖_Y< *${eu&JZ0 C e2 NrNgY7'-0~N2"mXղ]cw[z4GԈ6v.L)h^0#;Wn~T=v: ://!" qŘMg 6uv.Ĥ$jWO9$d2 ۮ*orU`ARG9@7\;ÑF}PElzk0mG #>,lfNU#C LƒeӜ*6a6s$=T⮱‚Zhfe4®ʻ7Hk6E$R l 9ȴI@F{l@JLBCokbv\`.<\J0z:/W/}=[.݌R7|tɨ#/u}ޠzg҃61+Y=aGڄq){L|H< ds44ʒGg92G~_ C7xT Y!H6~K@0D*-ብU%Yb6NT")⏷7=x, (*x6.2aXmbܿ/ӏUʧ9lheDel ?G5B;oQWOVb ~=SV1#4Ym z2 ?)WO-ՉaJhYWV7Іcl&#Hȱv@5C;:0W6jTwaRT nljȓ)Ҽc܂c+\?60g Ӆ':|s#~,dH"tc2C^d,=$U>2* pKsqA4ʬ_iz?Q ?KyՋ ``y?T1}3 K+/Ft惮X&Z"luNns-LBooWerTV"} 6>[aa3,_W"jbFJp>?.چZCS'Ů ?]9Ue@ 2ܿ=@y)B (•7^oʹXw: L]eN/,=q >KJa &qמB5鈔{Ci < CG|,mgTw#;XL .t=ʦ2Ռ)\DR y]ƩPn!Xްj+\kx\|hP2xPeZٱf5=9T[t"֟-l{&/ÿrcQF>Ŕ=DvP p[[CsG@~|gcj?j|~T êP/$ S}':\Y[Kʎ7o0w +2BVԭ) >}Z+*ּ,cFnIvMhb'0K8q r3vu+Gy[&e# DSoQr7'.GUB%L;Ĉ*|T4w^ VDkh!=Q(~G(4|ч)KSMZ.( b4kZ mgn[w:;Xutۖ8'P(M27`{J8m;/\=Cp-O\ 1pk-r2IUmj=5mfDI42LϾ@ tCo DdAA78R aF)X_Mؘ [gyƪ*b:dCVZ}ѵE{Z ]vq~Bm<޺4 iiȐ9fPGhu9 7qȤ1!0B4<:ýA7G֗٧V@%J3ìY;S~w:TaQob?gaZ;d%yy*X{66҉srZMٟ cȠhҊ3C_+d~{ǵLGHkO 7X29Rsȑ-뫐xO<橏vtD }-^kTeg׋/j_q',ud}aq_#ܰ6zGjw@ 5c:#GS_I̢y^{!7lsGqmKӡr^vJ5v .筌i]8 9vY/ 6%WS(5w> mM@RHsg|!۽zI% =jww8Mrv|xH43ByTQn ANc#fkeyP!0W/u\:q1`OS@<+Hj}NBS-vFiܨHI'b&g)d wv7 %TD'pSF5& d%B`,[T>,r̉(rf7K.:#C=WrRx:6 !~a!4R \4P;L*'n }rEu?xD }L$0;衿0qQ I#H ZO]( -:'4FWmhU$);Mk @Zly43|H3 ^`TU! 3nf+OT"Gz,W߉t[Zhw-<^D$`8 A%Z] )#3m4'RQʠT#Dz}ԍt/̕[F4cTMU2G3?? {[)C ~3nՙGT [cv@*'-0THտ1bA8yNpGb=B]A۩U/&S@>CzMLl9> dZFJ1.P}sbhrb@c[-kJu>UJ5uAkp2(l.:_ vD֚+m%y!Ap^24<ɶ{Yax-lZ*_Ww{4揝Ϸ{"O>OK>|"Mz@?ƌ>ZF#$$х,XzI4m`tl+ѮPj5u7&T1Ñ ֡V-zIJpv"zdn\+"/0 A+#zSQHu*l57IQܸL)~6xr /dgB3i)#y*,YW yiፍszK+ $|sAp̆YB4 .= 5 DžgxYtyC1NR5´Y/ոɺ8lh_|LֺObaf1/ !iup=pƪoS0bQ*s]U'(^ 1h10Zc ,QOpeA3]+Hb֒I(|{{'3ػ_NLXJM ?0ZK ?/ K^T&gӻ,6d3})^ZJϾ_- 2>>L42uMSe:^_9%g$]J Q B._0ƧZ+vɒV~uw Y17f3[GCkf̻5G}*_g gNIDcnfMF,Hk2r\š$o#Kx;}qn۵$ίYzW?,:54S=83I0<] (Ξh@JZٍ,hrc=mL8,Z}1j?ق*EZ ] kA%;;=ND }R-V`ѻ *P*q^f|O-46~3́(2K6~(y<.Z{*jWم]Ĥy Y`;Ok_N>%wd3UȈO6bTRM`<}{Y\R2`9chL@>" Dc@#*IJqf?6C[xHbjnSs6}0"t}}fbu:y{'[9݁؆Lv`ͰO*GB5{pum="%['f< 0ϫ|*] лQ-P:(\Wm4k60sXfDʧC,d% s\WpHBϙޭ, +!vv@}J!YR?a7H>p⠛  Kd넻B]H_)]/BlcB pNC۵ς8yP 4O HӢP:.A6a1 Ƹ¾|~X~P: 2p+8aLG) 13>m ~l+yo9a$SXԆDQ +Iuw_ T22|XM_g[Ynf7 6弽_sO+K麟{OTg) C ݏyqBf x{rpV{VBf#q],Q\R (wb93~$n+ SHK LL^F]aahTbZ7D/Qyфh,\K0\N(Z*2c}haC RCP}-u~v.4]bO?Ab1B{8 U0X1Y=@xְ"4&/h3w٥ѐye)V0ZsJ1 ?UdXhLJdJ5A;cHx/%<1U|LaEI{Si.ޢRT \ݬ2rvj=kqI~R-9cI]F.Ͱ=JЛ/FJ&$bD$sI:''% bV!t骧h*Sqvo Xv}m`ȬSc3G(4rf_ejO '?J{95C6JNR@ n4c8fҔ]dWjL4+hs%)IQURܐgw7T& ?uk4*<̬p2֒K-C]$*̆.U 䗸: yH2|eiR\O%͹AĚ]ftCe Hd\)0)\dVM7pXr}HHLYFYVw (7cwh5Hc GA ũsAoM{(dOi^B'+|3ܨW.sU}2){.^h?R4?5[PXsm^,EzUkAe%lu{T^ҡ0}T>CsW1ۛhc3N:.g<.geUpM p{?̯C 8/xWNiU]mvY)Mꉶɖ>Hح. pR=qtr,Hix"-2~N874@=L8fBtAƐ)ULOf::`$'Jع hBYs+oP$?# ݇Zr~^s,EY 6inF|}IXx;C~r}cwn4ujCu4i2Ch10, bX~lTa.䪸h anZ1HЈ6  ꢵxJ y@|$9Э͘r4rxQpVp֚c lM"ۧ;b(aywc#d57c[~AIe12*ILЕcEZG@\ŽBm⒏tM4,2b[( qt=|E8]W-+wy?Y^4hwkv3-jn 0VvwӰgsIC5eԖI";>H>|3d ^:!Nzz*GqZ XNYls ۯz5xц$QP-3nA(.4WRR;jmpY8(_O"J3c^Gƒe.¿fQRߥv}$,oN sǫmT7duQanTWl^fFp?M9r<4?X)IQ# dhDJ w@u bp5ܝfׇ1w,bX$;):R q];^2>,RlQui&A ȓ)%?S*y\Ht0Vۖ&6+I4Z# s/GCI2_lA}:L^qDXψ,f([*/`U"SIݵ"Ჿ#_xvXH! ; c(z}IwZcG4"PM֤5I.pgOBVV2,DSm:PcLzAO"򨈗#D p]s IBY^rdIcܔ@+8_6k)utɃn~1q &d¾ #a7kj5X[@i1YhwuV|#K0J\h]ʭr!J4 b=|R!I\YQz6,gZm2)Ԣasp]n ;_KN ܹ#:dB\"ұ`ye#Y[iU f1jp4&N-',b)#hǠTS^B!UKk9}2Ѽt3Fzr 3NWX5Lv<4Z~!ǦP܄{qр +F%&QTM맿J$IARyTvv"o%qA K1iZaVbϲ*,#ɹ>W/=Wl:.a+^VF&C0~aacW?pq j Er-b3 ͫPA_1W=Vh3+рv~\?!X;T+POΩM ,o^?Waea^xZcsO=kQI#b$U|EVlחiK S0J T%Nqg똆 y 2@#EAKag 9nH; v^eAja7FϦ,t\@fۏB`4ٰ8,j_NNFlq+'U >`Ox̡=e]ud `inBǏ-qb?Q!̕~-CXE}h!OkqףF &H FR⦄JW ؽQe[n&4o8 ] EѱeE8EKm;F[4舁@jw6[~p/1Sfa1YH1;FXdS2X i޻J|0w xFR8xQ-blW9yՕZdĦ++#gIxVеcgܿ)jcXA Q]KQ1 ׺9 #|*Ael& 1sD DFڒL[n:_ɺ̣IĄYʒ[tT8-WЋa]ȨrB(\^9R>3^G|Qrlʏ:tWe9@[V0d%(-1 S3& 1R^դhb;":_( ;} K66mH0kƶ)[]l>>n0~4I}.kHv[@&baa#{v[),[+Z#JG} 1*П?)M3(_QޔjW|i-$F?'倔!<8 h-4թZ[TyCW9p.0%@ucNE#[.vs00"GcBr:?C5P\`X#K68~&&}; l"|?bCEsY6wiwqؐiɒ<|tkfbCE:E fߵ}tOBAC=: 6+p2׻)(,kW0 ![n1GXM}͑W>'wu(fحgܺtj$V0? Y:GHz=Pe8AyOjX/0v)ˊ:xex0p;o0&4苟$dG4%Ļ a_SR7 H0p5X_}34ētv~S3'!^49/kF?8|JBuJx`ԑzݑ@/h^ݷOB@0b@Ni(4dWɤbṀ0ưvk!Gf8rvy5?l|'!Z mT;adC.)c,ճ27fH`.^pq1Q9_%IJbzq2EhF3 ۋ$Pkoh*re^]NBcrʿK_ԏi S,rL 2+pDE]2|}_oP='ulʅ׃ Suk[~@ Z dalT8j$(TOgS Q@~[Zn^*eռԕ9yi( ,` ~$Fn[Т[`b=ThrrhQ֦;TJkÀ P{ֹ"c*;\vD{ ǚF.]YI1e󄎗y&uCVJ!Nj??EhVRw6ԥ ˆT"ڸN{w~acjPEPλ6/MQ-ӃVv%:s,ʞ.XOO яrX*P,>J,ީ4蘲i.9ucvOH{$I jB^_^sLp! Mm}yˉGFq4&8'%  צ$FL4W΅3鎰Ycܟۤ|YծTv neL " %&fr]2P{HIcݨ+RF7L'LK@9AVucR^ֿTɵUEb0<ʓ/0fVOq}3uG^gV* fQ(Yʶuء~V)O@, *~t "ZdAsS^Wu[bC"B葬]mEĿą즽Sc2>rX,_i L cÛ>“)Z֔԰ Z9k.<+x\]+Vu?cӼ)`>e誽Ћgq !Ι}9{y&_uGo%[+:+$iY&$~ë~,DbDɥir.>{ͯ"g2ĵR~&CU7; 2OD49I 5/DZ,Sբ~M=)Ay|j"|kP4$BB7C1y#+Cv$e}[]+XUnmqf dvnlihal2\@&`R+/W7e٫If e9 륈OȤR^E>0 U2@xH(pyK'%:' m\6O:S6rq 4_qOڠ}d'.%L\LgiR$jIq{YIv%}}<䊉JT Z!?8}\|\^Ҙ^/IY ܒZ^Uwk_&Ӷk&l_ f 3 Ud%+]|ۡ0L :wj En͈%9Vb(Bo}xHE7y!'@!v=>پ-T&6޸M{#Dfc{0[?;,U[`e~YgGZE!Li e%$ԙ 6|8GV|ACvh\%ܻԽ(*i^j:LZW""Å~:8Ux$*uBKE*N~Χz"*ގ<@/et?B%5*o2Ѐ_y柄^1{뵚 `W閣 ĖUj[ eáN a$9ɸh:H^Q ^?e"&-L*ߎr^_q '"GQ]L1V NsAdKfAW(eaN W:cբa0?M~@ k@[ BڠKϲQK&ƴlUa QrYy-Խ;ru*VUבRcR'esUCVf.xyUv-j7-Y?cC۠"#K@ /E_C_z"ATs"RLʑy|AݸL* n"[aGҷ氯c|+6`BwbG'7246bvѣs`Ӟ%d+9p"bw`sPΉ3,8#^4r%B& M&Fg)ij@V?/bƒMQ迚6/i;6Jj?"F,DY4ګ[n}ʺa|:,_o*d2rHaM|# H q,e"ffA0YH/Rպ-k~rb # :GsҲYOqUV{<4p'F.B"zT!lW$<ٯuZ"k@%Ge?`Z"JmLNv5fǃ;y#% ?y|4 %b=ps`.:}bs(9Uz ?_߇e9O%~UxpLDv^^aGxFQeN|&}xU(=rF4Õ|w(wl+_t<3aAz0399ޢd 84U'?g[зLJo EKҖ+ Nn)n='PlF V*64D˃(v=:-yE,ˬHP ˩%_5Xr 7^)Ao j4|_ ZLX4os R#Jf&j/jSŔ[;Ka ^2r}!\.8~,qD%f`a;1UŵZUZ }..5y- E1E+B%=gw<+x$ۦ3hv2J*abΉ5ZꍃI6&aE?.<@!+!= g;*9UՕ:}!V}Qsb`$7ɴAsŋ gj ,ͤ؅(l @-HAq͆K(Uɢa Msq.dńxNܺƆqBR6-)7YRs&c, .L(u+M(DRІt 5=VQs%fK1-$Xt e,K^0𳈅S0qNrI=Cs82"6MXUaHsEEiGxOd )4VnS'uZ֏I(mw 5;eU ꂮzv]P3ZJB7E̕Xcw ͉t!K l\o+]BQ$͝ Dg" 8^=|b:J)'* *w/ >% %()TŤ&]Vr-[|ش%ZdoWjl3P|v]/ BA&?4~? Y/x3< aѡh,rG4GwI)bA`Ng?dbz;cORgG*FRcBp̙K`C׊k܃g.'X(v TG&;(_p6 Im}-^*US{gWs.ȣ:IKUK۱P,A]HA?bMXЃz.%]{y PC26x_RUǤ tr l= "^hf!m`4yf! '6?>: Jj(#EkIɬQ(t G (@lqh)33 }p]*5$:8\ ԉ8vhЫ,p}Јxj; Ve1UJb0? /Lf.8n2Z !vGp;jye'}~ D7Nv΃ñh+&GS" 4^<>?gGŶ)ewxo)ڔM< >_(i>>-j>AqFPЃR\|]JZk{($%1snŒp!>w:>kk8Q~jUB? Sgt$Bi_%&Ec-/w\[[u":v.τ 6eYcW'(_wb .n,P}=!\/$'2ڦ**j9WYGF&7;7B* tY<mh_Tz9!PM*.mV cޯ>ZYg"X7N2j!ЇZ!$Z=Ƿn܀159gYfa? r(wA_#d$bk;?'w}+6#.U.@C{CR˥!JRNU( Fvwu^;WKn&x/׶0ցd|("I@U-63 6O[B2mEuF,);A.z+2(ؖ. x^iv7^!*c, h Vڛnl=ڢm+ 7 (G&ʎfVQ)Q9 x+4cejLqb٬[#H>؀"nI8Y?ɵt' >l$#Tɲ2a#w_X=՟.lS?ZQZ;IAՖ+Yȗ6yDN?t0XV5ЍTdGuT!HХ88TalgFan {T:;!S^HGDCG5I.okơ\ϣ%Εm}y= F2 #Z *N."D:{`(^ĐtBH1wq/(aFk G7ɢݯ1J(P8 +|(RxA7s ΏZ% UHP΃Um螛GjWlC4gI[mpÅԜb3ݎv4y缸@)NX:o\0~f!j F]9)fch-]eD2@Pi/Yֿwrd3dav~f-偔rA0z8`PVat5F`l;hʹȴ̾im~:UB+H cOL^v?ߏET͹EGTAIv5A7]:t,^gd[e%2?fMҙª-H4/P3.lKrX( -Ff%#VWyFbw: Xhŭ6\-D}ǰpKW4bEu Ggc[F2"k!~=ƽ%nAǒ* Ʊ&!|)0; i? ďfBF`4+L\P+_wZRV:E";`h}(*wѵ "kIn [O] Fq\ϭ[NoV8zÆjkgLpq c,0`1`8_%T!gk5uc$#Ywq/fjJ4?緑ߺn&Vg{-f}@2Z0@:b3E$x:`Ul=ԌLaAOjLҥI[&Y~"o1Ho_sHZD Ԉ{+"%[4.{e {O2X}Ȫ$T`=a PUrbaZX]TL8WL$mf,>xm`>d75>)BTNՃi_RRxB(-Z r(KԾȋ: M z$EקX*#- G+ [f ?gశ'a8/eӽ=\Z4, wB& M!o4͛ꘚ{xLq{U -DYF#^4fǷ'u. hVg?qVĄ@m MaNI; dj)7MDq_Gi%H{͓$i{o3 Vܷ `8\Ol,c4/)ޔ>nᅦjD+7c9sp5։BDOnQ!3z\ӂ2E}1axvX..s"ߺJ:mN89rEd:.,Xf3G#^o,}S6l,>qpgALt\]St70ǠxsubFN h\H$%(*Uz]>}A,Ib2q%M;&2h!Kb%,MQzqE2wŦH2?f,:JWc~S=q RiPLh/Hۣv(`Iݻ*Fa/ٷx5M&ÊH;2fơa-Zl9#?ǥW1٩< a9={ Bd-P5I|q P$d/FXq{a jԐ&Ga-qQ=l 8g+pqЌqbmMQn-t_ûͧK<9JI$IMcC9J'DY\TןItTÕ44lBSRh`<}܉ci %txz@߂N@.|sbU4"C@e ҇1:¹~ljX3Vh,κ#0$=?u Nhݥ! :퀝*VoM[q)Ed^^ѵ1^Ms!U9?rM:#+:f  e>4v{#(TmlH%)wH(\Z:0Ӝ*hoaMt;)ߌ $ 柉v)6AENͩ <*+vV\3Xf|RRʸ@ X< TD􄥓ŰNrmE%sȼGVxW9ٶڄc޼O|$ݞ]tm!bsAq(f1J#+VגFpԇ3\0#P ݏH8<&gpC|a\J,2XZaC{ж3C#וf{ʗU+@ZQFiB)RDSЎ˫ɢB)mwA/ܕD`)䲞7tV3( (f],Go/l S83J{# 8MOFbvb6{^J1! 2&`8K HhkW..= '.t 61B}NAL|R !Wu0GYW/g^y{k IL"TUKo|1% 9R';F_*cN!p9G3lXm4ɀWR/T*]XJags嶵8Q'Px,ޜ<|Mlh2%Gg2C=9óPV|_w W w$gd"VqN^ѱ,вK0jP4_hw| Թ+kpk0Gj D V˾jd5=dũ> .n z+wtj"niC:~!{(Yȱ"`>;mB bH"ܜn 62jc?LH,lEhaIG7"?ټ K,҂u])m=v4NI.=&s IzȱQ8={qmH1e+ey!|~#͆)oWvh`Nf`W,Χw:T>ΨJ[o,"!Ns\N7E,)% P؅͞K>S`JӐ@5`I/`yw]J*p#^r@KշWt)P&Іn_)tpD%^pR3)%/[tg&'UL=8ѷY&H*Jcͬ>!`j8ﲳWI-&[vCbvrESrlG Aڇ}k٬u#[}9q;.췰F>7$Ċ5$i;hrOVq5ч8Tם [ jQed+ Pepˈ,`dʀHcQғ ="}"~=7%O[tؾR"Su| MN2hegcD󾎆 s /=xh1Z 11I~ O18JA|]XwzXݏ;{Y cU!\NJb $E"wdҮ(K M Ѷ@/~޻Xpŀ ]G.T'EOJo!:>:1* qoOOt<|w[+yf-l0k}؈vqP捗 Ze iN6gQO vqSV_z gz;ýɉ)]d2Ow8cz~tZ@pmKB~,7 ]kJ2>Z_\=e59z3@2r&"ޮ)遮|QYN^-;_M K:3RMlKvy"z1*T8)qѮ&*m-~q/оh4Ud{[DuvLY}U8]m{92mgf ]-}j@%HPRak'El_PDj~K?2YFN͌@,q77^~=GZ1Wd*U՟)|(.`5y0ʍ2BP6yƞue2/?MpycŻ:;wĞ"cǣPlތը8Vu73{Ri!NyV!Pm+Wǃl2!G 2Ov Etee滢wnMdADw񖫉0A(+a{b> jPʿDcÅz{\.zfzM"]/2gˏevv"0 *΃malO^ 4!Rbh]JDA}9IhSE UB YaHoCZ7 D1atr*D1a p?VԴH:OUYp6Z*XONs?'mD2}- ?@C !>& TQ? lVBE]^S_ ɂ8=w.C 2ۜ+ҫ9bKW^p{; ̻ hFP)sRڦmp|)"fRav!+o;X!7𚗾 }gd]Jhz4&av#M:.]%SLY x#A5+ QzlyusTy<ӵJBdu)]3MŽ@bv}򊟦!U6 u49-4;}̝mAO-YO(a8{Ce|]k?lKWJ)?tm1Mo Ulsλ_,VnxRxz<74I:;ch;`: n-*~ &IrZԨ2E_J'RXYx?1.r 5E?rg`f~3k0]I, t*8Vzv FXwpǰw&2GGdLʄ+Ol?&M@ uBl`*6IE&)|k=+DRFOFxUaX[Cu{9]i @Y^^c"@_Y,d5{""(4#Qqag,ZDr$&$JwHE,P,bYb_5[!NFi4jYdqU9WMN3&?;=k2-J_LC-t"sP־_;Pa_J`#Tm▎_L{Y yg\$ ot4%?[ܹxhfg%^;nq&$4,fǞ7u5eQ 1Hék[K!J3SD%+_9ZYŚ{S)@$JGT<QZ\.+ʻnיF]Tj)ʬIp0w-p#OߕƇ${t#_Ђg1]9~4ڸG(q~ ]u;OW2>)n-wzNlW옾_'x~[҂㡱q0!Sw=VP t0 &2T`*/ IiVB8㢅aq->c= JH/*˩?/Ah6://5f <0e_q)ḅyZ,J ;oC$LCcad8 ۓ}Yڜt__.Ɣ7pN9w ./ltc2(K6&V<ډ)1l \6bN8-  /xwڌà1|}4)= `x&1&Hk7^?xeIV{F*>hy=6*CKC槲cWĤ,;1ч !b|ոzM&Oy|6Oh-WUXGL\2̊Ƃ͢£q=0\R.ɕ=NqGe"!像4]LVZїsj>?5jh5ZUԛCw_v߹ srbAu@dx:vs`HYz5u-`ۄo7IA*L09Nag"") hHb_URyHm =vuT1~Uq$Co֨;wz{_\ pj3mɠ@6XJPZzv,}:oL,_Aj]t-3iؖZrůyE/nBorxiz(Sq1x|]e#գގmV YΗwB3Vjtjڍ~h>zGndzP9zpmw*FX8_v$%$i:8R5$;"qUU*>DW9qzD8$5< b$cQÐxf+I'gU(VA\@V{pLǩx!m Ȓ ơ[B>A{'ۙze!94DXUI!e±MXe a_ĵsТ+\/* ޟ?UƦ}wUbl_p0΀4Nz6޿2ܹe`hLUaXj`yE!(I"9Ҹ>$0b0C{Jvm2HG\SH{ls=W(4F7 O;R0<&F| 62htx%%t#sGVq.ZK\:6H3`(h8./:lP6WB!ܐĜ `쯿H]j*>fB7J{]LUueӳ nR(lÉ]YY(n@ISU}^Da@`tb!HFY7YVQB|4(4+!|gTΟCUĿGWtVaZπ 3\BvN2],A3iEг&]Ti&=G_H"2P8:G|+~(K_":^5h LǸ!eR|Dbc8}麡 }*1&fʐ=oj!]j aeLh^}OA[CHFz\amLȷ2kk pZ!Y0#.5czƷIbިw Қ7 U۸K-o@\)'ӟ#ࠣH/- {!n&ޔ8* CT]ӄzrCMyF}t&jR-Iff<Ta\ LXOE@󋄧џK7|U;΄I_, jcgVQޭ2hCZv;:OT^THɿp< B'mn %Ȼq}b/Q[ ϖY._v:HGíwKH(ӔYxlwsC63ՖS$F@մAldJ=?CCog|WmShS[:VCк4)I|O߀rJbY.;G[̑UIt =Í(١o-Džbf8:/ШL=Db:f}M :4@.$ o۔EJY3~f)c?*?pD2{F%htok7g]r9]8µ"^fͨ&6D 7̷K>j J E`A~ {D@iOL <0H^-`J{5@^bBv8nA4 2pGnxn.So1nU/i@m߬kXPhC?e.'F7hL'<#Zh sDm xAd/h ]i98 @ ]dN$؃x+emqk6]6gɺz2~JxT⸸Y" ]D,he%e*MJ%$d<69i{c앍3kПA5lbwmS>a8s f$;|y+bFS`#"3lbw![Y's QCN?.%*cSK`uNEzCݰ֨ހ@KW@l}+yX#M:fe¸3MA5hY2,XY<! -E RlQu;vlZsOeMp`2t恲&@~`G+7r6*|n>f)&xD=y|գ"%*/`хۍ݈̈N Z7NX}Z`qo2U:؟ba=Uz8_4zMm!hBy*:4罷{"% JeʢL9)BΥɪ8'AwQ|sB7I^S<)%#AEc"*v4$`sK$#V5iL4qu 18Jm:1!oeB?0!M %RTͬ@Si}Ot$ Ҙdi޻:g?!UUJkWn{B/!)= aYs8_lLrGXl^ y[tJ%d-KM'(V Par%pl! _YUo)Rn%!u@f5hJf.,a0mQ F:2TA AYH&9?v{ f~5j£tU˖/+ev21>T Rke(N#?Xeo֑fI1|gv7ӮۡL;z>fJ2"nKOWdiza/Ns1r!M47&&Ru3vXZ& R6 ?XCL -s^Ϙ%0G|`GF[#Ь٢ w`U[y=~G#i b#W,dh&&OFRjMQ]'3@Hm@M͇JNzRyI}&? { T3xW;uKf>-X2'|ceCۇuQ"U2GA<w;ܗ"%Tc'|Ja(zσQ鴟,BrnZjGll5ӈ/Gi( Ds|ͭl8AR#%*j[}8lP~=.+*&4Gm>Zg`8zrK' \~!SX,*#IǽF^E-& {O;[J]kh MH38zNLH&['IRBl;@*x4OhVlUt@jؑpCXr5MruSC!"(/ aI Qk.2jANUnߞ굚i:qxs-Rb%czUXᅽpV=ĩ_rPs$5\P,E+Ȣ&|>alMF9yEr} eh$60G*T"ξŞ8UBÜzL,F.8S&l pGB[_:gu^+P[^{W \|P"Ը%;Wl?@i=#P6MpZۺAN-4"lyZ im8CHلGp4QxK!B:Yeqb(\3N]$ q6X^|kκU^Y(R;7PPSˊ4,'+x0xd5{͡axжNM2̌V_)(s{㞱8O}V"fmvh(\=1V=t+7|üPV~0 Hu'22Lc:fcz|b +X~N+̓B(h/{l*"˱(r]#%/Gu'DL!U rP@^Mi+ xLBoT(`'=̔A$H(EK&tk)5٬OV{|5ȯbʋ'?^gtOJګ.sJԶS2څaI |Rj`u1 ~ۿVάnQEV;Fΰ0rwG/K>J>D<|ᕎdݥυ | :QɥW+~d8?qh'[BF>O"BPcPK)PL<Ʌw@2y.WK25I5bIQu(rohΔ,V+lJq쨢Hahqz并*/RZ=?Q<ƳcLSB*7lGXov^|H$Fnf׷ ub}jHۤG|d$s\[M+Mћeń*!gTi_r0M9ë;M B!;xu-|@=1 qͤ]U1s|F[ݮbg3h[Eb9dVZL !Qq8&d-,cT.юcIoSJvNyc:)VNI^L gKo/˭;x%UԪnZPMp~cFБP-Xa5y#Tf47%w Rȼiy7&6Ѷ@?튶Df/3/}CZ1=VdnzAÚ|+zsm6&EbOu6ΓZ´{ :a_ZgC :/w5mDT?_!+"Y{})Dέ pHG <6_3vSA3:ryOV=7fRPJŜ:|+4_9!yDiD>H@P̰AC5i(.Bj t0qO &C;J-ZǑFL nT@ GjuARoT_e2~޻Йtu9C%3o+@A!x; 4PUV}Ψ+omN5"E.^`>>ByqwƟn9V򩶟`&sQqV64JHz`̃qw|DO-4‚$(S=j"G[\;$"h]Sp=]]]܈i5tjy"5[10~~LJr>/{Z}"*lRmh$DQn5\#c0Qu.xd&Օk)RjE诙jD){t>1GOݘ2k86sq8;cE#cd# +˓iЌ I[Q=d hUst+:4D0A۩4W,'omH%:\ʛ)D>Wb٨ dLxjYx:`7D~yYF=#o2\ @Vdl ڼ<rU'/cf#פU~ט P+Rؘ'ۥBAʤ$ njV|j\؋^ pͶ( e_q:lD wsCH讐^׍"TN*@ ̱0$b qa}3`jvC;T`胬5)?97.i>gi=XgR\Q"a5xf,Y[#Ұ!ֈK= !%2ܔY:NP@5/|of)~&\HE= *FO0?=b_rE1 wqc06fQLE"Vz)(dp~`F—-Ը\0}9ո aGDŢF{,I3en]#{6rN-]3EUcv7+[k*oD S WF88|{n>b3XKL)n2ԋU ]sj|s)rzEp雧|3EY9<0OPdtf'S+-ql Wos0W0PNԪt~nKg/QP .Fo3枸82V֩6L[ck+6سvoXOEku`׮.pJ^ncmQ;yGm%~:V:i8"8!8L?Kҽ434̤o)X?Ľ4-=LHМ"n6tWq]]˿l`SXlv[w&xieiMcS[Z |qAL/936 XߴEw1x8=84c׵!/64iʬmz&.&cEvlZʾIS>‡ DxݠqN schn")zK=TPZg#^ TGNm@K9wb MTvG}VnDQ%B;U 9 gV=v*@5M\)5/F+l>d VsxPg}(iNK[0Uvs31ap^Ә + 3w7`GV+cl=`KQfhqЍ[c:l1S,X_UN41ls\QabQjCOlzcAӞ3 Ϝ|^m"Fm=؃/#l +k ͠  2z %J[P1z8r+* t{]tDv|EhY-|>09[4!uu pth+p Vuyޚu:+P!MN7sg2mCS"9[龑Q N/cj++8LL@ӏR X=y"yv,/Y|е5R؞W}!24z) S- ޷~͖Uݟ?TFoVfpզhYj3vE{~sS+u~+,}>U/P  AKoC$'ӆȨY$PaY:P=Aդ8Okn7"j nٶ ?]fVTɚ6܈Z?ơ6_ƀs& q'ò&սRe -.,Vqϣ1rNh $ǮqԘ tϿ|CflWSCMU3@}=zZw@޵?1!-vب)mY-lƂKi5gXAKlۢ:erY1DBG7[CIMWS $v Y ňM"AS8Q?$f:r$0x_`Ar.nr .*>wY-8|(.0K;,ᛕ1{&]6!ak5i0^cv nc|)idOxL&X{BVWl8Qvhu>՚i?y Pp'DIMMz4Mwxz/,sb .V~sЩ.u%a&7sS}Al \[(S\ۓu Gc4!L>s|z; n ȗR^ o^>ӌ)[ȳxȗF]/~ z)r黉Y_k'(öT`@v )<~ˇU?\}re ld| F= 1ZH.Z;XkɈPj}K|ܭ?E%!b)ژĴ(/p@>b1%R2LX2m?vl[`[pOp%<|zIӉ`nv6Ү>0@Z2Ϲjp>s7]?c֫k5֎(WUsJ|RwW^LDLS1EF*ﶗիޖ8[#|-$a)8DLji7@L "S)V]8%=UYIlT&ޡ(URax@ ڬn%}!.L0biO/J.k"H^RV{0ΠϨJ* 0 YZ*[XJ2VgR6 ծ'T?8$*Ou 6LY9!4wi,@l~Ӯlbx|gǦp<96|]"0\*hzC}ʜ,xr ꦆ+Nsׄ4/ij!U4t7̉ oOCSFU-|1i}^sCyW^ :קR =:EȨ/h[$"vP,:ؑ`_ GB0>c rrMY2ݖ\RpcOUEDY@=LmU+y4j4qYAP 8q-2LBD'm Q }˵wQJBL1mZvlbj>M]``W/yӎ r<]Z[xƐKNag4f tǥT[rhiשT{rp(A UÛ{s^dWg&d2|̸ "]|箖|UXRk5.sq8x2I?(2QIq^S5(2nߙ? 3!$—5PO!<ߎNw}Y[il5Bn}YIGhb jk6ׇbڼ+I&oYkUMq/O woAkU8H%vU&:ι%UeE=y>@|y-?"Ev/ST $ʔ 8$^Wk鋬na?6%v%"wx(vBnue4CgH/mƉ_>[` /V$ [9E}ÙwyEtTfCRˡ@\Do=g9=IlH,v21y4ZJ1R?phһo'z'0'@GtdpW{f򮇠a{25IfsG%I >}5cg(DCFJ#N+6Fja{Z_qy^ۋy%hK蛃<RfhʇuU. pd)T:QL8C?-?LX`CBIŹf<(c/'u[ V?6K;A{c>NĨ,TٖX%mM^YO,&S2q/=7ZMh1K]^yX]*COH쇤4'y|yf{3HD7AA+PU>LJgYί9AJINwG#@ J`p@빯/'mR7 O@ԪYOq 27GtDм78 y>/^ASVr؅#.8(0C]w\PaC?JȂv]!cHyLHNrhjH27WL דcX*_ßQNkqw3BFMH'M=81"}SX =*=k0ujS^{PbL芷\?l|/cԖ%.;s$Ur}j⟦@ S5-R6 /"6QSK"ݭ<˺HžQ*zlP}ĈN{z)yy}YH9@>{o[Y&_H ocի4z֬,l}-Y`ͦq$Z($lJ"% 3 z'{iTۥ=/zB=:L_( X*Ɏ9X.'pVbQVEȪuo @~E9wę\䴟}>Gk MRxoicX_!i2]hT@j  q;j |KKDg B1Oyì3scK}22 Ar.5~F3]xfR4p㒜t hi_s,>ecS{Do f=~}˶|nd!]U T@@񡍧@>wIX]ױb *V5턐˖o?:gn|go5|9(2g2.=(f~!;Ng͢,Gʮ:H$o;|0q^VDxtD]"& @WT*dL%x=2L7;V0e .ko痍Nlq2æ'[HO4g(u*/W.6BW袂tG$X톫Mp6ltocb9tbJͼFO{K.AcMN P(xZ԰hpT"Qw)ZOvJ4g26׈\$ӕQrt-x ;Y5,&U:z_S7k'93B[p,&HF2닐qu٨_˧י}>y" a2ЪC &f IRZ#602\Ql%uof u VY {o [~d]Kn0{jNbB9X:bظr5aB63b_3dTLA9~ r{)W VneIdzJ%1٫.KǵO;˧\ ʺ#. moy-2em|K*v.s#F5T`+  UIa="m^P. Eރr"s#I i 6w-`mxgsur]ޖεbdE)zɣ XO28ǤZO?O!R-DUy儎ܰlEyqԖW'l XF֮%26#fׯ KI<&֧6I6:h@鐦VҼѸ9k!Uv <w85XG1[- %M|MPmן,=wL|\gDv]Ap!.*3lbzLrE;>~2e)bdfyMKU, }mj26ٳ< xf3ܓZ(ψUBD/ h\`I.ez $qtF{G.: #q`ı"͡ ['2- *j6h iva7Wpcמҡ{c7LxS7uU#>]|zVÄށ!6 _?VI3f"8l .E+?+M褬Fi43NFjSSXY_ϯA/ɟP99&*ksZGl{Z-0rHdgA?*UKdr|7~*hd4ྒྷW{Gj^\-2EF",PEGB4?[fQ.꯳mq}\b]M~QK凵Qa[ĂPngW_dCE;pv۰)R; Bf%WZ5XHdj5RuneԿI7feDJDѐW-aJu2uW"{؜z/ֽnA0/)_@Ohc3?JYJ)݈"Ĩ4e[~YBc}B)uwsY#7a,鑊x!!fE큛ji*\Kȫ@AQJgߔ(>zHnPijzFvo͋GrXBc:U&λK.^۸fwR@KT,q&cr)YMҫ'ܑͪRT}4x o4}8JmJL~s֡X*Z &Q4"b(,a1Vyd 7`VvQ~㙞% ջfS_ b*mڔ>RI,l94M3OEAjz,Nh\s¯ PCU6=ݫu0 j>3.5(_)S~H_bwQ_qMT1]CbO7٦Dx#JNʗ9rN&I1lSM Z&5FǙh0EQU50rYmEg&2Q}ujSC/wEkF`!RURTl=A>?X /ʐ8eh!<-Dw SGp[p_ﲶpQ?й3gWOȪ.mM?詧ıiL Kl ܅q,vb+r5 h>tRs2C@`*e^ <~_/#-+a%$HT"B{Ws*;<p' Q1ϔ~1]Zb~B]_7Ue\t;5 ٓr\rݿwtсٸ8tPNð5Ng 8|iy򙭆g^mgQg0a΀\F-|sI3"7c=r_B-z񚯴C!522dS{ Ili^a#{+TsR6.ZU 9Se$TY[ltCSJf=^3EFS#o5 I&,X )L"dso^6;ƨR39XgsJpjuDbY7Xen㤰'q|3|439Oupۦ ] W-m曨jjBE5.Qw"8Ѓnj|5PF ~akTr6t˼MZci:?O?6M@C=O^:FcA[y(_΢y:OU xU ?6WF*I&f VUo` t^Ab D?rI&|Fa}V|_cP*_gMk:I6ã/þ$]Q\ϬF=X/}P!k, ;a+0O+KͫP J08Kw@T+8l-3 &B_nߢ4s/=iF݇ԝ-Pƈ cCl 9s21$l{D_Sr ''Ěuigi؉9U͛xx@Pq!7r{Yf~ :5/*Q䒴@r^ S*8 9jIdB?!u/>q!"nB^'BlcvռR2rZKP"bEPOƚgj ez啫5ƳfCvs-vmCmSڣufߊli,9b- mW?/[F/q4jhk`#wN5?lU+;Re󣊑Re"-XV?oG^|Mβ:$9[39_1w.kʊ33X}|G6uJZʪ$Qk7z"c 6G޷7i8^ ӆ=xӹt$8q]25z$’)t%v᪝yD i.%xmv$eCC@ 7(3 `d0"7oWd)} &(bvlpW`\.@vbuZqlIwFx {MДF8J fLCFH\UÅ"HVY kMH;MP^%f*7c᯸gs/@,1vP!%>IL0n wj]1{;^J [^z ƒ7!S8Ԧ4Jx5k eB- {89|iV]Aw _9x%tZ~}Тcqr5ګts )-6Qɨ늉K_86? n!|#\UEtNx$CBm{#39nmGth#/%96DK!jkj{Z}:0Gj VZILVg٩={$*¼*!Ns .AAS^gU`L*़nlkbposU|1Sj"KF~tSŦ'dI#ڃÃ% `z ՝byX{ guSq%?c[ߣy3M^31obyv֘dKXR%\G?A@pk+pYM>@lgKtO*C¯"Yz~DLBՆ{g&l[ӳ%?룿}SpJ{%2&Wo3=lV)HۡMPl_dUNEzi:)lJ>R^QM9E<v4Nw8KLj˃2wg9$۬ w|۴2t`*AuZ.*ċa,1C f=x52uб.dLfzjCP:#pbhb^$9ϘX,U/P AH8Dx,M4KOsO HUghaフzđ]m3yoPk"6Z,XHŇex;'9Nf]N,ze lgaOΟ'>>?ޏ E =_?{' |:G]~E%#}'s} =~O_ߓ^ >G~~VIJߓ{>ڍOu?ZŌ8t?,*%>QaY[JnF@V?!*~TF<-^9q;((y^ ? 5J#8eJMq43.}2Ls=oS@$1RT S7:|w-'dm3iIrc·YMG(4iokS~Gpt'2@b#T=k[P:Ye<]#Dp2@Ȁ!U\";0ng lUrMdY탲=bnvlѴB[@^h= K{nFw<7E! a;0ȼc+Oo>6OIf.;CFog Y_aӬto^*F0bΚCaNCgHŨ+OgpX;k@N͹ UۅYbmvy3Y%dapmMkhw ;U7tBc.Z#;3ow^C'8:]$Qʀ%D]S=.MN( x=rX%!WɐFx@dqhgt<2e\*#zxXwN^ 4!ݥF[I| G8sg8?<kJ^>4S{xx>;) 1 /Su ýLM`YXKMgP%q^-G:mq2i(eo"5Y|k`zֽ2E&(fj>[o ^8pikZuךw"լ"NҴn I1j)!AKJꨍ&mч)X|ڋ3.[7&h;B*yNb{bӡDPuWL\1phZJpM/7Gl[nf=%:"bdgAQPnfZ跜Wp!|%`Pg9Q"oEzǀ/﹈`n}:bU#pZ^Dk.)g]Ӵ)֘}m40>wO=w{ `:x.BœJHSu/qЏ5 6=i>\2fE_wD>H;ℒ DUN?)/Iwchlv#6i!uB'ϟ'̐O@^(өdV^8V>-"xR-[5Gy C20vV<"7+YɫN )n $VId\YihPq6!&!xmH hnnᏱs'tH]D†40J:<8O62x fwYrGnEK};?,O 9SD9e{f;ŷs&Uo)hjn i<4\ۼ\&M`ŲNdAkV }i{,}c}ʽ?Y(,y@E1]6ll(vqtxL<=)PBKTRN0㲄%]05 ŮHJ'¬m^&@KjΪ81#_95Ya㚆!*_SG6h H2鐶$4]] a0+e)G&-u[ʪy} +w|B`qsRy?}Ξ54^KcV5̇CFƐ]!8NqsbJi ȑ:TcGFn Vp6]>i+o')ߐz N(Y*ly;vVOkJD?hA>@{13e4/c16Գr2 18T:b i7luB- ƚ6c ?G+G\NwB+UcW(6B+9Ѩ`F& ϺqQVU~ ],4RiP\1^ |ex2Bs:0Oz1Dz*#0,-g|9j㗋St(t3K>&! vMKFZBŌCV7$ znaay + RvTX[‡Mbշ~mio f{"7 >ZP1gxTuBYO'\A ĘTG: {O)%;yHʞ0@#3UA!+o1>,PCۧw :Sv̈qJ U!pųrZ`+ݮe:_]cHR ΠD7L/J ~ׁug.XxqL^b`$>@'?"* .e$6$`!EC?UHu6>iX%DWY3o"(@uPuoostn=:6>'Ϫo\1:SM@-Sݲ N|.x^.uR/}¡La4L`PyzQ_u!Ҿ_o;߹*0Jß*HFCKs1i=z:[gߎD?:rȐ .CPUnxM87a&X9~ّ$>ew e3B5LQ8O`O"V)Z]R)Yio.Z@/A aSQ?}X#f5~=Sez^٦c ,"ERa;/TZ @};i,{hnl_R ˆ +noےh?//ԧ 8'YhBd`H٧yx<3ן5`CO`uS`,JuV0=<9HMM ] 'ˆ$lWpbwD,>+(q.{2Fw֑s",Eqae.UD(K<.% 2#DL- etw="ĵok4{-;B0_hJq%S7XkO[PoKV),'c@u,y lKT( ym ˕Oa9W6cWҠ߅~%1%hAkNGδ)x>~]\CP̧ÅWX'\Lcvq@E$pFP%7@Ğe4V*2Lܜu71 FC[.DC51b>v6G^ω7K,m 82qT+nzYzZԥp 8x/㺦tVY=ќvS{% =w)\rݵJPb0<+^rMbF/C[p+l=EPFԵW*.D((Zkf"鲼B88{5{Lq1c)Ixz^8B߄r^3=aF#N >s#su]F+S|<#0igݜW-vz^+B5ة5oT!.K}ZȹP^P ,선qAm?K̰1$aO;')%^5rRE#FIٙoav<;l{ʡg dLQ4m[咚;3 6U!~KTVRҔ6~ :> h!ftjhtn*-?L+V@M|uhS-Ƣ.>T"#q@)nΖf8`L5$ _m=;v< FN+Ы{)K j^.'3Vb DF_܅quC%+cSp3LVipI>DXPp %3 ӆ% BZxϦ%y튶M=~P|.xd2 UEJgf>&7W{!> YOm=?v8A XS   4>c"*5khFE.cUvKd2n?*ߤB(.ۉL/ ,YAw佪Q Dd[l%킴-bVQ^7Bh&8Ebܛy' jX_[&>9#9`&3f!!; OcT"> &i;pݷ^*[}ghֆq\t \}-6#"so96kd9O 7#Kr 2OB9Nrܼ.Yiz5mDu PX6a"$ g_&Nݟ%=[X R*^] dK1`!ǃ߮ lSԷOO%k 0^`_H=AH 2⡱"#fq 0 BhaO& {advQ$~{s>[=xZq'+4̮~ʼm7pׁ`!!*hIJ_!HPzѠP=à.XV2h ؆xI-u5{"|Fib.oⱁK(\rGB<;T*_l^Qպ='Św.G̹m9+?>dH.#4?њ ו;* ,tR_Ū܊/JyZV,x;{?o ?1=p8P2kp!; j%$ ZMQ !#R?AxEk3#1lO2;mC>tܺɕh1Nb,C I(<$ن3+K/ Ź.o'#4.|-x̩L IX-Gxߜ^mU9N2$ o8`cepJ `5Ү<%eۦ!2WJ˴is6.Fӿj-pe^?^. [(AYPeAp;s&M᭐O\;aӑf}>jBD/sp1`[ZG4XMN[t`*%n 1l%ŏtY{K)K#``]>$\䢊<ȍQo}+W=DG+c)i.G1s*s+\ՂzTa]>2| ._5μ>:S[2Zuz߲{;[tvxPNnB~{8>FE~cVWuE|[+cN .1̬F$q4|/ν#lv!y9&]WIEFa@zc Sj\ ӻjwj0(aY9u-h RD {M޻w!NV [0L,exbM6 cR_@Ι+E_]qJr#HIb֧ZVL(g5Ge΀q[>/bB ?Ip]\KvuKj7ΐQC L0V!ۢ.ME]F}lQnT?Ӡ, ƶ4sMނc8.1Z;5p*(S뎢]s4A6J_,|$=+#}a'1Lػԩ?ޅ綋X=qnБ\:P'W1>gFUԵ@ckYC~uA` (d?#?ӓo3W)v:Qs|qU>U7iAP5!I|q^ɞ:"x,t\q$k}2ase:{ƒ`yv*A4\AuDs6>1 ee'υ!Ys`EhRGLa=L2 q|ҒLd=X`.JGOBO2lCre' }0jLP|4w_'jڞYlL"NfPUu D:*} &w<BZ: eFS6$xB$S| ;W1r{áׂ2mHnN^@QXoȴN|z/~Bw83{7ɛ 昙TL1GjaL.ZHQ3( DUAw=%D#QFO ٔ=]{:3 9AՁTqc\SiB x*,  `"Ò|'^GLWQ Fo7A*Z{"Pس߂]!ڭ}qd: 4usX784rW>Dw@a 4 ʞR5Jt9 I]1 T#uYT٨c@xNciC4{Mv'U P-"SڪYͰړ@TG9F6vdqު0\p,a%4Y+V^Av0SH*SCuޣgo@a Զdh8]3آwSRΤ24_iXMG4@#is.F.'~Wә9TOr&CD/1-@)VD)hT -u4BR 1[0H3ڲHjƨ,u@j /kсc|8YR~:h6%(jf`s!dHJ^I[E -A?f`#6yu5y -BS?( , 7=܆77Bpی΍~g'?XejbeZg[x+qawnކk={ V6t.lJ ƛ@V+'XpcopPGp״0 }_^㿏#2,fNŲt`\B9VN2,K[ DIq:0a:oG>v6NP(hM36$r(1$gb3m"zRAzâz7c|=>} ˳hTS~Xg%^;TL Ѩڜ̔(FinZyW( 2v)?``gvª"D(" S~-,u9LGOLi\2YV}:''a6 mظ2Ww6 Ihry?V%Y~ݗ:}G#~dҚHqIb'ɥ"T5@+- USBX,Ba!ë"2 ZIˌ /#%u;/ch$QҥNiqL/;fX!CBK/k,CbkyKO)b+"[5n%$[x!*JE;xR㌎y3CM7qյiTWF1 T?9TjI^<}0WMtYR6[Qf!8Q?&P49mŶOs?5VEA$,RF/Sg"yH\4ko"D-6M|si;N9A"P:1[M| "%hSy2~b;Y{O  ױ,BKZ5$3::{IHМuڋ%PczR(HvF\/q]^7H^PEM˝#,[D&|9'߭sop_{k Iloݳq#@8S=q7C,8- !+ٛc\IX80fddWZ -7}u^f @S?VHN% 0}w5ooeQ*<4f mZӥKٌ>r[~oU7kWgxM0+ ޳r@Te$o!i^K<&]P?l\Ⅻo͓)iC65g^i}(19}4;(|^r Y*UUU Ex:Bn$>bAlrgO0q++A(J;ӔHu<2Ԉ&>f‡-gIH! K[ oMObU)~nEp`0$,tGVC +iwE%sA߰ASnƭ^ELr?~"'gScnerMaUGJL:nJ1\9]Evܪ+I$nf,_`Q@YudJ "kgv\uC$WIUuA9R99.*Vvfs[ /H cᘯ6&!tЃYV7tMiN }d v@C慤^t M!:*D$A[+EW4+SZ5Phe#ixr4-o cCS?Su2nf𨺘YO4>m0soχ'h*A L 85[ u/7ꍖ$ TCf14CJ-@Z_=!D4uqB;Bx\9's1 8`;w>E\ȁ2'QrDa$1kxq!?:91[Jc*̺g KA'%{UcmB.=v2 t)910?w'ͻkMزVmҤy%Ht-3VeVU'E=^ (x!ԒFV*ys]zP]W+2^pf'cTfS"N][iEfvdgO8v0t+<O?$yd>s:|S|C.0naAڐ9dopdP+Suy<~4ojĘ|?~b^mI"KhMlNjkQ2=A@Oww$^e j)^_UZķ^Tq0EZrseRD&N7% 5WB_Z9jK"Kz[2bDYo:tfl t"fhyȬI}?/ P*5(aXa.DS˯L*+EEZE! ^ @ouȌpb=گ#h _v! 5- 1A6GXlƵAͮ&)qzE,K4^VY#ߕrd Y~w}\wf8~Jgp$ WgIwJ&ւH\E~鱯ʒ^;>j\XOр#(TIh +nk7Bfq2 $A1E~r\1aX6kGB#ۯŃ|QQYO#W'P7t)l|3\6^ɁPG E;`j6F]V\?v5*[>VafM}9vĻajeܠh*Z h KAՆ=JZBn Q-Xrz~&R^|DT9Bg*z,q(e4eH:dBBzC؜@LJ:2``py"qsةۜWvn&©r//"JX:s[Rbť)eJ$mH nl]2Xg /:W?MFKC͈8A͍X/3KK ܆*qwS&a8JRʜc W/syzUmB-YRsoHrD[yb,*G?۲4yP[>p$ޢ-:1B5#)#Єr- e'&|^(HG6SH127z|?%zX<Х_WDb\KotL2hDŽOVym'<&{߃[ ?cp>7%b,ĉέ#s@!! q=uYvnXQC4DIY(&[_s!XAidx|~{ S -XMx?dhFQ.b ROBq<}m /*N]3;Vy UEO;b Vx"i[9*ކ5`Gȓ4{5/)C.)"W|&,=ۻO !}u6{A7"ߣb8A Ɗ xIX.B-#QR9s1vD(aTCbJE(/;j\34-s cB_P˖^?@mnA EU`;DJ%9}K{%LᲘ7&ӶCn #pt IQD $Ӏ"d|$[ڤ,9ұ?;.:7t'Fde8atL7crC1;ro8xu2]K}=dz*-f;,ӝ/}8/1FjR2kl`wm7^x:-8n"|>1QR+`scעmg.frDz#8{xDl>P/T RSyh]E6Do$dzi Ũ#no;Z^㴨EGc:S y'Zd.{CE[.in7mެ,W;Z(-ϰD2xa{NW2S^u0J~HJ`Z7'|yMPGG*1^`_情 hQ+ N">9Lw3dE+)XJ< I^h> l|H T(}-6I ,^q;}N'K̩|4ۘJlۗu ^iqF?ClϬ~P>7ڍhlSs@}RA|jp\BIɈ$։<:4 [݆kpfH!?Y۴ l g;SO"'վ|v`R#Lc8/7=Lԍ<;7Oq-=]-f(!ORN!t,r{#{_ + QeiC0UOݧ#; V^Ɏ_ރnrMLWD'jެJρ3 ,rY w[еh{fJSt(;htҨDk;"IMa=#(`|>Ux:nEC*S~&fĴ@H͍H-0ZShO> e'$r@͋1uMQ8]RnmFۙq |vZ`~E# q2X4SWO\}h.綕H/DE)TH9,P/ț,(lL>ɜ* %5ͮx<1n3O0QNBva Y}hpe~Nq Veo"#5'A??m=5FĹ⽶aICQ?p1bRqH{DBGÿ bvhX@k\-β|C+`7uҍhy ;6u(it=SFy}$ xWW5˸D:ikѰ˶_ 1 xb,gF? x, &y( YJϭMLn͌LLK~K֞i=oK5 4"~}W+N}rd)@T90Q#X1G|#oq;vT9 5:s A[#=JE~2x eA,s#cO볓#zzd&H<ť>3oVIc FX6{>6ow-gd=Ri8ӧJ^lvF%hݠx׶~YZ dt 7L=je#Գ-(gyi?]z0d,5%S!$̽26NEOΔ}60`ikIBa< F8Cf'aL˝J$ xŘog<wRȖ&'ʍEdZ`ͲSHm*0}ӝZƷ5;x}'ڲOmv*</QJ5({z=5r!i?\LDC: O"9"MqUbR_T(!1`K'7A1좳B*og _l ":JBv/ 9h~稜iɳ Y>NSIӏ@ҥf•pm{;c!TbJNm^vhK*Z@$Q)-ߧ_ @ٲŝ~;ša+SP贓(|,{*+E{N!HpÐJ 6g J~ S9% 0ls+e#G۶VNoIFjcGЄ l^;EڃH>P4%\Ief .T"TMFy3:%d=Dfy.GG4vZ UiHqJE&d#Z_g3)E;cO%7>tHG, #.fB`P \\y.2=|XpG_'^Tyx ‰+#KvlS5~-qE\_ U*q-~P>yMvG Vp:&A2ev kխbҗD6:*ٖdM{:;H p\*-#Tkޮ>'Du@F4~9A b.=O&,JsYI+_"GKj[:rLшZd0=P5]ZfO)ӁjU(ppţ+]On@]/2PkIAzTY_B]Z }X ac׼&jh]t<dĿR؃?jR_Ix~Y =N86(8b| g$۷Ս'[Xd&Bb[fSgsm/sF-j SmEYmj@7Qp:M*JV4[f1E'ʁ; m')1a"#b.hP! "gB8Ъ $P䴍Y^A$ǿȤ$$38! ]:"R/B#AU1p=b(]g_nXX>b\L"WcKg@^ki ȊQbҀUS@<`la(B-` Ob.!Ï9cRwB3|KQ4?[564b:r)ocJW% *Dbclϱ4Gvwe.C/57 ~S_ t#;Ⱦk^ԥFbOLo7wZ?RJzX8w@ҩA Xp5i{ (YUo_ ȸ~N3"D~4[wNătߩfџN<%aOEv=މ7jy5Ԫb_/1dFW,v!~ 2$B8[0goK?!5*n ULSÍ#E-QLNcWVm2-\vUq\]WJƏMy)o(]}iod|Xþ0' eJ+D vYQAAv^,L> x@bͯ]K~`!(}ݸ[zOh [%皿zqWCZQVM=a|^ڕb|[D$ۻr E: %C/ii XI;qόYp>s9ֲ{8\VrlflD~'[A8b ɿqD$Z4jbx[==L yx |94?o}/BMS fv*)OU ̣7g构(EA{Ny@aM`s)R8Hz̍D_YٳCO{tQIm,PEwp_]r#s8%  ªxejv87Q=X9Q$h[q( ,x)S2`[R5:od>b*qO= _:2yc lV#phyw&ryE|ѷLZ=O 0͓)<҄뙲ͺ3X[5wDyC#8!1\>[ƻh0֐/y&Dqǰ Fu_Ev=-}CϊD:տl"b_jR*{0M׹V,F>vK^'~]',xQvѲ<4$n 7k'mnjEIV"YO}]/C5&0?6͟HLvmb)9\5 _;KJ0D%*rs|cG, V<:h;['Օ#tԄIg4c,g=ɩCizlyGmp?Vk٧}ƴ kO^N,YyJh@o> mTy! |A%`:x>1@[)o0e=D{Y9k3'Cx7E]?2}悼\;nˬrj5FmꗹdN8gB|?t^ͽG'n8hk /uL7v @U2D)SwFMehúߕ?1t]i<rt?<ɵW 8A ڗʼnÇ#NJ8~IR vTύeI l48!bD{%B}x"3p=he?hRG7q \rO^<eԫ}F)':4hD%I|k>BMW!0% bCErbT415m]1x[Z.0b1\uP O YUcG3sf9xeLIl%^~\r2:CMM%4[f̺7i:n1=TXv>,M 8,ez}+.>C>DiT0lx" ֋9kPtzLyw =};uʠ׿M:ֳg}9隃/8s7`#?̻(FS֠)!g .G)I YA I@Ҥ{1zrVKp!R- N%._&e2+_w3hƄ.3 <=S]'9%X)~tsB٩Bo} ;a ۅ<s7`_]f0v&1Yy;Gy/l7x ǥJ#V{ *9]z?RONnF36J58tڃH! g,l=D0;NWʱ7r֞EoJӳ-t@ѽ!jTsPy qoIu#EoNr&p0ߌM{eڌ-"Z㤸]]:b1G ]wZ Y oWiۨR׏2Fzb\X>sm9F >с% E~N]df@]u8yQInBm"R+o44nMy5w~vF+5+Ze!Ƃnu[,,Eo\4i"7YNw%J5[7']rm<"$[NkIedFҜYDɮS{h,-UA:?AgܤW|{?1Ia$`!aA1y&kJy6w_J6D@^7aGXn!ŇpC11LWGJԺDn9KQH0#',Ńx]nse#-cwy8=n.JFU62pWh`s@И;B.XؙGUhs'Zta|X?YTAmƋ6< jQ?}&B9 <3o(QCf3œ#P$̨ qS$27pT/r~$`'*f{ߺQ~yA dJ!+6\B)PrL=0Bެ#kQckaW1f3e8lzGF݋Al6 W/ތ0<U_@<V.M%'p?¥Y3sF0>h_05|5oYcjSB;})FW醦g ZJSZƴ"˴lOMßdW^,Ӱ s\Z~qٱ}W4ǻ&2WIk=ukGTdE* a! ۷Qhb~V,;$4x}(jxâVvrHfE< ;w'vE>c=|)["M/ Jbnr[p3 k9H-L<ٻ"OV|TPGJr_|=8_<2j*H:e]Ms]YxZ5,eKi3nJ"+OLXH(-IaO5Z!^n=-N/2PWA{϶ 9! WY^ghͱGg}0l-ݱ6M퉶DRʺ[ /ٽD(0m&`$_}>Ìu!`JSf| {&& ,jR 9]<|4B!eqY>l_h)_܃Sְe@Ki4 -BP7+Jcuݥ{eQS|Rj xRJ+OTy 1"W*k2 (M {%,-K8%oѩ\L7. 4 r#6\*#%W#qm!9#2AS?f*lER>k20I*"o\Ftf/M -̳4} I:-jܶWLpyܒڽPH:a_EN0BZn^U~8]@Wp,p0RY|`\[չڮ-i)hjDC|`yV;BbӬq Ca=r$yPd+)c!趾vt]]T\WUӵKBU&5<0t]4 xmt(t]AhN acj :=&Lo[(Xm58nS}I4Y[/p\ V+iP\B;d@E9G|gI1^״T e]bXw]U18dIAh]7 r̭V?A*bmI^>NZ.̱Ո,B!r|>Hg;![G/cj Ḽp \x>1ļKl"M _%>Np=づ9?7 Fe\X3p&:~rBɁm )m΁i9Jcm cmUPO$MmP}3,ys|6Nkܒ? o?CZ<\~S,䐈)U $#ۭp+ 5lg7#doJZe%)~AsZd%ǿ 5x؁N4Xk5Ԍvs.9~~y9Ξ hw>bi WWnTn7ؗKL~yrĜ ;`83bgį^>1dTCÇ:Tg'Pt%RKUUwvynz8P\0f߫fU&U}E4>:vYhS^CJ|5_)Ӳ?";1[$ 30Mqԭmp [H h♒ dn%L"\Wz(-X duqCWҬZOlj^ #l[dR <\GmB,,=öC7\xqkvؿrg(Sw$J]ZB\2aÙ;=(xdzܡ m/{Zoo"-L8nꎔS IKN#܎N~:&ު-fSk≼zщ,9o|$&|<5~-.E%4NђaGc9`L &(lKh`V~neAj:يݿgcդtq#-$h`27k7[nV61`!\z>kDH*)Âۜ& '_pˍqk _ZKI4MtRl@O#r/8v+u(8Ȗ羀BnKNWEHC;W@_: )nOL*LFWp6Yxc8+hE%а׮YD8k:#W;DjƂ 9 "QXLi6L!O~gm>R$Ax.ޮLlK+OvqeS'0=q]~~q,<ttmG/gPh#˸TEKZ4aɂYHɓECm V…K.m>?XsmYJEaBZ%9}u3\ram yѪ{ܚkdFt<iPJvjBSݴK n q! }mtGw.XTz{ks~|$Ցg$gL,;|d4 MH7jL?xAs}MD ǽy 2W>|Q&C6j^ǁ\:Dc@d{_K}g!&t.-S\uR \־;8Ju<,5~#jB `ppJ`<sP[ߛlr@ m~d80 ʡ^ T\dZ|c^·xjL#!-jxGR݋Ը:GW9UPqo!.@OƸk"U LخG^Zd zM3s] wɫj:^MKWS{l\;)P.0iXSo=%[3„*[s QC͹%S`~c&R-{%CZE$Ѹb50Ư"7ܧ.eZzx싷D_WHDv;T:vXn`M2Э9&޽1aF( q?ChB5}|X],˵;]Uh#Ej ~vVo 2zX͜aDǕDӨ_XJߺ 0!a*"Uic|[:Jf[Ӆew\յINԕMu[JD.OKhv^ OTIIho'>/*;'fbiD6bƅV F}e99G觖fšA?LL $KjyKpː&DsQs ^2t## a͢%B$%AG*:g;,\"N:sn*?l*UOB6tN6Ekvs1Kp*9gO4+Fa1ƦI=ؚY(4܄ `jū%Ns1 L/v M6ݕH| 2Tg_f&vUhu\[s~Ùtn3yMBĦ1?<}^A'X%/ ĨN_`.K$()iaMywd_ 5ffV2CT-7·4c2YI`7+n9f`kEQq:[[i üAx*p9 {' u$0 +dCS + [1dvjQ#A{b!SeL[Swe2qh܋^# sΏͦԊ9nȨ) ~f oI(kqf9B]y!43/O&ͿET Ҿth=Z# "|iۧ8|cHZ,z&H#: +(UO RXITXU!̀ ˊH \%֔w^ݳB؛.lP@LR2Tp TZٱQ x];t9Xeݪ靮L8a@J}8CH&5#iW.:Y_#+t-z>& w4Lnd0^;ZI>z9B]M=x0SW8Z1ЌP\yETƂ刓ry "KRxq_[0J,4ƌiX4E98&GߡaN714se#%X~.+N8nŅFS R7ML0z͋r=R|c׮nG#_` 6-Qm-NXg!])7u`=i,X|'fʰC=S"]63p+HNPYtHHbQ@u tAg|o҃wyܜHlrccYu%2X++nȵ_Ak eZ%#DJ{pϙDD񟦬Cl*sKF%N4im8CyqfSy/MNVy|\` Ɉ ԫTH&͆)FȲ  S_Gi2s'z3;fkwr̋q1aUbY:ؘ7?GlD15ObLJ?m]QϺAT`m i,ȃg5華O%T/vR+,](6/ڏX}A̻9)dqmDERh ~E`HV'07tR*DWLTNYaR (XSIǡ REؑtو2ZSYNEd2>]ѯx[[{Ո#9Mߍahv؋:7ʼngfN[-)c}^qd}x.4SG_z(F'ۈat.ÌL͓C&Ba.1[Q*jΕcNː\2C]nғ^ _M AVbԹtKLb0 ȆU ǹiE@. ;M j[c$uɥUJ5.O} <!_O;ְ;9&@?v.,xF-)S nh'%q4@}Uי#clU,ME-V`1]5#:ߖX3~ 2/xhuRr\9=$2> & zopIljT.D-]**ϦO^/ ̚{H] 4Afv}t/E_ ͻ(%8 cY1 Z12A!zƯR6xaR9HG5Px>?y.o廬AńyA$fm:i}WktMԤ&Ls,gJ|2-B#8߅+Uf) g"Lѓ?tX( ۳;CF Fh_(w3i =s;HT}!p~iM$e]*С͖객Эy_q| \'xH&wFAć>yitet]ХaQ=pjCs̴#znC8!i S}2"6mlWp/tMc4Ogv9+7QpO zIJ7c!˦7[y50C _h66j~#}{48VS=~$o](8ۏ*s̑ds#P1д`ŬHV4tQaqFEɳյNq&jnv *XW> 0MSQu.Y؁Rd} ӘP>û΍uGs_mr\+" !8)w~oYu7tv`Χ U(g#Ř [8Px-X;_tʼnj =ҝ+4ya28rrw} "; YBPrgAy$?<@HEb\Dܮ4kKo^[&_8AY?}xC^@ނۄNKMK;b۽G̻4஧ZapJ$[ep k&l 뫩i(+j+ڦЊ:wҠ6)@H ˢ=88SցXD4Ia ʾ}OQ- o E=D#}okFe6~n,@IHh86z8$ͧoq <;8* c LU%U9T5pBo+zX~%>ʈ?oKdgUC#T!\[NKoG#k`$cRL:0ˑ xVS#9DHDL})t34*i*kR{FVO|Xt!"ڎAg6BY7:`鈳ݺH izU&9閽2a߽癓 t#f_ /R ,k?+~7@OIK mxİ*V[m]7OGvW$WahaSF!qs­<=*":ɒ(2'0 3`cIxG~c!Vzѓ`|t/;JE7_^#*-QN`k21{KsO@wD H@9p;. PzDo-P ^*IbRn=A9cAIau̍` c `k->X;@)Z{qTrc2c|``lCÄ-aI2F8#eVA=N&ϭ[1Гͨ`zڿŻ5rԪ$fD [RelE.jT%ؼ"z Yh#x{c *g7 sŃ.N!hmYcT1@|Ojɫ3^*s*:z/gC^qxJA*FRhQjA.;e%+C$W=2g֗K6.6۲k!O(>ԋNFY%P{/)W'P~o #HsG(Ś&xŨP⎒ojƓy b b(B+Z`t!R?>DţɌ,A/sD1ktL\NEuM0)Csp=A-ahk QYUF֠6N 8CB_Zx@*ߋ|-:mb΂+EZ|bjL{fJx=)$myl}$DfqLf7B_tSsb8$䭏W&ʯh CZ3FnJ{9W7G?|snbACHA*HtxF5Ae_L 2mxmA:16qCP=AMVewgcOkӻ^pRԙ )3ņg4?`K:ew{'@MqTORźA F{=ji2\,A0*IzҢ),5W(U'_dI,u9_,PKZ64,naeljSbMk dMk\AlϦ{( b]6ϒE-;%uگ3}A 5T,lSp/nQ7;W`| ~:ȦNW̊3'5(V}(=Iۡy}!k -!;VS+w~{CAҢx *vWj<Ǥ(t.1Z/UXD<߽&N 5(g{PE}A M^9k=p?f~ӛL/6LϮF.?T:DKsF5֩ bv-O-P7]N2'Ð7qFRFDj碿 ŌNQxܑ+?f ߈׍R|ؖB绋ӖF Z6A&\]#ĮSGfK&>S d.%|O1KUI9"UvBwmGKbOёtaRլO}ٖ*/\n<-uZ1:}:2"Q6{RD9k}eb3 \6j}m63&_> Cʥ,ߢMԄ}\c.x5fgpW8h Sgʵuv38P"3,ˢ$9LS߫@9 u]w4 n5RA$ߒ {fk7ЀkTÜAŸ;3=q%}_76b\]e^ApWӵ#5 ?Erg\$j]H@)X߂Is5R-7A>]uam$ւK#ƪOvaAF N(sFNʭg :$5VmgÓ s I ]l6e೪ 0~u8 RTkN<$Ur$ƻ Φ 24F̔$wMrCk,mޢasVwA7n>^A (CQሎz;$S^yZt8s>=G HS,y #B%@|]gAx$n,;cKM1kJkj. rQR naME4N1ftۧL:`T[O5#Ǭ$5W#.D0!گt(Pqi: !.zko7(2v>Kn}Aۇ{gvw BhK5 t 6FLyxo|9-L?n2=aXxhD:$HdB&Qڭ 7l52j 8`x=[{ةa}>d_BOL]Xd&<+C2EL0X@TM4E}yP0rnj~F ts%ZePn0"wHK-0ክ2-cN=ڷ=k؎x… s!^݋{KEy:ŗóˆ 9ZHn]_Yø)^;$<. Y‚יdA˝7:&3j2T5:\ʳׁMӾWn W5zo،;(ZTC|)4B$ԣͶnBd-TlܢXtzGm*upY)t~ Vѻ.Yd%_ *)k#,B謯WKA8P17 yW&lܶbmIzrR!e=v\ q?z 'z^߫oz&_?/ܦ|>|^Sz&wz'/ W|z QQ_{zZoϓ{>Og>O>2|OY}:+XSX=^g\b16Pp:tHw`W_Ԉq\W?ȯ{}RKǗFQ`%Q ,{*vm"kOKt||Bb1 ` gIRѯKS-c'y!cjȕ<}m=fl(*\4x:)(x9T?Tj̤ОSVM(Š9zx`Z<vk%Q1:7L-o!7⎜c(ҽ AB,Ydu5V-XfwysFg_ay/`Ux6 t(g X#6`i 2)HIPoi##\;woRS*7aХ]Z:7V`q*rK(= Țn#K`cPg z\eb7-Chga-C<,C&/J02h?7&YVZXxnQv:#9g\} ZiGM{l׊UM4j݁l>U.D^ AٜGĮzPcGʧa4_ |ψB,< q xR gD\/3q1j U~AJxHSϳƤ\[Wf\÷ 7W;~Wyٷi~KYCfL@sbS=FK, @T%PCkqw,?$y<ߤ3 Q*sC禖Vj!:8=;MI_M]]`@*jŒCpp|}4#K=S+CWuL9 +ˉ2 yawOk|J=µoI[kX{szoĦ9-u%LµݓC7zdsuf`}S o~_WWkl0y2<|(6_R%D%ǚ<Ʊ=̏`ӁCM8>Qj-g.%^VC| bn" ©LXw?QY$}<`饤T8V_Ir/ٔGnnx|1cD}+(aOcƘ KpN0AJg΄#bڻkvv'>n%"߮s/QKKɽ*\1=\uVzUR;ިZXuעM(Ӑ5!Ō ^)ٰG9PnYsNJx GKO_m}dD*T4GF,|r$`[G _ -ȩE]0iy vmS^9 1FJER3GǼ,&%@7<$d=m>dtmˉ'HeG;$ .x3*>;iu$2rE"!@ TQ,ъXK\!=m^l4-2]vLR+zag e`0hxo00^vOҜ_AxN!X!tAp93ԃ@Rkp,bC HGw$)A'z%@bEFbdžOGJ#9%_*l#B+o=) ȓFtՐYrMvJ͔Q+(}J7&7֤!q]i5 b4v;]1 gFzcfSVAѠ| HvgbalD[kp!d:FN[aUK5.kJ*~>[/Mw4g`l-t o+4aJ!JZGrjhBڹv_os6K@7% EcG[q>gݞ G{L!VӿEW?2|YS&rOWPLؽv&s.$8 K`r/olp G٫X Ll#tY]X/F2>[2Z2qHoL<a'NJq ?O+Lڸ$f?34s#t*L ^@糉BI,'H2=F;GL#=[Ol;z<6ZK/bGeI0DFu:U=HXNk dC'aG=cuQ˼J`B2`fFN $%Y[8D3+Lb;xςSlD]k]U"FFa<7 GS #tv b]0o: v-ع7rM'8 b~"h # 3N~0)N/h\qtsE8 vH&ԏ(C^ Dֆ%F ԅ^v{'Lls?;@`]РF bǮJSEeC(UxsPq{ (Dv}+(B hBЖ+؍ ݁snw%KOZ(NIwq 3øpfԨsE\S0ΰ]eZޜ%Cl"\BwC{d -dVnXzN[I,s{'X߾V0ʀ-hi1߸XZa jL_s wWi[]!wRGiva@L`k~c Fvŝ&8/A2Iu sk cQ*XY,W6l@s1Dyi&9Zk6+_U =SI:f^RdanQ3 IF` ȶHgvj:kQo%w⣍k1IZ8;jzG+;UOgh{]X7TVf`)bt7aKL .$d~ϙkdO!`nVׄ2jG)@)!*EpVtR V2r\2eXܰ/ U?6b?/+#|Lf0ht|fZ %ǫo3<azECCvQhX`/K?Z}Bu;u(PKHq]) G!"mޒ-l67XڍkV(}%lM,PkGʵi1>@6&4ì6e)S˪@[u**nz\* C-Y-zM_ϭΑc{oTAxJɬ{=M"X8C<;4f`ޅo6 ù&D盩8vD^ gudQ,]^ .]3wȤĬU̳!>Tw* 5UmR,w{;wPF!yA-81J gע]V98(sorϳIObXLkKKZN:A %U" "=y5BH=I$*Ϳ/n*>6_Q̵QggX>J/ B/(x5M2|-F퀁_PpQL!* dTvO G9[{ny[r,BXS%f"vVH;R;*r:\u>0,=l< Y[~nx @ ~{^`060k!nt2&[͞Q3@Q̈>XIpe$nc2qKC% -NMhJ|WոZ45s3xљ9}@55@c|[@^eG,m&Y4&|4vx^RB .IT\:GaX_Eꗋm źrڦS.%zHigҴXKEڵ3fY(D"yk/rycGfP lMS/I*ox F8vLzfJتОD]hk>]6iU69V;I#^a0&_Cl)Ӡj hr[ $r/Uab +VN^l ]~ -dx^ ֚ 3jFOHh_Ӱh<魰W[Xv-bPzև*"QBǚT8uĪID=kREXB87KzTbJO!&r]֘Z}ec57B1V]$ŏ|)\x[JW!0VƋy ^НXzl3[DS'~`X0Ė"($J~C>XɣpMk9*e?W-[E/7UUnv |CoLUA%awn:"(|: >-!TR `Jnw%f'lOtڰxD4q <[V'_[aoc/κ{ =cC/Ӭ_1|ٻ\dPrr(Bxj[roG; [N`\{ݵYr D 7Qh: {ziwЈ,EnV;7֊hj'm%L<He`e;+_gEdQR3yaWQ g`}21(ݜŁR?R.8}ݲɵN,`XgazTUk ZcU at~Է]Wڞ*?!(Pپuf2rfV֘Mo;@46|Z%ԕ*K5нqRh3 GI|3 5|5v訠 ,mO4,ŽUx&10`gL#O(dr / %0@i%/T;"kWcP[oY'/p-YBJB[‰E/V.v(AfI;ìZ6l/8klrެ`Wz '-by'I[<"@8!{qB#.+2t@{UCm9䯒cojyl Ie[&> FEACڛ6a6$ɘnsqfbxxHRr\)u| \0!CJxdn#gGܓκ^Vk bA`"b8g [R/m71H-Ų{>0[AoSzNcG3g\ю"@i7^ a<%5]#@jIDY7 _D 4) mI'x܍ٔߌIz|sOp  #Y֕xȿX΀TҤ]#TGjbI*Ŵ:|>V}a>\%]LXYهUA _\ y6rk2s _S6ZU lW ^`I6zr!/iSԊvpWX9ӡT`(*Ecx67,Ըe˗.EmoS*"B2/y]^0bbQc=e' * xf:r$)ntϞPM]v|>%@p:Rn7:+Yplm cdߩ \u֬g;Td]d=9[꣞QKErOçկ$=+w8/5 \r?lqnQWِK/rv%e0g:'u9Fɟ!8?# =)nyV`~4ΑpfA_ýy?-swk$c&mot>0`yi6WX߁y[- NyAc;?3bYUxD#ѥEJpwz .g5fEY9$Ruf?(F{յ?߄(PcA?*~+-%cmJ0Z>=i5E2z&/<dBT 1suV;0ֽ"hnYS[?ޮ _[!.uo`sp37J⬗?5R؋7Ԉ TI~$gM*f}G{N" f%-~Q )\-J~q2fA gڶz" \[l\t.mAF<. ͞/D+nPڙ5}t1, y7A_]̘< Ltpqi(J&2>i ѲH6k$.6iyq` d%w)1ps͌\HLH!P kSdojn3|%_`0]дd2I|um$݀z0Auׄo3>ŷ]]ʫHqJnJvb2]tr|ex{U] ԹIFk6J؄:r.i2KZ?nd'zsՌoS2_ ԲgUНfV}sū^ WwyLׁ H>9IA,zъbNi8&V0h)jWnGئ&1Lɔk[PV Y1*r;cM'N2(w-Ga#=7X6"Xwud?2,2 z%]qB41U7Pi[|{ьк!:.[?Yf%8ьX#J4_Wv |`+p;|q AQ06Xh] (S)`z0`@W0Ph2'-`M-tYguJ⹫p_ b(uDc(=K;eN~vw`!`[g(b쇻ӧ~6 6kZ@ujPӆU[ U{d="\Kbdu]I]o -3'Qߛ=_O[?mW\šQsˑBm$^kGw@l<'2Oӷ:, KX1 xi)j7Fgib%!7Lb݊L6% * miB'NPZ {V䳬A IVqG '>E]?S[(p{n.f3`>G+A6,̓:sԪ⚆fa $,E<{(Cg`> }c (8_%X$W PӴ o'e'L&^#e,fX o1; ˮT&+Ú+y8&K0$77 ĕբC"IYM}fkOX]Lʽx՚4V4umῖ 3BKDQƏf.ω[4dkp QOO~bvhX$u+CWֺ^A/,%l+~BW4H+Iݳ9|6Lt׮.;Ouv'bңk+2m:L jG2ƧԚ9I禓]Gz|UЭ; ^2lGmyLْ{m%:=D~=-c"zF )`^ꭉsn= n3*2D5~{>ʓl&j]-K`UJ->'گscJ;YȖp):O yW@at'ucMw uh2^hMFʹH9N|rީNFWC4{c47& mO#/M#hRЫRRts#Ւ9~wmv0x zX^uC5%p!yxF0+8:{A`)luv29}> 6 $P|=W&~AXzLsU|]=2;T7*ŋ !#?jt>KX\]Jk2^ kg/4фXa@&:8xft-ҫ7M̾P~Wjg^/:XYEqhFE,Rm"K&|Y Q9Χwu3)_TgLotN0 w2"n0*=ל??ˍ:5yhryߏT}1Vc'2-*ӔT:DuLyAWz{BQZlVH~`ih?>哅h:F_*0<i?7<`'=NÅ|1ݖSyi;}bvUp7.?֘!R`D#H>rN|H1˔Z#%FGBOs?4z1Mp) AS¿Ӄ̦%v5ǩp/PM=W$()vnti /LTZRh8f`~%BJX/c8ۚd@7S̎80#޲TZI金'ZX#Ea18_!xB'G,)Ff_o[ui`S ;E4M}2s؟"G$z#>eAm:p{_5{bj0C=jot%STwH˭d׶]ehcsQʫPbZ_yBrM`Uc%k"5s8SmWN= cP0mnVQ¡͈Q: 6" z8- /&!|>d@@;rru0GE.GeiNX 2Vbd=mVlaX0dAD^̵P4Rm Oj \vAaixNN{ gilhT2,#Y-<{+QI'TyFU$BĢt/T$)&ZxRXNԫU.a=)Kza7I8(NLV]|dPq6P"N,a7#{ Sn+ՐMvfk(L$bcm{ITWT]|#(%lM8^oPJo4jjq{`$;y\>dɀ(IK*/Nv'jypzPh5%@#F9w$Cx{=ཬ[5H9f차W‹.$\̧ 婪>@1<^S2 o NҜw@1NMU1XY  7or/DG^m )T 6/ܸ_` <&ܹ QL94Ò@ #+qm,agdqY1&'7 lm~ˎh1_djIZMt(tʳ5:z,]bJJEb]WOV Ֆ>3*֜1!+%ynO>8{ìfFp"T w(vo,\K񚇇fso5FTYN3x.ܙ%jA^lH޴ c/*93GMvYWX2*:5P$k6E޽yJ7 =,|& m$1:%>*ง߳oYKߐ/dIHUţ9.I7 pp}S;b{ľ=gI;Ѕ1 ΏwJwt򵐳'~~ fn< ]/%Ne=5'5zUA_c7}㋗T,.{GG/ Sr27l ( xQseL8 8唞i$D%>dJmNJ)0^G0jbh:"Ln{ԩZp,Km<.3 ipKbl%O(iB l3&Ao&jty@\-D+Ք)4+mw80ၴn,Fvw A 9Bv4|)BS J<͚ vKemߣ@/}Xߩw`YSw|EWڸVr*$7ӈ^#+ӢD+X11wnXKB}}3/sؕ0#<3aLWB0'ƈJ1c t~w ՟ $c3am&"`uS:"zK=i>{>}OD,=zNۭ-]?3j"裠"qi2EZ;jFҜY[a,;cK~[6-FuivEרW%UqSQ4cAk9h#X"<ŗ^qTio}`O$T$M6 U$C~qsg/:B,mvTu}0`&^tZ$2EВĬ\HrGԶ9juPP6GO$\kc^z(blڳhE"dZ3Dغ#E~_ :we}DzcC k옉_G ߡ?D7e=b|U>dEMl1IlE l[Mcc))>3?YkuMS;m&a6S-X=(+U *?)r{q0h'S}W6̑NW*bMr8j<C"iFa*<,r:m"K`kCbryЋtٔ H%YyXB]}̖o4m-:}mp00iCsЁRpI~10}IGXgA_%.3NF@SӲzyf}JK/]vU2ȴlnOHUa*RCƝB n.~6+[($'z͋*xf:vС|DeNm(V)8˧hC>0Dp8DI/ XVI C9b T%pAx9BJ6 .ٞ?<-+8q<;#)uaFoS#rm@a]~~KÎ/^ ;G'W7⹲Uĕ%_hW8pJ*pHĄMP}jZ~qr'04L\pBq;䀇toKnRTO+|taDdP}Mtq0./Q6ōktm^`Yq{ԚG~H~k~ jV4"CKhiN) gOc#.Ʒ@~+0. ŐZ*[?4뒨i$%{Cx@LZ+l` qa1Ic6lTfdy,, ,QeIPO=6Whߩ")<'NPNj?*U,Wd>},Rf ӧڗN}ScHWk0Xo5_)ub«Vlpv(\ `&}27Ҙ&CLZx!AA1JQV #3<"Z暰n':Z.,rDW]>|/ O[_Uw7|W% ;MpC,̄55suqbYI!1ʋ_4.Adz,,7CULmww&)b~O6-DTj,If]dw #SWR4E] brt  EľZ)j>;nj%pM?g/6Z8=GB~V F񦕾犮ȔCbG馗Y2 dz[eW= r:@Љiꦁ-)1NZ)s_CǠ9I)'aה̐:eWc8hg7d÷&D`ږ 43FhrɇHW#U0E۩b0 ŪXv`nqMg:~U-KnqH۟N)1z] G@^G6A ^6KVe_!-;5Q%8Ju-DZr,cWޛyzGIVYsBDISi5g?Ԓ=Qw&J-B]FϽNvl :'c< 8-UҼb1R  oϙpK2\E<$Ksu^g? %aE4KBx'mfչ૟KX1(umIx|NZAp_"^HD<2D@㹶n^vt}c;E*W\40?,zmJV+4sm8HZpX\SYE'!6"pb9XOzlwNTlr1qȴ{l^I.Jo+̨N#l0/3P6@tRn]S2>VP>_$'2 %Xx"S(LSnIYAtՇv|1=*]>4AgfFA*;nG󢳴+~_HC6benn}`FlpjV4?.>F?? 0mή*nZFLM|֐(P×Ne %/#[EEmUHVBXګ>^]656j^j5VO0DBQ#+/H9AFۧɑ39%G~'2h #.`g{-8uM/y.C6j*4+roPRqErJ'RK [D {}%ż8!_*3rk%D8Gt!0|l5sQ#fwRe) E0ݽPz/}C`.j f"B Xq'r_9cPw c`ui<ugz%͕t15E7@u412p43jjLxTRzX[0Lmp wGx,fKǽ{˝ lMm;^SrYҞL[Wxeh%vN>?Ośۻ>)߈'\.X]N":v6EZ~=lQz$+whVOP8)Y 5Jis/sO3շ!JC9f!,|KS6ֺ_;< _-/yCԪGI>=tc )g CIykX`7:"N}J(4#^g9OpY3ٮ ( x =JlZ@ndɗecxZVӇqr|lXۀhXr2uȅkPplp gF"W=|LFZpV̰40X{ ^CC:яͭ'xjJN' (__hQt`7g׸n1sfI?]–I-7&m{:/wyTO%]Sj,3 C2xIceN>S&6Ik ]Mߩ1RfPji3.3/BWoc+ofd e6)Q{1 RJr4}Q~~Pޟ9qGJBb*SgS./E[)҄\o+oLA$pn~ԐB l'DAڟtG!z'pm9 BEBV:0$WJ$sT~ Jo,M]蚧yLHK_[Z4q'WΧ~.e@ʙH>'/V˞3j2N_/+n<ƪm1(9@\q &EQBA6F@;>1H=fj̗~}Fy =5]G fS:oG4ZgI8`N׎PV?Wl1yir- vHUw H*J&4 HjOoK l.uwr~cmL1]A5سphЌf<GRJ`O=* FzXBw'B엌-6QcC(4K0KUkaXJF $mO^[a5B=Qej/a 2rc- yZV)r,a> r<- Cl/lVNlMr,27yPic?VŒN~W"frh$eޜ2@sjS;NI,oDBnl7akeTdkoH$eGaMkc(f7rdu&AVgS۹AQ ^vuY<9sChoR-+Ā^'"r+~Quh u:|Wk-܈pS7d{:YC0_)E2)^[YD${ 7쮬N>3:U=^6h({TA ƪW>9}0_<]i nx 1D|.|W>m͒JKZ{Y%?KYU/uGIVcћabH~J +_'SZbgpr#ŗVr0ٮ bCBeUќ_fNqzxuéiٮ;OZ5?v}^}>{#hgRFc0 $,$m= 74KH=9Ԟ O~ZByBHv [pCfIj'Cʣj"0c"Ngw׿uRf$h!@[ bI+'F\"(AL!˺ӻ N7CjY[3h4z̀ dxid \ģ+/mIn)-LFfR [$_WcW`]VO dj;vhpaJËU-PSřw` 7z:S-),q(:@_*/,W±,XKcT{_׫/רy?d~VPWW[@q-/yGsLʫ%+Aؒ0;] Lq KCzڶIq̂)['7a+~tJxٞ'ʘOzuJ>FխF#>?'-$+\ 9 С3͌ -yy>g׾0v&@YyuKFBIP? *>'Yd7b}>UX:-T3KSȔ/P}𡀐gS ou| M<i׉3pj"@<>#Q/,׈'^Nԋׁ+ _-3LHiBR2|JBzuqf Gr37``## @i{ȷLv<н4u׳ɲorI9EcG=E#p%롿 zs$ҧTLjh H˿ ԼuѯiGl˻X?#h1Ve/흜ucbHSp;3X@!R_ʛ{dX }y' )_Z@xC

sr|97}xO"L]HK ^nW&5s c8b Pk҆y~׿:r W5Sz;},^ Jvul2>Or9Fކ*LyE&hIu71RUP+rjBh&ohdwF(߆#5M"ph Xc]`۟*ɦ^G!?>?b (ct tAΝ_d}*~%̋mJ*#$LlD=$2/]]>~}8ǎD5{ma%A= Voa3[[f+uoӨW`[`:)6zRB*V/WwZJANeSPc1+(EFv u,8 2`$a4-|t}6 Vt6ӀjKZU}$T>B ̄3kΝ&3Ss8ĥdا.d$=_3r'x,])"mlL&t\5m(O;ڵGO]{SR8G-m}V4l2>@ž+g+23$qW,em@Q?M WGyUV+kCU!t-DYI1FazwTFs6SfL89:9g:?8M բW> ^hbJ@T<<[ 9pVN mC *$ :SE/ ! `7fKJʌ%@dYQ;J{? ^@=ɳC-:oTCnm}5TP3m2(R *t3|rK&;m a"%jm[EZx5]K5WVkqZQO5x>He/['6B4@z{ΐ -n[i#ف[י}LHXEs5Nxc;;Jd'u;0\7:pUֈΗ(,~ ~Rso񫽑V@K={[;o/oGp -EZK@$s )w*YNFoMT M< xe ^fT|BP{yu( '+@M-+>en@# fݫI#'l7?Zq/.u4-{,SU1D E[K$|BS2l\E1nptF# -3Z8mM3.O(zDFo햇MrOC SHJ=0ϸZco2.lq]?q$rjˈ&]]+J%)Nʵkgl!usʱIAs}pg oĠ]k$ d V[8J*K/* x{FJtĚ(y4l yKX~xRb`I変`U[KcE0f80t9>24馆0JQhKdv9Ogp=wn wt6Gy=&MP )@!՗))s,Z^O಩1J?ZQ1W FZ k՝*.5D >SXnp vlk7vܸ)b̼7_~Q{C] d5`&X"#rl6:8i={U};-CA^Ͽ^xUZWJ!7D&,ы-߲ +; =G}4dOf;*gq EQ4#ύH΃lƥmTVD͘Fa*,q"-22ȵ ^xG<`m, F1fF̲=!8.egz ,m)UXVp.mt-:$`U ,r]1 PV]F9Q[};;Bv|I>ocno}Zy0[} -^zӻ1E^8tS\Lj9)%S8jR =-zLPͶ& Mݎ/̈́GNV鏭):7zqs=w(OCT +p}(?{W}eK`z6M=CJw'EȳQ6 (z[idiarאjxR/o*#Qp酻%(i/id*&M:R *nƏ W?%[1S ?#,zG Hmw*|JP! Wu9Sͺ_AE+ŝfxȭ.͚ݺ,FlE {]'Cq࣢4hcѠ )@eQc83xLoL• R!y2'7+\c^>jdJ΃ Pn b]r+nznlM|hB7԰Dc ڬ[ mm3]4N_ԭߨ x`an\jN^/慯-"n3"Lݶ ;^eq*s/٭1|!}#++R/rwxJl{pmW&-EMGh՞!ee jDi6#|\J!ߜ4y 4Ah^+%[ vCǦqG<[C)hERj kÛw@6J\B}Tg~eH,JoygqJb(UfLq5"4!t򙅼}А҅a58;c}Uċ |S`b2ЃxGe/x!Ro~ FÖ3q 7MmFG S(;Eu g*D3vH`^oc6MFo:{Ihtk/4lLr-g^GvKSыLpԋgйlpijO΄[Moϫqs\Ƥv.*~]ud+t=HlqN{3ط`x[2JG*#1n8AG4&(!ЉIL!-,.~6QSDͤEn 6$7[icU^rN9St#)ZYEQ8!O.6lQǵRd<2oLPL4[K)b(9.Ow/2S;l}JnjFօ'RaAPDX,D-':1{j4B~cZx¢}vh~JÀRX+h閄ռ Pρ <in9*XhJ:NjF^$Ev^)^@/{İoIJ8ds ~Gh. #2S.7@&, k>^e1%VC^F0HaKM[>%.KS&`_}LPʎM4nR4ޗZZOKk1eyVӬ.$}r'd`q82X3{&!l;YG Or)gSL~$%n5b8lh\{L9;314r0`A+*p$K%C}5toŇ6W&巉q :UEU v?|pZfdi+Y83Υao(Z@!1j:څմ :Hrhof&WR{z\{wK#'8'<>?yq"Xlْn }2(&\tWk["@L3ݞm$)&"-uEi`xlCl-b7T1Yj!<r.PʲȺǨM}/}ٱlj_06);vg%23k3gW5:qv}l^j>_"E#-4R`+y^ONj? n QGMgz'^u?Lo,үt{- )٪Kw6,)K(/|k 1|O?yN#?t\XLi<~zB_k9;(A ZIE:e^-^5嚭@.g/ eB쑎NOIq#?twC1Ԅh 0WA☩ Wp&ۡBvuV[/X-j5vYH|RpjNxB9pƔpX>pJuOWS:g@ө[pΈTS"[_LN;q@GHH՞P AI0Y$O$`̄o{q?ʴLfrLOR}f^@i3Mu{-N .&KFHZϩ..a8 ~ IrN*ցo۩C'Qyv3#g^2/ #!tyslUl Z48c۾"޾6'IŖl[>R6JaatU+%ŤMکI"4JPJy (ءi 6Gޕ@NSS뿫]ϵHJ;m>nᑚ$<8d6@`j_`.D)vY0M!Y~@O.vq 9b@wl\Į, u[ ఩K6 ysĮu$:cmweP\wYxpPh> J'̄ʋ墘 WwCE3(rçMLhߛ4duely6G2'#~iAMmMͶL#]Dъ`=N~A>_Z)a G&X;T3P `0{war]_7=;]\ +r_+.ץ}~n2-MKcȼi^lOZa>&6!qʄrHg3ƽ{ %n0&VuZB2P\>nZ0ԭmwD^ 7XV. =!U 6 \9Fu}@Wp rTm(⁀B*^L1,Эn9$CCV fG ֫|PL 7fף/_$h kô)WZ܊#~E&GעiNYgL*?ie .Ym^ŕgnUȆ/ sPɞ1vGձg..$)]QUb Q3Ž][j.fB TS=⻤ )9LW1%^#u-iF ̍Z"fRZ:~9OqK;'m7X nN)Ft i= :G ŭh AOts#v716.XasC*;Kv]k B *$Q*kN(O"}N3ӢYs,>Ty%^]|<馶36flÝ1lD 1/\ĜߎӞP֟dShޞ,Mcd~>=,If1o@& X֢5#=:/ 13RnQmFc˸+cPIY@cyT~64ߊEwv8L(O'vc =)!ò\ 6]3t̕N?>B"_;sТO Ta*Vh A>ŲyF"Sbۣ"pCp aMVJHi>wO?:e~zJ%Ζ+-phTi*BOHQ91ΙVaJ:FݨdUtJ'NUR^wMQpf ׵OSrt|$$$y_v.czN 0:PO7Nf8$uB]txPVz(ci?#kŕaԖHHC:g 6FoKm,@$-Enlq)%3/_? 3g Ff5yB ;(mbF(p׆!326Ը#¿վ++Tj Mjn9)]g[su1 0]7-euDƵP}AoHf*Դ61Ҽ6=dTSplYJ4flשE lrdИTtL „EpƏ3mDGt\ Cԏ:[ұ;>gT& ylyDmDe~`}DI^uDzg!d@$`ɝ cBiyl {u,$qRs|K$/%hK^Q{}#7;_׊pD}OhygѦgx&!.s ^݀ ̙(Im> kʦZp8 xPmj[ _۞iFo&oRmcu#s|Ɗ"]*nZB0eA\b>DѹM*qFApL`MN gwg \z^ePM"%6[M0k,Z01zVX ~^x{LS8krdF핼!-3qBG^ib-*82~G1'\Zlv3WX ` n 3M*͝&!^&Cy?>6&Wv ^)X%4gko6jublBb?<%JpNY 'Չ۪)ɑVﻄM|(| R DvHIR-<ݛA#}בGfCDɿP3P෽ɗZKH65 㳞h#NiHt!? y!ɬ{6ol%!X֩itRұ= Q).7B"(WHMzrƴ1'=zz-#Kibs dtXe#.b%< aN<`.0N[/a1a M.TE)[KC?MQ96Ogc֧V߬$ SA_n-|j/b 7E+I1]\O%2:MҬ?4/+u%쳯"nӪ8TEA ~_zAw9Em [l-ŷj\%ư5sȨhmDt mD C]aF^ի}˻%^k o<;wHyג?`/cˬ!Ӳ('[j{OY/s{x<ꩀP/0a1i<" ZYQ. ,G*"wOb1s QVO4gp 88Rcȡ(+[ܱRd/ɳP/[qhY>h.!;RZ*pk@LMOhHp*Qed0ةY`x/|]̆gV^AnCARqKKqᐏa&s^FG$39ևts~w2k/cAb9g}[ؓ3MK yə Q* jM]R0Zx /%nf&Q&L%=ErT_(j[?Ds4`I?qHy_aZ2ỮՕ'}]CMPl%mF Sn򵭞#nZ0ӛ d8_FyOR8<ϷM+x1X<%v:-n{իYɞ8o׍; EQI0`$mBu: 7m@̟s{{D?w9Qެg^[ܰ?=S{Y(KH.ei~I;SW/W&6B/twk`_=_Vo-R VdɒtTTpAqlmڅ}KD9$$(7,SDnP-՛մ;zJ}bHWTC@Egr(k([ɚ&695BL%eTIy0EϧTg9P]؈7JDRSTäjuV[1uN*< AkjaO1 1_[Wofi: L-GowqaLWQYCY&iWϹrT+{=s31RZQkg lB'~q?uꋜr:gF =( B L@D#;gmLD-`TTKwedݻc/ɘy"yCE7~ۆev<+Μz@^E|DڠP ̺H[s RH]5UB7D@ xVc2J-BkbOYapGRѬ/n0Aͪǩ@ujl*9hbKZ ~>W%j8 qlBcȿO}"6<˘<3:SGdN\NyJhr . .ڛ8p+)D́mɺksWW)NzdM D(L$vt|Y sD7z'zMF/Tly;S|hBx[c;=y|@@ER8Ծ;g\/ #C(u;<./GC/hBSW5!,[TE ]aS,( 5(oց.vt ǝu^!X >]D1gk}y xBVtl.r|݊CByC;"e/WEAv~6h^@>F+y5O]e=3(b~׸7VzZ֒$7w`8" d3 < 0GNQA tZoZ1CgO%,lpb}Ͳy~t3]>qg8͢r>d")MQ5ofRw Z@Rk./J ILHJulG|u?)RkPo&.*& M ,/ |m~q`sxi'6d|Xbҭs2Hc: bNp4c%(\i3eō#.s%wo8t"V@1 qlwY27PZcfRd)z,"#뜦i"/|M DnAHO%@_3XWP#sU]{DziH-Zl&+‹զ"aWh"{g;BN`$6y^.w+NW)MB({H եqېwKc;b 9[}o]ee3)>T!f)uP~ [("5ΐ|M.%" p|!2b5È&۩F!ߚGP$H@ C6=csNӶXy/v~T:^qn0FߐaJxl0AեCTIKҷUjNy0ejUTğ0J"ģF_U=n`Ś-]roR(,>Ke2HuЩ單 v+yT%:%`! I^ls[=w%qߵMlǝMdM\w`^L/> UpG=2LQq3~bOṕ "xp4x|­~ KP$G w۽ xB@MǚZ) ]< WChhehfkWI=2A+a.{1bz~7l}Xρ/,WZzImիi W KϨ]_Fb֓o/w KlBzV&cA43C#as­jz^L/dyeLzYNo,95Z8TlY!~a *[|ej^eCt635:DxB)Ӟ$=MDa|WB(D Sc*v{h7jr/c,NJ~[E XwW< ??g#ƺ6P}&%ldC# !Aw_rn>Xsr\@F21S"zz'TG8zt%4P6zF$5#V[P2p1v|r2("b0g-0=Dt;mAߣ`@f_r(Njw^柎) pWs:Br"(L"*2 J8vpN"daJNx- D\ *X!]_VWǽdy쥰+9(i+"߿^SxS҄_hS<5(F@BD#)-o+"TGiZxUHRJlݗΟR^3T@D~hDA_oֶۭQ4H_b se8_ao MnUy0`UE6qAxlhrSf"_,LE] cZw`wʀ%"~0*΋ԟ?)!6ӥjL>Xw@s1#s'wԹre4f 76Xeh홍 ,wºPϠO}81і.ZcϢ05kߴ%꺏} db&d ˪IēN|xT WW ?|!1ZJZ X.. I&HQbiR\<H<_j~d8}-â|GkX:e.=f+c:^/81I,)*5S@/5`/i?8&vU,fAOHCP:P Hf_"Ӧyh7>YR J."J.Y 1h.8_RMͼNwXbw Yl7K4B3|S ͡ SQ]'\Q'"gq7YrّS0_qoXJ-]O)>xM9?6TVQubﳁ;]$\B~U^z_AјkՔY#%[uﳱMĐ'A+IS/ڈ"ֿ?Tt D,|Rp2cJfhm3nޡl@ŠWX,MZdݡ&5s\fP(IVBrTLY)_8^ Z" v"4J_@)ئFC4Vaz"i3hYl|T'uHD"wh,ciׄ 6nR;!CK>aK*``i$ܶiո7P/i#N0pDͶJyu _C3ض fe5(qP(-yYz۠.'sU15L )9mO?@z,.+İ z Q#AqۄBVn4ʩa+V̿2$ufI (V` LW9B\|@Vd;P$;g)D GCVaPCy-ʍ4&憺Za^%i-.dN/\4+Y>OS s]3HCL$?`~iWm,nM,s#rb\(bEFcRT1Ȕ/1uc~p;.i^Q67@[W_B _D81mۢ Dϸ{R"@m-zvUlW*8JVζIa`5)MB\‚4WT=t) hu:/ eRlY}܎感qP2FF&D>{ߋ)Y%(8W>GQ>Pl=⒁vsTUbÏM$U"E7 r\x}Bl*l2zȨi#D $;r*"))X Af z&eꅧf;#lQ}(&0Θ5{5Cn> tfpvO'l DSI v>]E;`53U Gu$geDYΗmYiG#Ch}(3qȑG}8?Һ22=Bt{HY5I\t6 nOi}Jm!ph ?^LAnȵ飾ZyZvD*l[fP A%_{j#&;sAid%[ţJia!Qҫgb65OӸgLeP[6HҵԽ( {cE[4ft gKa=Ih>K)Wy/R_˝2[Ymㅢ<mZQ=ʸnp^m,*^_RO;8W70[xަ[fB-8N ®LJu"7uQ5+]˒<$۳-+XZOjU卣3Ƭ@b,~Xؐ Br$b|$Z!@Oy=)MvF/LG&\v hXb"g%/zhL5v;6\HʆpBwpl$Kv$3a;2A"2FN_ٹm45N٬RT|BMM1 _}x'f:a "" _9cB)5ZRQfL'OW=o6Κ,=P+ [-LK|6A{c%Kq'bk=pMҿG 0s'P`Yt+(ߔM~V[07>| 7~jISV27yk Wڞ=0] Ti7Lۅ=͕'L@ޏ"X4P}mCabt,5Hnғz.ыL+ H 9 [yJTq}Kxb1kSYQ=UO=RCvp Ѹ vbEsj #9󿏬`rR R[-s -u.DRMb1/4E:1w[YEn A'UP/1wkB5f;蛽cg)P1ͭPԛ>훩]ad#gԳt(?$ l)חEnԈ֞r<3hBjj@"(MpkƟFWʏF[#gQ_gMs5$ɔX)cg8+m_5L1e\ [2M:mq[˕ TSl~JBqMXd (7PKC?`i+iaX/}j[ٚ<0[qG2/4+%;@uB_0nࠚB8ijdz8!-Q% 4>wP´dp4`m51o%9b EhsK*rC?ďC=i1x2թ;%ziɝ.w &uIQQYT j}E17o >䂸L=eK) eō3OFa>c"X!g#W(]FV ݪ1DS\>(ҟ6Cʘ ZK? +k&ǖv6 <ϬҞM/PjvLgLUCae޳D/X;1֏sk K󑎘՞R!= qp6Sa@>Zt)%Yrt!쇎 fC07H ۄ!cF LDUzV')wQ dA|;P7%6A^{n58n^> BMgڪ똒_QLn =N\.t>h~Yw*2/,zP5qjrdt(T a*z2K~`X[sX5LC4Vԋc??ăZin/Ng(a [&ED<T0z8K"MFi3:y.-:MF,\+:r]bD~l8dF ,A;O+GY˾!hL֛S_*M8UZ*(yҖ4ͣgZ+ ɕ!huӭ9m3?E4][8G,dBC'b3(5\#m GA ̣kߵ?б\j7Ć X`Y &?}މu+<'jm&m5./uj|pˆ>S`L*u!Ħ)')WC'h脯7~_XUT''`=6 pZ|ƔwcNFkNXq|r)3^Hxs;N2{s8YG+|=W ";\2}z&)rM?2J7GɗAvG5X&M<Չ O~i M?Pyo<`]Dm>;NjD޿Q)a|}Ɵ8dz}D1GRD[ e.IluU[?:DM=Az2?!w/?46`n 4{.29A=#\wӎБ_g`}KuQ=&vI; %.ʚ]0;+jUT-^>?*0E w kP~"TP1/YoU+YjCQlj3Rkg{>R"-$v,FhL[Tf>9;%:Yˢ*忄XDd-tOD:pFE`3w&K/ fu-p(jm睧{sbhL܋?b|JBT~2(u{R %nmNn6E)P _tOPHFrWJ)7N+ 2ـ&iqHy."+w(uLڍ( 9RN0ܙ`AMWwK E[z2­ov^`'"z; V愉x̦ijE^f %\3f"k(جA v,ikS얎8>Og rY ;7d2Agie$~Jw.9܋ :AaDߖt&9OhW/6a{99f 6TXNR95!R'JV]X3rH: 4ɭz۱W0 2p8u>oA^kE_kğ 3iWJ{J?i9Q/'B?j߲ü!>~>Ǝi\n!H%/lѐbBAɎ +Gr*|f M)Upfga?sttt~zxD՛8\Nٜ%\қĨfT,gغ`uDÀT8o]kyfK'ˋ5u1Ȑls2CZSjqA&B$Q [AN=24k+`.*9"h< ΀mLo-jg·9mdʚ یd12{Rt=z2%X#(yP橀u}{Th۪'Z'u}UT @HꂃFZ&[ ?':[X|5mG2(N4\p2ʶ>* Yٳ/) $#`a!#'yuŀ0|1 $$d]l"{_e^3 (ozQV_zc(-nY32VqŵXC `GP7AC s;B3!okoO-g V ұvc:#^W&vYL~mZzxQ7PN:7쀭P%B >ɮm{2d/&2A!d+l#*'Lu_Y}5ڨٚTB&W-&v\)EF1 U:Mګ[ƂH~# Nc29$FTɵCelRKD>Jn]) ZI-l>Q3>؇Bh$ńŔd H%@›3g'$a3o%.*KʲMhʑJ<;\zC >qZ& US(L#)36pGһ|ݓ@zԇsJ8uҕ{ZJ~ u#ndDŽAhBڴn:=Ϋ~q[*" PrGoEhmMia -俫 rTW!;lrqoDž$' qV%;գh`C<| ɹ*:hT%=ArYh}v%FCޗ9y'G2'^# &0Pu89MwUaf5 ;hAL /5Q%@%"@ NR νsd]]@S@}=]lHEP"ۇBAǣm ~||B({Ek貄?*;p '޿4W+0 +g?G9\)LzȮ>:FrJa+Yըf\x[7m]`"? & hͭ&lƊzń)!!S& H"F bJQ!Aߖ%BBze0joEN0E(G ]<2炣wך;{"2p?A[ؓ(7{T` j&CB+4ؖGvb9/@"Beߩ-G&:X@_:@t^Xu;H,g[V_G4 - o-Iƛb}H,BRqeѳT&˧wXTyL<#_2 Pf:#;~?< ^)򝕂gbLvA6>icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/dmov-zsys.icns000066400000000000000000011050141506470510200235230ustar00rootroot00000000000000icns is32 !! (Ҳ#?ʗ}մ7Cٝv}}t:?sR}Pt7?ݽ|a{|{_~7>ҁlxj6=tezbv5?:ogw|wdr39мeŸqŘg3dեfآ( '%&%' (       rqrq+z]o{K{n^z$+~_FLIKIMD`~%&{\E0oEqsn/F]} $scH4l@A@l4Hdt!jgG7icf;i6Hgkc\=0`\8\`/>]d6\Y9.74547.:Y\VN3DRM/MRC4OVIS4GTOROTF4TH     V    ESKQNPSPNPLSEC><>A@&@A=<>EA><%&%&%&%<>B:2-6!776-1;4/,1 1,/5.,),-)+/(%!&%%&"%( $"4"$ $!"!!" $ &&#'&'&'"'&  s8mkfff}b}util32 260  ''  ("K *&%  "() SzѪҬvH|bԓق՗߂hk~єӂӗ΢hЍՂґщՁӓӍܓɃӁˇׁݗ\څߑӐ~jnjёg~ll҉wfjweԐϐАbwhhwލq}ڕϐϐΖww݋juɌΐ8oo܊frϐΏΏ͏ΐll܈`m͎̎́ffۆ\h̍ˎˎbbڄWdˌ]]فS`ȂYYƿP]ŀŊVV{μ»LYÆRRƻzûJXÀ€QQm3\ERKKZ,%3gGVȆNN`3! #5VZU&,YXYX))WZU4"" <  8[QnrppM\0 Q=Y]b__RBBZc]b__eF~X][[~ny}~~|UZ~}~~X~}~~XX~~zcxy{xvQVxxzUzxwSSwx|wbqzuw{yOT|URSRU{QQ{zxs~]mwqtUJ@AK=urssPs;t=KAAKVup{YhsnpOE=>F:qMpoMopMp9E==EQqlwUbokmpoDIqMlKlKl KlNpFFpomisQK^lgigd?CfGiihIIihihHeAAefjfoMYhdffd>eefbkITeacb_8=bDbbDbbD`::`ac_hEOa]_^\5:^A^B^B]77]^_\dAK^Y[ZX16[?@@?@??Z33ZZ\X`=F[VXWU.3W=WV00VWXU]:BXSUTR-1T;TS//STURZ6>UORQO,0QP..PQROV38RNPOM+/ON--OOPNS.4FKJH(,JI**IIKD4 "6NLK)-MLML++LLN4!!" !!"" b )@8^][NO\]JO_^_^_MK^[NN[^]7A#<.4GDFBCEEKIDEDEDIJEEBBFDG12/A7FHAAHHEFHFEHHAAHGID:0WDDB =>CBDCBCBBCBB==BBCBHFO>A@@A;L=>==<78=+=88=<@<G9::;;67;)();66;9<8C7872-++.#8'8N#-++.287:5?454/*)(+!4$44$44$4!+)(+/4462;12122-.3#2"2"122"2#3--32213.7./.)).!/!!/ .))../.1+3+,'',,,,,,,,'',+.(.()$$))))))$$)(+%*&!!&&&&!!&%'"&####"$#!"!! "!!"!#""""!$ #"#""#"#"#""#"$ $#$##$#$$#%"%#"##"##"##&&%&&" l8mk<1 <]J]: C8v ;@ h[$tzxwxxxxxxxxxxxxwzuit32xX/9@CDEDCB>6+1=JLMNO NNMLJE9+#8FB=C@4*6" -:=/385% ,8:-153%,67- 122% *12*.//$   -22-    0/0' k`eScaba0b`dW]ѲԱ~[iT`bac^fXZ>kcW]ecdcb4cdcdW^_ήɪ{a[Yecdcbcdce[Z`~="kbedbcbdfefefeedbc8h^ҿֿ~^gdcdcceefefefdbcg`|<;μeifgghlӲ΀ Ѐ+ѿfifhfjf;x۞ltnqorvͩڳotnqntn:x֕kqmonouǬʭmqmolrl9 ЀjיipknlotӺүlqknkqk8xՙhpjmknrձӯjpjmjpj7xٔgmhkilqɭͯinhkhnh6̀!֖elgjhkpρ:ɫЯhmgjgmgρ 4xԗdlfigjoūүflfiflf4xבdjehfinոʮfkeheke3͂֓aicfdgl͂ѷŶɀ̀ϯdicfcić͂2xԔ`hbecfkηүbhbebhb1x׏`fadbekѬʮžbgadaga0΀́Ր^e_b`ci΁Ϳʿ͂ή`e_b_e_̀/x}Ԓ\d^a_bgչӯ^d^a^d^.x~،\b]`^ag˩ʮĞ^c]`]d]Ӿ-/zԎ[b\_]`fп̀́&ǮͯŸ\b\_\b\͂ξ,xxԐX`Z][_d˥˾ȸѯ[`Z]ZaZ+xx׊X_Y\Z]cҸºǯüɯŝZ_Y\Y`Yӻ* ù͂8֌V^X[Y\bƶȳ؁ίğX^X[X_X́ν)xrӍT\VYW[`Ľѯ V]VYV]Vɾ(xsևT[UXVY`½ɮƜV\UXU\Uѷ'p͂̄ԉRZTWUY^ˀ ȁ<ĿͮŝT[TWT[T͹&xmӊPXRUSW]̺ЯÞRYRURYSɼ%xmօPWQTRV\¯ȮǛRXQTQXQѶ$j̀˃ԆOVPSQU[ʄʁų¿˂ʀ̮ŜPWPSPWPʁˀ̶#xg҈MUORPTZµίĞOVOROVPȹ"xhՃMTNQOSYαʯțNUNQNUNг!dʂʁJӄKSMPNRWȻĽǚNTMPMTMˁ˴ vaІJRLOMRUŷǜMSLOLSMŴ vbпҀJQKNLPUǖLRKNKRKͮ_ƀ'ЂJQKNLQUʀ&¾ԢKRKNKRKǁ Ȱv[̓HPJMKPTԽԥJQJMJQKñv\˽ƿ~HOILJNSƿſſžžžſſſ̿ƾƿƿƿϘJPILIPIʪYʿŁāGNHKINRƀƀ(ķΜIOHKHOIÁŀĀŪvVʽ́FMGJHMQúĿÿÿÿʿȝHNGJGNHĿſſſſvVɺĿſĿĿſ|GMGJHMRƾƿƿƿƿƿƿǿƿŵǿϙHNGJGNGɾƿǿȧTƽÿ}ELFIGLPāÀľ˚GMFIFMG˿ÀçvPƾƿǿƿƿȺDKEHFKOʾƿƿƿǿǿȾǜFLEIELFο½½½½¼ƿvPǷĽ½ý¼¼¿zDJDGEJOû¼ýýýýüýĽĽþĽļļĽ̗EKDHDKEǼƽľŽžŽǤ-M{CJDGEJNÿ0ɘEKDHDKEȽÿvLǹļýļļŹ|BICFDIMǻýĽýľľĽĽľþľĿĿĿÿÿŻřDJCGCJD˼ÿ½v=f[rxBHBECHM»»ʔCIBFBICĺϼ¼»êi__t3-HN:O}x@GADBGLǕBHAEAHBƹĮmGAY08v27LSDK=X¹ºöz?F@CAFJŸ»¹×AG@D@GAɺÙIDGK[8=t,309B?]VSu@F@CAFKȒAG@D@HA¸McIC>706t+04=??MW>qv?E?B@EJŒ@F?C?F@ĶWJZ@A>=/4t'--7:??>MHƵ´x=D>A?DHķ?F>B>E@ǷEJCHĎ?D=A=E>\=FB=:62(-v,$.47;7VRYu=C=@>CHŒ>E=A=E>ĸN_?<973+&*s )$+096OKFp8>8;9>B9?8;8?:@W<;6/)$,p"+))$((+Gm393649?ŋ4;272;4µ4,)'%**+o"/IIRE;TVWTVWTVVTVYD<9797<=SUVWTVVTWWTWVTVVTWWTVWTVWTWWTVWTVWTVWTVWTVWTVWTVWTUZK<;797;4.42!@9724*DTaYo^`WhZ-'(,L3!+((*t[]\fe\ 30146;<rCsllfaZQ]psmkpsqosnkotoOS\bhlng"bHmih^ZQZTHpssursvrtrvrtr F_LVYahjl5W/vgkWPNAVNAt`c``abc~`c`c`|}?_>ILR\lhpv@kgWOKHD0@EGLN\idu[h^OKH@7?1hr^`^__`a|^a^_^a^zT3<8CGKR`k#w p\\KI@HK/=r^`^__`a|^a^_^a^yz.:O>CGPZc X gYRAF6QU$uo]_]]^_ax]`]`]|Y.d8>ADU^w iOZL=>/&ep\^]_\^_y]_\_\_]xN"6=>=>A,D@[vputZZYrpsurrvTYWtqupvqtiV\bqvsrttOBC@B?>>=>=>>?BACAPupusqusqutrtwt>surotsotsotsrl@9<::;:;2:;:<;8SwrpuZWWpypuprvgP]YxnttpqvcSZ^sprupsJ8<;:;:;:;:<;8Hrtprupqtpruouw=trqrq rqpskA:f=8:9:94:9;7dB6WtprsYYXr{nrrpt[UXgnspprptfT[aorrqrqL3aJ4<8:9:8<3]N2Mqqrqqrqqrqur<~upproproorpotiA:<9;:;;:0;;:<:9VsnrqVUTm|mqrpnRZVz|ltoosorfPW]}nspprqJ9<:;:;;:<:9Kqnrqnrqorqoqtp;~orpmqqmqqmrpokA<<=<=>=>=/<<=;>;StpmqaabzwnrlseO[[rqmprnose^ckonormpI;=<=>=>=<<=<>?>@BH[e\a`ajononp{}|pnonqYTWfkpnononoov|~umpnogaa^_KLI@@>?>@?R`\^`honoonpnnoonnroz9wyqmmplmommolmoloroosmsXEFCDCFIRn|lsooqmmpmlnkjomlomQXTr}inonlomloljmllonlpmnrpnsVXSFFCECFE`tooqpoqnlonlonlonloqlz8xzkpnknnkonknnknmimmjkpSCCABADGPiyjjmmjnojnolooknnlhPYV}qlpjnoknnknplnokmokmojlmkTVPDDACADC_njojlnkmokmokmpklojoow8}xmml!mllmllmlmmllnkpUCCABADGQkyjnlmmllmlmko_PX\lmllmllmlmmlnTWQDDACADC^pkmllmmlmlokv6wyvnkjmjkmjjnjjmjjmjjninTAC@A@CFPjvgnijmjjmjjmkjmkipVRVe|jlinkjmkjmkjmkjmkimkimkinTVQCC@B@CB\pjjmkjmlimkimkjmlilniu5xyvhmkhlkilkilkhkkhlkijnQAA?@?BEPixhiklhlkhklhklilkiQVRoyemkiklhklikmhklhjlhjlhkkjRVPBB?A?BA]limijmijmijlhjmijmhlkq4vsjjijij1ijiijjijiikhmR@@>?>ADOivfkiijiijiijjijijgNWSvrhkjkj&ijjiijijjijiijiikRUOAA>@>A@[mhjjiijjijji jiilhq3xsqjhhjhhjghjghjghjhgkglR?@=>=@CNitdlghkhgjhgjhgjgicMWUxjhhfjgfjggjigkhgjhgjifjhfkQUO@@=?=@?Ymhgjigjigjigjigjigjkep2xrrejheihfiieiieiifihfhkN>><=<@>Ziejfgjfgifgjfgjfgjejhl1ppfgfggffggfgejO==;=;>AMhschfgfgfggffgfiWNUWaUVUVVWWVbgfggfgfhPTM>>;=;>=Xjehggffggfggfggffidm0:mnfeegdehddgdeheeheeichN<=:<:=@LhqaieeheehedhedhdgVQXUPPQP:NOOphfedhedhedhfdgfdhOSM==:<:=Kgo_gbcecbeccecbecbhqpsrqsqrSRPkr^gbbecbecaedcecafNRK::797;:Thbbedbedbedaedbedbef_h-3fi^dc`dcadcacc`ccaddabgI986869=Kep`bcd`dfacc`cdacd`A^`a^`_ITOolabbeacc`dfabeabcaMSJ99686:9Ueaeabdabdabeabdabdadae+cg_cabbabbababbabab`dI886869=Kfn_caacZR^bcbabcdc$d`JTPsg`ca``bdd\MZeabbacMSJ99686:9Se`bababbabbabbabac^d*ae`qc_`c``c``c``c`_c^dJ785758-,*,*.0[gbdeccdccecceccecceccdccedbgOIMQlddbeccedcddcedbfafQ-.*,*..EYSSUTRVTSVTRUTSUTSUUMNvARLVTRUTRUTRTTRUTRTTSSW<.,*,*.0KPPQOPQNQQNPPNQQNPQOPPOPQOPPONGMKYPOQNPQOPQOPQOPQONTB..*,*..GVRVRSURSURSUSSUSTUSSNK>QLTRS TRV<-+)+)-/OVTUTUUTU TTSGLJU_SVTUTUUTUSXF--)+)--EVRTRSTSLIvG -;NML MMKO7*(&(&+,GMLMLLMLMLMLMLMLKO?**&(&**?OKMLLML NK6(+U!! t!OKKLKKMKJLLKLNA#('-R#! u( FM)LKJKKJKLJLKJJN6*(&(&+,FKKLJKLJLKJKLJLLJKKJKKJKLJKKJKLJKLJKLJKLJKLJKLJKKJJO>**&(&**?MJMJKLJJLJKKLB0Y-&#  $% ?J"6KIKJJKKJKJJIM6)'%'%*+EKJKJKJJKKJKJKJKJJKKJKIN>))%'%))>MIKJKKJJKI,.S+$$% t!%! -,BMHJKIJKIILHL6)'%'%*+DMIIKIIKIIKIIKIHKIIKJIKJIKJIKIIKIIKIIKJIKIIKJIKIHKHK>))%'%))=NIIKJHKJHKIK<,)$#! v !%)" 7IHIGIIGIIHHL4)&$&$)*CHHIGIIGIIGIIGIIGIIGHIHIIGHIGHIGIIGHIGHIGHIGHIGHIHGL;)($&$((=?>=>?==A,"  "#9?>?=>>=?>=>?=??=>?=>?>>?=>?=>?=>?=>?=>?=>?=>>=>?>=A3"! !"4@=?=>?=>?=?887?1$ #$$#$$#$$"&!U $$##$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$$#$%"%" ! #%#$#$#$$##$#$$ 8;93   85:&970   !"##$##"!    $!%'#!$  $!$'$!$ 2)'#&8x:D?IRAD:TN  ? %i D?AESDA?D ~&"#$&+2r4XLMGD;3>jonlnnknnlokRRQPOPRP_omnlnmnaWVWWVWanmolnolnnlnolnomnnlnoZWXUVYUfplnommoWPRPOPRPXmmomnolmokpd54?DILPN9LJIA@6FG,QPPRPPQPPRPRVRVSRRSUQQPQPPQTXYYXYXUQQPQPPQPPQQPQPPQPPQPPWYXYXWYSORQPQPQVSRRSRRSUQQPQQPQQPPSF1Q6;?DIKM,W*YIL=77(LP$RLNONNONNONNHFFEEFGFKONNONNOLJKJJKKLONNONNONNONNONNONNONNLKJLJJKMNOONONNJFFE FFIOONONNONQD.a.059@MIW1LI<6320%/JJKHJJHJKHJKGE5FJHJJHJKHKLJLLJLKHJKHJKHKJHJKIKKIJKIJKJKLJKLJJKHJKIJKHEIKIJKIJKHJJ%*0147@JFJHB641(") 9NHKKIJKIJJIJGD7EEIJJIJIIJIIJIIJIIKJIKJIJIIJJIJJIJJIKJIJIIJIIJJIKJIKJJHEDEGKIJIJJIKHL0#& -139CLa=C42)9>%HJHIJIIJIIJIIFD EHJHIJHHJIHJIHI$JIIJIIJIHJIIJIHJIHJIHJIHJIHJIHJIHJIIHDGJIHJIHJIHJHJB'E+-18?Ew W;7(1 HTAJFIIGIIGIIGIIEDCBBCCDHGIIGIIGIIGIIGIIGIIGIIGHIGIIGIIGIIGIIGHJGHIGHJGHIGHJFDCCBCCDGGHJGHJGHJGIHK0"d*(,+:Bw Z1G?&(7JFIGGHGGHGGHGHECBCEACCFHGGHGHHGGHGGHGGHGGHGGHGGHGGHGGHGGHGGHHGHGGIHGHGGHGGFCBBEBBCEHGGHGGHHGHHGGJ+#&,I6=w V)UO""8BABEHFFHFFHFFGFFGFFGFFGFFGGFHGFHGFHFFHGFGFFGGFGGFGGFHGFEBBA7ABBDHGFHGFHGFGGFHFH6!+a48w Y/,",4DHDHFDGGEGGEGGEGGCAB=5CABEEGGDGGDGGEGGDGGDFGEGGEFGEGGDFGDFGEFGEFGEFGEFGEFGEFHCBB@4@BAEEFGEFGEFGEFHDFGG@3'".7PQJEFIFDFEEFEEFEEFEEFEECA@AC?AADFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEEFEDA@@D@@ACFEEFFDFEEFEEFE GHEK@fPwWJECDDEEDDEDDFDDEDDEDEB@?>=?@@CEDDFDDEDDEDDEDDEDDEDDEEDEEDEDDEDCFEDEEDEEDEEDEEDFDDC@@?=?@@BFDDEEDEEDEDDEEDFDCBJClSwUGEDDEDCDDCEDCEDCDECDD@?>?A=??CCDECDECDDCDDCDECDDCDDCDDCDECDEBEFBDECDDCDDCDECDECDEB?>>B>>?CDCECCECCECDECDECDEAJBgQUHDCDCDCCDCCDCCA>?;6?>?BCDCDCCDCDC BE=:FCCDCCDC DCCB??>5>??AC DCCBI@hQwRGCBCBBCBBCBBCBBCBBCBC@=>93>=>ACBBCBBCBBCBBCBBCBBCBBCBBCBBCBB? :ABCBBCCBCBBCBBCBBA>>=2=>>@CBBCBBCCBBCBCBBCBBAH?fOwREDBACBABBABBACBABBABC>=<=?;==AABB@BBABBABBABBABBABB@BBABBABD$#$IBABCABCABCAABABC?==<@<==@ABCAACABCAACAACABC?H@dNPEBABAQBAABAABAABAA><;::;<<@BABBAABAABBABBABBABAABBABABAC,)KV=DAABBABBABBABAB@<<;9;<<;;=:<<>@??@??@>?@??@??@??@??@??@?>B6%<\<@?/@??@??@??@??><<;=;<<>A@@AA@A@@A@@AA@A@@?F@@?@@<;;84;:!"2bBBCBCCBCCBBCBCCBBD?;;:3:;;>??A??@??@??@??@??A=E=`KMB@>?>?>?>>?>>?<::71:9:0/..//..//.//..//. //1$$74,0./../ 0/2;9909::=?>>?>?=D;`J!LA>>?=>?=>?>=?==?=>?=>;989;798 "$# %;88;899;?>=>=?>=?>==C9^IwK??=<>><>><>><>><==<>>:9877898%"      !##!  #!*;887899<==><=><=><=><=><=>:B:\H%I?=<=<<=<<=<<=<<=<<=<=:8778788"$43434334343434 34434$!!353343433434434$(:778788:=<<==<=<<=< =<=<<;A8[GH?<;=;;<;;<;;=;;<;;<;<97683TFKHIJIIJIIJIIJIJIJF"=YEKIJIIJIIJIIJJIIJHJ')86779=<;<<;<<;<<;<;;=<;;A6ZFG<=;:<;:;;:<;:<;:;<:<<7757674F487878868879878878877;&!'X;6887897887887887878#)75669;:<:;<:;<:;<:;<;;<9?7XEF<;:;: ;::;::;:;87583J8>;<;<<;< 9"EM6?;;<;<;<;=$(75678;::;:9?5WDE;:9:99:99:99:99:99:9975472F5;88:88:99::9 :899;('V98:;98998:98997:#&74567:98:99:99::9::9::98>4VCD::989989989989:9::664,64I7:9:8::7;-!!0;8:89:99"BK4<79;4#!':989:89:#(64558::;9::89:89:89:99:6=5TB C:989889889866544510/702/A17569898;!5C59897;, %S:8897:/#G7:889986645 $1/00254469989989989987=3TAB98787788787786,+)*)1()+*)+*19779"9D498879487669-%H6766-'*)'('(' ('('*)'-67677675;2P?~@7764*'h4#(&''&)$f8#16658!9B37659%-P3756658- &G47650^F*&'%+ZK0464:0O>|>66565565565563+'/)'&/)'0574B265AD1845647,!E465565-&-+&'(&-,&.5 6554:/O=z>46445545545443*)')*)()')*.5536&)&A@1637-M845447-$(3K354545,)'())**)'(*,45455455455380L<x<443434100/.,+*+-,9,2/0343445BEE63536#-M0534343=DG=254334201//#,* +,,/..00/24343438.K;v;342343"234234334341/.-.-.10C/52443342210/3 44;E.4234100134325"0.-.-.0144344343243 227-J9 t;1322332332/122122122//-,-,-/1A/3231331233442332/E:04133234332322312 #/-,-,-.0212322322322322306-I9r91211211212.., -/0A.4122121 2214("J21121221213"/,-.032212112122112205+H8o8110100101.-+,//@,3/0101011/3 -G-20110101 01102!.,+,-.20101101101 004*F6m8/1010 /00/11001,,*+-0@-10101001/1017A+2010/0101"-+*+,.0010010010010 1.3*D5k6/0/0/00/0/00/0-,*+-/?+2/0/00//0/0.@:-1/0/0//0//0/1!-+*+,-0/0/00/0.3)D4i5././/./.././/./././,+) *-.>*1.//..//./../.0*B2-/-..-.//.//./ .//.0 ,*)*+,0..//.//.//.//.//..2(C3g5-/./**()+0>+0./.-0&!J10010010/.-/!+)()*,/.-1(A2 e3,.-.-..-.-.--*)'(+/=)/,.- .--.-/"* !).-.- .--.--. *('()+.-..- ..,1&?1 b2,-,-,,-,,-,-,--,-,-*)'(*.<(/+,-!,,--,.+/ ;1+-,--,--,-,-,.*('()*-,,--,--,--,--,--,,/&>0a1*-+,+,,+,((&')0<(.+,+.$H+,+,+- )'&'(*,+/&=/_0),+((%&(.;'-*+"),+ *,+A'-*+*,(&%&'),+*.%<.]0)+*+*+*''$%(,:&,)*)**++*.:; :=3<&-)*+*)*+**,'%$ %'(+**+**+**+*+*-$;-[.'*))**)*))**)*))**)**&'$ %'.:&+)*)*,*)**)**(&<5&+)*)*,*)*)*'%$%&(*)*)**)**))*))**)*(,#9,X-'*)()()%&#$'-9%*()*$%*+)()*++*+**+)>0'*(*+&",)(*&$#$%&)()()(,"8+W,')()()()(%%" #&,9$*'((!'*)(('($>+&()*+("%'((')%#"#%&)('+!7*U+%)('( '(('(('(('()$$!"%.8$)')!"&))**)#'*%B+)(% 51%)')$"!! "$%('( '((&*!5)R+%('#$! "%-7#)&''*%(!"##%)*FF*&'&($"!"$$('&) 4(P)$'%&## /!$,6"(%&&'-0,$"4EF3"%&'#! !##'&%)3'N(#&%&!" #-6!'$&%%#%)/0.(# (6@D=,!!'&%&"  "#&%&%&%&$'1&L'"%$%$$%$%$%$%!!",5!&#$% #"%)/332/+'%""!"'38?@?8-#"'&$%$%!!"%$%$$%%$%$%$#'1%J&"$#$##$#$#$$#$#$!!,"*5 &#$$##$$%$"!!#'+/255:8;/@5.)#!$&%#$#%!!!$$#$#$$#$$#$$##&0$H% $# !,4%"#"$#"  !4 !#%%$#"# $  !$#"%.#F% #"#""#"#""  +4%"#"#"#$ %"5)#$#"#"# "$ #"#"#"!$-"C$"!"!"!"!!"!" )2# ! !! .'!""!!""!"!!"!"!$,!B#"!"!"!""!"!".5%"# $,/ $"##$# $"!"!"!#+ @#"!"!  "!"!"!#*=#"!""!"B"!"!"!"!#)<$#"#@#"$);#"#*.,--,-,-.,--,,--,--,.+--,-,,--,--,--,-,.'#"#"!#)8##"# 05454454554544554554546 ?45544545545445 47+#"#(6"#"#"#'  #"#"#"#'4"#"#""#"#"%$%$#%/"%$ % #"#"#&2"#"# "!"!"!"! #$#!"!!"! "#"#&0###"#"##"##"#$!#"#"A. $"# $#"# "##"#%.# $#$!$#"$.M<$# $$#$$," #$##$#$!$#$"/*# $$#$$*"%#$!$# "%# $$#$#(""#$!$#$$"# $$#"!"("#'#$#$!$#"#""# $$# $##$)#  !#"##$#$!$#$##$##$# $$#$#$# "#"  8D '$%"%$ #%%#$ %'S 6C$%$%"%$ #%%$ % P  ;G'#$%"%$ #%%#$ %! U   8F#$%"%$ #%%#$  R  !%$%$$%#%"%$ %%#$ %   $ #$$#$$#$%"$#$$#$$#$$#$$#$$#$$#$#$#$##%$#$#$#%  8E($% $&#&%&% $&  &$%&$&""Q :E$!"!!"!##!"!"!!""!"!!""!""!""!""!""!"!"!"!"#!!" !!#Q  2    !                !!        207(042-  96; &;81t8mk@ r` _3Cy w}~~~~~~~~~~~~~~~~|u& _-  d& _ & _  . e W}& _;||:Y}c) ;G[z( w|GX0_.i1[ _  `  ^ ` N*)((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((',&b- ` \ `  ^ ^ D7 c{S^c`aaaaab_eXg`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`d[|y\c`aaaaa`b_kР6Y_e!8ebG      ic08. jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 A|X8џJ\orO5SD(-8ihAEinBm$VMW\~ܸ=ץ@PlLgl~b_4zcg?k'ҙ0?,t2MIX)_-ʽFɦ]O|\󟥬*UVB͝>9Čv ʳ40\IinC?/g0$^;fmx+r>[yotQ4[˭gn-Gl5̵;=26XI:7Z˳ۼvD^ b`,C.P8bGRvOj🴇NAL*S T}<(O8Uv}/^o^'$8Nt%-?:z޼HV (+4kh+ur,U0[\BJvoSٴIqu'|cPDw4nCtq `rϰ'[q>@|f !=6zN$Q}ycM_Jh֊>LTe#'Zϳ''udR%ʩK`0ۡ@`J""|]'XeTφZo02oX~s^G~wn0jkta,e̖,*,8r4ƪ>i[QdLVרk=HIqe E4ve_kλlU6EIwH`ꆝ>yS64iY$^S>T(+n%cP|:.};VzS\2|xSi 1Zvw4)Z+ a#]f!/ͤ|Ά`i41ѐ>T9遙Ѻ8z[KmƾKNDFSs;TMM9 +IS(SV?MddW/Y b螌v<c 1n~ ^Tm^ `^]QW~]Xj&Рɚ]HC7*&lL=$ݽb3 pڡw }_rzyєƁTX)r?@9h6-f* mEoQH ˙|/M$yi.Ņ~JSUP逮lSLc3Ţϥ 9eHF8&FY?H~ #bUנ0"(^S"7#Df厣 WT-L#%kV9vkN,Ԃ큷r{T4K:-?\L)m,efL K7eX 8Hg6o n.7zZ%]B3ʺa}!ؑB:7&I7=0i4qHݝ2}Ҭ/ả_*1Ts':=NT4`>L옅Z_ZS0׀Zf]# lɉwx}_۳eqJoH3j彭rfy^`mqsU?dEd,"GWzh9g]qa"*/xeQ X0@BƁWTG|4]4G/g!54bl߫7쌑*?LtA8 , %;5|Qұu݄F֊.&{G;\ }6 (< mV<~y?h 9adȍv%lknX̾%M]f7ITN#>>A#kiDz#bupͳ0-oJUv>D8d`ml] hi5&o&2݉Lfx;Sh*'lرep,bi VWkmفoؽ b ٽcd4hm "Om7tY,bE = 5`EIѯnd z{1pFZa_׏<U}z}aڡ[xXsO Fr*MZdn,y6r ӥwͱ 6?` :6hr`W>䚲%+%1H!j<)KmU!}/ TY E>5cH'EGnSt0BҺ6Kg9J 2ϬNY9 ;ZrY$BC*/  D;7vEAwQE tT,}ɑw0h rTz_6-y+aǘqm# ;Ε-A85 SPi蝟IUKv QæilŒչLv3a6b)p6{*!dL[G%N'[MkBs]Cs&1D$jV@m( ?P@C:9^z9>kOdl`sqʾ<4Vpz#Db˰op@+?#|Wyؚӝ?v×SYHNWz$w:>h7ҏ5ZQ.nd"e掘vQHIyei I 0Bk ԧ4! |{#fp #KOR1m=pEGb4h ksgl]O@v̀PaǗ3<#jk{UW`/t"P6wQNAaٴvÕmj&L:e)W:$½ol~cu  1!L'|Nnn1D[~opX;o(x8&g7`F$n|ˏjH0a`s+n7%++ecW@Zԕ: (޺ic)~DO}F!{~8aBߔ.#7 BE;xD{,fnC&=f; &{/ {.2vmIHHWdxU9,)}rƻ,Y/ïgbEߜ1'4&$[4x?;cI"_b# gGAI1rva8W2p8 ^GxQ6a?2نኬ$oI*` A=MuBgzo*'P鋝 L(E ofiM䝠m#^dl l\mf挐e _ly1 oj%]{^w:ڷs$\uJ+}0Sj}JE`rŐ @tk٬ߺUň/ ;m_{na'jdw7` V&s|k㎪f*vfuJq]sޫff[d0M nw)p[_4j!bGbC𥀘EAO"@H$iX g1a괌˴}mr ed@([ukf'I79Q-6A1bnD ^8;6G#My}>]ܢZP ۈO1W>wSpdDR|;V r{7 |0%'[ޥa˒Wfm;(|dO!Dv@&kҮC8oײ'˞-tO srT'e_<-J1^{t3wɡ! Hp!|94k> Ox dǿHꦿ xԘπ\UoH>{t>oW;"q}*UGA{_W53~*+|NW{ïuKɸEXJk"3COӅ;J:e 1_&nK{h8q4^֯ĪD`ꢛ%%1x^ Q|C{Id=827Vۓ -nkؿ*a橘@JVH/*3dE(5>Y/ZQtKplUYw5+kvЏgEMR i? gKatQ8%yUOyHǍg%*Lc.߰ƍY/rV<'5jMwsXJ$D@t„vۖĿo)Ptv=Pe%deje߬2o- B = 9=G SA 1ɅFR3[!N A:4&)".({4;\L,} m!Yg6$ F}#cj w;a[lr 6];řY=|$Ig<^c. fV?; v0˃,-Mh}3*õcj$\&4 $ e H5&qA z.}as=֬3Jb)R?.] ;G4x&"C0>n](U?\##ݟ('()+PM."#q~RM;@˜ (.UCpS 7-X s14ԒDbD0=rYN!!Y~.;d!7,هWnrN^d1,l(~,Ȟo#ń\H15 LEbݥ_I;mk\>Fvua` ON AWbsL^Rpyព|pZ_0K0oeJfA*3M?JӦa(5ߪ0r)1(-C lf4:f.s>{>(}S`nd~p|1MzlA;xߢ׬{|PTH Όb}zy@jӗ*i԰W L4seK2ޥ!tDk6JPs@2v٨7􄶂Lڷ )䃦J?R;aR"L%WY29 kC`I.ec!^>#=lǿLxH[)59܈Yv7.bd 󊯔]Y|xWKf,e<6Yg&u ?h$u%n15˭Lq cgUP!(#;YOsi R.,.כ`0D\|~w58YQ͊*jnD~u>3M-]]Am">|㼴u ZY%BW >筹uWhx G C2 SK3ؤijḄGi=ٮZ˯1xrF:.BEC*G͙Ntf|o9CԣƖKCcбY>>OmOFfft( 7h 78PS#h 33uAh"&Ѳ^"D x?45"=RB S/2o fl|sO͗C կ+xNᙽ8o D"ԪI"%yrs& }F3e힫; z)Im1OIƹu|P"!4WYS? wDa-8LBrmLGQ_%W6d47#{'3ͦmmRnӕX!:b\5Ԭ! Lbל\")|)V" ~Qr}p 4fJV7sUA3p`3(P Cd5T6;`U{h ֽOF󦀀%bOܬ]4M"Aզ'^t1*m.h\Cf}6٣ЪCS'{q`PkփVը{i/3}kgggRg}QPNFCےLX\W4.?>l䌱IE(YW Q{w0IPȨ4x ^1NT8M>1gO1 4H@_@|-OrT{p % C!Qs(4'O/6g;ψ;,i ;ö~i$ģ>/^ |ms쩅+̸7G ߻ 2{e)fy[]QAmI]Ek\M3IVeQږ%D u]&fz}!2!;cрJ3ZXЄiX4z rSLuJ1ޛn bBcC:Wd@LQuk\ j/Zk`"$grDD*4JD%rG%+L 㓎Ji%RKت\{TW޶j9L>2дثĩ*L}޿PUk !m YHҊ jk<3%TQ3$0tn2. k޹![&=]*^-Z䣹u0j) vMP/RtgK/ _̮w (2|JhIt6hSJhRpubVMuSp]Q9䟔8^VKS9Ȗ/E.X#-%!w x?7\q>ɑGd4~:ܥK ab& +ޓ,7_bMr;͌gU לs}f(8r@w;L]5IAڷDnZXQBAB#_I6k%vH5 aE*_ xɂ"U̓Ke~ص-T*I;py90 iN˨̔ ӜtuayAמ%$*ݝ#D<vժ.{_]k'PǾh_61уX%`ՒS12){kom`Hx(}%K&*JG@V-hhk\ C;|5^t0ƀ7f l o 'De(0w7*z[>L>/.w (zүUP"HɄ3 ,9YzI+}4E9љaXhKw@j}#`i!7|M˽[%QCi5œ8p.l媑\(Ό 99)i?W01ÕMlƞ[O Ȇ/V9i+V**[`v2h ǹօ5"_(k>p,=Q*B.&4>LB蔌īE dBm^FO2D?̃A6Inx!orxbb<_\I7y7F$Zaå߯łxw܆,Td ŸOȑ&Jü;J'J)4l\5pⱥ98ꋱL_2YE")㳰VF#1qOqa->-ÆzHWfo,_d˂8|;- MX$) :/kH)?XoGmr ؑɹuE)Wj(u8K^tnL(zVtEpKxIRJޞNYB;2~praa2@N„R | `>Y'5Ӎ?uȰD^i(ɯv)I HG?ԑ,Ehf$6zlBp2gmLlot]Ҁ?U'Jǚu<_9mGgU_ͻz} ZzNk1:R'so]G <R+BҙftR'+^tķIҧ!, {p#nt(g\R|wZsQ aJa&=CoO=lGB?.nmeFaJfKl>R9ȳ Π&* p)ؕon#xK 3gܲj* x#M7$z>.V] S`hul:o :}H+fFNU)N)e$/H-DC| "CU4ad /CxALtMrq=R(28 ^m3-^"{?*Z`r$gQF^GCF8q#|^A>'}R|KKvpqup[lT7cF>Ӂq6:]IXb8s"}8P9JNwj˟Ouh^HzL7;CT@'QMܢ^p_AVWvt>eғuBceլ(aJ㡾PmoW-LKYb?&PWDQ 뽗%v^k @kڎdܑbK6{ըB:0L20֩J.&(h(vI;\ g\ )0Ky{\`w`9! 'G60EQf-."^ef{G|sXRz c@mҐhAj k*gT@5q 'e#p1҄Rfn0c욱kXwԆymz{QAl@YNhvrY]zZq! |^"8bzVI&}RPL-_̯"2XiJdx[%uk:ס6um:m> jbڋbV%b0Pv19Hw$kN_MXb}9O.92b8?[@xO74Q%eH8ijSTt=Z`c„6glSϪ([ F?7lG f[t_Ⱦ.L/3^$ʳ(Ty]?Yr|C\)Wd u)T5v}@5Yv1\Y[s>tg9ձA'DaޕY\Zp򲩃 J7V.?j>)GM>Z ՞` rΚLL6lPEӓaϐ.Q6YY.g# &qa bǮra1P_Єhc; }(1T!(fc3aPAgk㜑. r$cʴUڡ |q)fsP>n?Io 4gal[ǧכ*4Ccm+1r$Rc*/-~hQM{s}IGږ ʟW7yW俸SYϭil(KcLgPկGxǛuMİ:ˬ>!gڵSR08K(6S_1RgZv2qp4äJ6՟s_d ߃Sd6 3{~گиg sNX1 L˼i|/_ǎfʇ ._؄X'hWQBmA!`DO"/enmrL1Rw+U uKԥ-;6tLb c6TC}cdvU4nF6X0թ& O#rj2t\=e|Y$z3?&K`yFcUeyx{X'_saCgx6(szY% /بB'sGqޢeW.ӌ顶P䧓ku׃5 4|.c5E]1\qa,?xu0JJ!h"O}`w4nc 7aKQUg{U u㏹*}MP>MtM/4jM 9Oi; IѰm9005>N$Uhk]T:Sպ`sK0^йL,nЖTƘYfn9%H8/Ϋ|V^a})V0T="#{n~-GҙCtRYFQF[A^@n<@f;%" <dk DX&%q+{S'f&3k_ޭ$A$s}O5F%"UT5Ǥyœ-&2"{`_cs~ 'eԹ7mSʍ|_VU4yx+ ax6>7*fq=Ғ[ jAhXщkp\j|z݌LjryObr3O+5~$Cۑffb\rt Gko/pZjC*[ƥ]3F? k:@ZUUp'uk%ĩNdD ݀^3h$րG61P:kQ5 qp&E5:xCIWSCwmFӿL-HYRuf}b:؛rX#>}@{W.Zpz> :iUzf쒙y _̮^@+rZ݌bNĬuAvfb0VLNd3f6?IBװV 2`RVn+by$mA{GC `ߓe(lj ̤/z,&Cx9h#hGa:}\LUIϔ]7HoJ+(H. 8|Uc?_Teœt+3m6v&6&[~Jttdn ^L#40>١ e`t열#D}Hiڔ4 ʷ$b?qhxFR| bl=8p#@ b|sIDZ=rYW[:܌%%GL7;JU'l);פ2+V[c9W%ݥHJ:U•r9]3X>J+5FE9ICç}JMP ֖0HOT ikj7:.{Ͽ`ƙ=՘Ji`W}CAg! 2ɏe-cfe;ZvVlS,{!S̈́8Bfj ;Dم49+g^S1O=i0!#Vp  9wF඙ Rba} _{߷ 8r2SQ:לQkY@$l@5&YZ0;O Mt/ƭJgiio /D>&Հ]*b;` uQmD#2|/1eM8U B(` 3p(؊R09cmE "LlMn׃얄ӪUc]o+_/,*C$"P?y;yrJϕfi"$wT;* 4nD.]f"k =%~Wq5X2Qj{uzҭ'xo[ c7*x"{6#jjFrt^ЕSI3` M۱p3k8ܞ fN6 T0ߊNhl)OaU®wc^81Zqc8e|q`PTIkJ%Hn#" wSn*aK}8 Bߚ% O&OWr`%N _DхY[TVKu*Zϋ['ֲ`MgCŅQ D\:1q/=vīܤ}a[WkҘq0vm 'HR'm~<7F-7 ֳƠ|)%'Bdj9iP14$;RYC;w>8%.„-6lI R|nRLJ :2Nē5 Q"<K/c\]+&y=\vYȦ 3$ ˀѷ&hQQ*kַ;WHm)d9g]lNIwA@w %\/s7s4qco*M? քTlNʚr&dX!~p3-)"LIx&?{@Dh` jwNl{}{πZi٥b \ [Ǖˬ{k%rS y_1q07jvM\_0kq'K%BdkDx Gp/NqJo1~W̽+{Dssr .=9;zlQGٽ]szԡa%6}ٴũUS{cJR򗔼^3€+W /c&BQ }~$m~f˦]%"|_rS9SM~.:{dkL'_s8vp?H Gi[(J108hn#ŏ0K 2el!j/B.a@21AqnqF)=l){DrApH}[|T$G%vS%{Qjě!mo ^ XQxf D2R*JrNkZ.`d|K _M47l^%؎/S~6W˙/^UR4t#dЇhL Cޜ}lpJ[ѯ`sk-1Kq ?L;QXTxy&*ףNzf|%vZ0ex'ukaKE RGzٓ'lQx#ϔX8Xv65`nSy^}s4 Hy5~t!AYF(Hb)1fgrhWDɣ>K 73\>/^}V"^z Z WOp31)z<Ȏ"+;]ug"sJJ@B9iIMMfET Ct&e cwV~c(NmC 擴E}zzO_,{ʠb:&u*p懶xLU5N61F"͊S-ٺuVFhqvcXŢ$"B=(u^2pvLnwTAiܱ]Rc@C4z~t~gANw  47ކ 3aՃp0 cr"[fb\誓Lz.-"Аk%r\us$4]ӨJI+4Mg !0D˗&)O\M2E8%b5꣐ףs_ک_fWY7Rj :Ir'I4#HTS|a7ƝLR@Q}:U8 XfA PY,qaDi {sRCM`5'ԕQb==yckĮ̻6!䪙0HQ\ϖ7 &Cr(]d'VoqD_Cb67tqDA@6>5ŔE[4HKjYδ )jE|$x&oDnCҵ;!9ĭ7! ,  9i8F4L*9sCD[ʘX'et[ݫHJY>Qe!0;g9SrQRyՀOݖ4߹9{oQީ 3lwljc3]@, R73ϓ8\OЛom7vNʕPبe|)R9& u%Zj}VE~Җ2|/PRaxVRV2E uC2>Y7&u{XҤ;"A=yG([NOmžp7~cs>! Oc\ѴMEmYRxy),<]Ca5&!<7 &Ѣo (y oMG}٠ 0:C9 l \Pѭ9{ˀq">{QX{]soRI ȃF~Jb3ui*Am4q2Tp` ^_L)x~44@Sj ? YTJ22EcGs6\˼3rc' ߇:n4Xt}e/M,̩G<>Q(yb">"sZ/̀ZC0s(X ?R;l6pVó}V U ,T{#!mRazrDg+T'X /'+`G֋K)x7^#Pw:_G:uׯ܊:;,7'$l{=|ŭYN aJ{Lf."UlG}hU5}Xw Q)/R7B%tspԣwW8֣nQ8 B` ن|-=]E@^Rd2UqD=;1 JmT=[dOC$l51hn]:r,-6_RqjSGek^RGSW"x09'XliS݂gs"muTu [Sg,,o{)$Lb= zu% ³{NGp-%*!A(ts@\RsY,!Kt!}}⚴}lcD^[G,@60D:/Gˎ1N~xiRez͖P2!{]c4> J?.hKrT=O"wE_np_Ո<)HhF?): DXN>!zLvhD׸Iكۣa;>Gf7MӉki[qv]gdJ@XI?}D:ٱOZAs 9Ռ^\$yi RƙH2Qe0Tka'n EsC%g7}|c Y`Iz<̴q\҅OLy:JOc5Ot7X`|8~~kV8 OCo"ܩq;qcH;`wPOҕ]-GvT`j_x܀E{)v)(A;D ^ Ex+k:JzvF^-%CN)oTm[jsUn4f&t2$8!d f>O]a nӈ뽽vsތ *# 'K/5W̪̎M1>|Z+>5&X#*s:bP8BxfePnԘ>*񥛾oT휫/팱΄W YSa VtD-eK!$؈f2>mabrv]7\-6"ѡy%;ٛ+Q+/vh&`,T.m.v4Yt{l;+Ţ1$-N@>f +UhS۪zٽHnHz\?ay $s$~%f]Nn8ݜo[=K EEn񸵄:4AOB03V12iw "dx" "/ MՂg[]r2ܜIOZ:5ē[򍽕v1@3TsRZc晪!lPFp b=@JI1pZ?4EFhmECT)h,aѧ^N7grs*؝zx"IG#V ~wL"n@|F%4st\Ua5=;x-Ï,?EdJ832}fT;Х^`%fRf 1/ŀ'5XqP4Pl=:q[”ZYL[+ؕϸZH `!>g$+F2twg}PRn)R-TrӋU"Evn|p<'dtSr`pٚmgej:vcY"ik+1A*n֊)+g@)/.-aӯ(l$z5ۅH i>wAԏϸS\j5[lC4ڸW>4rtpKO,řn^_/@ F>{Ff"Qah H~(1|/MJ/*!yǡU)6 |Cڑ)Rt7mϑ;V-%R]Įp ;Bie\Ry:AُS~ {*@9y ,qaIõa|B<'mȎ09hfpJ:׋ć8-oEEӱR`uoʴO#OyAT6 ;|~UzA4@Q)?6X#OS6I1y 6J.A]"+e- V0KƩ0WA sAc~MhXwCuUgVR⧐Pnֽ;m6.ORGJ-~R$1OYRE8|.ĹmYP'[/wnc9c.,e'ҵF^rJaO:H2*FڑE ?zB[5mZLlOSݝÈ0dWuF8:u0@!<: /L'Ms9Oq'^'gɺ6L|oT-Zyt"l#K'P0j }Xo41y,p"e|= &!O>3&a_io|VAaZgtqq@ޯVg;r[f/ t5BW!X< wp5WG\T/VO) {t?b{_`aSa!{)+&[ÑVJO̢Vsv+Ր DI Lׄ67VT#BҎipRY Ɩ*Yq>ڡp{cD/Q1%j[i1m :Ƕ"V:[3uv{UD g#f@lPa`0^7c$w ,&M` S/+LNRn,}-c{j3l6zu",Qjsr2.`d3f'w网k]"{nUlgdjحN59W֙jcur0#˵-Qg?E/*GP͇ w?Ki&}ORj`>I+ޒk%敄.o3芖lCt.G8Zhb-;ic&N]\2R޼ᅞMи$]76EK*To@8Dt(Q%*udm7A@XBjð Nٮ= oL /K;eM'H=.`wԱxu jA$[ob?4]^BtpD_/؂D|$pj\Î_4Mv DXB|*eHV-$,,5ȅ#oyy5DdP~*$- !6޾S0A"cc/a Z ɘ:\GC~zH`LףYb[ e+VS+^cx]EYff?J*Ы`Ցb3h6[0YDۚ8/zk`p~1}tTY[dK^D[ }Cz~X:TRU%zؿUC9 i!+R%n>3 1֟7 @L(n>1-jhOoW~RQK0nARV)/Xtb0U_']ܱ#dR)zKh@KwcWJa䛏́BFȽx? +L| I)}E $}+Qd$7vvqr:[k0llW&}؎;Sp<*(墙q6yZ蓤vMgM(WΫ}r'7~>*Y!8%nVH> U~9N-pUu ؠrX)ҥ0D9pJgLմ7#N!6J:沤hޏ*!V>_z]tc`R|^+IA">y/}XG[]HXx#(A(, Vn\'Ǐ2Tw5$pˑ{0ʢRq-89lv*[PGBPe-H<|CGVn1yHiZcU5%Y]5X1>1/K A0MGX(,zo`' jr-#^~hFUU0Gk6h51o`_c a? 4%_>8ɓ%ʰou̖0fLt]H~ceeE (ԍX\PFwGB"+Xe TNd-gf#M1y0nqHt߲L&a;P\~+9,(;;cǛW$V4 $sF}<*Sik|gH޽Ə~HDYNTJPhkݐpIK]ո@+.Zi?Jg6YHI;Mg1z  轮RS;`$RΦktrey['B-\Hm}S&A[H6=>y졊>rd[ O nIvir+BdNRQ;:N*O:-4ԿȆ6s '00lT;u]AjzFJ7DAQd0q3sNCW|9ͳ6VR4M2ړZ1VJ 48 /Q5 T8Q kBR&CUj8\h]_p(B Ux;1Ũn@_SXմ(PyEM /)Y@Sv4x 긤+*?_֫ j }/D&gTf֋I&h9F+VdZa.he63t!#Yp?챚]Z sPM댡}Z7 GVigo1RMu{p%M8w;ԵtA=my߻W f[~&6ZA*AAv/BXie/|:L#5fjW:;* (x_C plG@A"\'Bt #XcXr}*0_=iu+'2~7O!~Oar}%'Pe-C/掾F} ԰.{K(cp{Sab-{;dphlA:dp QDYL߻d O ^hm~|+4Bd&&axmDы#amt(|UtSPm l PX/Z!沸qi1v]qnrpvGL`4̑J&VdI3C\`*bMҮ'sŭC%=/Y(Eӹj8О XӺ&θNrLiZT"m`D!.SP8O^lu`,5N@Mj$0{gNbQV_ r~|V䃾* .켇&{AKrwK (5ޟ\haKE Z&)y{_ȤM,'|O?&qlZj"M`E㣷3^ms=83w1]bѨJ\!oĴz0 1)k^_"TWH{%^.`dӯ/q>Bsгc.Ǵ$UJ3/V'I|T#xئiGf3Ԃ~!B֎OB@JD4a=MZ w?`ʼn=9;2P|<'1T}o 0 wsXv̅Paw:z*uUmBý\l| 'S9R,(:p8>$bS͢Bg/e~C]f(cPZتs?) N5)xIJ.'$T$_(S ΏL6Wfj%1.`ljh/J,퓇bP =MJtCKlXtJqRuY{p}$"GV ǝG4so͐] _HL"m wb7j$PtJTa/pݨ̓ y8]Z:dL7BzHҩ(JVgQNy%XnΐcZӲz:>uWgS e"/m-\1a'*\灔 < ςEg S-IUdna'0jye=0sp)z/ͥ_|`(򜬒ӭ{[JgnIhY:f'hb= oKĝ0SȷggW$C?CD <H5wUYg/xL -jtl.EgpJEܗWzĆBis~cy^&p n[@y p>:6lA F !+[i[H k KvNg2ݷ0(\oO-eP8m6hv原r-G'2ALyAL?Wis\LP^P=EJHy[ejP䚩G+ܭqkQ;R=_B!4R>ޥ᷿UWѨSxeM.sŠ;|v%K5R' BaI^xϷVs_޷-OԩWVMKBv'Iju@ j;o;KK&&^ 2Z$mEa^F谂OUȈ>vlF\래r,ftBd2[=BZF(Hϊr3/0 K n_c7V k3L.ȨTpx+B t+ VcOWGJ)e(͏~sV2挏)oN\[:բu5t=m(6XwAh>iZtĽ_l^gGo$bz죨%Se{CsW\[5baZS69"ZCN4}Y#D8A+*k2^#E5iyr G]Knv+X8)_I0VxC?8EKt&(+u\aP æՔNz#88OLg1v^[W?-ē [7SiG5u."P8ДKþ.&cK'ZP]X'8rV̿u?ID [Q(]zS/{ Dadzn]}mb@aNxY' 6_(쪯`1p?49*;b$6bX#SXAy#RhÞo_7}GDi]mKSto4&|nGs@lm muLSRR -.D` `2`wo0V)s9X(ol T`)vY[=K*JBTɕ`tH]>b_f1vO<>PDˡ HM:qW@3o8jS\-aS;Vi/"u'6H|̣?ߒv)]OVFVeI΢sj$'A&a,Jxt1i)qu*@&SӡA붉DrbŐ{=}HoJbN*2 J{vrLr+cjv{CX]7eЍ|U!#z u?Px?Kx+nLIᐃx$ե8IMTR!3Lt`z3SQq80y[ ?],r1Pg]_T #%sOk{GuH|Tg$ },A!溼FLQ ?< ?jo!Ar7D;M~yzafjŵHԃVêSx-I<9?ϯE3r<=ʾr7yЗ o[7EcCE,N1CklAwfM־T3`JBD\J?Ԩ!"gipb s!Ј['Hjՙ|/wunc7'H7Ik:pѵ(5eID pK:bK uz`Ty&A2[!q 0ySIM G%tJOvW~;jZ*Oe(LsO$qV͹0Ci1NW2{MofoT93_qnEg'C5df`75Fu~'"bZCfJܶUog{4oOyv'-Mm:]&v{@3zj\RBt-r%?cg^_EZ3f{g ֠"F6og/mkV./g]U# Xx]&Uy\?uSA/W~5@YZ=:)1W^Oe ;cP"8X a7X'XNxЄ,[" =i*B'>::hNȚVݨ0u,j$mOZ=\~9|/@Bp Yυ#f/$Kqs#v[`pZ, jR'S5Ӵn!$\$9Okeqf z1֚vC"e9t>mIČ&BDž-WlmfXM%Pޓ~/剾6*o>0{tOA|W̐|p2*6 TC7nDKHČ+9 x*lCc!_~¶8 T_i@,XJ>CNSi!*86Hуco-ڠ{kE؀963)ybn⌝1/ ðVБ8;l@I`ʎy!5ȰUHp;Ki" 'nrBIY)5C,MdjmdpAӖ,cnm~b((p6pH!jr#յyPDv;Am'yji8 @YXwvk]Z@쟥h뜹t`Jګ7fnFQ^] @ȤqFnP V@G'#@ wEoA"nYqi;ܜ*ۖʈсqDX>e~Mδ|G9!/#ԇw%R]n0q5@ʖ~q4xKI`s~XF02͇õ#&wz"BZ]Ra\Ed Ҹ7TtI S%+`Dz-<2eSK#8HLQ)K`%~[m яP-Cj|lݮH_$B' Z7‘ ].%'W5S[9׋1:#W·寪d\ akIcg9u%I=QI2ubⷅ@ Y<E(nF9@1DKdzJ&R4s? y\u8J˵Yl/I [GŊ!6{@Rfjz\] TE$-ZGXG\sK4"XUyo)|q4Ot3vkg~V̐Kxja˱]cH@cDPHD h[H[Z(Cvvf>vĿ FGL.N(Z{*$i4[xڮS`ð7a:A 7?dv:^)_Bb%忰{mdYbɱR~TVۀ|/iI I7ڐ^0Pf&)m~|86ﳭy?Lk6k?O(g/t5+zktMƦ94%sxX.`P-UT֨?yϑuJ<$ۭu :krml.]]%yymJhJ\QvU]UiX۪b<3 'IFA;~=D@;u_F%;{iW Yr3Ɣ>lenQ}Yųı UsosKh<3G֚5Ggmo9b Dro*| /#<mN؋a/?9@}I3ޞGh"׆;h#'ҀjRG4:c}%[? U*q.D@ )2+n~qJV8Lշ63? !\lGMwuqZA;j.{ya* W"x;ŎTjܡ^Oy4m@/Y21r"ȩASv {^\W:[T4霆 wgO@^CUd*Ef,$հ9/ QĊۛA2ک!#'OKf<1uuz|{?!*VhJHs=גF," _QB#r}ep &f^ bϥA0]bBݎ} 6j03.V}<Gu@ttj!J)s uu!zr]%DsTKK!`7JߪrLK!p_uf5jR@ۏMcX[zUZOC! g>DE5S8M GOÍ2rOr`nka #rN+U=(YO}DYyogBJ?N搂_SSn?&KqيWaX%99R0ҐɩǼ]b#B9=4Q6m8#.}zUn|mG `3"#k1&dN?dN5mz" aUX&Η_" :Xt6;X5hrXvZ\t̥ E 7qU)RX=>Jp<^ˇtb>*^!yąr`[^sDϼ|8rydpfeȺ gңX::㑯hs|Ebvf[j;:DnkUV9R5`:H;cwgYNc8},VBJ2 WPjԾ0N5e%FuCQe BDN"& ¿?f{dr XD>O'/аշc~dXk ,.1۾!鑃k̀KGWKlɬzo<V.dZ>FmKr{pۊq: v0?{y7'{ Y.4+ x-PEaI>Ìs$-xp0J,饞1([ ua( * z Z&n֦ n? c*rAɤ'eaD/sc\čv8\I[%-ډ,U]̂ LpIR8 o H:ArttD٢cƚ-mZUr?tj\"3sfJs/q^3k[Ia KZW^nTig I"9fIbTZoɟWrO1mOa5(mǶvG$&bB\F"1ߤR/wT~#HWnw'mz)i)Ħ~{g>lەւU_ZuhD-3?(Ҥ_Blg=B"؞ljˑj8Қœ8Ur_q xGTZ$)ǰӁ ,PQ-J$[-a:ŪSnݶ76cL2i5҇|_lCJ蚓,1,-&e$XcPL¬/fenb!dںk\(Wl^JfBDodKLiZo "{LKEϺb3=_ XvCz'{PD 3Ǫ6 Z͝ dzW .vj1^-|a[|L%j-fkiD=~x }-DLܤe 3"TWU/$'૊ЕD*8020`$tOo$]lb; %# yJg—؄hg TՐ] .` ЗqU>ycn~ӥz@3?c~F dQ WpU 4$$d&F@(WPϝ(f 퍆/6JA]w2@-H}y.< S ^ (VV"; x^|m7MC4nM?S]loՓFxg(s"FkTL&i.U[,­@[~RB|<{OGB%?{VBˑvv|ooc^_?O??WF |+փzȀhV&W4g]O_յdcu0ϛo+|Kpe~ bx3U吶:?3 XJ מQl g TE\;" ƥZ"plJ]CW)g3w'CT`:Yp2gtu@׷aкEB?H8 ZHmͷ9;9,̄fVVNW.>-ϋ],m8>M`t[0SY>ۇkq $F֥Q67P6T?҇+RnmʡՙCpה15FRqA4#l0S^Ҙc/rN='Q؝߿ 5s>",m [(u~Gs:|$Hll(Hc Jkei &'O}Iw'?b}/g |W؉œoo xpQG T|}ֻK`-aM"5 :`Ç${)ᬦSN) /\9!-̇kO'xAǘ HU=T'iPŲى@C/t_h}ͱVWEa΀%䖨/7k \T.Ih0D|&uw+Wqp\#Bф_[(NRw'n(48%Z咐'E09ۘIfJūBZ.E6vҡy Ǎȭ'70]S9 Rzɑ{s_اY0꯳& 4e0 \crIϾ}aa;g<:H<w0t%`ل Q$q-/B%9J"ڵhWl.MhFdrsk0˨jG3zS!p v-~A ^iۘ}HiQi 6( }G`o;|T1m&_4X={ZB8oVL:|-Z6$ףaO zžk3&ʲI+,7GMyN&䃌FDrg`^1} U>:.sT'%ԙ@W j;n#) D<|1F|RV)?/MPg/c뒂RM7ti?*.c<ܰ Na6դD6U1}NlӱًD7 \cgϴ@!?/7 OmӘr0>۟$=PY/&]`zo\$1qqk Lsv ,"sP *w&1J pd t]D^nytcVb_aelˇjnطd1V}e{"+>Cmlxu)fܓ=Ѱ]t/)^*5P 3b_r3φǂSCJԛ*=,Oa8"CJbb.1^w=>J]MT #=ȧN?Wbbn̢`B{HyppT O( >얇2Q*rw؃>'@n-ȫokٺIckue BS\=h9ǩa\ya.>yAR|@ϫ-b#Ek A&9fTD*~5g/Ki1 D -e12l^DPS&Á]/X1>;FnKAq}]aX˗+뀐Hv3HlþUpmsilMccmK/#q V6Aku|b[xSյ:,_ya(V˘U| t19tϨΓ(mf632bjd?Dv.jb}850 xW.5tdfa=_t8\+/#icFf}幵 Z9HZmA)`Qf_V8I!?"W@UO֐ɝAMEzLPُd:N28wW\潷(h cit s.hߺԒy 77j#sdfFqvVME^̔ p6v]1u e8#\R[~ڨȷ;p`Zǘٹ9fZ* JaB#JX+v(Hm"c~UۊoFD tywGigc_kNqK J5~T^3x *JxD o":PF3WB]D5~s Aն BDs2{Qce_{%~..Uc V2lw!]{CL#F}yȗXC6v# m9bIǑ"v߯G/!6DKEuGfdU)7௅RP fgQL@WھY#k>E]NCexMHc8({u (ޫ0 /wuR;F"0F1 yڡW0Ay,~*ExR"VIU.Տ̖oK۴J"R ?xM6}mO˟zwx|+`)WQlKeD wE&" A:tLpkVDOhkԢOiktsJ/Oo_?qz_j3LRLkËzǵXc.pe( Ysk\ANh"e6sQ; =nU"j-Sd'H}]vZkw5 u5nA/UT>O,M dA˹7 DdW.̸C 2I7骬qb<1wP;k~7ا#yL'SAWQ'R ~h xw ŗeOUnjdSO9? ckYE"{zcڮP ӡRԧg{ӄeQ =Ɇު'RN܌jwrGo 7>VHRn 5Zr+OLH3^= f%8 [&+%`!q;iUy|Ml1) L iߪyp2 耕\C>2A@C7iNھ \%FZ : 7T xI_Q]Xc'~ 1 9E 69r-U$ͫIhuLu{ r)!D[l;C$@KTM6 ܂&3Iڿ;tK|E G*q(]^5_{ 9er^Be;:4&Z> 7yZ47.&7df2X) s#y *vhA=cwg gYOyEW9pFeTW ̟),jNU/.zNz -cQ^Uү(W7vqlsMfslStOA%LOaQm{{x:yDss-鶚z  Kp~tW"p!l>ə}=_huR pj'VRklq&pǰESvD|{&-8?rKhԨCwi& 076ނv)kbA | O@0Nt)(Y;pʶbutdM'䣑)0|30tDܞ `EI״m?=2~YھLhsy =%(+Xވ!,(rj&FV"yҡ݉Wʺ$ 2 28iƎ(5Z^ ?m_ln~"$4 PDA[zPQ-:"X_fXl (r:j4x'T{8iD TjCMsXQŴu_Z){Z_bd#74AUDa |!1xv\KP7K)7&Թs/OO A-}LҩΓ hIOQNݨ4*&NpfY'~sSseØri cӑMbBPY׬ TTeBQR%fXqNU=/T̥ q`H\_J1׶:ʮ;1.ֶE%;De|ǽY WxyWX J Lk>GM%fO[V 9r$uN=xO{~P}|o vq9/rč8RA۶,V*LvJͦisq:T-hd)B% &Q(ShtGd7xzhOb칎/S>kRg–o%BI88߉?HF je>42o/7B>S /v1yoF_=g~ž*eiWVh|w f}Ȁ(Ѕ~X.&˂ֆLHqIϝY$x:ö&( PܧmTn.kj~!uNv'Lae؎?X]؎3Qƭc!Bi`mIG{{ڮ4Uu\5A$ha1iȑ_cة,)!؉3^Gh ̓VRܫfN@!wGCN1vwuʺ"%ޫ{rL|%|3h>ǯ)]9y߁Oa0;ifH\$wKPzыdSȴ=IÉ~TcAs4ˁ(l1>/]O3xu[ ~Bo%ŮsQ, .8.JBU4yBT$J(Ԥ_U_*TK-s^g‰#.߭^LzY_{2@d(3)Ici] [sIAg'QM\ۀ wv/*σwr)GBW`+}o*CU&$K?OtJJ~ީl/˓t;Co5/z0!Mm8p%-CF J-VJئlV=dg[v.읁8tHT%2dJ@|rekpq1.yGl~&pذn>qdkߜ~ Öw;#UMZpԨ{Bv3BcVKz]!? 07e,RNt<{+FljoFK~2HդŅ^q+Ǯϓ8t緌??meFj>>d j2+9+mB:C5e_-B:,Mĥ{U1 U]GM*l׆zO<nv$͜fZjed=|+sTqm,b*As~6qѨGΉICg>8sur9]CkwON9=kPTܕ Ua\ (K}7̊<-'_Na&U؏{\*kMW%*OɐU&>@_ ۉ +¿.]qNbB=W@]n*u7"S$Y7T9pS=#(niW'ZsSNNjg#>G#;Iڼv`-4T$8 r,~j>xz옘V8N~P5+YyW@r=ZTjH'b=4c n.+S$$Òb8$ESf EgO`sٺ.H$% 7mmz6Uт(Aƿ^iy{z{,nGݏHUOIАćǛo&XzY%x^(,{el3\"- *? L [o_ 4&~[MVOM_{o -Í hDTɝP_[Xn tIye- loI 䡗 -Z.6lҘUfFZY3 u $B׉=̾rA1_HZӽBSe/PӺsYW pwwuZ| Y5 (u_n5Ji _oOe,lh+ɔ}3#r5wd^B`+J_&4wq _b ::6ٽ[ܾ=[t`IPnXr~ *|# Ch8A;( vw-Nt3=@:I2BRTyoec%j9*c*M &=8p$& w+s%9D:I`O l^Y1yтj`2l# BbkPRŗ6 ]] {=E96OU(^ex ff!FNHOcЧRcѿ1wZep^O+XZn/]B#R`9@စtA|"XR ^z`Ĉ@;oPG1%Vǩ|`@ҷF .{Sl57mH$@X gęu < 6D:O dI|ZEiB`ؾmXF䊣ϴ${K2C '.Ye<{!]t3[K}%@ݮW&x>8[$N_a/a0;1ˉG 9FSf(r`f%{uYFh D ɧ6h@hvyx0^ϥ:,xE7" ZbHۋY+n=)LߴƢükBXo]gj=mOI.h> nOjL߷>[UL}Z )?XOH'rN<':DI~Q ]PuMcY灕(T}]9w2vu;etL|8;"/6-GLE-0>q&ژ SRǝZׇȶd &7V&-YfZz4-I,oSI X~QmH  tGU#$YZLR*f(XFԶE8TmAt7_qn X:NPY[o0m&!Nl~k> [ty{BS &i^0x~ 5mB9AKyKU?ێ20՛)%j݈b* Jewt8Ku(8|NB7ZT!Tj$E@i%h B h"A/홯}G15ي|A6h;ٔ8-gNlߗ.IN8|"a&\gh[*\UGY9k:'e.yQaa |p~\۸PyWmEc5`/(xJ+*udiel4RQm7!bât9 Ęܘ(GsԿm`Ag 1ʵvNv^ [vZP,pX-.ni} 7/!T'G٤}5P=o ^)@MC\f{O_@ȃ5OʂM,6E=Pl~kYƔy";5ۻϢqt5cWyL _}K7:m[Jl DnS{dpzdaSOehHgZw;vp{;ÿ}|w[8*${vL]>9(4Cl:dqJde&*-ǟ Qa w{n.l l$*WqCớwӛ@G?$z W">q䟉BQouzY"l 9w[?dB9ZNfk~%̸?f'MlMLӹr3jdq!Z ǜ#}qnĹ^k-eAWqYҳ{hnj˼b?!5rS,9 :ї%h$q$BO?M}`sqAm imn4B .8/8C:=G}Gɍ_\'qr10,;<E`OH+r79l~։} 5Jpj`yh\=Pc`: 7#ي[{ٳvڼ;˸=>N5[-զqBBn dl7M3O@P\B!"nk s&WI:4k(Z=3z:XG}0oC쏢%v +6N@4;}8\L[uc8-#v~/SKd@.ݔk,(PtӹoiV5lg/9rtݘdVT~I.xeTuUa% v7X:}@BS~L p3Hԭ:4KJږ.s 6X9ͪrI j$wXS*\<<#е&ݞa5oT H\NEǂlJ KɞJ cÒBO0 vY+!T>[`&PG)9=}fbӱ|;d|^a^ʳ=&R!5T`91qXA̧[x5Л9: pݩHiʞ6tšSE ݋ 1ݟIn3ӹ Ӎ$)GB/"beG kT!i%\*Bg1hOB1fn'ؚ*fCiy<مѧEy^@a0[UO_ l3oA9{{ W5!%cD'2mqcw Bq@aU3,oDلb|'o.pOJf ;uK1LqڦY0U!߇xH]=]<լ̚r2e\̳On ?a߃Nn+ g: ]<鮒lNI탨Lhu>K7{kt%)̓H\|CvKKH:;̶, &m \r떏+5c{85Bl0OvS׎K5)ߖR] !)|yH~;݀fa22ɣT\œ,.7޹E7 FYXlGw*e(gvF_ѱCT:FM K1i:bpt뱁N6QsUni?HVg$?G&017pڤc0,-,2!v%g<Iclix/H ~ Л#$zN.kUXC}~7e = *Y@FWI_xOρmI(/ *a#Umn_kz\FQ}t9TIid]AcldBb׻}o^7V3\2?ɚ$zF&qʃv+v'ldP.}tD%h?;|+DgpT {$9KWE.{T;޺Oڦ,ӣ1 9UxCFA a6XKG !}AKV[7sZ/2ŅE# ɗWu-l >6ם':SJkћMYdaQ'^)+RZmD+oۣ_nwo~/ߵO-5adFdu 4sGaLk 9aDl'P[v-H8 )j/->j:*sX.dtUe29= Ώ/?eL :F$w- kH:\7;P]_>ݻcdG\ m5|(ʴDPq-xa$=~;Et$\ -o] $*6YThp0[VrLܽj7ˣŹwB U'/Ŏ\^:?+pwPl X[NGs V;zw'~'<5KԦ鼌·R]N')uԁÁ 67F#@xP+鐁͊nhI!GqG|Teb?]jpL#ti Y|-! #ח5T;Y@⢵!}!r/V{V\knj/a~~~~>]:Ψkj1}-,'GXZ)vWcxr߸8Ahꁽ?t -5؊|g߉Do?I\ ւ@{Y=(g B*t נݿ_! ////]Qa#z] 5~>@sh}4]|OqyWU,+rb%E F0<9vM{3_!\-ˑ%&Mۂg7xBPRUœ( 2"&|8؉4Іc/-hHJP?((!Td5v3A}>s +?C!p8a)/v ɠ^`xX{>CpL 2O,C̽=Bf,LI.{#LWզ+{*I1/Vm # @oR[h kߙym[vh ׄO݀%Ve=z|b̅1*BsM~(/_#D[6$eO2UoA< "OF;@A:U1‘ӥ! c^ʘ4 pKSanrI!= k$lu/nNvڋ5|"le(|_PBdSK)I- ^c|j2o .녨YMϣPcbcqD{0&OqC/P-Jv.xrSq5$!B=%zbV3z[qF]= F2ТІ`9(}kM51W*|K|J$=[x~g|ȜޛãMFrSJ)^(Mw ;c 2MLI`MfZD7|R:!cwCvj)Ɇ=d fY0V;/utpHk1}S婨P4DI&Vz{>l3Mvk:͵Ds &ђt kEkjޗ4IFvyB& Pp#O()@߉hBvon Aek~9  Vb5phsK}vE,\+ `_kt=]}2 1SjiOydz%Lo5mQ[U2 )ȇc~0qxGw6閇91$4k`Wdxi1j%èT@U>uNv£U,J&×2=})b cP-F]mw;DOhhp r{A{e¹Mpg!T)})Y>=qX.8]`!5J3.>xp̭HVNE^~g!_ڍ,7n>?-dH.d* 7|?S k𕔁/آđ>!s2,#O)S8d͵1 x1~]1 sOʗa"pgbރzz(wd4 N][t eJ1?Q*h ix &'9ш|Kqq߲}S_(ͱ3J,&"MU2MJQi&M6en I*QNMD2_vWrfܜ 9}^-s AGa̺RDK9I:-g^)Ȕ{仫I@uk^ӢxC%.66( `G^6ɹ4/4> M=:1koR+p&)#.lˣ"쓙/zܭ s1UV lXp+XC7GX|(ynp)ºA ߭DMZuYlsV8Ŵ/]$1HV>^`_<*ij5vBV;nAiQ^2}^#} 3.%F0 Gq.k <ݙ[A!ik^eeHxoo%11Š>\QbJX`^bM;x xY="p?A<|f !=6zN$Q}y`L>Nu.K XN,%ߎ-`~7 K 3qS#YpLPֻ|{d^:1cԸzVyL<+x0 Sis^G~}Ʉ- {w_QmmI9.aHkq}_@c3,aȌ\yg&u!>"h6L݊%3c"fgxok(>iY$^ !O1\|~{/WS9HG3h/L/ r;jrhĔdNU0-:ѐ>Ћ eϊw" bΣvټf[iaɌ:Q?*ѨnOECx"|w"qz"Cɚ]HC7*&lL=$ݽڣ] y4n'Eq9QNc%J0*WVvݲ4 \*A xKAe ˻[rՐmtcF;~l#bUנ0"(^S"7#o`"kaP#G .BgoyQ^1aYRV}>%qމjZz#k:y&O` gB!z4OGwG:`qNJf'=7u4LR*O z1V #$?Γ[𱠜 FZ@9 K׭^ 9Tb*!JX?CpOb6}-)=HY8;D-wq%Mk&V{yOJQ/sO3){}a۵@õ&XTL??5xNwLnlnDu_&_l?y$g[aHYHokq<ӛUH2ܮX+{7 ԅ&vS;:VqKS梖ljIw/X7~8Ur),vK. l h#?xR96$IrB:b"v]{Z'!e$Si£&A7 {á+d e/3*Z6 iBU=/'5z^_!E%oWTFc''& G 89U"x'< 6 ?c0-n'!t+'>OTf>s؉Jnqe M*!MhZ.{&Б3W?JFJl +s )=muMbq1 5}2,V>V~ʚ` +*cڇNé&rO@ :El}UM&5i:8yQ<>녋LA硪#Qw6n 4q2'7U?,A`AC\tLw?u dP䜹LaqChg0_z;i`(58"q"yM-^FLP|uq%g*MY"\Ա Nq4T2+2Z<+Xd)>Oke'pU+sZ뵃Y` +jb;q\wA'Aj=='v~c7)z.[ir>||ޝedƂY]ī^zt-Mu@T!ΑUpƹQY\ \S[}˒z8ؒ% uEqY5ͩ7~hGYԯ5@(/%@@w+I!Akͨ6i@LM{NR2_6bhUِ^%"b>~JDK0YbpsZNm <|AO*8=|jxH!=UwoY?0TZf8i64FϽccΌ97~>gʈ~(z4֎:U?\Ϋ*?  4ǸV+fRh+ڟ ^i3̣Ae}˂ox + ]Ys,}.u,S)* B|Ċ&3Nz Wv G{Iň>ldb*e8mȏ ˩014 a> ]:%*S}PF!"7uz l)/ihonw27ͨ=l:+c>ls:Rf08U`(:i>iuOf lؿ\tܛ^ PD:Dvr<vŻQUcvY/Sq%pe9 C.oJ!Cc Ӊ׍O3K%\v\dX ^K@yyf)?c᐀ԅFRS 4 DC?ipi2=L_@EX+vכ~o(}HE㷢$g@h"6:K96⪓1"(- aÏ׼hSsn>m<!iu?p&k=Saɜ29!i#˾6!"ȃ @)elb<`^F:MbCqGPBᙆR1Wv?@v9ĭD 0,u6Q=;1zݐ~ JT0ֿyje>*v!8AN %.D[_V*,څ :5 Ö sq#)?kwPWMn?E>5O2#.ψr"SYԓ4|H(ԾA>#P0>}sJ hUr-7@SY3_ ١NŤPmb2VL4Vn`.դ3mE6KWh=3কJ o +OXG܁%#ƣqОr/w)F_?_FI=$$$)85vA=NTdyVygjFgch.rXt\XyӀm<@hFj `SL{ߧaפ3c-ENA,2!3v4Rn^,c.e«)zGXI3W_?j>4#V2D,B,gk\Ld6tWi$fapm~|x~X `i5+$=r_BKņ6J-ڌOH pE_AO~pKJN.0e=\IYun˒Ws6@C5פeXU,jRsѱ vW9%T.nX6X,a$ u#[M?=N4ev,Ҭh *XȖSP im *r;,5P ^ Dv @!-Hq0kNE+km f e^΁"{rr|Vs2g(y1CCP>.3En <០@'11W57T R.QdA'QLjLhҚ?4V'fJuw5o0;n~v: 3|l;@[A1 1;)> ī' ?͙i\ю+9m"B{\A)^a׋#[[Yi!W=Y ;iQcpp> 3kiAp1]0Cơ񵞇bjۨiiʜxog@Sp& /CVv*Te#wЯ|x-T9 s(%X_)$5mj-:h>|7 Р|&E->wp Q1 u*Eԯ3ҵ{e!Nx, Ԗl24gd-"GNtOf =Ai3)tJ!FvJTAe @2#{.PQA SKCҙMCȏ6lp t؄%+Ay^H3Q?ጬ` >K.õM\xw>ԆY/]ǐ5̒e`c* 6[!&-j $/9mBmh ]819."PXns ŝ*֡!Me2>cqN~F9ӾcviUJZU7J7"/ 5wJUroݎga3Rfah݊R #k#0lūCl/hi8N]"ڮݏ|9Fs/G6p(?S5?:;l| ~s=~) m C=ndq} aGiKwcdR,EIpgؘr 84zTiQd}@u;i׷-P@0bX4;X[tY1(׆/҅=n^ȝ<\}*NNbN=/8VGw=6ܒy>y`K#Z}gN'.T (, ry) Rv/–uHqkL42\z˲wll^.oaNX-Jn4ˏ:,^^}IrF~AwJmSOh90q6e}A,=הl[#%>6?9083K*Ԧ?j7<ø'8nM(tvuT!r0m$/sd[yn K7~5 4Q?AO.æokO1\Sf*o"fl2rIU󬈈WK cby&3)ɠG44Dpe A_Xo d!s\X XaI}~Ӹr ZL/z -!vZP>KK w0X]a3)t`ǍbAP/97 h69Ie^W4هZ0Z{:BRF gE@{4;Z,eP\UAƵn?3j,r %sTra2@Ypm-8@ѿN lwR=4RҎ'&D][_ZI'B[LnI046&2G6C`|PB(+EP^ebp*S6)Uki۪5Yek1k;TW I9܇O7IJ9:RDWebwj*ṿr΄\C~FUuas.l%P!6Px;LĨ=ۅd3vxLA0XIZY9$ wYhv'R85 {9/ʭ.![)bfBExQGPS]'¥p4GAksa $bvWSVԾQ F"x;H4|\LoZ4yp7-z 2 öoS+.fڱwzl;i?'$5"i7-5^;=Sy%-Yywըp0$jW@NKZ/3qE}.R^yS"A"sC:͌zVE7bMh0N&ɐ͍ _UKRE\?G=y%_o͡OI Zǩ"vU֯%7eL{Hw"3~2pB 'T.lD2p{"NGhOz׆[ocXK욢}qB;uz+5J>W!j3dEO 8-hF12jW"JƜ/0WhR߬J!c ~t*!iPݍi_e =z]ru9H٥?. X$,3|!o'vݰqf*;;iwYaSꤿ%}p蘪9:ub}4 /eEaǑ[LI:3]fjc2B v|mT+M:YK)Xz};x`;p6Kl Փ?7&+²*V|R./S"*p ,n>wҝ}H!F-ԣ ӝƢ7F}8T+^<q*BƗ,͡'D241;Mufq'{&}VSCj9T4+6 dv5nm5eVFb NUNe(ZlʞHxOJ0F*V -1ZZ'8J[}b xY'H} Xc\io8͸VQJ+GS E[0X4 GALخxȫ&l#*,'FTj:nq\uuw_h-p{>+'5~XM[f??V=Y=ۧgbtKҾ]cDN@NZzXr˻]&>=aθJcc ͢Ҧf!)~,2g$95^fcAz jp(As 3}o'/qE'c{){Q,u2A0 B,zX@0|L3ۂ'>KmUYZX}+-Js:TϞz%5jVvA 24m#m oKa[:^5Qf%s }T%!$Ogʶ=;těp$ -( !x 9/M,8_,^V7Od`kz3z&@|&^J& ںKBVfM{9v㴨ub{E֓8g,G@ {mb<%#tR0=K- }'d@6Qu R5V@Q66:Bwrۇ#;жוr=7t$;ܟPe.μ "f/3pPKu>TLzL AHLjQj]vS{N6;@T% {B0!ZU=PGKby+ׯD!nM|Jĸ #nF$1(8#<|uܺ.S0o;jIU*8ZsRxoE)RE8>)J@{Ǘs(r͐il:vؤ`("EPd_x/XC- ;EȃpPן[qtK gz#_Ë) 4Z!zgK0 Vvd BhbRAHVA <{0cEeJ( À',EҲ8`/az3ۈ"J[_Kcm0kg| p_wF.->hS;zpHʚ{hsf.KV7dOfyq}PO/ҡTʩJ!Kq5bbAȆCu(0W[#&сep׮F'Nߥ ,f14KY!}1X_q=;dkFǤC8pWԅA"dAzqf5TufъoZw&dӋԔ@d;?m&aUՖPޡ2>| ̻5uK 9-_Gdzh\S-TQuEhDij$ R/o*}s}'SAK߷4)FP;%1_UCbjáM:!j{ޟ v >~6=hS&5@Y&bQ0mN{zP{fS OyE=ke[9H肬œ\l@?f.!N {v@`vm&_y1ӗ`MMz!ՄEA_xojia tіlNkB$)+2팞E%މ{w6گT6$hw]7( j(1DUG(15勅 ǒ7z?Ob ;wM%Sbt+Yʼ* X!VNd&>=6P2rZwyUNN.ɉ~験e~%,,\!"Vy%P~m57uSW>VCgMDբjz!^g/ gH!r*wOP뜖ӯjukz]ʼnH<8xΡzk_WmvDʒx)V|ϐa*u:g)ĝ&wQXA縐lXqpf ~>G>MI癶H[_~(}dw[TG-{xh[ HPprGdyy`C*شy!hW^S3Q#.3˶N4L04xF?9 ZCviNV8]E S+BFL$>iR_%xjpڢrW 쨡Cib_/G5Q/J[@H5HTATR5?`9E> FH k.3̯M{ҫt^2gnwc,p `V` m*a,yߠ^Y*I<``! YzW8i~flƤ"s9`Ary6åYF䓊t?:[ĵ#gmdNK#|ǸZ6PJ g&T"SO'^fet! `g]K<~jMA,u^;;kv67T|nhKtgг- *R܅ o]NJ9vL9q6;m6n,Tv&. fDD**,z2@/Cb'FW_1I> ].I,%#J6m#Q,sK0^йL,߫v[qoF`֐n/0~!t$ϫPƀ ؑ=ڪҝJ}#ͮ dMeC)L(d]Efc9kTMC Q[0 7?"/z7z2;ߕ#iǿdu{{ pJfbus`6lO(V-T+-â)B°Psv1z BUc: 8Yk;ezbۙ2tٔ;P4?rI'՗eu1]D(b<_氋!yx6 bt;:t"; Rl]EW%~=A?uLN*H8nlNz3<}%+\sGR5¦P?>yg'GF2K\?k*x44l!v>s_Pݸ:Q4qx ~DE wu %,ƠJy- ~ꀁ[!_$݆ \̅H?[x >Aħ)_4k6a @QsR&_g* eh^Y&6"e>%c`~NLT7!ndM P<xdyQ)ON"ŒIQ+"kΐD`81 =W>ze-DUD>d^NoGD >DX`3`20q6ΞL8W}>"U:!VJs:= cD6ȶ `vQB¨IiyN@uN:>“15kxߒPNE$.Zw:ث.3(x';9h23AU-FmL7C@?ґG)nRЂϦI>Z(,hɦ'WwG&2l_Y!sR&@| *LI#BOma˅8'V >O3߸byz .JPz0Eal 3jc/=iWOO} n" Iz}mQ"ZZO>uFJGeGVť鏲%gTz./HK`=x+, A7ذ8hN|ͯj׺'0|@&FX ֩VC{~aڋ\\ gLᇉ/IwanzR e g3oR1 !%}ҝLiOwy-t>#vSY]w,{"X]ײ`9,pov>SXLlgLXݪj$ŗ|% yUv<2 _GnJZUm.ؙIE}j.H/`_ C35kBu _(aL.=Q!i~kTj'+'+iѮG|;' QGřDPݾhI  N |W <˳J3N3_XjBZ@cX0yXB.ϧl&h7 ؈YL~\!yѭ =IÈ`W2İӻ,Rj9j; Z)-{EQБ617|+қ`'^O¬_6~,nFXg̅bf}E?_7FjI%v{NP lCx*a +ͺLScI st7I:W,H$~_Mʴ>@gG:O4N159>;}98AtzUM2oxlUЈ1iZmDdk? 쇜GIU#4x"&f9u%kkK]FhnT>_ M/azvyi ]HxЧ/&6#wf[n*<8Ӗ-_7w]༥ΐWr6 DIC4w2ߪ_1q KUnoABCzERhY@{yլ~X;#}UP rRiBvp]L^ *W+S5Xl<ҷ(7Ǡ=z+o.$c<>ZF4;{4] |D.QdB GE))rdm C J)wܘeCca:HMp~+s&0ឆU6ڬT n6x?R,jKN wvөuc˄[,㲩PV e5pOf_G8YgӚr1DKf;-Zʼb.Eʞ4c,Sᙖ`[`Prك, y V K};)5K&mfJ=wS@8%UlB qUYk*DF;6? xQ|]=;BNbTBOLDRZa-,W镯`2g4/Jul#uKB1!i0e-Y~z6D1/`yQTA6hg |t8)a45 wAAؿY4f5o X#,Cs "޼,j'k ᖿ UL3[ eK{r6\O^ m U`𦛶LxDRſ6ϴcQGA 44ihO1% hZ x{>nd{Doecv;ŏG='>a@Bvw_3!̎%Ŷ EѠ !qi|rPNZЁMro&-v,aB9ߠ3esmsO~[Z^|F|6(XWR`\p UR+'ծ,[-"c-5$ yEM]BYj1OTH+ߤ&9}K?w~3_a89Wb{n>gh-`̺t[2__ʔ6}1E5ݬ.#TJqx`]x?e'cmj\=SNZG,f S%- yl2@_&VYiB͢:_ln1 *O;a,1l' v3%/a*S<)NΗ՛N4M +Ɩn9XSpEp᛬7c) ZΔDU2ΐ~OW  ]ɧ~bg.#f3ޖ ȓ*p,/?ń_N}qG=4SvQHnq^] ٖY=j~\P!G^45TgG!&z<0P㙖ԍz٦:lKRS! ,7(^v"M''؎϶/Jswԅ;:,r8qni{KZ/8Grn֚Jc '7w1j;ߡj*5{<>q8z:@vusWkp Pe@_Uo.ߴѢWL[oq&rq3I:ӕov\,}c{]Zms*19vT/<6o4a^ AqdNBEFu&װbj'؀yRMXIZX6Ҝ˫'9$3^gj*#d :ax^d:vG`1zQ_]RG+Ţ~qB \`}qMA:_@A턴>blhs=iC1%$4b5PON/WH7<ÇF^A&JBR8Ut![]*w% _D6NA֢QPYrEYy+$>1udpIURhƉi"}="oHai^U2+$Θ=:ӽ/Yt=V*%Oޚa楤q6ŬsO@/@ᇏ1l$ﶻUF~ gYB=ًywCUX0߫0@ϼ|z|7՚$ bpfP ŽZ^BSןVJq%g  3&va ecŦJ(aW<:E4|&Hx ^crJNɸA9'!j U@41eܛ|/`C^֖G;|, e_}+r|:0ѳjk>Ny25i =H\?ȑS"&C7k\|2=2I {`|ApW-0weUo (bdbEG߾,&4E͝fgB7O PS,>{SXWmd,w&]i>Del12WE}0);BVWiWVĕQG?.1]9]yPXX0j:[ʠc5acBKӂмSf^nYH #G:T,֒ZV#oK oR5g,A,Ua1\#;.d UoAӯOz0JD}{TM { ?MCPTQwYl_k,8-YK'h srnFvLjcpWVr/w~/l[B5krK`E^O$k]whyA;0utu1t% 4m(nQ_fh8˵̏M 'sAt;ikr¸.m*+/sEI$S Bwlυ4#Q2sKdC%-@RlS4$ 1ku+-AsL`gt# U Vj^ES=#\H$*k]>3'~XԔ""2J dG}=@8b[ O,vi2xѹ%m5wS؂K|J518E ^@/6k"m ;m Ev;wiÞ8`ڼwexI-Cf-Jp `:j:ֶ@ؒi79U;- !OJ¥bh]+yLiKiFnKr_p-/j +ƛf_[(+n)]'`nyؚ}Ub{z_Lˆ̠zgZo -L)eGułjvc]?)a4IF*Ț틗r<fHM4qh )D5b1pWY[0ahecs}d] ^yT@\YU{-]-Қ'{b?_졁6hjk-) 8ttH%ȞKcL61(d}1" "~E}d#1~.q2I+c+pe2grU*K;2+Y3HZbC~m`SbKT)0 Kg˞рT)EY?F X(u6=hMPSj)&4d|qzPԦom%p^.cqg(hcnl~CLmǭǕ:9͢h&!s]~?l T _6Er %.ZJ,#^orZB,@l9/{8&ʂ0d| .#zS%hQX3QSweߑTY"Kl早97 Ds;&A=vœehtu5{+ jϯ "J31zk礉T;K|ԕx\[wXReQ V%>l]6dAeu2A#Vhd~^^ I쏓TJ#Us*qI] {#{5|[:WA+o˻G 7HÞrV-O߰8ex)>%<%`nSc/d "My޿?P:&[Cv%E|U:B#S wDe*LDu'.qUHxI?ξ@2f/r n@b‘mҐ"(B+ޕ@! []N_RX_Uwo2nJ쇉8xȧ_e>l-nj ~_ ˺MR͕/4j)0ZwX8W#>Z=a{ISOA>1u)Q;ͽv,̼Ѱ+}2]nĿ!ovW\[雯O~y9کyLOzkRY Uvz~T!z ' ?AQr|EvYYdn1щYOmIy_}<B6yF,E:ȴ4e s-/l Tub+6K`Sr%K~`$kk2s7ú^J91wdmNk)'3kjc9(] Oi,- mœ1kiɓn6Sq+d!e=^c] ֿ7Y(ӊjlKMl44NLsL${<_(k]>6mfUgGai),"E/Ar}x"P p@7(1%fQ KJ"[n DtƤ,#$uf~ b}5!eT..DOF nǀ}j+;j]! P@\}MaHS鴹T⎀BˑP^iXk)W9Ψ&&ZϿ~Yx2~l-82)LnIpov#+$0؟]ya Y^!bml +̠ U.)Q_y K@_9 , 4xddǍ.Nu'N3i矫𘶓 &_TăzlEI< !*g^Ӭ|%%VY3HVre;` ɸѡHRGZƓ$3 x O6"GR^NP5BL`{ O%n?N^OV̯D$PL$ [񺏢 {u7+&ƈ^6WKωH  g|Az4|徠hW{#uAM5t%=M9n!]vVDjBBn`ղD wYcſalὐʧM/DlW31N /ͻjSxe=uLt?=¥o}?JsH0o;7q&hN8:m}ixm%T[z-Hv /L"zw8d>$9Іv¢F Hg%Z|-SV8]v3PO9 :^+3 e9gzz "t,˰л?7E_zSaVғ c W߆ ND9 ,˙0Sp]90~% fXT]#á؟*vԀXcOmq3Co0Sy! `L=]ZK5Lry 7?ۤ~2Y!CIB, w P )+&3 -Ult0:Jec+Ef w/1/rMeՌ,QYhrq 涖ˠ:"qQӍL #x%rd/}=a}J)P~BoMѢ"Ox:nV3c͡l,LOEφAh tERU/Q"` }X5CinܼzMnNI>QugbVTnw Qcc䣘$ħyuvvT'h*pB6Ÿvz%5<{LuPHoF{Yӟ +gU0ZM-T$q{pds,NM>^Y 텁eQX KI*LY$YH*l_ ^~6f&!m$HBg*H *mxEh$'8߮@DLAr9uxM4< n[KV5?io w2]g X- GC9$$AT4M @o@[PW3?z|X4>Ttk +mD18s4_5AiTG3u^Z":ɯS=m&F.|{ XjA^7n}5YCL3uߊ.{>ə48K s曅'K߹D<0ŤlY9pŶ%O-"-ye#8T;" o9:*;Sn 6!Q4 >)5dJ=LYw]/1˃fxid(KtYQLߑ27w'.Ñ9*L"sՎ15q>YIe5DoGȊs ]1q; QΞ]y-~"=?zļ@*ά3߅4 m?ϟ /BAK@L) 10s t@O=J6Cuxj _"ɢ{ C\45:A ~ey̴W}46+EQ?NvkF=6j;b1P*pG׿C8+(Es+uNH[lT𣝣- :ƛ%7£A뤕kkӧ=U088lٞ*aMtu\cGW};3i7@Iʹ%Ĉ©Lx,"&/OD}&Ɉ}Rm@=+ 4j-59zGSMXnSM II-48a`N4焥XbR\J) M?i &`?^;~ө[H'fpv^ C]5Cm9HкDx$|c{z<>Y`ٟyV+ hiC~~!sTÌv<5{ ye>Lfqmj")E'8TSs}*{blO= XeXM"@"ũ=#r@`E1& 'Oqf'Sgnu&1%ɡz;ރcUp^i\ׁ ?cĂG*ݮ.~@pZ@Q'4^s;Ct>1 vЬMں8j2Ky5B`|{4 9|͙ ZtV⫓ &S˥WLivOM2)zEa3ٲ#V0` ىغw|0ݶ:U%djQ$nPE2sXq;* 3j H A3R@@W,ҰNOX)%v\šbZ^h֦jKĂiԡc-! _G|1sєFOٺI|Fžgj=_\ L ,f]VVkzY3Q#]Ѹ(w7?]+İȩLXg߳B@2HBl5 ZrJܣEB:9R߂.Mp~j 8z;69gY`Q ,C~|+~Oxz8O9lF#1A^ƨ%oO z֠8*pMoq %HxVCA:g"|h+<\F &Vj,>4lO R.:^쬴\3'ut,qvR^+ cwJ3}k Lk+.Dч# /\8l_%:)  "_"u&bYN`Ʒhztc"E14, z"bX|ZVpa^ʳ々UQ)Us\ۛFr =+VN+T1$Z `J'J!J˯X;az߷XM ='byH8{FzȲ2 CXrI\.$*0(N`Cu3k`܎U'=qB=` #NI דNP4Hg2X,4ư,QEqL_6 ?.TgUͭr~ˏf) sf٫J{ICI |c%UnWc[Wi@ɅUȭP&T1u:]VRCZVMZg"CW/NLڷi(bf죹%2|ɇkBh৷ܐ0n-)u8]^T=JlDzZ@ YfVY._~g:!_v8,~BN;Ҁ @WĴۡ:N[Gn1޴x~BƑ4[.pU̓:zJ.!=Υsj$.T1.S$)6=]`cܠY=?"b1ĭZ'SVH'DeZ78ƭw֩A:=R.[uo `EzTJߔB Yfe c3}Q Zu!mqTٜ b2ɴ{kF7o2/dBcW-Le,Gś!9ʃYz֖JO㷜6leD э3yX ܎WuI$ꛆ+Z50 ց)S]& ARo|@HpwueB rm J@$R%l҅"(PDמi:QYÔIqL/t&[6t1N/sYk73q.p3g3؅_:PO)O>ׁ *^cr'Heh\ߘY,y"&"+ [dgyskQٕ"uڋU8- -?pn^^ƆW-k`d}w I$ѓurX9'~9]3C.[>o'f۝֠%Fwyxd&!i\$]p){@tH[J6z瀊9?}e^: \. WC-iyj6%ԽJ)&_+u]+en=h2we~܈ﴡЬ`F+mx Ԯ@a7@-ɪ,j7GxBd<8RS6WR㵰UU^)۴R%'<_RWB :R^\{^5uyjZ,?ݍ{ظd;x!>0lsYoopt. |׋gZT{)dżvУŬn:Btʪe>ahgsS8 ʿwMHO_{yu٠.Gpq$a:=0_ ;ƃ(4-Vÿ|Ad B"B֐rmv?btw Ò7qNa?#0YZoFjA92D  +j9֏> ٯRfN;#9"g퐐>8e4ǞAt dYRsCf[ ċ! >ĜEdU[T?~1٘nP_fĉش`ʗ%,⯣WVVWT t@e ǨI` H)9O"P+Jd)udi43ڍӛVfs_LwH6D7" #B*''lXhb(*|LVlq|$!]%UX#Rh4h|;b`]A/Dl)kSY}hF`8B>-d6'lq0(cSOli6>% {vd3gLUJïljCVm7ơV~ DbZ`m Q59+q57QԺ)ms\)YhxtW7Q(FzP{A &VwVKt>J0sPdSKo Q{9Bb ; 'gKש`aE~v'ۑwa~SߟFozg<`~nOoJ?xKOqlԼ "&/.M2CF]v|*s`dZP5nӕD%5aTȌˌ_E&S33Ϸ۪⃟f"I,J}A<#yv,aPA^PTxgF}$Gyts6TRH;Y*He_T_qz8}[TR%l4*XkhĜ|1n8&>d)'QN`UPtqR~ߏ ,I@dmf{9e?3~i`GR8<o'/LRKWX}fW`CSDBhM֎_.?ْlV8 o[_^F}`FWXu] L\vk$1G0Z3?J)ee2{<6)s=Znf┽W1Ͽ8/_~R@oP]gH{mv1iC}Iyi*Fj2;#09b 2#,01M4NIN.4zL@A$Gos/ځ˪vWґ⮼qoXm&ϕ7,с MCWb (ӶpeXJ'>.g:иEGCf+:bF7#̯h[Dw|i|?[+tn}hC$7 jFahvpɬݟ.{s󶷢]hEhv6\V͖/tcP UnjX*XYj LsL+-0j|c_Kә~ؽj՗>GkJvW 2f+B߯v}CٴW%a+~&#XhÊ;RJ]lB+3GIO]_"A`u Yʏ&RR[%2QPHxHW7wyI$9-R9Z1KǬѢ(3rJe7ۆ들&?xM5Q'2 'l(Oe mW؂rl& LFe c j ~bZŌ{8v7$wUw&ᛙL5;ExU.{ -F5n_I*x.wj)g{q>Z&rD_4JojJvBoU)?L hm75*TaV-∫*Ƣ0<;Kf<m+}wZ*[hu 0Vya]3egIX<"끳.qYa$L']Z-,$m55 }w[>,ۀx?^(R%Km5>Cƒv.CȤ2ڨ+ |ch%] Y3\ުCǺXUટXph)Xh^Y^ l{x"w/Guad| >g۬Z|`)yYuV\ 5qaSljΓhMۿ?~ S~?+IhŒ|+=aת6rjoΜ|- =d H :Tfړ%ԟߛuNs OV-=d}l.]6.E$O_|Uu]YPХ\_!**>]~̨6uF#7Wz@poK3vf&gL,Sin"o'0bP,7bqc~l8:0K L}ic*ݼSUA LWHJ;(ը/{:G;AT(ZI>^|\,),?JT{18[ C8TH5...9@@y_ kS R4jkKNy{}+<0o"c&JUz|.nLbbfRDk飍ҺDag]GhhF}}.pTL^7b͞ SK,TH}ar }d; }N?0H83f۫47gU/Z7b.w.kYL60\[k'3̜QOr;*mb#M1Zu>B&BUU+X?VNtI \7FslXt _Gt *[Đ-'"X-|Q7} H{xv`Ɛ*a!v (}z,sfj= /^mc(@y8ts\p?L\DLwD=r~[He(o=ŘNep% Z m@Ýj/Z望Uro/뿘^sՈaNw{UŸjށ؇ɠJ :g|X?KHbE`3pgVkR$L!zz*1H:i\9Wf׺>݄7jVۚg//v^^qׇex3Bx!&fv,m>\3K@؂*raVȞL\-vКu"nQ>B)ÇFS|IfZNY|.lQL5S/rT۲4"^.$|_Ќ)m4O~k q2F+$6sɭ=%7 p(Q4cLsmꈑYZrfe0UrɆ@s-}eUpEМZcW7tԽG~/%`{B Ҕ*7>Fa둟u)<١ lq ?*ߓ W9F *m2Mڡ`Ǘ3AE7Ghc $?Vb xp pLAÁX4T)]9u)xj3YTܟ]ˢ 36)*e՜b l9'cIq85Ugz-}KEE~w^|"7uԶē0ԓ'CQ2ah\7&.%۰.4ɈixO<(@0;fΖE.TGk]}5%q_ûv焊g}˩% <1> PÛy@+0eo#CHXnj*Gz2I5dnqFu8w.J|Bg5sp/4y>Q#<-6\p]2ZOّU\s t8 ^l7jiB0kWJ\?~(>vEB]谥}}Ef4. CubQ(Ԇ8TՊ`(pʁ3!Ds.:jc!,^_mRX#_B[Nxy%N~/SdYX tڅ ʏ+$w+ ;f/>eEBbƄJ*]v#ݷ9;+MEggnC=9om',MV\:D3 r)ip{JH\l7fW!B/ `d ltt}J((Rwl*kawڞPr ?q (" uWlPb_ _ImڀeRQbπ۩b<ۑ O8Uq޷SP?)X#6+8[+!bԻfi @+Xt%Z!dQ >8E?j ƚ{awiPT?9ӆ+"utbp~'U<;!ۿd.6NHyRXT󍥉`HiVo#ln,X*\* c4}NX!Z*lSvǼ!rD#sIN᡼C2U '53jS4(_;h"k`\- Ɇk)>iu8$X-pD\%w_g), VAuK!{&#W _"StB_NGN`otQ8:~/hrr~֗Cj 6 lD&a&so%g-i \.y<ء(6%8=]#cK=_^'6MO29?nMZ} a"p'zr1KA_=ϣ D?I|#,Q/=t桥DcG' F# {"u( VncQy+(; Ot~ߖr9i%Ȫ#iERًS8o $X6tf _CshpnF) ?6c8TkZ;/<&&x I?Qm (dx צjv}SS@2Wb0< z`To3D6`Ey^p`08hE3q:ݕr.wQoPÌP`Z :sOSݬ+3x@bY]o @=}Y)v6"vp )Z7}u19m 5`ԹΦƑ~uuszF]ᄤ][vUcVqĔEt1hMc )B*Pq_̶J<@8P5?>yh18^,r_Èjo6N!VI0fWP2EG2Lf.~l>-'- |wFU$@=Ǫu| TN0T1vҼ[x+NC3 (B\u奠D&G 55*_( 'tۜ"}WC.E󖳦)kkV~IT(ZGKGV|4EA"IǸVp⭵jE`k5hUe*ǡRoJK]N"GĻyLo72s`OucVp7۬skd5:H4OYV` 24߉zZ bU_԰؜sNr_B g[@IV?Z 7脼oe!~:GigTzD10@{91J5"sRC,i,"BW 4 ʴtVA7rӺa^ ϶FC*0;$ ̀OC## ΪYTJY랾7͕f()\ x3#h/8"Mf3ë||0;4IA5;SI4_#D"o JnywTy I'-]2 RO=Xm\0hK8Mꂌ]7'V] !ka@ ;|vw"J\ \uX;ztfΚ͇3t"p3в?d;Y7JWICEE76pLck|}ZPfQSψqm ovY%s #zRO2 +Z\_9iP3 ]Nryx\Ǟqi J7ˁBבWaT: l u>h l,/?tlZeP?TwgRg fB~dUaH+equ2VfkaE([DyQT3T#'UUt-sQ~/|PbQuiP,k[@'1$bԨڮO'ĀgZ1)4'hjC4PL#h{HDpclPyf9鄀䏛:U>%d#1<'2fHMn0=z9bo=8ho}X+aI\:hM,si̡i,ﺫQk ota:g:ծ59AVv)t9׎'5v!O_ņgHi*,.廭_P" S/3SʴHFJMdb9(+#;p3[OKPe^6w:d}:p/a [r#-=Kj7xX„_[ojـ'j$f*Lbf5ۄO'#B JV*tw+z -lay/$x襛u*{Cg|>l*nIaQ'e{D/7MI}릉{*rwra_qy(xyPHa[o$- zr¿ YM~M iD5ghv{lB17qMYA F;A֤I4q _ _%u>(! GD̈́ s_b7$:ﭷ&e߈H84 E',ׯICl:̍^/͖`H= YR4kAδB:R=ҼC v@s؏2|x@$}^c/T$ -goT9 | qpS3yXDwZ5Uh@W;cPxh̐ˆ ]Lg@m1u lK8S,GLcgo) "cwUcؙdeTs:=2pu/]g '=K@H.b#;{ cYkfT.q6}I9ܫjnen!jKc17A0j{k @( H òA(7懔j.?k6?oQmSo& օpβp#=s^} #ܪb>^|ҝQRPo;%|vV-ZXCglv\[vNy iw:0wG\*v4ԣCuISd.s~qcjU;]ͻ\xp՛1,YP$} jܳsoo%bi+xGXX P"L/v,Hrk?8.Cc~׶ zF { ½*CBf-oq~emcHac| 0W\#@ɺ͗x@Su}h:[7sۥ}v^JL@9+(YJKgw:,i!1ɖD bk:hT^kg삇tmB 띖[Kj[j 7,B ZlF(1 l _[ʢsCۊ}Ϗ١ V)&=f{sAcO:⹇ȋKGi99-,LCE<]aA}h}~J{ ?Gٯשmt:ϋth ֗wMZ3a3U z%DXl)>X>~\uC fIxRBZ-N{ L #IdKWģ5Z"͵ziQ˳\Ri|,A 3:j>vBTW}w.ZcRr |i2!8U@6F-1m_6RM|ܙJ.!dt<+O'X2e3|"{`' 򍘎,A>1ͱg'ʰuTe=mUzbHvjaxK% 㷮T{(B CoKGɆ `D(Bz)e)3R)*O_/pU;{6t0 ur+5(#@*KIe[$u>Q>s>1xJkϓ ]Ҁ=Q`,!4tI2`\7zSs.5N򩰭D,2sxweuV\kzM'"'n:ڬ"zKC5p7ӏw}^~z) zփxyP. 5ai}|uWcbytOà'u7-tLۖWr-a`#x *[0  փKjX{K]B2_ʸ%U1-] g 2¯ 峐Ǩ">aª[>wp\v&w$!.|#:3h2;mcI1)iǁZ&:{sMK+HYS,5':T? ǪĕḸ+{"JcrFv %i1u9S6&0>hùwlq'!^|Lq[>zIY, 1MGntљga"1KӅWA5CW/.\}⑍odXtrY4I s*pN! HUWоhÖpz3B8WOC`3~@tֹb,PbGm_DP'ZI91oJt!Iq&d(X*j;T8-έE>ZZJњV,i{[1Vʹx$EHZnHVOips;g,Hd/MrMTG>=4__,ݨL!Q0WA/bAggj{u@E?l_=cy)jDN)8Z BPc""\ĄO$yB\rmMHf)ђ)]l~?Wfѿoz`]+W{&u #˶ٶ:$fk?Մn05^Z̗тަAWcrtɡ rعY,;Mv٦=kZ&',qA!2`,QC"9 £ }вJW]nɛyk/#1 zf EL񣹫`cG-&BC6_jdLAd=?_H,S}qgK2J}#0gbʌGHD$nw&|Kt(J>F[tghr3 G_@Z ZdLGkpk!S@CGK^GR3 S@*d@UCbQUʸToR8xW,ZavV6D8\;lPmmZ{V !S(_VЭK4,۵l*T!R>[̷\9m00$O~ʱi.d ezz~;Pj?s "50P.̐%ʵC$4$DRedŝaih]dSKnVjkHɳY|DQ$ˁKnMRX]Qn^FM{6#C { Cb:"ݧyY]ysOX61fǼo`v^N~S?G{3y t朕ݼ[% B0]w&OKކpsw۴!^;,Y,+W_ɞ?4AFCa<3BWpht\ \3B%Źo5Dzmk/R@ܯIT\iUKGEBu[`4p!?o/fS0 vil͢ˑ.~60  GwN{K S F.pCE8޾ 6CrRylɔLki-tgS-n/./Su_ Mj£IHT F9o7pP?: 4%+|<E;+}3 mhPT팦ëX!pCPxZ l]\h6Ƅ'";NXy\[qmC(ݙoOanj#N9jmzt(V9~@11mAm OV]B\ϯ8Z IT7i 1bs؀ԸL|h(ҘA`z60`ekMK crp$w$> mO_۟rSL[Ng9  ]HQ 6 ^͍Թ@7mPYƒ7t]f'qch݂?yX ؅ F*((zSGQRpE ɪ*iuAz5sߖ7[Rqsx'oj&sbpr %>Fy\9gwE\\$է׈Ul`YbIk?(gnƯĄlSl}Sq5j\%Kmw{(9MA3Fbh L.ZW9T !=H»"}y1F6HeRNz%S\-_ii7~QB19M}. T5Q\iHbֹj)3ъao ģЅćAAZj_ 5> e!\'ɓjM@\D~ˑnR񄻼+lG/O .לPN> 4`|TW:?&J_Y4/6$Ym񁷬 Ux;y˾K:V]~RJְt<GiL7[G攼Ԝ.R4q]e09WG muHqY (y:gh6Nw~<Ԋυy^ٔw۹59^.h4g}{2#Οf1´b'EŌva'}S}?=EEU܉#v `rkya>aAgṉb~>h"bȁ#X (bz0W!KzoisE NWkTUG"E|%|,GVQHBsIH##?Vg %/Z[[ Cr7,$qt;|\~ypL>N`=d6L{=M/oae*bF=y].׎rQ66* AM鄢 :@5&fH /!3Ky7|n Quf)iSUdʭ7»(G=Yw "nQҽ=;Xw'@ûV8Ap,[V 3Ԙa<# QJ-;?)Xkc׮$}w y99&۬+bM>s y5V3RӸ}jK6Xa*b^]F8JMxӪOn+ۖ Ucƿrsjyz9Q}ya!_LdP]_oj>|yP"}DǾ S>|ʚeXe ߭Qx /O "g "؀14G5Y.2&ʕAmpΫld.@s-]MQTM!4/\zp [A|^ٹ"8sG|iաUU Wܺ/5y8q{~9nDI+zY!z܄Gt5\ * we]?r1X`|/ ]гJȶAV60C#wMGkR3d,>1F`YIzbZ ?&ӢPD#<0$LI" 8#FP,Uy-v $ s_[Np'v0PxX~"*mFIQUnG/WTOgՐʍ3 ӪuPA2;>jz3$W߄c~= .-HۗU=#/Xȕ=G%iĦ~{Gˢm61?2S9bOpk=!."պ9('@ <[3'æ@T9}%,5IR?oL0 T$?'abh2m< Ѐ#bC4فus{HJdnh{1K;dq5j.SY9pî)}RejQâ5{p97w<5{AQUc R ўV/I/mN)W:Vi! y\AN7jpdVu"teSrU23UwA($zIq (_f;l$&,9.@M(&@l 6g`0jd&M6J~Y6Si˳L)@En_jǼj.C"]YTb(eucHuZ "mL4T1%4?/!'M;M;[fBc?CK%"TNX $=ZzV=tl qܯB]UӅSclؒ5M j"V1[jcj 8l`e/6w:fSK0eKD ^NO2;ύi,jL8h8'q1d:1줒CY^2qA_<콇 -_ J&%-i,wVxQ8'8HU 'J[&֚d:NILa@~ˌ )W&´Gl ]OV|Ty=5#9{B>D+<Y'b ?3(R;?UcbWy0?*KTTL&w9"^/,D{Ss+[ޛ+7RȋprpnkMz:`;'pN&Ԍg!~%cSV֓U$V uO9Sw C+y|2^%&3 Jb6MY4V#ĭfDCQs:Ło)HĩwGw5e yel N'%~څ$~e@)BP9AlΙTO'Xi< gH/baG3RQ_YY/L^3-~N::f Z:?u&35 D֝ ';<)v@[Fs;Xfo>reK{@n|6GȢ5{3[o0eZom?skRP`PzcV)E},ъAaЮ^w3t)nx9Els`%~ qA[ꅫZ0yο*RY)j >=y8N?@zZ/j)ݲcن + ޭx#kk.F!V:i?ÆRH$I˧8i'#9;`hdnr3̆G,d2RYB%W0E5p1Ģ}aGH5E)aJmo.u@+rGd=P؇Gz?kA%u[g8gm*_"R^3No㠍 69à z}n @X~ieJ\]|2:g—쐮hL^U\ 5^j[Hc;+q&h%=fkŐ6Bc,?T=hO *<"|gsnr;Ji,ZPٟ~nw5S(@DVG+W r0kR -%O!Ěȵx+U3 '%|Sݸ.7 {?~;57t4z]2sNK`=~8fQT+fbFԠ:i2Eʻ]' jt%#)Yڕښ1F#eQ҈ٽk DcY7oI ӊ#eCܯU 3eԲܷߞbY7d4[GT&Qߖ1/- %W.4qBv 8"Sz:SIaB OcLh1AnYס AqF  6$̄'嬨yb2eVǛJnhp!!v⛜ T'(,#b+$:~!QZsAժ{|LhGJY[/jhƽ´o,V6Xww.j̇ZwYig3, %?C?ci $2"aQ`S]~H]㟭yw?Jx4FDyAE w4Y̔ߩsK=~zgT ~QE-sOp(ui0G5Ne }4Ggͤu̇ Y1qt_)xc+DNP$ DqMPY Ʈ ׺ߓj2FZgj,O|A~>Xy<h8q&%uwa 4Mͱ]AP>42cI+Jָd"@R>[KOz9ql#3"DGAT4:KLۊ>zT@R]#Ecn]I|Ϥ<5CĖ+N͗](_rrww{ک7ع8y7o[.)p}OC :氀wioLs]YcAXlpv^^tiH - |iIy/> !vn9%`HB/nD^XI(U k< Ҩ%Z#ZB9̋ m\.$KX!@y@َts>c"M!ٴ0\Ua 1O*(g6ǝOkE7|Q]g@d[FR*"jH^l\`87:K 0m֬0GDiX\ݭ<郆n!H0loe,-B4hudQwz@mQrOEdQz#>ÁlvgAu>5cUQԚx&]8-z!;k:_%6a,,@M}z;\i:)~ÃbZpK y?Fzrl:PC~!gP [BJO,J"F1Y#LR`UT/RmDu*g8XnTƅMjʾW,uݻ0])A.W[sJtPrwxt]\?zt7ֱ; 7c[eYZMUW~2tS* ҔmGۛӞ?} F3xkhԋEn%=ʴЇ G)NNˍ$t(ҩՄo kMXrg&(m1SSw֙\8BAx@PXy0ֆA&)vBvaMGs~md\FRIc|ϣ+z5ojB/mvډ*dvyQhAx|qMG+{!6g @1* r5uZvX[)$Q_ ZaQZ2"N.ܸ*餬,Ó6G]R|b{ ܿ2G* 8Gi٥5j&]}xbʠ  ƥv{0C}uV28TqOC@Ll0[:D}s1%zn.ٷ'Z;Vy3'" GzBT.B]] 3/MT2hZDm]ަR;`*!!մh` I";ebi&q,X$_f^ӑtw肓ҹw9wGיh):/xm3pja)oAv8 sg\X5cebU=eiO5nRl3n&~vKc," 4JCJY A̍TsGļ=%lR&˞Icǜizp-m.-xLB[ ؜ (O9"bmц2MА,^YsKQN㷁Kl(̕2PןuWLļq<ܩu ]*RY-(HE-A/tnΤZK ^<>Qvnf*5jiQ!@QX!4I 8B-ڒm("T$P `KSCM^y+]^ԠE/%J}ȏݚ1ZS=r+1 9 ݜnPyWd覶HJ F{ݢn@(YeIcy Cj([J$2LJ%%rw_mw\q@QUm_ |Y.0SXTV.K2 L`WT#Hbߺd!Zu +>l |4ãÆ8}H蝩5>&^{2޻p |Ќܭ)<<N&^G X?l(DXEjN_a [x_KZ= CZ4)d,x%̊;|2 '~}]^B=-]jz `[ !'PIK_*5֚feþ[Zs BS_쩔5SP[O|ih)ŜGN`l/ȕ-c޾(DZӎDoؾ?8ՌPh;j/k +t^ߜ K 8?[;Xqecv'G4H{ᙷ972xnsO F=C.o̪l(x$ذzѦd%4zQ bT7kHrX="Chfxٝ ~!B++dxwV(>*`ܓ,>yOX fL:P[.F|LWZzNFMe)D< l.@%HL#Ч4*O}PM5i R=#2N?XH%kTaQob?gaZ;d%yy*X{66҉srZMٟ cȠhҊ3C_+d~{ǵLGHkO 7X29Rsȑ-뫐xO<橏vtD }-^kTeg׋/j_q',ud}aq_#ܰ6zGjw@ 5c:#GS_I̢y^{!7lsGqmKӡr^vJ5v .筌i]8 9vY/ 6%WS(5w> mM@RHsg|!۽zI% =jww8Mrv|xH43ByTQn ANc#fkeyP!0W/u\:q1`OS@<+Hj}NBS-vFiܨHI'b&g)d wv7 %TD'pSF5& d%B`,[T>,r̉(rf7K.:#C=WrRx:6 !~a!4R \4P;L*'n }rEu?xD }L$0;衿0qQ I#H ZO]( -:'4FWmhU$);Mk @Zly43|H3 ^`TU! 3nf+OT"Gz,W߉t[Zhw-<^D$`8 A%Z] )#3m4'RQʠT#Dz}ԍt/̕[F4cTMU2G3?? {[)C ~3nՙGT [cv@*'-0THտ1bA8yNpGb=B]A۩U/&S@>CzMLl9> dZFJ1.P}sbhrb@c[-kJu>UJ5uAkp2(l.:_ vD֚+m%y!Ap^24<ɶ{Yax-M}]Wqٵv>{W=='?|#l|&?|?ofa?W7cQ\:'7A?ƌ>ZF#$$х,XzI4m`tl+ѮPj5u7&T1Ñ ֡V-zIJpv"zdn\+"/0 A+#zSQHu*l57IQܸL)~6xr /dgB3i)#y*,YW yiፍszK+ $|sAp̆YB4 .= 5 DžgxYtyC1NR5´Y/ոɺ8lh_|LֺObaf1/ !iup=pƪoS0bQ*s]U'(^ 1h10Zc ,QOpeA3]+Hb֒I(|{{'3ػ_NLXJM ?0ZK ?/ K^T&gӻ,6d3})^ZJϾ_- 2>>L42uMSe:^_9%g$]J Q B._0ƧZ+vɒV~uw Y17f3[GCkf̻5G}*_g gNIDcnfMF,Hk2r\š$o#Kx;}qn۵$ίYzW?,:54S=83I0<] (Ξh@JZٍ,hrc=mL8,Z}1j?ق*EZ ] kA%;;=ND }R-V`ѻ *P*q^f|O-46~3́(2K6~(y<.Z{*jWم]Ĥy Y`;Ok_N>%wd3UȈO6bTRM`<}{Y\R2`9chL@>" Dc@#*IJqf?6C[xHbjnSs6}0"t}}fbu:y{'[9݁؆Lv`ͰO*GB5{pum="%['f< 0ϫ|*] лQ-P:(\Wm4k60sXfDʧC_rٯvuM$GjI1?Pm%U7©aElCj.zK L ؃N>KZñx~ݣbi Ǿ4f$ Czv/j O I6l߻ ZIQV X?sl/ WT#ͬ1lq%7PxI+6n A{1|#||1Akw>ZX5:2CLmߘQf:oLU qe )h8g\h'5O1%SY 8AjY,~y=]1ktL1bi*.kw I:ā$HG[$g/h@ОKyºz1hU?$l=MR?YVDtJ2 OcyK ꦘ32dA[yU>WQSmRxa (%\\=!j/KޗKW<~-tN+s\(<B7rK{~ TDIb#A5s fqd- }'0K4'ָ1H~@(7 c` ;BSB'ѮM:'ξ5lCs=1 Or:ݭKT>yOEfuyL@[,0!*)՞˗LQ*fu#\CTUQPO?Th R=$gBx O%oj]DqFbD6H)"tp牊 q;z/"aKGir2SF'e Yŋtʎtus'd*:.@-0}ZLRR]|Ek)LtAwtwrqD,LtG;-ݝTa@jS_iw}Ȓy2ڻV'DOf$rY~40w?p@ (l'O<7Ǟq0}V:PYK0̝hMfD\@泦blƾfd YFZ¢,JM_;MgtK!jm 8F:R2{ Wn`,Jby ͋AM})ǬWށB2X "!75[i؉DWP6ENv?(cgUSk;{$G2rvj=kqI~R-9^6%8%TWiEؗn [}XǵQvIP玟y1&E;`T2t11s!04'}Hr:仆Ɠ!Z.B%#pxby@ Mf^hRH5oQpY Tb6fþIQl ύ].YS! Qj$K<#yy[+@ߑM (d1LiVEYdoJRžd##oNW(GahZ[SoD1QFv 2y>8eKd[81 95+_m޳^9WqkL:D +θr 0KSN䗃 ) p Ԥ 16CCSFWL^[+49.^3"y] ߠFѶ֜Ё8E~`ggJdyE~kq!,Hk Rgof!4;ps h3嬳Q p[ ӱV<P֘Tek|X/, !HA)|B<\g`YCnrZYIX1ͭ!!apG^C`kCv53:,~ڈ ^τ) /~0)X>5 {UF8s+@Uf5IXƉ\(g;'n;w$&P1M\Q,-P.gS2GF=¥hruoyRsN"Q'͹GT,RlQui&A ȓ)%?S*y\Ht0Vۖ&6+I4Z# s/GCI2_lA}:L^qDXψ,f([*/`U"SIݵ"Ჿ#_xvXH! ; c(z}IwZcG4"PM֤5I.pgOBVV2,DSm:PcLzAO"򨈗#D p]s IBY^rdIcܔ@+8_6k)utɃn~1q &d¾ #a7kj5X[@i1YhwuV|#K0J\h]ʭr!J4 b=|R!I\YQz6,gZm2)Ԣasp]n ;_KN ܹ#:dB\"ұ`ye#Y[iU f1jp4&N-',b)#hǠTS^B!UKk9}2Ѽt3Fzr 3NWX5Lv<4Z~!ǦP܄{qр +F%&QTM맿J$IARyTvv"o%qA K1iZaVbϲ*,#ɹ>W/=Wl:.a+^VF&C0~aacW?pq j Er-b3 ͫPA_1W=Vh3+рv~\?!X;T+POΩM ,o^?Waea^xZcsO=kQI#b$U|EVlחiK S0J T%Nqg똆 y 2@#EAKag 9nH; v^eAja7FϦ,t\@fۏB`4ٰ8,j_NNFlq+'U >`Ox̡=e]ud `inBǏ-qb?Q!̕~-CXE}h!OkqףF &H FR⦄JW ؽQe[n&4o8 ] EѱeE8EKm;F[4舁@jw6[~p/1Sfa1YH1;FXdS2X i޻J|0w xFR8xQ-blW9yՕZdĦ++#gIxVеcgܿ)jcXA Q]KQ1 ׺9 #|*Ael& 1sD DFڒL[n:_ɺ̣IĄYʒ[tT8-WЋa]ȨrB(\^9R>3^G|Qrlʏ:tWe9@[V0d%(-1 S3& 1R^դhb;":_( ;} K66mH0kƶ)[]l>>n0~4!ŇiǪeF |6Ɍ9|P7 T N#-†K p:0;Ck侥ھ"Zv>O%tT8c1Ҥ Eb "߁%M!U~˚/Gf(m}ѧUe~ܶ< JՌH鞏K?RZ9!BmqRuSj @n2Ľw K |R[{”s̋zF |))OJjIUf>P n)jcL;*ItJ;z| ]F;m3?2,ȐynFec,Fmct;X% }vÖ(pZQ+.P1! Lc!6&ٺʼn3%(c98- z@|BGJ]veI+ȰW,ԢbK}NɾԺvӼEq؂l,yoc#ۉUK4fj {ɶlӳ{rn6c Xhm׫2mpOaTi+KS_J͒.hnR2QnTl+)ߤ'u]ȦLVSc+~zkEvpFy)J=%V sYXn FEbdnˋmL/? `ٺjNXs)ӑo¸b'Dl8H˒[hȷ5^Tj!Q'w_:d3ʔ8u\0Bc[eRa給0Rf\*QsIjj iܸjRNvk]xѧ VˠvB2D@vF,VPl$EЋ.`wS6lz :xP.ul92:8.Ii嫏:4"P%81&RPBC kQaR}]Yu g惭 W |~N'pA^ě;˓*1f8l.˺/LFa:s>?tС7lV8 6w'u~yĝ d`-_ t:n/ִ|]TA6 R~̧uV{m:w٭muRO>be鶜 yV a& 8~BSZJz_ rKac[3+~EN!`!- &`2Ng ")P,O JbZmz4HhB%ߟ&=͊uw81ɨ/$ڜ͚RCBM8G$'QT(x4'ip|;j/x({y(Qn3]qk4zK?pQI+X@)IKTg喂ӵe }(@s+yyr2w-t}}UQL4Bx)& <.1\A%!^|XndZ*#ޥYÙE::k UEtjAr'Ɔ"E]wkZS5 %%);$r-E}pXw?KX^큸'|q˝~9)4IF-;g}Xn G~ D٣ӓH*ɢPu3d_` a3c|ֵҋc(Yc?sy"Ҁ^2d0/~JJoR]qv8z`ƮNvH٧רi7qBE8_ȿʋkgh-k𷸸<8~bPzn:OV O. Q},V3pҵiJYOۃ (5+ΉE$P܃!@'+4뚿JX~-DTI̜DžI2b%j|<˔/:IJM }} n8VB oTԍ V3Ơi.kY;0dYysR"1N/ˬœqyt9w+JvSH r.+%_~rd ϣ_\RYK\Qө`yq:@nWGOW`J,LkMbLd}Q'_ȇhngY?Kc:T9{}7]ر{T6[&v65*GS;)1ϙDŽ}Tv neL " %&fr]2P{HIcݨ+RF7L'LK@9AVucR^ֿTɵUEb0<ʓ/0fVOq}3uG^gV* fQ(Yʶuء~V)O@, *~t "ZdAsS^Wu[bC"B葬]mEĿą즽Sc2>rX,_i L cÛ>“)Z֔԰ Z9k.<+x\]+Vu?cӼ)`>e誽Ћgq !Ι}9{y&_uGo%[+:+$iY&$~ë~,DbDɥir.>{ͯ"g2ĵR~&CU7; 2OD49I 5/DZ,Sբ~M=)Ay|j"|kP4$BB7C1y#+Cv$e}[]+XUnmqf dvnlihal2\@&`R+/W7e٫If e9 륈OȤR^E>0 U2@xH(pyK'%:' m\6O:S6rq 4_qOڠ}d'.%L\LgiR$jIq{YIv%}}<䊉JT Z!?8}\|\^Ҙ^/IY ܒZ^Uwk_&Ӷk&l_ f 3 Ud%+]|ۡ0L :wj En͈%9Vb(Bo}xHE7y!'@!v=>پ-T&6޸M{#Dfc{0[?;,U[`e~YgGZE!Li e%$ԙ 6|8GV|ACvh\%ܻԽ(*i^j:LZW""Å~:8Ux$*uBKE*N~Χz"*ގ<@/et?B%5*o2Ѐ_y柄^1{뵚 `W閣 ĖUj[ eáN a$9ɸh:H^Q ^?e"&-L*ߎr^_q '"GQ]L1V NsAdKfAW(eaN W:cբa0?M~@ k@[ BڠKϲQK&ƴlUa QrYy-Խ;ru*VUבRcR'esUCVf.xyUv-j7-Y?cC۠"#K@ /E_C_z"ATs"RLʑy|AݸL* n"[aGҷ氯c|+6`BwbG'7246bvѣs`Ӟ%d+9p"bw`sPΉ3,8#^4r%B& M&Fg)ij@V?/bƒMQ迚6/i;6Jj?"F,DY4ګ[n}ʺa|:,_o*d2rHaM|# H q,o Kynz C,ͻed( NDh1'ǜ5NbcuƉC(DZ? >4}5pYSX9k0Q,rm 4 !1?̝݀xj6ƅu7NMgRG˪|OVr*0$a$P&_QXo!%%s}f U>~ւ`/p ; sX6K2 Ik-heV" UcT*%"4b7J~f뱺ekJ)L\ªQNu^wat_yKW ^-^FP4)aδjSXa *=g˺U._KVi-3o쭝__xׅZKB~eHbJ~Qúf-OF%5jwɛ;:MY]R498Z_:YYƋ]EOϪ(< I\$2q$0|o'|G =MȰ?5E{C@ ah%D5zm"s+euҾD yl x{!J]\;;81+ڮM4bPaǶL/`CvkD"!n{ +3%k|}?u?3ti.8!zb*(8h`KTzl]~XoWHELڎ.Ouh7 ~_?4a7;4ݟ&wT x +[&) I1)qڕ&*ݨ1[Ja/бvIĵ5bX w [?Z0(DR$pC>O9 Љ0xx߰MI+uơfRc94w]4'(ff7=@{hidurrJa{oIE _}n><]'U0L:[:PkμMNޡ$\- EF>2(YbS29H { 04eӪ_h;`a|TM$ySV#oeaq9Q ]~d]Vf| ?+əuOFK8鱋PȌ#:jmk]1DZK!-1O`؜ V֛[cs| b 計"˴ [GԵWSZ 8NJR5]k5ј(nkskTwy={n*Z9h )͂T*M:8 C7fKF4%2 ZPmt@+c?B$=8H2ƌsiʌ_'L3@8eh~>n$*$k|#1p4{ogR'r\pVLekDݜʤ`H1^lq&;Z1UJb0? /Lf.8n2Z !vGp;jye'}~ D7Nv΃ñh+&GS" 4^<>?gGŶ)ewxo)ڔM< >_(i>>-j>AqFPЃR\|]JZk{($%1snŒp!>w:>kk8Q~jUB? Sgt$Bi_%&Ec-/w\[[u":v.τ 6eYcW'(_wb .n,P}=!\/$'2ڦ**j9WYGF&7;7B* tY<mh_Tz9!PM*.mV cޯ>ZYg"X7N2j!ЇZ!$Z=Ƿn܀159gYfa? r(wA_#d$bk;?'w}+6#.U.@C{CR˥!JRNU( Fvwu^;WKn&x/׶0ցd|("I@U-63 6O[B2mEuF,);A.z+2(ؖ. x^iv7^!*c, h Vڛnl=ڢm+ 7 (G&ʎfVQ)Q9 x+4cejLqb٬[#H>؀"nI8Y?ɵt' >l$#Tɲ2a#w_X=՟.lS?ZQZ;IAՖ+Yȗ6yDN?t0XV5ЍTdGuT!HХ88TalgFan {T:;!S^HGDCG5I.okơ\ϣ%Εm}y= F2 #Z *N."D:{`(^ĐtBH1wq/(aFk G7ɢݯ1J(P8 +|(RxA7s ΏZ% UHP΃Um螛GjWlC4gI[mpÅԜb3ݎv4y缸@)NX:o\0~f!j F]9)fch-]eD2@Pi/Yֿwrd3dav~f-偔rA0z8`PVat5F`l;hʹȴ̾im~:UB+H cOL^v?ߏET͹EGTAIv5A7]:t,^gd[e%2?fMҙª-H4/P3.lKrX( -Ff%#VWyFbw: Xhŭ6\-D}ǰˤI+R3\ӯQmL:.ssu*/+;oF >j B^BR - }r&c8'q>vЌ5^6JWꦠia+~[/%>េx\=͘(RM՞q%`ymKCShTLD eamJo K#oV?IInht; BKiBrNݯ"da?Sntf+Rqi9Z&2vV@5.킋XˇC!{Eshs$A!ŶZŽ|)%**0m8K9V'.qh;hZ+J ڼu!?+z.ٴyժ֚=11Ǽ&nZ [}HƦ`dޤȾUd&Q 7Kunn SS*`hN:fG3HǂeĠkdstjI1CP}T*J?q;d7V%zUr9vSN UNN̗Vܗy #mi!ǒ!N*JD?ҁhh\zvSVތ4|K3H;.H*E N`TX*[N#|Pw%ܣuk)8H;ybǹi'$D R[Q& YFXI訒wKylZk7]a5OX?= =MQ;oθ)WpjhB{%ulZJ\Qۍg7j~g Q2?Ƣ'M!lxf,V v\Ok:‡Gu#*kާ.qF#t:IWHAp3itF LN/Ψr9_S1 >!Yn#`) }`:N Cإ'9ډm[sG}#0 =ʊ(B 7sh|%i`6)zJyCF~Ng 1#O9sHL\-a :Mhp讞ԒSm䄃X7:|޹V<?5 ̈DBN. ;C׵RC~-JB|@BN;VX-g 7.+rNWt]%=_d5002E%}GX# g.cf@W[& N<7VOepYl̦4Y%W myX:`#g Bzo1AFt_WEsHKK9~N瀟6QhZnSTT5D}X\<Ï'|hLFQ٢ ؑZK`}"qhNp-S)х56\~0(3~'/1ؤ%B;6pH64̫1[ar1a%Yp<EDRA3pw*L= 8T8G#a!T&Dֶ9'޷,.Ib:W 61 uzlI9ԇ3\0#P ݏH8<&gpC|a\J,2XZaC{ж3C#וf{ʗU+@ZQFiB)RDSЎ˫ɢB)mwA/ܕD`)䲞7tV3( (f],Go/l S83J{# 8MOFbvb6{^J1! 2&`8K HhkW..= '.t 61B}NAL|R !Wu0GYW/g^y{k IL"TUKo|1% 9R';F_*cN!p9G3lXm4ɀWR/T*]XJags嶵8Q'Px,ޜ<|Mlh2%Gg2C=9óPV|_w W w$gd"VqN^ѱ,вK0jP4_hw| Թ+kpk0Gj D V˾jd5=dũ> .n z+wtj"niC:~!{(Yȱ"`>;mB bH"ܜn 62jc?LH,lEhaIG7"?ټ K,҂u])m=v4NI.=&s IzȱQ8={qmH1e+ey!|~#͆)oWvh`Nf`W,Χw:T>ΨJ[o,"!Ns\N7E,)% P؅͞K>S`JӐ@5`I/`yw]J*p#^r@KշWt)P&Іn_)tpD%^pR3)%/[tg&'UL=8ѷY&H*Jcͬ>!`j8ﲳWI-&[vCbvrESrlG Aڇ}k٬u#[}9q;.췰F>7$Ċ5$i;hrOVq5ч8Tם [ jQed+ Pepˈ,`dʀHcQғ ="}"~=7%O[tؾR"Su| MN2hegcD󾎆 s /=xh1Z 11I~ O18JA|]XwzXݏ;{Y cU!\NJb $E"wdҮ(K M Ѷ@/~޻Xpŀ ]G.T'EOJo!:>:1* qoOOt<|w[+yf-l0k}؈vqP捗 Ze iN6gQO vqSV_z gz;ýɉ)]d2Ow8cz~tZ@pmKB~,7 ]kJ2>Z_\=e59z3@2r&"ޮ)遮|QYN^-;_M K:3RMlKvy"z1*T8)qѮ&*m-~q/оh4Ud{[DuvLY}U8]m{92mgf ]-}j@%HPRak'El_PDj~K?2YFN͌@,q77^~=GZ1Wd*U՟)|(.`5y0ʍ2BP6yƞue2/?MpycŻ:;wĞ"cǣPlތը8Vu73{Ri!NyV!Pm+Wǃl2!G 2Ov Etee滢wnMdADw񖫉0A(+a{b> jPʿDcÅz{\/7D35uٔD%eYoݣS^Ӑ[V'[H6c5b7D-͋ \6xHL7~0Mc*PLY${I$ L>xu"e\;Ԁ<{s۪|N1g7堒8 >]& Bv_+l2*H2k12'#0r VK@Me+' eKby]5\4|IY*_,]ȴ\( jAw)Z$9ZLS]D? lv鶯Ĩ:hm3!ɪbO]mm?rV5K2J]T=UQŜ~S)LBjuA$ ݞ6E+*d+I + ǃv@ %ȚJTSqTmk-+U<1h0RʊviBοɔ}f:A2 rA9VY$+5oAoIB3k%aQn9n !H ;DLKa ű88;#$,}򖭢?g4{N 塴 !QٗJɺN{DEnB*N u,Qcy\emᚊ~-z#$#  ->dŊnJ0 5']N43Rcc.ؠ.q1=cÇvc_+o2=Nӌ0hT*);G3ON>JuIY%Wa_\8hOicA]6@_a]}-<_˳ӽ/sݣS 6ͶjgV]ͻSp"õ24e fLXζGװ\fvo w+u)&0O䧶}acH;d~2mh_n5?!+١ >)3,ƉD , pB:\>O"T{ܣ(Iwܴ{ٿ:C ŠU~{U,Pݽvo9hȠ*J(Ѝd,`HnhYY7zsHb"+4)?h4U|+ &lP-u RH cUuE<1b&™6 sK (6B؇ ms#R=¹)~CtUOxw1KJ2'ꄰ 'ח_\Es%)@ZĨ<,Qp[!IãM7 B `~2+;4 t) 7,e q' ݖH?J2+5m.RuTg/{%9ZF4GY>3߈VQYm,8BYrx|DK)&ZtBɥYn29E@nL\pp>^GUfc]jlC;julw\ƃk\c[}jW5ٵLi)h1k|xV洮ؾȜ_EfVBն%A'-6ݚՒD6_m8F_/k9os--G D1Yfd jZUvq"2Í&v5˶ 3%#bgWUԛCw_v߹ srbAu@dx:vs`HYz5u-`ۄo7IA*L09Nag"") hHb_URyHm =vuT1~Uq$Co֨;wz{_\ pj3mɠ@6XJPZzv,}:oL,_Aj]t-3iؖZrůyE/nBorxiz(Sq1x|]e#գގmV YΗwB3Vjtjڍ~h>zGndzP9zpmw*FX8_v$%$i:8R5$;"qUU*>DW9qzD8$5< b$cQÐxf+I'gU(VA\@V{pLǩx!m Ȓ ơ[B>A{'ۙze!94DXUI!e±MXe a_ĵsТ+\/* ޟ?UƦ}wUbl_p0΀4Nz6޿2ܹe`hLUaXj`yE!(I"9Ҹ>$0b0C{Jvm2HG\SH{ls=W(4F7 O;R0<&F| 62htx%%t#sGVq.ZK\:6H3`(h8./:lP6WB!ܐĜ `쯿H]j*>fB7J{]LUueӳ nR(lÉ]YY(n@ISU}^Da@`tb!HFY7YVQB|4(4+!|gTΟCUĿGWtVaZπ 3\BvN2],A3iEг&]Ti&=G_H"2P8:G|+~(K_":^5h LǸ!eR|Dbc8}麡 }*1&fʐ=oj!]j aeLh^}OA[CHFz\amLȷ2kk pZ!Y0#.5czƷIbިw Қ7 U۸K-o@\)'ӟ#ࠣH/- {!n&ޔ8* CT]ӄzrCMyF}t&jR-Iff<-lDK)V%4E?8XlߜMW Qv>@8=<  ?˓@DBYА5Xư+#HB Y-V550nqTyoQo`9GF}CU.TĄ=UYJu+)y5t|,FIszàs 7Zs%wDzHߐo0r|DoU h!y:I-pq[Z H1y6(OG଎XyTפDĉ?tY/%1ۚWETgǤig+ Hl"'kTpE+@H|Fs+ǂ՝.xlKШL1' 6cN瘟Y0V9Yl<ؠFwcMMll" ?<.Dӣw oiSZ2NGCÒ,f5+x&8LnӛU~~] ȿ.ܚ.E^ݛ[3Un~zިQ;2p,A3ٶ 1v9<2mS  fx-3rSkAOSTl𢱝7Ҙ"vsTzgޖXhjGVoQFnÜH…cvQ'x3Nזs: 4WA: D~Uĸ{2{,L4|"WT "µ.!V 6 ­TCrH9K$ۚwMۢ_2q? :T"P?4H1׆.:4ב 0(|x#v]4IR2l֪獳$sh`b %sFi !K@vuupaMw"?_G 3X vz )qO#&^rո;}׊m!wh&YnX'95򚎡-R;ZbnnT=p^}-M,lLN k<.UƜ~* =3$ n`\&jd2?y&ft^$:O_aARjckĨNek+ ryi-ZxW\3sG;UdC1DzO^%NNH9^ED~JV '18Sh-,1-H,D4?v3D kvPKF[,Hp;Zo765Bž|nr=dy6^#_0ExiB.n9_ϑ&WXeKDP5d7.Ы# 9V ˾2Ra:K7 Q~+YzV2raD2~GF)*AMHqPpDPHx/YuJuA& %S1tۆE.j4Ȃnː_&#^ddBɯXZ& R6 ?XCL -s^Ϙ%0G|`GF[#Ь٢ w`U[y=~G#i b#W,dh&&OFRjMQ]'3@Hm@M͇JNzRyI}&? { T3xW;uKf>-X2'|ceCۇuQ"U2GA<w;ܗ"%Tc'|Ja(zσQ鴟,BrnZjGll5ӈ/Gi( Ds|ͭl8AR#%*j[}8lP~=.+*&4Gm>Zg`8zrK' \~!SX,*#IǽF^E-& {O;[J]kh MH38zNLH&['IRBl;@*x4OhVlUt@jؑpCXr5MruSC!"(/ aI Qk.2jANUnߞ굚i:qxs-Rb%czUXᅽpV=ĩ_rPs$5\P,E+Ȣ&|>alMF9yEr} eh$60G*T"ξŞ8UBÜzL,F.8S&l pGB[_:gu^+P[^{W \|P"Ը%;Wl?@i=#P6MpZۺAN-4"lyZ im8CHلGp4QxK!B:Yeqb(\3N]$ q6X^|kκU^Y(R;7PPSˊ4,'+x0xd5{͡axжNM2̌V_)(s{㞱8O}V"fmvh(\=1V=t+7|üPV~0 Hu'22Lc:fcz|b +X~N+̓B(h/{l*"˱(r]#%/Gu'DL!U rP@^Mi+ xLBoT(`'=̔A$H(EK&tk)5٬OV{|5ȯbʋ'?^gtOJګ.sJԶS2څaI |Rj`u1 ~ۿVάnQEV;Fΰ0rwG/K>J>D<|ᕎdݥυ | :QɥW+~d8?qh'[BF>O"BPcPK)PL<Ʌw@2y.WK25I5bIQu(rohΔ,V+lJq쨢Hahqz并*/RZ=?Q<ƳcLSB*7lGXov^|H$Fnf׷ ub}jHۤG|d$s\[M+Mћeń*!gTi_r0M9ë;M B!;xu-|@=1 qͤ]U1s|F[ݮbg3h[Eb9dVZL !Qq8&d-,cT.юcIoSJvNyc:)VNI^L gKo/˭;x%UԪnZPMp~cFБP-Xa5y#Tf47%w Rȼiy7&6Ѷ@?튶Df/3/}CZ1=VdnzAÚ|+zsm6&EbOu6ΓZ´{ :a_ZgC :/w5mDT?_!+"Y{})Dέ pHG <6_3vSA3:ryOV=7fRPJŜ:|+4_9!yDiD>H@P̰AC5i(.Bj t0qO &C;J-ZǑFL nT@ GjuARoT_e2~޻Йtu9C%3o+@A!x; 4PUV}Ψ+omN5"E.^`>>ByqwƟn9V򩶟`&sQqV64JHz`̃qw|DO-4‚$(S=j"G[\;$"h]S1kn0{}8ˁYzRL⛿U2k"⅙<E1E/aقpq!)yKD٨b<`XZzꮸDTUP~nOЙ>{h}.Vb,kf}`GL;s=DM1+`>k&(\46[ \Pцೲ)͊A? F@ԁL,dV(B> ]ڂ5%(Y#9ĬO| y}lxwשpR>{ێˋu(E0 C7ޕ7Z OHEˉYs*h<2@[xlQ9tnsF񭑆W2JH "}=Ҙe,6hmϘ-0 ?1L+d?Y+2t*Պ56H&a8 8Ө4Wӿ7ɯqt)j˩S+ui("3NXE{is8Xp)]nvF4Z5scqPklOM@^K>X3Ǒ,LU*@q' 'K>rP2d*SZ<6/ag0dCxϸWCśxOmIxM-!@3~9mx!j="i]SU3@ޮi#6'Ed{? V]ʽ*}WwOOb~^ϝ.e:nOBBȮ3tOf}= '& Bulׄ e%-݋GJڅ%#z b3%PKdN+Agޓ_Hy,.,ƣ^B5p+&|AE@V6Xas?R$n9y$?#NWs,DXI](^P,Sޕ<:hA^5 E7_FFPekmI@Q #OSw\ WvX̓`DuX P=w{v\a,u*"]=~r`^ztXdžBZvf fOݱJ2]6DJ,a`'+NjLϩۨ4M2kPJ:liU+ -gLY$3|ytRT\9ͺQNL!Sn0Jfi<=rݺ T{կ4{E+bI걀<-2:RƛYCZi\B,M iJ>rਞ7 "a;6zHb&Fv+{itm!/~$W#ڿe.1l$SF|:"HJgE. 긽q=پ})̯C'Ӹ΅OWw4aHg!P>$N7یy(nw {_ Kl6Wov9`;Iey*)g)i!߂ w-,/^;BFRjj!S1C9 5g8sʗMgp #<=CL91-FJJG1c<&ٔi.D_Lofj!"On,+/i{YRpU -*w}Uɴ)eĒш1>z G߸a .TI\Z8pJ v?l\HBz ZL-{&wvp c wW`D1%atMOS;GLuߐ3<1y^k؀;FI\!'3zvBɇ1^! >1Upgu.A:QKH[,ր/7T#9n6FacCG~qmEz׃tML#u֤f/Ke:qٟ*FG2$ xs0uL FNp<84@$_ϷJf ^ OU&"4w>u$߅2*L3M_ɀnRY1fv }e@hQKF'"oڐV1L1gslZ҂lK~yA3YdFȗ+P#1զ`]F>69"Mp{|yBOD,2|x(A)j7YQ %MQqB%Sq+2wQ_^o{wJ(G ѥVvQHja7  ,9Pd[B4qA/(kQ:]ܬ_KZnٖJf!>#NXC,%]X")`FGj fĦsL]} ^ݚ襎]4ˣ6tMԎS4M!дWqrmI7 x$T~L!3ըe tx4tn|Gzyw -7~R);!5΄Ϟ?.˖m%7=ųUWuxBFr4!X: ! q6%K |XىI"ZPZYۈ}d$/no7ε']uvdH"B'2tnf>+l&ʻW.rv{U+$ 0xcTf'٦+EBg],$ Ϝ;52&r&˲>[8G*rtK`,J:̓r,kMC U*A/3Mɯa(%r4sǀ0O"ycK ȐiHCo&eu7QAfN/MTbGBLhҹX"xz/,sb .V~sЩ.u%a&7sS}Al \[(S\ۓu Gc4!L>s|z; n ȗR^ o^>ӌ)[ȳxȗF]/~ z)r黉Y_k'(öT`@v )<~ˇU?\}re ld| F= 1ZH.Z;XkɈPj}K|ܭ?E%!b)ژĴ(/p@>b1%R2LX2m?vl[`[pOp%<|zIӉ`nv6Ү>0@Z2Ϲjp>s7]?c֫k5֎(WUsJ|RwW^LDLS1EF*ﶗիޖ8[#|-$a)8DLji7@L "S)V]8%=UYIlT&ޡ(URax@ ڬn%}!.L0biO/J.k"H^RV{0ΠϨJ* 0 YZ*[XJ2VgR6 ծ'T?8$*Ou 6LY9!4wi,@l~Ӯlbx|gǦp<96|]"0\*hzC}ʜ,xr ꦆ+Nsׄ4/ij!U4t7̉ oOCSFU-|1i}^sCyW^ :קR =:EȨ/h[$"vP,:ؑ`_ GB0>c rrMY2ݖ\RpcOUEDY@=LmU+y4j4qYAP 8q-2LBD'm Q }˵wQJBL1mZvlbj>M]``W/yӎ r<]Z[xƐKNag4f tǥT[rhiשT{rp(A UÛ{s^dWg&d2|̸ "]|箖|UXRk5.sq8x2I?(2QIq^S5(2nߙ? 3!$—5PO!<ߎNw}Y[il5Bn}YIGhb jk6ׇbڼ+I&oYkUMq/O woAkU8H%vU&:ι%UeE=y>@|y-?"Ev/ST $ʔ 8$^Wk鋬na?6%v%"wx(vBnue4CgH/mƉ_>[` /V$ [9E}ÙwyEtTfCRˡ@\Do=g9=IlH,v21y4ZJ1R?phһo'z'0'@GtdpW{f򮇠a{25IfsG%I >}5cg(DCFJ#N+6Fja{Z_qy^ۋy%hK蛃<RfhʇuU. pd)T:QL8C?-?LX`CBIŹf<(c/'u[ V?6K;A{c>NĨ,TٖX%mM^YO,&S2q/=7ZMh1K]^yX]*COH쇤4'y|yf{3HD7AA+PU>LJgYί9AJINwG#@ J`p@빯/'mR7 O@ԪYOq 27GtDм78 y>/^ASVr؅#.8(0C]w\PaC?JȂv]!cHyLHNrhjH27WL דcX*_ßQNkqw3BFMH'M=81"}SX =*=k0ujS^{PbL芷\?l|/cԖ%.;s$Uri\<ԸciU j*S%Ѱݗq;#︞9wMO)q[k8r$^` h(U3%?A_4{vX>*S`/hhnd .^ KBf4ǵ>1Oܦ\g<<}YںA}2>qFMvQNA^&E^kaKJwSɮ0i) ;m%@@R {-G=דS \ 4[Pm.ĄZ!?\X`52"dofA#|9jܜJ[!->vxw.3\s,cup(BSq!4_Ʀ)a}NZh0R\) EDGa⻂v9n9Bs|P PB]#ҬCD)"I{ .͡=:GVvBM k)Bag I@.}::Δ\>r_-r9dh7mW"Z:ɑTn~/2@j ?`uEw!`:m5_W^0 ]ucƪP@xc"u})EE2LOW UdƓȤ"IDBnT9kҍ0hI1k\(W Ca77_% o(rH#`C6Ty6z<45y]8h'K졖MbFOegI_N__ E'oINIr1°1s5c&+aoH @n}%JnB v3;zχ'-R<ktVrW݄rrCĎ#l]Wyc!MrSMntO$d#)Ozpa6bDM)ZעVda896Է멋JP3m-:؈׻Sf?L4 n`>P] AVw?ܪpЮu C>tud%ÍmDYoK?6䋀{OwnK-ٖm,i'۷Fԫ?rR%4ebSY%mlk+2І:woKo|\ݾE(>ۿw |AT&X$ZZ @ wKl#ɡ%\M [I"|B!TH19K`]^j]U |?LԬЫpuOD *rʚvl+e񚬇Crb-I4j)zTYFy'tYY*N75\m 3ZbhLJy&*P|A}uȀgACQ Q*P(T"сA+ҴpB5%QGt]7L|QX<B_9b5A%.Z%dQf0g)t ZGEyYR 7֦$[o g}qorɰBwn+@{.&7YZe8 Qy69],-ЫzQGHI.0R*QqG?fb)lq*& 1׊O g":(ZƑcs ac0̤sis0~URw ƽ-NhCjC{gRzVA}`漕J(fcU2{(DQPF2Y2 g87:,EDMs.e8fkWNm` {k2]l,Q1O;#wDsֹ| yA_/FIMBS^'z{'G#IP/GCZ~Ma 1a. 2^ϐ~h.x3 M#L@6#ES_TWgpZk&G‚Yc inA&|;%@!3iJ脪~,b0!9Yx/Eu #"@r$iڪEլu4GȨJl|֨rxٴ3$҈@K˲ɄScMьD7zŎ* =ēd5F6tx-F+Ρ󄢡?1G&:k[14W%8 ~KźgѶt~ȇFQLrv)2 Jȳ81uB"SjSy@ok ~T y׉"oy0GA'`p4iޠ)c(`}S܋LiHfȷ?# sf!Ri|3@#a.' &,IۚZSgv=N*+)~%8hўqF^v -4)c# 6$P ጆ˷w!lPΫ-Ⱦ3OѓBr6dQ`ı"͡ ['2- *j6h iva7Wpcמҡ{c7LxS7uU#>]|zVÄށ!6 _?VI3f"8l .E+?+M褬Fi43NFjSSXY_ϯA/ɟP99&*ksZGl{Z-0rHdgA?*UKdr|7~*hd4ྒྷW{Gj^\-2EF",PEGB4?[fQ.꯳mq}\b]M~QK凵Qa[ĂPngW_dCE;pv۰)R; Bf%WZ5XHdj5RuneԿI7feDJDѐW-aJu2uW"{؜z/ֽnA0/)_@Ohc3?JYJ)݈"Ĩ4e[~YBc}B)uwsY#7a,鑊x!!fE큛ji*\Kȫ@AQJgߔ(>zHnPijzFvo͋GrXBc:U&λK.^۸fwR@KT,q&cr)YMҫ'ܑͪRT}4x o4}8JmJL~s֡X*Z &Q4"b(,a1Vyd 7`VvQ~㙞% ջfS_ b*mڔ>RI,l94M3OEAjz,Nh\s¯ PCU6=ݫu0 j>3.5(_)S~H_bwQ_qMT1]CbO7٦Dɧ@}HO@3Ctu"ٹhd2q6ψg_۞v-ޖp:WSk_^Y\|D,w.[`%[gp _c^9d ;;E|}v_d+&TT' ٲ;o #4$$I6KRR,k4ph64quRapS,1V:r wmIe:]>[%"@֬H ;EGy `0H-%}z$1ڼ~ QY=|w>r b{u ӳi"&? @SkM`'E|Ɗ2ޢ`AHƣ ? =Y] aCsSѱf~A8^'Գ|742׾,k!&@Si`7oZJ˾fB}]48BxW!b2)e=Ɔ`$ZvoVYHe"q~{8!_d܆ 19*F+~ݠ@fQtRLeP1 ԯͩKoXx0| d B]º2r骾1 py4[ߘnKfn~CDXȮYf&BB<ִ=k?D `t$F3C0 q2 gefAbnӉkΣ8٬ :U**qds(J֔rۜQQ,W2gu! ~A`* N⣈!uWSo~LB%S^bM\E|JG渢D+a+#uQj~ =*܎$K(j2NLc/ Y>{wl/yGϹsmFIշbABTQ0/#``8*y! 9s21$l{D_Ss#)$Ff#?U ҝυ;luNnߧ|NJE`MVbs4sww# mn% iBAb:eQt,;&| <6%[Lݑ7 gX+T#4=u? Lti韪oB%M!f9x(?'@xL!XpyiSqrIkYwv?zEF L#_K17}NjԌfݻXႦ%؏B%HBXJ9u[Gve0eMGq \h|s9<$dpN es_GmAKj:FTK3X:0µӲAL&9aWJuCލT0 0,Ge*a6*XDmѻ@/U!$[c%=rɂm64 f' |[_Q,>z<6cd&W}v!rθp'~ZIyv^gYRULsA"쬪8Mg%2K$: 2QJ6>jcrD m&#]Q`֪L ^+# GyxP>f/fKD #D.ЪQ4ent#b8H'PnKb8 5=úQ.K}4Tx寡X dUVnث ^ќiBLn.Ϙ#_] D(+VbZx}erG}ܶ2N3y\Sݞd4uq5")L™% p 61BNѦV(Z Mvj=(`k r޵ 3\87} I3.,=u?&V~։H_z/zLE: lMuˌ} K7d yo>9|iV]Aw _9x%tZ~}Тcqr5ګts )-6Qɨ늉K_86? n!|#\UEtNx$CBm{#39nmGth#/%96DK!jkj{Z}:0Gj VZILVg٩={$*¼*!Ns .AAS^gU`L*़nlkbposU|1Sj"KF~tSŦ'dI#ڃÃ% `z ՝byX{ guSq%?c[ߣy3M^31obyv֘dKXR%\G?A@pk+pYM>@lgKtO*C¯"Yz~DLBՆ{g&l[ӳ%?룿}SpJ{%2&Wo3=lV)HۡMPl_dUNEzi:)lJ>R^QM9E<v4Nw8KLj˃2wg9$۬ w|۴2t`*AuZ.*ċa,1C f=x52uб.dLfzjCP:#pbhb^$9ϘX,U/P AH8Dx,M4KOsO HUghaフzđ]m3yoPk"6Z,XHŇex;'9Nf]N,ze lgaOξ}?z??'{a3=UOTt>M^_/wGWg)~Opׇ=OUz|7n[}%}'Կ}-'?ZŌ8t?,*%>QaY[JnF@V?!*~TF<-^9q;((y^ ? 5J#8eJMq43.}2Ls=oS@$1RT S7:|w-'dm3iIrc·YMG(4iokS~Gpt'2@b#T=k[P:Ye<]#Dp2@Ȁ!U\";0ng lUrMdY탲=bnvlѴB[@^h= K{nFw<7E! a;0ȼc+Oo>6OIf.;CFog Y_aӬto^*F0bΚCaNCgHŨ+OgpX;k@N͹ UۅYbmvy3Y%dapmMkhw ;%i~f |akr#2^hF~14maDB; ۿ"cL}5!s;uraRE/+l 2J%i3Oollz%3!R#j OuBI}I*0XMbD ntDyInzvV|Oo$1Rj%V^)4>MFmڼq5e+wr>Ž1,{bHS h@:˚U>g;ƅ{ f!H1TbH;8ҺvoE`p/תC abd>-^S ewΪ`W!8.8$cڎ4_jzO^kI#5tm2]@McoGq7@.aC|%<8O62x fwYq8f Y} mԛXWL{UR5寻I(w"5CålT̫ i<4\ۼ\&M`ŲÊp$blݝk 1EpӁWCH: :\XN@># a+{@+3U2 SjgiVwnU!v0};dXZXxbq)%|䫮Jj /J̶) ]\6T`?>*Օ501c}CgiꝜuX|fg6AP #VERhJ+L-1ޑ >AF%uńAfQCE~#wd\_NO!AR%OJ:&%iC(˸["qMhJ\7oPKmIG2ot8o,ْL]K˘]^~71Ԯ`)h@{U_"Uo4HU_tWDwdl_eZ. O>㬜+s.A|S ILG=Dx9:_]cHR ΠD7L/J ~ׁug.XxqL^b`$>@'?"* .e$6$`!EC?UHu6>iX%DWY3o"(@uPuoostn=:6>'Ϫo\1:SM@-Sݲ N|.x^.uR/}¡La4L`PyzQ_u!Ҿ_o;߹*0Jß*HFCKs1i=z:[gߎD?:rȐ .CPUnxM87a&X9~ّ$>ew e3B5LQ8O`O"V)Z]R)Yio.Z@/A aSQ?}X#f5~=Sez^٦c ,"ERa;/TZ @};i,{hnl_R ˆ +noےh?//ԧ 8'YhBd`H٧yx<3ן5`CO`uS`,JuV0=<9HMM ] 'ˆ$lWpbwD,>+(q.{2Fw֑s",Eqae.UD(K<.% 2#DL- etw="ĵok4{-;B0_hJq%S7XkO[PoKV),'c@u,y lKT( ym ˕Oa9W6cWҠ߅~%1%hAkNGδ)x>~]\CP̧ÅWX'\Lcvq@E$pFP%7@Ğe4V*2Lܜu71 FC[.DC51b>v6G^ω7K,m 82qT+nzYzZԥp 8x/㺦tVY=ќvS{% =w)\rݵJPb0<+^rMbF/C[p+l=EPFԵW*.D((Zkf"鲼B88{5{Lq1c)Ixz^8B߄r^3=aF#N >s#su]F+S|<#0igݜW-vz^+B5ة5oT#4@:TX8pD'5 XBp^ ~͔}[aޔD05~~ۛL?-G$V;%.' hb7(?6 'Y Glza8 VQU= *' _Zb4n"Cz9Y>Qa#@GTcjhx2 vg _ '`yX;YT|2$va[0!d[܄=@;o1E|фV[a/G[fUY=a+J^< y3^pv4ˑ:q ');Jy$C]%]Y,$ܬiQngN V~A\Uqjibi;uOLn9Vg݅9P=pAB“9ӽ9}֯z\ ~Ց ,<_49LZm [Mj;3"f{DAq0Ƚ&;S2.a Y:yI2S'{t<̔NXoܯzU^ wz *YMddS&BN߻Sf;z/9{,p+nbE/!S z'*|Gn;`{!8û*2Y=~b !]pPe~N~5Yفd. O HQJrx0%32iK{Oep54} jZd?PFuK.F7& 5)L[;j[c~8/ ^_>-]O#JcǠF{,sO s ro/ּkP324yd]:] hYh]ve!aۺZ9FӱJL: pR(mO]Qf6C!?ޱ6ܣgQ*ʰ}{OvXFRY(͊c=z=0|v+Z;+66$sMI'/_,uo["܏D;45ZS;j Ó3:v﫩sm )i*,D  L:ēٱ9Ybטhb0?_Z wCyJɕEe\gNô\a*+20 (1Ar+~kpqm [+Kv/+MOUc~Nu'HjS)o=Ւ{W͈cѦw*;hR'~{踷YMD_a3 mST`[BSjs5_qʸZw^mvLdi8Dy~PDd>'C? fTm%@+兔3H SscX-р2E?ZbKCHMWg{"YC-5yR6r=(=( _P9[]xC֋ѹ$Mv&7T5; Bh6ft0΀P#Ya/msڕ1sZg5Ge΀q[>/bB ?Ip]\KvuKj7ΐQC L0V!ۢ.ME]F}lQnT?Ӡ, ƶ4sMނc8.1Z;5p*(S뎢]s4A6J_,|$=+#}a'1Lػԩ?ޅ綋X=qnБ\:P'W1>gFUԵ@ckYC~uA` (d?#?ӓo3W)v:Qs|qU>U7iAP5!I|q^ɞ:"x,t\q$k}2ase:{ƒ`yv*A4\AuDs6>1 ee'υ!Ys`EhRGLa=L2 q|ҒLd=X`.JGOBO2lCre' }0jLP|4w_'jڞYlL"NfPUu D:*} &w<BZ: eFS6$xB$S| ;W1r{áׂ2mHnN^@QXoȴN|z/~Bw83{7ɛ 昙TL1GjaL.ZHQ3( DUAw=%D#QFO ٔ=]{:3 9AՁTqc\SiB x*,  `"Ò|'^GLWQ Fo7A*Z{"Pس߂]!ڭ}qd: 4usX784rW>Dw@a 4 ʞR5Jt9 I]1 T#uYT٨c@xNciC4{Mv'U P-"SڪYͰړ@TG9F6vdqު0\p,a%4Y+V^Av0SH*SCuޣgo@a Զdh8]3آwSRΤ24_iXMG4@#is.F.'~Wә9TOr&CD/1-@)VD)hT -u4BR 1[0H3ڲHjƨ,u@j /kсc|8YR~:h6%(jf`s!dHJ^I[E -A?f`#6yu5y -BS?( , 7=܆77Bpی΍~g'?XejbeZg[x+qawnކk={ V6t.lJ ƛ@V+'XpcopPGp״0 }_^㿏#2,fNŲt`\B9VN2,K[ DIq:0a:oG>v6NP(hM36$r(1$gb3m"zRAzâz7c|={ oƤs*ǽ.K/ (#lcN) ˉR@f{;ž(QИR)0BLeAh*dc`"b!e: VFڡLxA+x|oed=UtVFbJURV DΣ^y! k .}"j%ߎ;K.6ul 7}71D.)uV &Rx&+-(kÊȯ φ eVLֱ̂DHz 0;2 %RGNSpm0soχ'h*A L 85[ u/7ꍖ$ TCf14CJ-@Z_=!D4uqB;Bx\9's1 8`;w>E\ȁ2'QrDa$1kxq!?:91[Jc*̺g KA'%{UcmB.=v2 t)910?w'ͻkMزVmҤy%Ht-3VeVU'E=^ (x!ԒFV*ys]zP]W+2^pf'cTfS"N][iEfvdgO8v0t+<O?$yd>s:|S|C.0naAڐ9dopdP+Suy<~4ojĘ|?~b^mI"KhMlNjkQ2=A@Oww$^e j)^_UZķ^Tq0EZrseRD&N7% 5WB_Z9jK"Kz[2bDYo:tfl t"fhyȬI}?/ P*5(aXa.DS˯L*+EEZE! ^ @ouȌpb=گ#h _v! 5- 1A6GXlƵAͮ&)qzE,K4^VY#ߕrd Y~w}\wf8~Jgp$ WgIwJ&ւH\E~鱯ʒ^;>j\XOр#(TIh +nk7Bfq2 $A1E~r\1aX6kGB#ۯŃ|QQYO#W'P7t)l|3\6^ɁPG E;`j6F]V\?v5*[>VafM}9vĻajeܠh*Z h KAՆ=JZBn Q-Xrz~&~KK#{SMOoU hD|4G@Qm 69W]D9(A S j<ÄzMں u5d_֘Z+Xޒ[K X+ ^_vC}ln9tPUnP.DTk\-"pJ‡6e Ͼk{frFw]ݲq}+73fԛnyj?d:89 1#T3 mYtEB$k)%5̨NHi`DI\ MF4_kq*'*v/d`T&̈BM׺^+ܑXU:h'[P6"s߁~C/e 5r264RblVQ{O *p%C;?1}{ŵ=7ޓڤ[q KZY:jD{@L1HTX]ؑHe[)GN(x#,-miבnŒ VC,87$'yUz48/Gvn ͡X]^롯Qڏ'\C ZY_gC:A@^1Js^,Pg8i:+B6Dap~x9RLeUr E).ԍ۔I4õek@\FVc w'".mN8i\|ŭ+ccT*>iO]!?_K6,GC v3 g~Rgea. !}Ѵ_oi2Q 'Mi4辣~rw-7 B#:˷YDeDҐ^*˯ LuS!|_Vw.`D|/(6l^11) OE tżlh8Kټuo-YFp?WUp}})@_s,8WF߅d^Z [_8P/Ԍ|̪@'5&NͲm1/s&sf ;ps]OΞj>fǐޖW%yK ̪ԡ<"jWueX6|:7p2@{ԣ"* j9X9zllvo9 X`xD#Sbq[@pr䠪UwHClPx8]5OtN0?cnDVOoP9}Ȩr+DLhȃn/-zy<+dnegsV!*T &qBGNcTaގa4E]t:svll_37aXfzujlYq3$^G7j8E XN=$D̕=ድ$'E 8~;SC a]l"uJRVCz)K|qd0,۽Zm^o[@U4D ~b^Ꮋ<):tA(vw,ʳi Ũ#no;Z^㴨EGc:S y'Zd.{CE[.in7mެ,W;Z(-ϰD2xa{NW2S^u0J~HJ`Z7'|yMPGG*1^`_情 hQ+ N">9Lw3dE+)XJ< I^h> l|H T(}-6I ,^q;}N'K̩|4ۘJlۗu ^iqF?ClϬ~P>7ڍhlSs@}RA|jp\BIɈ$։<:4 [݆kpfH!?Y۴ l g;SO"'վ|v`R#Lc8/7=Lԍ<;7Oq-=]-f(!ORN!t,r{#{_ + QeiC0UOݧ#; V^Ɏ_ރnrMLWD'jެJρ3 ,rY w[еh{fJSt(;htҨDk;"IMa=#(`|>Ux:nEC*S~&fĴ@H͍H-0ZShO> e'$r\;-Lҡe: ]Xc$;@ѵ[NW-( yxdtS;! PP`g#gÌ4w+͖V]=, gdhBɅE9)'0p}[;b3Am^2a_.خ-=$Rd F"]me|x"MEYOk|^=6Y'ddn;5$/96ؐ0t6o/`#O54b[P.h\. MB3*jp xr1fQz?Og{ڞg\6:1tܕc ZCv[b[@m+ȁ̱-H`V 4\S҅E<_OX_{ -F 7z-e7`[4_: XU =pnɊΪ.J' xKp %ы;pQ2x]U_"dۡN=˘~"Y 6.Jo4=d-ڈa6)>b+[(sJw9 ӓ |I6(ܥ "eqm(@|y0Oaػhxs@Iw4gFJlPhi-"1&b3-ݷ&?bFN4Oĸ ];11R/%<$!lq8ₓюٓTͨMzfCڹY7l E9q؝K P8Ft-nP 5¬ V3DЎ*wydA#oTbTR!+]VPCfxvc7\U}ٟ8حXM:, qRd5$d$lhj|ƾ| &l@mk=Z'L Ia[Aq,H<5OF8E`/Dխ<\F 4nwObBe1Pv'^ls NO{kog>E$*CMK,$;{ ?=~#VJp;x4T-.g=Y誠M7 RwaHyySبω}tVR,ʫK=nj@n#]Ie~\3:-K%&t\pGrQ^SM%BN[bls^D3M8JL!yA|~myX_痾CyןZձ؜qlr1AATg94є"Z561WK{>!Ц4$vn⨚ POP G1PtUJֿvD 'XbonlT ,M5ox=ɸXr;6T'uWͱ|Y$hTຣ ɿ5=,JAe(0`|ԸhSBODCrkhXXUci9|^LlPE.fZwuqɵJcSI戞>vŢgh(F'bqceEoX*jA }> ɧ#xy+~.ǎʖ֛*V'y_|0e x@bͯ]K~`!(}ݸ[zOh [%皿zqWCZQVM=a|^ڕb|[D$ۻr E: %C/ii XI;qόYp>s9ֲ{8\VrlflD~'[A8b ɿqD$Z4jbx[==L yx |94?o}/BMS fv*)OU ̣7g构(EA{Ny@aM`s)R8Hz̍D_YٳCO{tQIm,PEwp_]r#s8%  ªxejv87Q=X9Q$h[q( ,x)S2`[R5:od>b*qO= _:2yc lV#phyw&ryE|ѷLZ=O 0͓)<҄뙲ͺ3X[5wDyC#8!1\>[ƻh0֐/y&Dqǰ Fu_Ev=-}CϊD:տl"b_jR*{0M׹V,F>vK^'~]',xQvѲ<4$n 7k'mnjEIV"YO}]/C5&0?6͟HLvmb)9\5 _;KJ0D%*rs|cG, V<:h;['Օ#t{R>R]Ҹ HUUbyDn<3#O))EH:+Ѧ8/ >ؕ'?aoXFƚdm)SփO2(/AOX ыA*鿹OJ8xjqt`jPbzh2{?}|sb4G+a}:e)#܅ &OFI`h !"y@:rFܞ9RTB3v3sB|L4P~; h C܊xxs _Oq]Yiŭebcغs@7n3N@rzgKIj~yix?F0K<=Too=JE֣Ki"VoG`d͓eyvUf9~BysL(Qd0} <4="hFDq4GfT5:?Yd$+EW)t[c%=A6Ԓ-`5*@*=6&! M|Qzϡ)ע-*O*q=`?NAi&_0:²jjrl8X>5ɖ;]~ ?{yH" PR' mJT^Mv-VP),:ΤakV2Ʀa=0\o^Jl.p_q 2*Q$:j+ߌkbڑyvT/$e#-jo:_0mXC#{<='xxiOT'9C"jv4`]gU|D5K-3;Agæ 09QC}J3Q3o F~z,ϱ"q`nj?, {;L m܎ $E+:o܎o`̑@db੖QrUtQlπ{Z>xcWa#~hwWAЏ(T2a! f_+c24 c$Y/fWpZta|X?YTAmƋ6< jQ?}&B9 <3o(QCf3œ#P$̨ qS$27pT/r~$`'*f{ߺQ~yA dJ!+6\B)PrL=0Bެ#kQckaW1f3e8lzGF݋Al6 W/ތ0<U_@<V.M%'p?¥Y3sF0>h_05|5oYcjSB;})FW醦g ZJSZƴ"˴lOMßdW^,Ӱ s\Z~qٱ}W4ǻ&2WIk=ukGTdE* a! ۷Qhb~V,;$4x}(jxâVvrHfE< ;w'vE>c=|)["M/ Jbnr[p3 k9H-L<ٻ"OV|TPGJr_|=8_<2j*H:e]Ms]YxZ5,eKi3nJ"+OLXH(-IaO5Z!^n=-N/2PWA{϶ 9! WY^ghͱGg}0l-ݱ6M퉶DRʺ[ /ٽD(0m&`$_}>Ìu!`JSf| {&& ,jR 9]<|4B!eqY>l_h)_܃Sְe@Ki4 -BP7+Jcuݥ{eQS|Rj xRJ+OTy 1"W*k2 (M {%,-K8%oѩ\L7. 4 r#6\*#%W#qm!9#2AS?f*lER>k20I*"o\Ftf/M -̳4} I:-jܶWLpyܒڽPH:a_EN0BZn^U~8]@Wp,p0RY|`\[չڮ-i)hjDC|`yV;BbӬq Ca=r$yPd+)c!趾vt]]T\WUӵKBU&5<0t]4 xmt(t]AhN acj :=&Lo[(Xm58nS}I4Y[/p\ V+iP\B;d@E9G|gI1^״T e]bXw]U18dIAh]7 r̭V?A*bmI^>NZ.̱Ո,B!r|>Hg;![G/cj Ḽp \x>1ļKl"M _%>Np=づ9?7 Fe\X3p&:~rBɁm )m΁i9Jcm cmUPO$MmP}3,ys|6Nkܒ? o?CZ<\~S,䐈)U $#ۭp+ 5lg7#doJZe%)~AsZd%ǿ 5x؁N4Xk5Ԍvs.9~~y9Ξ hw>bi WWnTn7ؗKL~yrĜ ;`83bgį^>1dTCÇ:Tg'Pt%RKUUwvynz8P\0f߫fU&U}E4>:vYhS^CJ|5_)Ӳ?";1[$ 30Mqԭmp [H h♒ Q ]( +}?tt 1.8e* 6Y"L2; ֺR. "K V%Q?TuӐ>W/am=_& 1]qIR]#<=iPo]ZRm4>W&Q$2ЏBYt! kᛟ"Xfc9p3wЍC0YGeTh\itB}nKc.Jž2ׂR`P\;גd!3_-[\x F/a'a;\r%gf*,Uu9>oN2j*KX1kqh7O}G+1e7g{;(7T0!eEnϩ֤lHr8]GB֌H\euZCP3gCyFZ㼼tIo:#:hwQtv%)W|D"ZP\{W' E)jȂQ1xLEzȞqH=@>.H*x+XJL0(v bW*K&_S҉TKYQ*(~>g#/WfRqjl}I6 gW$^ɚ1~v$ ٧K Ê =̪o .> RO6A]U_̓&PL%°)-ax loɼLh6 /$#u(%*"{Dc(`f$ zM3s] wɫj:^MKWS{l\;)P.0iXSo=%[3„{3ͳx×6uiBbKjIWk*(Hoxw /`fyepS~=Zgü;G}jў/c Ѕ%T݇͸s;}b[3Vߕ//h>sSq_w(QgOxZ(ٻ]㐩7{/ݱ~,Gqt*qW4sؘ+x}Yqq:J+k u1f=Wcv}ɑ`yw[TB]* 4D=X(k]*HN?r Mi!{h~WъL3D%DV zѩd'}*mVOa4螨950 tpq:`:]ZV-LySP )XW%Ǯ ۅ6ss{xPHwoWJGl GM$ZL[s~Ùtn3yMBĦ1?<}^A'X%/ ĨN_`.K$()iaMywd_ 5ffV2CT-7·4c2YI`7+n9f`kEQq:[[i üAx*p9 {' u$0 +dCS + [1dvjQ#A{b!SeL[Swe2qh܋^# sΏͦԊ9nȨ) ~f oI(kqf9B]y!43/O&ͿET Ҿth=Z# "|iۧ8|cHZ,z&H#: +(UO RXITXU!̀ ˊH \%֔w^ݳB؛.lP@LR2Tp TZٱQ x];t9Xeݪ靮L8a@J}8CH&5#iW.:Y_#+t-z>& w4Lnd0^;ZI>z9B]M=x0SW8Z1ЌP\yETƂ刓ry "KRxq_[0J,4ƌiX4E98&GߡaN714se#%X~.+N8nŅFS R7ML0z͋r=R|c׮nG#_` 6-Qm-NXg!])7u`=i,X|'fʰC=S"]63p+HNPYtHHbQ@u tAg|o҃wyܜHlrccYu%2X++nȵ_Ak eZ%#DJ{pϙDD񟦬Cl*sKF%N4im8CyqfSy/MNVy|\` Ɉ ԫTH&͆)FȲ  S_Gi2s'z3;fkwr̋q1aUbY:ؘ7?GlD15ObLJ?m]QϺAT`m i,ȃg5華O%T/vR+,](6/ڏX}A̻9)dqmDERh ~E`HV'07tR*DWLTNYaR (XSIǡ REؑtو2ZSYNEd2>]ѯx[[{Ո#9Mߍahv؋:7ʼngfN[-)c}^qd}x.4SG_z(F'ۈat.ÌL͓C&Ba.1[Q*jΕcNː\2C]nғ^ _M AVbԹtKLb0 ȆU ǹiE@. ;M j[c$uɥUJ5.O~ =WK@ՠ{$>Wuy6:^7>A'\?chol Z ޳G ȷfnJJx4T,$3r5ZQ oKG J~^Ifb6cB G=3e t ?W+T=btDז+Q8]cd&ѕ!xEYa2cUslZl ]>N3Jmeӛd3V7Z RfjjClI!^Q}Βf|Dly @*50423Xo} MI^9$#tYi^C4+N) 7[%]6~8*mV' QfuujRxgfg'Vg5'_o/bøY#wb}LWXs c ,wk}W3+#L!=.Un MJ\ 'nn!qpegHtL8I/\dmmye ñEHXIh&!>.oQ2nhqa_ך^pop5rF} ^d0֔vS Ķ]"0*ϟ2#gC}&I,b4K$ͯZjWiw(*-[ƒ]Jf)?}hv\Izbl9SOO[JUp#iG4wfeE3.M@rZR.K.1MZQ%5فGG _ ^Ql )+Tt8,CSgLwVE:1y^$Լ5,~8o u1R1JEƓt(KD'Wd&u#uVNC*y'q_= no.΀0Xm :oQr@VCtSx֙C=༗FB>gvk*8Ŕj\ z\:~W]H4BoW77GxۂAf8:qg#.h̰AGSI /f.chTQ>"$V0ZWt]PN!G9(? x#}6{g&ܗJ^g҆B.]-ĎٝslAhA{`d`g$6+Ă0e4NnyEwh/'vU |J;eQ+\³|TFAh4: Uջϋ[+j3P>PL@$-K Z?'爳W5 lP菠 vx)DCQb(yX<Џ5)\Ak&7*4̱\]-XLݪ۾HBK *<7a >VcN^xyRDW ۵D6D\ΥՁpx}@tdQ(IU!W bG9,{q筈sYfxBE(Hp$0QJl?W ! *bܚ_+om8k;.@{2+93NrA FC kp kpGM !&K?|$ѼZiJ*z'1>P{/)W'P~o #HsG(Ś&xŨP⎒ojƓy b b(B+Z`t!R?>DţɌ,A/sD1ktL\NEuM0)Csp=A-ahk QYUF֠6N 8CB_Zx@*ߋ|-:mb΂+EZ|bjL{fJx=)$myl}$DfqLf7B_tSsb8$䭏W&ʯh CZ3FnJ{9W7G?|snbACHA*HtxF5Ae_L 2mxmA:16qCP=AMVewgcOkӻ^pRԙ )3ņg4?`K:ew{'@MqTORźA F{=ji2\,A0*IzҢ),5W(U'_dI,u9_,PKZ64,naeljSbMk dMk\AlϦ{( b]6ϒE-;%uگ3}A 5T,lSp/nQ7;W`| ~:ȦNW̊3'5(V}(=Iۡy}!k -!;VS+w~{CAҢx *vWj<Ǥ(t.1Z/UXD<߽&N 5(g{PE}A M^9k=p?f~ӛL/6LϮF.?T:DKsF5֩ bv-O-P7]N2'Ð7qFRFDj碿 ŌNQxܑ+?f ߈׍R|ؖB绋ӖF Z6A&\]#ĮSGfK&>S d.%|O1KUI9"UvBwmGKbOёtaRլO}ٖ*/\n<-uZ1:}:2"Q6{RD9k}eb3 \6j}m63&_> Cʥ,ߢMԄ}\c.x5fgpW8h Sgʵuv38P"3,ˢ$9{hVrurG8C[%:/Os9xo3WGׄ>=~F*8=s,`=qP}[먏g OU!)]v̛2B+\w_`6a13 fc!4]6Mnt4]]Mh$m7f <0M B:w%4ɚ* _eȼXAHlق RLK4<]uX2kl"(Adb݄ 3^K!ڞ%l1I"?oŤWJۅf֖m4*P ؤO$Jo_U/4hK-۞JkA{2O_u2$Asn] RG}q䀛vI.xdXEN ^A U`3ZM-QiK\CSCTܓԢxxZQ•!o#ޗB,ZjYt:-u3 | <,S# H$v9܁~ 2{E Tt(FjتHx$3zi`ѰKrLp|=_ =MFQDþtbO{\K p%gv]w3OݮYb9׮)0:awi4e 8 G?|0Jv@GLXxV29h<?\Ʉe T(q.w󉀌|)4B$ԣͶnBd-TlܢXtzGm*upY)t~ Vѻ.Yd%_ *)k#,B謯WKA8P17 yW&lܶbmIzrR!e=v\ q|^z&wz'+ W|҃z~QQ_{zZϓ{>O>OD>2|N};+XSX=^g\b16Pp:tHw`W_Ԉq\W?ȯ{}RKǗFQ`%Q ,{*vm"kOKt||Bb1 ` gIRѯKS-c'y!cjȕ<}m=fl(*\4x:)(x9T?Tj̤ОSVM(Š9zx`Z<vk%Q1:7L-o!7⎜c(ҽ AB,Ydu5V-XfwysFg_ay/`Ux6 t(g X#6`i 2)HIPoi##\;woRS*7aХ]Z:7V`q*rK(= Țn#K`cPg z\eb7-Chga-C<,C&/J02h?7&YVZXxnQv:#9g\} ZiGM{l׊UM4j݁l>U.D^ AٜGĮzPcGʧa4_ |ψB,< q xR gD\/3q1j U~AJxHSϳƤ\[Wf\÷ 7W;~Wyٷi~KYCfL@sbS=FK, @T%PCkqw,?$y<ߤ3 Q*sC禖Vj!:8=;MI_M]]`@*jŒCpp|}4#K=S+CWuL9 +ˉ2 yawOk|J=µoI[kX{szoĦ9-u%LµݓC7zdsuf`}S o~> 7YҖec"3 >+&o5+_ ^k~ibΧ?VWj[#b[M[3O,hT>LRh&%(bǮĹJC5D`>Akb[ǖTur%XàqʽRF976Fu`^v=|U|}uR`zqh`OµJbLy!]UL^HT}Q4K9od_x]>r5>[.Eo|TM+Q}b'Vn]k_vgٱ8cpw^HhUGDiVbunnTbcK`qO' r7cXߨ I(NG4aQ3A9$ 4]l]mHx"ɫZP, uÉ9e0LBb{F amiQŔ'jU)S Qp+WltG_x萆^J#K29ݎR|+r+Bь*߿n0eN^EPBX137BtȆP-0i iSTqmlVfzTb_+:!xj*Kmkb&UbSr5ӳ-Ê׏[|xBQ[*9*6"-QhGP7_ Q]ۥFʻ44[yrr=K*g |\4.oi1fiw]I@hH wi%A<PQAzz$9C$WNj;LDf4fj^v̺1某~7m/}ՊYUSu^0u$h#(>F(\&أ>6يѫP)hӮOّT;Qwu#9[W/ƞ|A!!]]BNKPW?u#.%mZTU[)Kn![ uT%^\B~ZyJ)&!祴#:Pcspo' `‹>y,,#.dV5AFx5&-;R&S;Fv[bv bdl@H K}3.?8ł ;dҿ%1MBj3vb]~ Ƴޕ,tf B**8ė;E9rvϦYq0|71xi}cYX o]]Q#Ԯ҆$Pg灼 ]ዽ:!huK^1?y;Dz4 =g#RK=2֨fM6|Ygd NNrJ5cp׾[( =[<5R6GkȤ+I57~EҚpY~Ƕ4g#$󜙭ςg\ H~tfĚg;'+V5+$脽? ٔXݟ&,r#F$bҖJ DdU'$5 T#Bgn&*_ΞR0O1r[sZW4mR[?pYO%?R}$C&~ϐ&͙TdlHِS /DwMjRe*``yO_ޚj?QJ.`K"|lxh +P  ]݇˺n.Ua&cn m^A6Yq_XuFa"#+7`7v<* |غ jL_s wWi[]!wRGiva@L`k~c Fvŝ&8/A2Iu sk cQ*XY,W6l@s1Dyi&9Zk6+_U =SI:f^RdanQ3 IF` ȶHgvj:kQo%w⣍k1IZ8;jzG+;UOgh{]X7TVf`)bt7aKL .$d~ϙkdO!`nVׄ2jG)@)!*EpVtR V2r\2eXܰ/ U?6b?/+#|Lf0ht|fZ %ǫo3<azECCvQhX`/K?Z}Bu;u(PKHq]) G!"mޒ-l67XڍkV(}%lM,PkGʵi1>@6&4ì6e)S˪@[u**nz\* C-Y-zM_ϭΑc{oTAxJɬ{=M"X8C<;4f`ޅo6 ù&D盩8vD^ gudQ,]^ .]3wȤĬU̳!>Tw* 5UmR,w{;wPF!yA-81J gע]V98(sorϳIObXLkKKZN:A %U" "=y5BH=I$*Ϳ/n*>6_Q̵Qgk|6ZcI<9o &~3*,*.ڐrJ\i׳FI wCESiHбiGP j]^-Eb?pӦ#:Ya{s=5蚬Nq]myg!CvEVw\i+" b1{1?悌%4}@3c]k 64X]t.HK/є+64(XtgS|pɞ 2ރ6&k D$ytE71eQ=ð y x Li?hN@@GqJQO؟t#`N'pڒZj*}hWbzfm4u'ڨSCP.](@7jMT/ >OՉ2b9nۅl*?TO9@ `>Q(6uMқ <+&J6}uP5& i=^ʆFLkDJ=t;γώ`j6k x-R $*-ދ‹\hf/6s?dS.WoY1+>DBIgj] `<1W>ݤm_0X SF$4( #lع|Q0C-ZĄ\b?*n`7zzO8K-%`:ѠokYك+$YZʆwf4cˀRMW/J,a4yTg2dʸ'/4&RKI-Sv lr6X WX)IQ"wZ!/b:ƢwB&mLg}5b\SP`O8b Bnjː4~Ie-y&Gw#}AT̙OzJ1(plꞐz*K{!P/j翸\v}bO.EV8AMo).4}e*M%T#-Ƈ'.^QSWPso$4x${\x>ǶVBD+zR5vM5jBGpq68qm=nque>[]Q;;iD1y>Ei1VH&ؤrYӭFFB0UT7&5@о3D=Or㗯/ y3'j/ +ԁnJv]mRKO{tq (?dG M:}ؔ>s%O&粘QD >Pm{ևXG, R2Wwoyn7e|pJ2](A; 3~ nCx;<^DhtE Q=dx8$[}lw?xOU! (- DJ` S gf>áPLljxQL+J9]|aLk BTsPBHtz&$J&2yiO'(d4}}q/nQڭ7Lϋ9h`:p/I]9Nb+˅cı5Rr6Yϕlƀ[Wd1fui L_^k.ܵ\oU٘vO4|P96\c-?M@1>$*P8/6 {a7`RFb:2ާ}MY%ӬX^|h;RHh5d ](y<8ZLgT"-ݖv3UUX-\Wٗ~V4>*鰲A&) i"qn \~G=A/% ltnqK֘ Q`kiQƻtѧ c FEACڛ6a6$ɘnsqfbxxHRr\)u| \0!CJxdn#gGܓκ^Vk bA`"b8g [R/m71H-Ų{>0[AoSzNcG3g\ю"@i7^ a<%5]#@jIDY7 _D 4) mI'x܍ٔߌIz|sOp  #Y֕xȿX΀TҤ]#TGjbI*Ŵ:|>V}a>\%]LXYهUA _\ y6rk2s _S6ZU lW ^`I6zr!/iSԊvpWX9ӡT`(*Ecx67,Ըe˗.EmoS*"B2/y]^0bbQc=e' * xf:r$)ntϞPM]v|>%@p:Rn7:+Yplm cdߩ \u֬g;Td]d=9[꣞QKErOçկ$=+w8/5 \r?lqnQWِK/rv%e0g:'u9Fɟ!8?# =)nyV`~4ΑpfA_ýy?-swk$c&mot>0`yi6WX߁y[- NyAc;?3bYUxD#ѥEJpwz .g5fEY9$Ruf?(F{յ?߄(PcA?*~+-%cmJ0Z>=i5E2z&/<dBT 1suV;0ֽ"hnYS[?ޮ _[!.uo`sp37J⬗?5R؋7Ԉ TI~$gM*f}G{N" f%-~Q )\-J~q2f1ǟ*n}BòP3lЖaafoAt @οumƺτ|/{w#b硔!ż$.ЈKɾ1F`J֒N!(ƙ\JH2-"ܹabKE&h B7/7 sPn?M8."T[1ڜ^KdNKa ^/u"^qleRG8|spH9 St9:v7n$9ēS+)n0"p5PMm ] 5(D!bEUY1]խ[҅O&θV`# Cyj!=>ԛY1FWۻẆH4`+X}!s2*eXCzLvz-bb쇻ӧ~6 6kZ@ujPӆU[ U{d="\Kbdu]I]o -3'Qߛ=_B>ំpJoJNk— [!=Љa=Գ)12Vp 5鷛y/ϗGG 9 Ih" t)|8R8K|$sIU9||'=6mjsYUXލKSxnlóY[m|vZ5 U= 1ׯҍcM+sHE^܋ 8Dhtϔu •SϜz:{`0q>#Ac%/uĢ- W^N2-H_ !^oTO^iwXbVH~ n.Tiqd]r*'[-b.z٠9 glﲨP។vқZ D+Tx܀y6Me)0«ߘF[}p8V jsf2 "6EqH4-Pհn\ELԁEW?cƧ.4P3;(p.8ӽ)o`Y%HQ7a(nQyp~뾾;,VEkٱ6O~Nzx3iIA. cI@Z5i:oMw[|d6˰=D2Ts^pü49[#t+Z M٘.y c7F\*3VB y)/{|%&ݺmy?j[}}5bo$8 dEFn}fTY ?*LtC$=$"Jle ,cKzCXz V}.dwi _;3i*5H_^jw*,bV.E(d`i5% ctvvFu6LJ;wB?k/9J~mIhLVKtL5WOw,b29zG ԗϨwPyxF0+8:{A`)luv29}> 6 $P|=W&~AXzLsU|]=2;T7*ŋ !#?jt>KX\]Jk2^ kg/4фXa@&:8xft-ҫ7M̾P~Wjg^/:XYEqhFE,Rm"K&|Y Q9Χwu3)_TgLotN0 w2"n0*=ל??ˍ:5yhryߏT}1Vc'2-*ӔT:DuLyAWz{BQZlVH~`ih?>哅h:F_*0<i?7<`'=NÅ|1ݖSyi;}bvUp7.?֘!R`D#H>rN|H1˔Z#%FGBOs?4z1Mp) AS¿Ӄ̦%v5ǩp/PM=W$()vnti /LTZRh8f`~%BJX/c8ۚd@7S̎80#޲TZI金'ZX#Ea18_!xB'G,)Ff_o[ui`S ;E4M}2s؟"G$z#>eAm:p{_5{bj0C=jot%STwH˭d׶]ehcsQʫPbZ_yBrM`Uc%k"5s8SmWN= cP0mnVQ¡͈Q: 6" z8- /&!|>d@@;rru0GE.GeiNX 2Vbd=mVlaX0dAD^̵P4Rm Oj \vAaixNN{ gilhT2,#Y-<{+QI'TyFU$BĢt/T$)&ZxRXNԫU.a=)Kza7I8(NLV]|dPq6P"N,a7#{ Sn+ՐMvfk(L$bcm{ITWT]|#(%lM8^oPJo4jjq{`/~B^BdƩ0Jކ-K1?Cvhr}XmqcA.~n@4ֆd|~* qQ­=5x)>@SK &(UޕWu7-Y$DJŃ yR NW"KEZ"o[Ť>}վ݈DbOcHu(j @~ʀB,yp4>+v_Zh+Ov>9@' ,S~ fn< ]/%Ne=5'5zUA_476:OKQ2| N0r>AT<7&W^Ov} TDlk˙iʶI+n S KFE+?/7QJNh:"L&ԩZp,K:>#0s.%}Z&2iw1J?}9ڻmS"ݰ5t *\pr 9RUUOqnV0b |~q\ n7J`_ci${*ϙX4@NL- њ1r© 8[1R&^Q4GR_PD Xwٍ~bB8'H&.vs O1ؿ 6R?Qhd/Z 8ן) v#6b9їګDYTy ڙd6.Ohh-X.eaJꨉ.2aEұ,+1^ ;1dS@7WIʕ#VvS@yP1:Dﻪ{A#Ɲ&UZc_( &..2ތn]w@zwNMs޺k̓JNhG(fYS *;WS"X+dax:T!-epcj%drǀc{ nՌHWǰWn>y}=C O9i Q`Y82ξT$?|$7dy@Ï`nٱ={3l-M9]k_fz"o5@߿f-BF"Dz_Gtp 펱F}A)c+>,pގUF%s&_4utE Sb>s5m….iՑ ! ŏD^<$z7g[ZA,W,͊(?YiD T` U3ya~\XP.pqeܻU͎$F UhfiBqp7X)+V98 nA$^wƼ- (TOo|^zn9!5(ےV!7Ari(%ƗO=DPH 4>V_F6eE%&H\q˻@Ta*@:U{; KoK%R״g0 6=1F_xuY{TYkV\Sh6Ab(|zzr"05./fBrZ9(cMF`4DGej'#8|,Y*C0f%0Tbb;"ܰ-{a͟2DteuWwG T;\38ZI%qY-ݖ=R3AdPW #W*yi;ͿR#bB'shqkPIQ̷*6c0j7V_Dڌ/T7+^y#!Wd9q5dQ`]9 l#ú/"V]#uv0? [wt2uṬR US:&]E,epvW=OlR[r-?8w0 1@3V%q(C1;oO[cގ}Ub_5 KEtY$o͆%i'lRS]l]ֻl-^f4pv`r((dY~z Zט1RPsC}`> H%YyXB]}̖o4m-:}mp00iCsЁRpI~10}IGXgA_%.3NF@SӲzyf}JK/]vU2ȴlnOHUa*RCƝB n.~6+[($'z͋*xf:vС|DeNm(V)8˧hC>0Dp8DI/ XVI C9b T%pAx9BJ6 .ٞ?<-+8q<;#)uaFoS#rm@a]~~KÎ/^ ;G'W7⹲Uĕ%_hW8pJ*pHĄMP}jZ~qr'04L\pBq;䀇toKnRTO+|taDdP}Mtq0./Q6ōktm^`Yq{ԚG~H~k~ jV4"CKhiN) gOc#.Ʒ@~+0. ŐZ*[?4뒨i$%{Cx@LZ+l` qa1Ic6lTfdy,, ,QeIPO=6Whߩ")<'NPNj?*U,Wd>},Rf ӧڗN}ScHWk0Xo5_)ub«Vlpv(\ `&}27Ҙ&CLZx!AA1JQV #3<"Z暰n':Z.,rDW]>|/ O[_Uw7|W% ;MpC,̄55suqbYI!1ʋ_4.Adz,,7CULmww&)b~O6-DTj,If]dw #SWR4E] brt  EľZ)j>;nj%pM?g/6Z8=GB~V F񦕾犮ȔCbG馗Y2 dz[eW= r:@Љiꦁ-)1NZ)s_CǠ9I)'aה̐:eWc8hg7d÷&D`ږ 43FhrɇHW#U0E۩b0 ŪXv`nqMg:~U-KnqH۟N)1z] `^;ysE({)_o/PC:Ub:|#^N%M拇dysCñG m"^ E|UJQJM,q@S&\1$! D9;U0㋩2ֱ89{ÎVzΥ=ͪM6x*oOe\:f1I 7A>"p2+zW^Q2,QnV;LF%;tMf\h.Sr};ΆL{ig ]1I'DpJJ-֒]u+u2.M2p`HgӇ["" X_EX1;NԚYA8 GMkSS@pFxU &39ހڶj 5QnXӽIc!Ҩ*m))kD"sIMi`2iإ}jK|~k }o`+E=aŹU2:?&}|E$x;(I5ܴ$Vv},P*&0m%ȦȷL{X䢴+T2 };(,)k@O^:wcb٭K-֫!4Jnd<']Fu@4#d0A86n#O>D|꿘]<:(ʢlT,7_A~l5+8H}r$\B)VԠ荒qQhOi>qr_ L܀;\]? )yPN4ʓ.o/yI ? i7Lj[=MfZ)0fxЍB[8xd;a ybW%e(-da/) c^H-hAxyC 1[8 :odZrd IJ=|)*MKtF}:Zd0N"MVu4W`z CjTھ2S?h/[hG`.7& @ v7wk{"B^aKp,0+W v C7 oZ'tY&,* O{ ~$#tB j_! ':YoТsinN9Ӿ ,A<l2;W*'ߕJD&w;ۣ^JS_^%37E?Fo,c:5PO6|ȊȡJZ:*Sgh d9vF"wȥJIDIQ)SRRRo]1OZgϖ/Gԭ~k+*F]08ҲoWx#stuM!6`kt<.:&vĆWF-FsOKLKi+9ɥց[ؠ?y6j|/; Ov4sEKM$m|SG^X.#?Iy9bXoq vb2bjgpm-й/H-W)ח>SMFQa\EPoj^-Dvq fpû6OxVob7r)m 氌t= <`E`96T2@(ٸ ]Msgn.85%^$O;~ 8o7eIdTO2up}{aoߚ{nPBdWxkrvHQb5/@X5rF~g 77(1//.#HRc!VX ^u rǨWhQ@kc(f7rdu&AVgS۹AQ ^vuY<9sChoR-+Ā^'"r+~Quh u:|Wk-܈pS7d{:YC0_)E2)^[YD${ 7쮬N>3:U=^6h({TA ƪW>9}0_<]i nx 1D|.|W>m͒JKZ{Y%?KYU/uGIVcћabH~J +_'SZbgpr#ŗVr0ٮ bCBeUќ_fNqzxuéiٮ;OZ5?v}^}>{#hgRFc0 $,$m= 74KH=9Ԟ O~ZByBHv [pCfIj'Cʣj"0c"Ngw׿uRf$h!@[ bI+'F\"(AL!˺ӻ N7CjY[3h4z̀ dxid \ģ+/mIn)-LFfR [$_WcW`]VO dj;vhpaJËU-PSřw` 7z:S-),q(:@_*/,W±,XKcT{_׫/רy?d~VPWW[@q-/yGsLʫ%+Aؒ0;] Lq KCzڶIq̂)['7a+~tJxٞ'ʘOzuJ>FխF#>?'-$+\ 9 С3͌ -yy>g׾0v&@YyuKFBIP? *>'Yd7b}>UX:-T3KSȔ/P}𡀐gS ou| M<i׉3pj"@<>#Q/,׈'^Nԋׁ+ _-3LHiBR2|JBzuqf Gr37``## @i{ȷLv<н4u׳ɲorI9EcG=E#p%롿 zs$ҧTLjh H˿ ԼuѯiGl˻X?#h1Ve/흜ucbHSp;3X@!R_ʛ{dX }y' )_Z@xC

sr|97}xO"L]HK ^nW&5s c8b Pk҆y~׿:r W5Sz;},^ Jvul2>Or9Fކ*LyE&hIu71RUP+rjBh&ohdwF(߆#5M"ph Xc]`۟*ɦ^G!?>?b (ct tAΝ_d}*~%̋mJ*#$LlD=$2/]]>~}8ǎD5{ma%A= Voa3[[f+uoӨW`[`:)6zRB*V/WwZJANeSPc1+(EFv u,8 2`$a4-|t}6 Vt6ӀjKZU}$T>B ̄3kΝ&3Ss8ĥdا.d$=_3r'x,])"mlL&t\5m(O;ڵGO]{SR8G-m}V4l2>@ž+g+23$qW,em@Q?M WyWGΟYJv  Zu"j 'ob ..Az\A%)C ̀D^!+4max3(͐c В#㑼8f}V䮗CZO3qS`*Q>aB띮(H!K{z6Ni2~. H#-DB|RVPx9z)O.ɾ|>: SUf XV⶧Jx E6 +vҭ2X#?B$4^U{i!VnDk1xiD2w%bq뎏ɍ"ϳKkqlŸ49=΍cmm9owi}ݲXvOA.%;54-gz3Z;z?Ǭ~FFgp1D -,X҂]}7J zxYSA` ?#ء }LmM"8l/*S\& 7ոw-ʙ"  z:ӹs^ / T Y L'ֆUw-1zz)OnO?=B(:gCYD/s9ZIUBgce:8z(; 5FNд6HmigV'6}mYjompRp+ad>qb AP;ܓ<+4rȥyC 01&c(قFbWwW'81)JpiʵPDP]p|~n|2Q2<"vD"ÁKT)\P ߞ t `2q 7MmFG S(;Eu g*D3vH`^oc6MFo:{Ihtk/4lLr-g^GvKSыLpԋgйlpijO΄[Moϫqs\Ƥv.*~]ud+t=HlqN{3ط`x[2JG*#1n8AG4&(!ЉIL!-,.~6QSDͤEn 6$7[icU^rN9St#)ZYEQ8!O.6lQǵRd<2oLPL4[K)b(9.Ow/2S;l}JnjFօ'RaAPDX,D-':1{j4B~cZx¢}vh~JÀRX+h閄ռ Pρ <in9*XhJ:NjF^$Ev^)^@/{İoIJ8ds ~Gh. #2S.7@&, k>^e1%VC^F0HaKM[>%.KS&`_}LPʎM4nR4ޗZZOKk1eyVӬ.$}r'd`q82X3{&!l;YG Or)gSL~$%n5b8lh\{L9;314r0`A+*p$K%C}5toŇ6W&巉q :UEU v?|pZfdi+Y83Υao(Z@!1j:څմ :Hrhof&WR{z\{wK#'8'<>?yq"Xlْn }2(&\tWk["@L3ݞm$)&"-uEi`xlCl-b7T1Yj!<r.PʲȺǨM}/}ٱlj_06);vg%23k3gW5:qv}l^j>_"E#-4R`+y^ONj? n QGMgz'^u?Lo,үt{- )٪Kw6,)K(/|k 1|O?yN#?t\XLi<~zB_k9;(A ZIE:e^-^5嚭@.g/ eB쑎NOIq#?twC1Ԅh 0WA☩ Wp&ۡBvuV[/X-j5vYH|RpjNxB9pƔpX>pJuOWS:g@ө[pΈTS"[_LN;q@GHH՞P AI0Y$O$`̄o{q?ʴLfrLOR}f 4(xIwUYx%mFo*V)x:Ն,G7:I%"YvxX_E- Q#hiNx(?9lU05 8Kb%L_vu"s S.]A-Q6 Jg)R(bfILV x]H~A [soa?#T\_45'̶+V(!}6HKKRlHHsL>$ڟ\cn$uH)vlYo1~Q;|y`e1OE{N!Df)7aD0ᩕf}8.2h3J&qrx/$DLʢ{Z 2R].7Nb5^P;ONW'\v*4F=5fޭ@G]4is0A&j? olO8a,לF ?(Ta] o6J HvHz8[:J@ȋÿR18P5mǛQZu{2Ńt`lؕAfps(  ^<'%_c#/ZE΂wD?顡pIy#r#ױ/fRƽh?:{+AIUQ C2ÜXIutY dKd(1yd2$ !w g~VH3-u܅ywDdgS ٚvi(ľrmsr;~;N{MCZ~ʙNNѢCz{G(79t(%Ǯc!zSBT=CqG@B\_S}OAⵝD̠s#^! g#!rΔLDw&G-!Uq9%#>imʘrڻtD ?>BSJ#a6A 8qǦbի99R#2`sd}=u7ZFu/_r9@O'BsRF&1RmmGe!eje8rՕw_o|#Q8'ѫH{9|Hl˿*Egihm0+!E/Asr4z)P-onG^0Y!4KْEe{>(+YjO8G-;~&Z6GY=`UpYnSi4D)"f<c0 D2z![gAng/xo\>iO@.GxB%.g4h(BKj1 k."NxE8Ї\䯾x'Y':uq"m:NH{YRhW+! gd#6K.!^7ٳmDRv!褗JEpj['~W6/ac֤b1}MOˊoG=>:c2yıjwCF OcmWOqW}?8AL*uf ;a0op2%*GMjnmU ? OIk `|:ۧY42*P} ë5ä˙S.&2aϦ&ut3\y㺉DdgX9u\kǍ߻؄ӰRʚb]^,e @&_rW*97z+U}pQِQ2o3:Ɣ1-oe,uH8%mӚhl:.tBO"IDO?0PoM턢:f0 m.[DV< 0œg,03HwYԘto+;,^t[`b/LaB<ɽVx6gihuVxI<z (( 4*׳s)NuQ.ԯ4$҄<{2#lMQ ܑ  BYpĦN2w?__pjhCN@ȁwH>Xe#.b%< aN<`.0N[/a1a M.TE)[KC?MQ96Ogc֧V߬$ SA_n-|j/b 7E+I1]\O%2:MҬ?4/+u%쳯"nӪ8TEA ~_zAw9Em [l-ŷj\%ư5sȨhmDt mD C]aF^ի}˻%^k o<;wHyג?`/cˬ!Ӳ('[j{OY/s{x<ꩀP/0a1i<" ZYQ. ,G*"wOb1s QVO4gp 88Rcȡ(+[ܱRd/ɳP/[qhY>h.!;RZ*pk@LMOhHp*Qed0ةY`x/|]̆gV^AnCARqKKqᐏa&s^FG$39ևts~w2k/cAb9g}[ؓ3MK yə Q* jM]R0Zx /%nf&Q&L%=ErT_(j[?Ds4`I?qHy_aZ2ỮՕ'}]CMPl%mF Sn򵭞#nZ0ӛ d8_FyOR8<ϷM+x1X<%v:-n{իYɞ8o׍; EQI0`$mBu: 7m@̟s{{D?w9Qެg^[ܰ?=S{Y(KH.ei~I;SW/W&6B/twk`_=_Vo-R VdɒtTTpAqlmڅ}KD9$$(7,SDnP-՛մ;zJ}bHWTC@Egr(k([ɚ&695BL%eTIy0EϧTg9P]؈7JDRSTäju\= -q+P3 iGBYB#oDPN?'̥?vT$ '=$g `| X*h{ˆw6KW8y8rhDtwrpT{UZҝDlhb0Q\?$ >Q:j 8H:M ԁ$LF=lDvܸ۬`3^CIOsEk5yE>| q:r) Ivz &RٟVv``41P)"©;}}8=Z/Z262 pi'5﬿X$~ᢛqA*[gXߵAUoa%dTd#\W[`֣f?iTX(!.!խsay8wŏ059Nao'5Ȇ;Ǿ.*5REMݽ޻^4s>~ % z#:-!W9zthʻn\q ƶzr[W 5hz^ZtTGڒLFNx삀P?C8y`~cἄkĠ,` j H/@|L4մ_4(^ᄉe83Qӈ{oh<ġgoyKfJX+Ma#:*wo 6jTfe'$粒"gԁstHl[h-zp_bN/)M/9r'8drv3#2};|%E|J-̰*فҭ oԢ y%Qx@+K%9=ِ,R 5绫yDA<  ;эl05iϡlPaep$ Xh}s%oN5Ĕ #g/%Z"Լ)gx:o,hL'!G_*~cI}XKYI+Dm,$ڄ!v0Qc4,%@ML%.XVNfJ 9͂ϯSUZMD3:#U^=b+5ffeY2ycFF4RV1@@FJhX(1wS ^65DR(Y npICA:%*(Q'!tk(]{o~2ʄ*}g-9T6N]{\8B@NUй%oSu)]HT dnADDUOQ2v4 S vaQ)Nr[m> f'Yx Ptks%>@5XcG)>V'}{(v m{K/ iawlZ3Zۥ2=n BķK9$k`u\h "$1akto-=]e)݀I}|dTLZZ?4!-D՗3ɺ'1iFgz3] 쪧.Vv>MY"(U72g|Fr?̚,5N]L_ .кj D$єGbS|C_Z\oRp]Df=!D([)  A;ŰfGhچw!RtC]A{=*?%wG$Ɗ. …,hy[>53z_O X?C'٧Ϳ) ^(SښCFE[){R"+^*׃Kx:DCĂ9 ߜxyB_ASn2KBODi#BJBxH EYX4/8G'Qc' n_#XoԬ^~TO?'SPHrgH2<|Ѯ_8Q~/ D^7pAUzNj]CT& #)cu*L zvѼ74%9}}9LޏLPM59qo*.K> db拶^7k()"0F+ $G|K6f^ry@e^( eȷ:={8[~#W8xn!qTq+#py4۩@ \#$[2&@ΈⅨ/mCVScn '!xЎdI!%KY?kYc8"F='&-uįzc'$Uix#E7̦?N?Cߓ(^/V, a&XZV[P2p1v|r2("b0g-0=Dt;mAߣ`@f_r(Njw^柎) pWs:Br"(L"*2 J8vpN"daJNx- D\ *X!]_VWǽdy쥰+9(i+"߿^SxS҄_hS<5(F@BD#)-o+"TGiZxUHRJlݗΟR^3T@D~hDA_oֶۭQ4H_b se8_ao MnUy0`UE6qAxlhrSf"_,LE] cZw`wʀ%"~0*΋ԟ?)!6ӥjL>Xw@s1#s'wԹre4f 76Xeh홍 ,wºPϠO}81і.ZcϢ05kߴ%꺏} db&d ˪IēN|xT WW ?|!1ZJZ X.. I&HQbiR\<H<_j~d8}-â|GkX:e.=f+c:^/81I,)*5S@/5`/i?8&vU,fAOHCP:P Hf_"Ӧyh7>YR J."J.Y 1h.8_RMͼNwXbw Yl7K4B3|S ͡ SQ]'\Q'"gq7YrّS0_qoXJ-]O)>xM9?6TVQubﳁ;]$\B~U^z_AјkՔY#%[uﳱMĐ'A+IS/ڈ"ֿ?Tt D,|Rp2cJfhm3nޡl@ŠWX,MZdݡ&5s\fP(IVBrTLY)_8^ Z" v"4J_@)ئFC4Vaz"i3hYl|T'uHD"wh,ciׄ 6nR;!CK>aK*``i$ܶiո7P/i#N0pDͶJyu _C3ض fe5(qP(-yYz۠.'sU15L )9mO?@z,.+İ z Q#AqۄBVn4ʩa+V̿2$ufI (V` LW9B\|@Vd;P$;g)D GCVaPCy-ʍ4&憺Za^%i-.dN/\4+Y>OS s]3HCL$?`~iWm,nM,s#rb\(bEFcRT1Ȕ/1uc~p;.i^Q67@[W_B _D81mۢ Dϸ{R"@m-zvUlW*8JVζIa`5)MB\‚4WT=t) hu:/ eRlY}܎感qP2FF&D>{ߋ)Y%(8W>GQ>Pl=⒁vsTUbÏM$U"E7 r\x}Bl*l2zȨi#D $;r*"))X Af z&eꅧf;#lQ}(&0Θ5{5Cn> tfpvO'l DSI v>]E;`53U Gu$geDYΗmYiG#Ch}(3qȑG}8?Һ22=Bt{HY5I\t6 nOi}Jm!ph ?^LAnȵ飾ZyZvD*l[fP A%_{j#&;sAid%[ţJia!Qҫgb65OӸgLeP[6HҵԽ( {V8L..#P"H`Gli !8KjZ営m{7<8r'SRVkTCZxp:%Yo g<8?( _CϷZ,+$C:}{ q2#dN/ssq">G!q ireTO۝=N̑2v;6"=j8#(:y޺k# ^Ÿ U 3ۇSVѓ>6'q.iATRWd$}*֕ zf{o`@iFԽS{8b§'!X'Fnz>4=^]qQXpf\}xYiTΪJLU,3<棓D|sqr ˶%ϊC|Rpvyt#vs̟YQAud6~X^HC| Ri=j& k@D+j0_Ź:j\^Ci+}VnNj[f\<?!tx2mQN?};|eɳ/CbU;ՒD7(FT-Qo'ZƁضf~%yמѷ?B8rNmꁩ숤uv6(ore ?T#y'y>5pB;K䁨(/6.;+wDWkf AI5{~azEo*I\Së0e(Kf+)ڟ_4l0Zk7Q%F0c1]Am@;7Y}Z; AԼ[}0OT o,O vQX{?,23)czLBpυGibfvO.G^;?Rn7Yc QuoX_sv 5d%)DQUŭJƝm01X.2S@7cDSIʔ_-dK>raܥv?m(`4ĩqӐը~8E:H3 FHucL^a= j9&=)Jp]ڟ!ɞqɊpsWbVS1]jrnP⭄}cfŝgِEjZV *9`vRy+E#e[E\e=CUmFߒx`\Gv:W)GM"4M2Ira Q,&ҊNo{bicq(d|cC|/`něT# \xfX<\,g=_۳p˨@1) Ơc\pKB +ybFbT2ͅ<"ˠ|2[BhM9p,=־!c=#'3j[?n{?!ٟ>tw_iZ<.뗹kh~u߱dn7MGLp_\ŋJ~V֜`Ɏ JjrX5_B]Rv)Mrt댱M q"1X 'FM#.%̇L*U* =Ohf*j4oV6\27OkW>R}LI6üm)Im¹'Ol:E^:)^HX tPr6y%8' WJfn2L1ߍzu;G1&9ҧMyf2`6` 'ss2Y箦I.η1\ jV>YIVခ%̇mئdc4J.=n2T[٣gH%3˩#k _Dxz٘4Ә&hj8*RҚAw;(ȵ#ձ0ZuG0#kC:ca:wj[cTl{c<]:Ö3ZHXm5!վcyQ;rD$;ܢv!2U9&=Pߴ{D<>a-S} =ƣ~ |Hl`Y &?}މu+<'jm&m5./uj|pˆ>S`L*u!Ħ)')WC'h脯7~_XUT''`=6 pZ|ƔwcNFkNXq|r)3^Hxs;N2{s8YG+|=W ";\2}z&)rM?2J7GɗAvG5X&M<Չ O~i M?Pyo<`]Dm>;NjD޿Q)a|}Ɵ8dz}D1GRD[ e.IluU[?:DM=Az2?!w/?46`n 4{.29A=#\wӎБ_g`}KuQ=&vI; %.ʚ]0;+jUT-^>?*0E w kP~"TP1/YoU+YjCQlj3Rkg{>R"-$v,FhL[Tf>9;%:Yˢ*忄XDd-tOD:pFE`3w&K/ fu-p(jm睧{sbhL܋?b|JBT~2(u{R %nmNn6E)P _tOPHFrWJ)7N+ 2ـ&iqHy."+w(uLڍ( 9RN0ܙ`AMWwK E[z2­ov^`'"z; V愉x̦ijE^f %\3f"k(جA v,ikS얎8>Og rY ;7d2Agie$~Jw.9܋ :AaDߖt&9OhW/6a{99f 6TXNR95!R'JV]X3rH: 4ɭz۱W0 2p8u>oA^kE_kğ 3iWJ{J?i9Q/'B?j߲ü!>~>Ǝi\n!H%/lѐbBAɎ +Gr*|f M)Upfga?sttt~zxD՛8\Nٜ%\қĨfT,gغ`uDÀT8o]kyfK'ˋ5u1Ȑls2CZSjqA&B$Q [AN=24k+`.*9"h< ΀mLo-jg·9mdʚ یd12{Rt=z2%X#(yP橀u}{Th۪'Z'u}UT @HꂃFZ&[ ?':[X|5mG2(N4\p2ʶ>* Yٳ/) $#`a!#'yuŀ0|1 $$d]l"{_e^3 (ozQV_zc(-nY32VqŵXC `GP7AC s;B3!okoO-g V ұvc:#^W&vYL~mZzxQ7PN:7쀭P%B >ɮm{2d/&2A!d+l#*'Lu_Y}5ڨٚTB&W-&v\)EF1 U:Mګ[ƂH~# Nc29$FTɵCelRKD>Jn]) ZI-l>Q3>؇Bh$ńŔd H%@›3g'$a3o%.*KʲMhʑJ<;\zC >qZ& US(L#)36pGһ|ݓ@zԇsJ8uҕ{ZJ~ u#ndDŽAhBڴn:=Ϋ~q[*" PrGoEhmMia -俫 rTW!;lrqoDž$' qV%;գh`C<| ɹ*:hT%=ArYh}v%FCޗ9y'G2'^# &0Pu89MwUaf5 ;hAL /5Q%@%"@ NR νsd]]@S@}=]lHEP"ۇBAǣm ~||B({Ek貄?*;p '޿4W+0 +g?G9\)LzȮ>:FrJa+Yըf\x[7m]`"? & hͭ&lƊzń)!!S& H"F bJQ!Aߖ%BBze0joEN0E(G ]<2炣wך;{"2p?A[ؓ(7{T` j&CB+4ؖGvb9/@"Beߩ-G&:X@_:@t^Xu;H,g[V_G4 - o-Iƛb}H,BRqeѳT&˧wXTyL<#_2 Pf:#;~?< ^)򝕂gbLvA6>icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/kbnp-doc-bitmap.icns000066400000000000000000002342361506470510200245270ustar00rootroot00000000000000icns8is32;r,ǐ.++000111222233333r,ǐr,ǐ쉁s8mkil32)?3˃Dà;¼> ͶA дDӷA ָuxA ƨm  '' --,, //.. / 0 000 000 111 111 1!2!222!222!333!333!33!!!!")?3˃Dà;¼> ͶADӷA ָuxA ƨvm  Ě ݰ        !!!!!!!!!!")?3˃Dà;¼> ͶADӷA ָuxA ƨ]Zm  vv 戆  샎      !!!!!!!!!!"l8mk(_ccccccccccco`oItXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmoj3yy4it32'ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ źʿ^ ƺʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽD/¸ ǿ! #$@&''Ɂ() Ӂ*+  ۅ, Á -. Ɂ/.// ́/ Ё0/Ձ0ہ0ށ0000000011111111111111111111111111122222222222222222222222222222222222222333333333333333333333333ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ʿ^ʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽ/¸ ǿ @Ʌ ŞӅ Τ ۅ ԩÁ ܮɁ ರ́ 嶳Ё鸶Ձ뺹ہށ€ÁÁāāāāāŁŁƁƁƁƁƁƁƁƁǁǁǁȁȁȁɁɁɁɁɁɁɁʁʁʁʁʁʁʁʁʁʁˁˁˁˁˁˁˁ˅˅ˁˁˁˁˁˁ˅˅́́́́́́́ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ʿ^ʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽD/"¸[Z[[Z[[\ǿbccddjk@qrssttxxyyz Ӂ ۃ Á え Ɂ썌 ́펎 ЁՁہށ񍑄񍑄񕑄򕑄򕑄򕑄򕑄󕒄󕒄󕒄􅒅􍒄􅒅􍒄t8mk@#056777777777777777777777777777777777777777777777777640'  !ӆ> /= 9_Bq#Ja&M`(O_(O`(O^(O_(O`(O_(O`(O`(O`(N_(N`(N_(Ma(M`(M_(M^(L^(L^(L\(L\(L[(LZ(KZ(KA(K+(J! (JC(J#(I1(I< (IC(IH"(IK$(IM&(IM&(HM'(HM'(HM'(HM'(GM'(GM((GM((GM((GL((GL((GL((GL((GL((GL((GL((FL((FL((FL((FK((FK((FK((FK((FJ((FJ((FJ((FJ((FJ((FJ((FI((FI((FI((FI((FI((FI((FI((EI((EI((EI((EH((EH((EH((EH((EH((EH((EH((EG((EG((DG((DG((DG((DG((DG((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((CF((CF((CF((CF((CF((CE((CE((CE((CE((CE((CE((CE(&AC&#<=#3Mapz{qbN4 (׺ y_{oؔs{/uA?8]1(v.xz>/Hwɳ"tشd^+Q%Qs,Oe׀! t=e_H}PXU63CRWܐb'M2 DiaN dD~7#l{l>M+܊1DŽ/("L'%s @jhNU]E2O0eU+WV.!3_u_mq_+9aFi cl#3pxK[\'f$3 rogc^[p+0{,},;E'U)4GwL44zJ+lԏ uX3 +Sa]j0" |I!_t._2d0GNK U>7f Au+I~b?T̵s 碯?o$&Et<䢩DcZ3#Mݎ> ,t_N-c;r daCڳ`Ċ=}ۮR۱SsZ^!.3as0 )K8M1Xf#Ca~;FeXPJ7'rĽy |/v.XcAO~jPmdOF^͋v3гF.s͠I2DuzHS>E!4Sc4J3΢aV\m Bsڃ?y ] 3|dl^(ȭ">g(ǓSo0m}\[1N?HjEr1<0:ʥ8>2}en0"n&lZ oQ4)D9AtwԿU3o>Ai˞,cD2PGk/b)y_3*I)"m*~#h;wKônęn=5aF]؞-O'0&.Wy0 *[/H"$+4׬޲s>1=meA`QQU#i9F. aV\xu.dfX=?,GRllydNLeA485]@hB5L,r2˛Z呥jW_p@7=]}d*=uqF}vXAY|-~̩ҧ-mj0>2ڣ P Mtm5!jƉ"{jVFXO_nM43gjZly+uo(h$s\-M) OnӺT%ٮJ)rnc`dn>6jmM8"[ ΫZxϰ7gUq7')BAiOޟHFsJc_ )$GeÚlx&ܲi>UH)x%/t@}]Rb)e&"_t2{yeB4L9IƦ~>#UI UuKSerZ-ÅL9 D6UI%![Wt UzC -r4GPjmbGEm)lI*;+Y\egߧzo~^a~M`&n 4>aEčJPт$.Fu2"cRn.'ı`$G\qJFkXZ- 4vtg)]/ʡL[j.>;hUV ;ŀ@ (?ӿ;]&d0ЏA!C6 sMr, Gҍc Bnf}bY l}s3s))}A0'#7bV1|6jh:,uccC828.y"['/\-c6m6,(Ί%G8cGJÇijքs .p,=O39gP4Ui-v ᗑJ[bX{:* +>`i-(ٰrr  Uq-S{OoƮ3]op70ནŌye=Rծ.̼siǽ=P9FK- LS wb#oC> #%ϴ#jfXf|: tز*zQc]1aI=m~~6Ȩ&nAxjtDd$ֻRNwc$jjiܵܧ;yr9ɳ_>?/JHu$̭͠Avz <)VҔ (լ :bUt>MkMےI$04>ݢqLs!cᶞoKҐQj-|,9距6br$i_^@c+mےI KN^I|3 LRdmd= vO3"БYB2V]'IG[-0"x9$VWxN>$I%M e;^qax=ѧcӵf7=ؗMVl<`)b [jT9wMv3t֎V.'!8ҧ8wUC`b?* [[: zسm0\<2W]GjH _*m /Uҹn_i]R<.8|~;+PdcJdB&vz+P)F>6vkt}Yگz~K%ku'Mg0\.;f.~S+'kjHDt7aV>Ye?C--pS yIC]6afcߦJ~8L&(>7꾭3rbd76FF푣)&ὓxF/zZ"̆!xn%wm!e%d#iGu܌.tc)M|CrvsU8nd%Nj7xʸ;;R|o0-;i&<'d umC]9LY1=ڀ L%+rPvH_߄%A\2YH۶>An8iPrD֤ۻwMpHHJS]!wQTM+É*%ZC&~\D8qxL],3jbnגr6k0 6a&`Q۔aJ;jeY3H)Oa:ʅ@1v)7"n3* cS gTրBCs#?tX0A3Q\h& 3զ^ZS:t lT՚swd)+6#᫼4jC#y#SU9ϒWv&`k8duhJL^}2< (ˇS=(D(P, 4@m#\!r%:2A̾p}x| ~cg2Nɢ*&Ov\qL-ʌrg> %/-Q)D"" S$,c]GnAwS lᕅXW06.QQ̔3f֏G(f }Cz%hғ=gX7CցEӥ3ؓ"9'jt|f&(H m+T{ 'FTOR2]A6"n,[0D1bwT2Pվ?.w1"'F3>K@g1Ǝ.5.bMg+5Zbk޹ )iP ̔h@fJUt,?n @m$IT G^*H{JR{I$I%tw`oe\,ݡf}1e$b-Ox lR!7Aq=A, 1שo.l rffܺLY.q|MWn3t IZ(;U\v>x H+Z,hZW:'<>S\as?\m^yaΝIOZo*HN h6Ŷ+vN1:2Fc}z acr5X'@ =KO)uwC;Ba+gs\k]e6X?C9G\hM.fN&e)CC7WA FIt=ʝ衮 y EeJ&=V;"1嘲@o:'iTU mߠú4QUQiCj~B+C[VvߨC =33:4h֌W!&@ ~w`xȒWB^V?KIE2k{4}x6~2Ē hexIw/طUQߚ7Q×zoLP͛>sF5;46"ԕooў Marq# 8g$""N0Ӛ^lX^A_eOvTL7+P`.HKpcoN<8Q2&`<}p iX|+鮎5kNB.V)`vejI;LXɥ?JYDzEl #x/I8,Ut^WUr4qC y0QjMK٫K3 /od2aƉATO6]6x&^]Jd`l1aޱZwp=̽ +=lxq1,dH2rBqc\K w0($p.o_FҲxVKh2 eA u|3jT߬jX)9yQ~iL,Vx:AO cFfkI!35w"Ůev= [qV{`Uy5" &!n Båc7|Ȥv$AҠB1maR&_ޛg+PcqeJ-@F 0uU^#0; r`GtD<8Lᡀ+A )̹f%F-s41 K$SiC*Dm+^ދa\qs-Yba 4 R@e"ՈrRc=Ti 6w[uB ;E8 e0#VKCWz>2FramR&G!wtVr_9> tnd6].a rRގN#G3On{:C>A P>ϐό\% K^Z:əO!Ô>/(؎ɗ`R΄E\g>?WU&N W-e6xܨ*_&Ű9dG+Q&[gWݕQn3o:cd'΄gWEgm3A!4߼۶5z"[mCpѢ:$H1k٨5T]kr!t{ӯaݒXЊENF~5JdtQ ՑA^9˩jC?1(iRAM96tj>eI:n97E!뙔 _ `47 8n\黇d26xlY g,$i@Ϣ@Q:sSQ!8qlfEqSV;2&L)NeO^JKڎd|m2StA =K[fG݆%06DF­ìcDfӷhUe(u2POT ul!%*" }]Ѹ2Ԟ*ϴ=$,VzO; t|J&WW/j<5[Ip:c]!$CbjUx#G6 l8`jm7SQ>#DeG"i= >k ى ES}j0p(LjIh&g)iֳF@ّNN]g舉BTX($'7k6Lq?]sq_cueY !wr)zBAΰT|\8n 6b$597\tYl G%i5pOKRB+~p쐼aq.[:^Ł۩ 98o.{{,;132^8joՈ&MH'5QȽXbD$RRT2U|V1|JɦA}b6I"m;:Q AF`7T` Y"!~'qY9DH5)ŕ:)~$6YqA}}n_p0#YpXw^OQK$O߉ [=Qd_S]As%'ʢnQe2ӳ Њ!-z%Qh>ph0DY1}NHM.ց1)<'.Ao3VBa=ջhF1(%ȱ@- *Lm1ST0:XIpL]_pD txPCw[Icc2" V?iFQ.S lPB)Y/q#p!!5;f}[wO{GMRQa *Maso0{#; r:S;53ܤQ!zo/u>,$!49zMYs>SstM\ʃ۝+IVc,,dZ윁BDϟKGQ鴵A,l,A}.B+Yl|'_a9ę615o\q64*mԘ!X?P+ wjvjx ;P:$B%\W~Or!^:g2 *Wj-Եү-6F?,¡?>?5񬳨|W(b4)+Aګ3*>%-Qq%DpóF6֐V 5?pl7AB61fK&}l, gOXgB;lγFޡ'GءhV6Pȳ;qf|Gi|LZn+2`r>ϊs\xCR C4 o:'84$*NE}X b-(>3F~Kra`? ۯol;j"p7J?AҠ'`B8Sh&ynL9irv%(v [o߶Y=W}eh|VЁG~ Z%850CE %a"mV HAWd?kB`^%ܑy_O?OU˖b-35K$~Y$P#+ 2ś;^y6_4a{hUSsYcsYcsYcsYcsYcsYcs9ύjxMԄML i)֥3X^,~J6v Mߤ-9ԏ$ft m'K6ݖQ/4 &[uw0EO6j #'qAm 8MwD<"zgwJmUAk]jimf))L mmm;A}M#*t -"tFd<y 5Irj[as$e+NYGlωm fg(!LpY@T|p0+ J{fI&{IN7rC=_տ-xXDwک}*a#`sUK1Jt)IoO֥Sc"^ :4y_&BoR9!̼jߝt'1:^ E9+ټA80雭@Ә&tKǻFP+o)XX,-/'ɼfû$}0c2o[VS}x?4y]VVEȏ}1kC,=Yl3jk/Pg));-ƍȈ&Fڛ;&j3P]FT&ͺ7`roP)lO!{O_ۆ$gnCV+wL(C(y A@sbBL$f6♍8,5:*GGƎX^]zSd ABc@WB"|gFqPPqB7_o!]VyxP<̯K5` lsDsj m`<='.gT _"أB& z{fH)&lgIt٣V%sВФ3<'{ħ_Sr77JcA^ATo PNG܆LZi&" p HA~*SuKJVVpZl"bXhUb`LpmكT˽{U3G>>LnM 1y嬾 | MW_.YӆLtǮyT˭n{aA`7`^/E[pSO9 YWB5i<)BJ8on?W&bc瑓^$[6Cb8|QK̽d#(WEv:m2xHآlxqWK\)OCpX 8 nyT4JT/UHoO/Xb3v}g09DLdK&pĮЀ'0rAK]l 03 n/6 ߢbEjN]W5XE[ñ*EM~ClgHuTކqQܼ;n#Gj88Z2`kơ0f=34'ԩ6J;J4uĔl 71|s1-d|kS1Ƭdc6T{?FEMP, 9;:t1σ5s plY6*mmmZL5N8Cݿd,nI$I$I$I$Ŧ!M}h7c}n]y6m8 vB qlE?Som6(%i&X ٖoR $,NU uB*&v?TRg]nc+IIb0bI$emFq╂ڂ:5sޥkwHd=5u 9_wPsDW7MuXY!g(ŲX,j3#^=]8(=ժcN+ e)x08 BYTܶI-rݿ)G JUAȡRi#J/_6~P613̡{*p[ 50;;$(=Ď~#I+@N&1y<2Ve$P}t4țRq{4KxltG 5UZ M97\c@j5w ;tJR32 L@GQ|2NQYP70M豚'LY!!sP;meV#^՟%@˪n]w ҥnz^>hlgruR(4)^wRWv)_qՆS_>ү>xyE YR( 8$e3W+|kB\ufY}{=e3:gg(H0casb otuwfX  TPqy0[U10w"(qkl8 AX;lY__n`XJvK*Xo% Z/80\|,ZGڶTtw2E4x2DlZҹXw&wڀ #~}lP봷J~/v2= a*PuY\Ȼ?,\$&wMS6i3t $vH:+Nx b `1"@-&#ah0QɨiH  ^!M|C^FMd$["ˀtEŽȩ)U+R_CƂ;gr0E+:OOnS>NhY (FbCT >?#6"0}Pw+ Q",Oz&4qSV% VJcˋ̪-J :SeC.0P& Y@,|ʭ+zR#Kvo,̬"P$n_F; >9=t*)*),E|K [덊X׉3%o&,zYV&$Gl&F P'@213,&s'S:g| "^P"?^orz=S@F.d;#,G[6v5a>^" _D_VoEYCm&>8/+?w7D lw\h.WZ"^}3P"'caΘn}{QHy3 Q%k]q9e9L (pcD  ouW:WRWp~$;kYXx&/ ;ngQ:>ލ?2 >@ ;ZsF&]}_ܐRP6bH 3-Eg+d m"M&w8>4:w O _R7odi - \kb6؈Ժl"g$I/uoK5ƚ'&.ThU JA:l 1mu*ۅ(eB_@يj={JW_ ȷKG(?7H?$ǝ"8Ai46'p@0$ЖTx(A:H0\)п92H5'xH2X)J4! TThje [[.0Ib v9)ZARs0|gwe.Ulz`mi eo [9o1}>&6[wlchtbfQ[`B5HDvT-0Bⅲ[Zˀ'*JF G;҄FB'ͽQ{Cz}RikYRWy;Go~F?k>?iB?PPt(8d']]LOQ(IQ `GQ;A)c}wD`@w'#vMQ;%aSξP ;SDS%sŴVgIli=јL5hs%DF|͉$,s&LR1⨉[8%ɒa ^ $Z4Pt@],$%Y4bsh1 ]q-S-^Bw`0Cp,G3Jw0(`Vz`+h.im}MEBLnP(r/1޵Wk[cYTtUŏFJUTHuZ ⅲ\')9!1G:r !d!We@#LS-7El*E <~OϞڛkO<'΋ՓMv;_%`A3 H8̯16vC9 KH:BZ8\򾸯3dzT<sPL\2O*bҘϏA@ ™l~<&=Lļl {|DmL˛')\bAr3 )l+ei:i!A.h! 8N~vV_-%T9u(d˺|)ùAk;_TY踼:QпN\X!iu}H~5 z}\[jlxn>%s^[_Zbl,8a!#΂_KZf'젌i:I?*R[f O /ꯔ*HE\Y2"$}egjL )=o1D#W-NWKwc,](֔Q# wH̯.QGl>A _h엠P xLQk7_eKAkqZ_Hhyazmvf b\knl&W1.ts١C97GƋ RoP1{#L4q_~ ow)#^ ԕ`KO Rơ|Rc& (Pp)\6 שyC@6+.cGܯA0Pգҡ 5fry `!"L\gِS͸W{^&pp0p @ $ AF h?tߴ01t@b[4'Vߡe}a4LLˆ7rWTC_.0%tI$h=J*yO1i@>Wu;Bߌ TNa zA>Gzd `%a0β*pY$VYL(Ju9.%[D,uG& ^ĢLSlI$6@%%!f- єቮ7Gd'UJ>D8h$9c;SpBYۼ`@m܉4ic09x jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 @zո7̢{Cy)e<aH*0:dUlE59DͺCZ0XuBk:PƾSWj$w;9o._ Kc(_a"Ў[I_u㚣&,,[C+3TM(< 3z$veۄ: DgvGhڲ {.ˆrs{dl{1^8c@A/ez|Uiy wRX|tOwҔU}#VF6W=v4+3Fgjn"+Y̷H%aZC7 [ $v^\>q=+@$|+W2=fq.SmHܹ}N88r"??E~ GmC+j̳f)aN-Fpy8NSDSw VoJڹUrvº^1A (6`KdԪfh)dN$bR E^8Fef*Uսp9LY9x)Iq DXf~c~@֡"ItKI6EIZNs/[s!;45 d"u18(G(Y}d $V͏‡O## n&}%$az՗Z,usωϝc L0Q|'Y>.CC3DZ?%1#z HgmnEEt@IG.ZH/cEYvm IE}H lO)#Bvk>Ё+ POؕ⇩ڜA6t~e)̵Iż6Ie72Q sI|9S͒ l{9KMbƪE|->~mC굟S4 !OKwtYpp-D4ER 77t`Г*\oߡf$N% S^n"[0ɄKXCoߋ`1vA;%DzL/ hp~]*MN) 3O MHxyKy*m ?O@wÝ#]g/^9ݯBB9'ٞۡo.8d?g/ٽJK( ;%'^Q={2'EۃkF#X~ګvIKw?Y/vGb!lR2="_bo2Bꯢu>/_X a0iÒNOCϡ' Kmhsbu+R:f0앍Nⷣ}8#-8FBS~ʟKe%Hh;#QYFؚ:aZygGCdftZݳir>2'Ό Rr B W[gjT&`Z-pν*|HIR0"s+/"e XuGvVlJfc@ bv)Qm-|fUY ^Eϭ՝tIr4d'@75^e5IVɽm"fWop#7Ja'm xӯd)s:MTe5Xu֓2 b"_sw ,G (ı)8Fuh|{)Ru)ob%' 7&BLLfqIw4ocɍ{+W3>:Fju,-y֜2]BRRxGO&ZT&2,o/dqj ~?%HоwpCX q&]&)^&2|e7} s!K\/Cy; ^G,CW)"cRn.'ıg[Ӯ8hFq͋e3Ƚ UQy> $/զ}YAd6ܾ-j'o#0X tRS`n? D![P(xXm \fvW5awJ{@m@̿Ka*V)l{DnV~0Uc˭jVqJ87YC \bULB؅:IޥEpUUt9;O \} ٕ,a8ƨF:ZQiqhhԆ .HXq#Fڲ:ܮʷ}+rbƷ&0Qۂ1݊s$UGfK[PjJM+,Ɖ;%NT ڕ@+iz; Тk}x2*Eys"KkvM|v z{>DQcd?,R׿6=Ik&t$\T7{t5]ۊILIKD+nN ? _Gٚj~}5g# q7m!< (·. s8)M2)# Q1 3N B_o{!NuuEFfqjO"ޏL _K)Zxw}m8AI{-:yNmcoNoaf_M ubhccYIpKr"S zk1YmŽ**n<1Ww'^ <; %oZTחb9EEq{B9-8sC'1G4EL0<lzY{XØےI$ (oЮji@ل -\ ќ&v|k@sסsAc nI#L6OK#qoȆ]Z4y:QKΊE8ޒqYJCK_!`Q=ֿs $I, l?KQx~vň YKjȗnmeLvEQqS-4HiHgLܖ 쑙4ܗ03T=G, f`;ida\}Ķ#T(Dm3 =ӣ3߈"Ƞv\YTmqY1(`&&B7[[qR۫!ZO SbjGLm ˫S=ݺi#PPT:g> cc;X$F+1|KԷFkQFzwAɅ/R&, w#4H:X,o|YXlݔ M?n hy+M;.@6ߞQD"J۬uű'e3ܪ!ii܎y}tg*iJ،Oϻ/vX׽obۘ$[7N[>k3~}>|݄0, Wd&`Ϛ$kCv"{˺ߴkh_A  ab[05ߵbBjM:i]qj>IG~ BԊH\|>tPq~àrO >"%ƌRn`K y H=Ɇՙ翧i5 xbd&:ݱII|1$T$ARZo| %1_Ǫr0c a.֯jϓ#iV0-9A=[#"e y>=Yhz iz!C޽wQ@Ke{rsx=0+Vph3#:&?nu_|mED,`HD4cL+U B\NNQ`E9TN;5Gr]<9HΩ$A2Mpm\%F6?dSrRޠd? %hғ*4IlgV1cXe!2>4B$ԌwrhQW6͞ aSd V:$ b @.-@.)@Us #> R)-@T= YFG+P0aC$[5N_ĭuR=HI-|?QrCRI$I$m5dAj$c[d· B"mk6w`oe\,Y 9V7;CA|`:X"]<*;>FHקgvq+X.v?>2O/{čYș+4e]DZkػٖoXGLny+' mKyڮd9sTn,_PM.G_8 E vF徙3ä+lZ=jb?qnU;g yJq8V>տ3'vpMa⠞4$4/UJliݢ ;6 %{!'<|df7ͶSEz01._ aˈTc~wӈA3QA8߸+<>܌;W+҉&`[# F^.{-"7hBlȇN0+6cOxD$9=5{stѾuF`s$jOPCH]^g"ezЄԁ-F42xW6|l$tWS]H3 !y|'yw1gp-GS:?4R@ i8kEmӣ:TOZM exؓ=G5`ܧa}~hx]uBsXΕث7Yp}_'I '?GppSTXqj|Ӱ*+ᗺ?KM"bV#쒷̎u5F*pf>ubDE3qe\Z;KH5] ݘmT'ƌ:ipG=偗7u% 21$wQ :K67"גkWHu7.as]oTNP>O~y ( )_2$<=ee<}-59..J1;vVSUWE-@nߔ)fRP!g&Z\reL:{/Ꮰa#>۠B9S]7T}HMP(Qlh>Dl֐9.3-Nm)ާ܀"b!5" d3be^AgLUXL&>PO]F#OG"/Tc pxkSs$5nPijPg!^H-sgًJjݙ/R5}Nv8ZPhroKe9g1W,=|a[7WЅbҔG"&$bEwZm!wǒ@QN{W|H/=.Zi?+d^7 Ugk,'\~ ;Iq l٩RWT|/W͏ԑc#YQV}̾,gQ4p(_ ,~OGfSYSE-S}ӆȊw=z J fTm0$*@ V6{SfMD~&&J,7Qg%ՍLFV@ߥg Sܧcj}`xdEZ~D`FvĽ pJF-w3tft3'|eYc@ .RzáT%&pw(P~*1]s܂u)X w*y}*:^ d&&('fX3hhMD84qXxX![|[ fx^O >}kÔi$9)Xg6CĨv~J{y.!rQC:n]T]P]wZ)`j)tJN /uqŰvv*_TO%9sG*GZЦ7Ũl=0,_'*Њ{aȢt 32fǵ@W94n#Mzې^y%Vh `w]ealU(&2opc "Vus--1,y~eS[yo+Fq'6l(.h~>3F~?)`Bom:lQRo7h[?[MZY|7O̐3!ū'=rcoo])d#X/v0|1K:48>"z:ʑdԴ*7f|yטZxM@[< P娘cе{uA맹9}!=}Ru\ #=mR [{ /|> E9OD`,e:G]v@%  <Ӑ}Y0.z( 拡)6ۦLBh`+aB}Chv0FNj' %2ukd$1JTܿy+oK_ 揝MdP28cK$nwjĈSni M5Z2ɯng%@#MT @by6mm+;9y -A}6s慨۲LmW6KrXa ळ6YE:kTES0p̔-ꠣsitHVe/eަ~Z Hj`}}EQ kSl gv5?i/tﵴWH\Z`p۞bScN?nvBH6ZvNGb@eZeZeZX%{ cGApK? ۯox-al6 al6kKBu.˽LaڪybSNd!b*18yc(XTdĨLK p8Kh75k *`nx փ$Űf*HSq' 9)nfi~mRjkK۰hP05ƛfga/ү#yYqT UPyEXVi m~Y`ˬY b{L0I#Ӯ7i6H\Wt)ӫݔM *9*OGC!|7]HT̚L)b/Bu3OkZb_U@ht'- paO;)<`T6}&楥Ʃog`xDt"2L8NRUVH_Kf&3 24V*^؁OKv5ܫ tٶ|:ұ统}[)PJnc\`8{"]7a}Լt`rU(o=R;%F1J2S F&sYukkG3&3 يTD53XZM45nE&NUz*x@9-kjz`-.(ùȁ /s΃Du? 9RsߐO$6¯$'8Xx.eVAi'ô]!G042}/ʃDIH57 $dzӠg}MGi*, Pbҍ|dn4E&,̤a;$)VxSL#kUJ6m>U+Z> a=̂>|pB~ \+xVR}"FAH6djmd%>F)%5keԝbXEϑFvD$6ci=,G]?Ӓё+K6]<]z|T%ZǴEMa:~R/L#+8IE435btQB$"IkΰùN<9#dĸUI\_ "R(T4 ?Ec8f2}ljlYv5%8:AQG4:{aY҇9 J-G2SBOlkJYzvNvͮ|͚VI1xa۳Yw%1E7?0 غ>LE]d>0%J- ?`ZU$pK#[>]Gb3N#HiJX<樼}yMrYaՍĨK].]E&E+$+xvԱ!E1ShyݡBa=hɗ;ˬ=nN@`?$%Leօ!p8]}>?q =ϨM5-7xR)kFv0 p HIKgsi }nj9H ƃR 2>ؔ\<M#z ;D+!~80C@A\i^v0y#0-2b1!RdXH#taǛ\'* ?TVjtBS$P>/T^8j#[([p*R#Fd{gA#?4 >KJ <|i*(j{ɟhAcwu6bW[^B6̮$`GaFΥw`~т=bvմ<0N/,ӀSD,7+3c nc.uHonx`/?wL7kdEN}RC0eEkO.&¢Kk%ł]ʆMi֤oz~*uDOqMRxsn8*gpQ$xFLMTc2pmj ]&nozO|~72ȟK{IqgТ?) !B>՗% iJI 2 6F Bπ5es̼{ڻ0ְ$ȳgF'PTIgx.W7l>'B،][Kɥ%QԢ´Us? H'NWgO?WpC":$ڻ_ꞚȂc {;·;2rfݽTTB ZgV*Zdx!N@w2jS˙FBȫXKm'h×t3^|w0ܨmpr NG,)nK$f&<>:* ` x j5J7Hh|Z?—0粅H7co56 !ΔoIYU+1sWK`kJ7Z^"H*{AԒ1h^ {φM9`d~]zZ2w :4խv 1|-u`ds4D/ DKuyߘ̐%O G<ɤDo;_~/U~7~ToPNcOl&֒yeV|wyNiG΅Z2#3;8Fn0}K:%!i ( ~eqB@_bH]Op;>r_a.Ң̱ދԩꅽlks_af|ʐBZQdĮk }?uhkBZ@+WjY'#a :{r.3`ONarY-rl6(ZQʅ6ߩ|]ȝ0F982إY>Y›[9hox1{f8䶕r=|N.Թ2 (Ƒz5U^B_`%UM3Yj3unVC:c/j-׭p{ Q-\Qo#z\$pQ&N5r">$X"um.մV0q"J>[pZ F.+lZ~Qs3'90]w3KBLI)# OuW".U Qnwp+n=^Dmb*y͠菧pa7O 0*2u Q+㈌^wH@p%*6 :n5>Jdr"3S9®qۋ'a3?~%1j\ϨXs-MlgV(M4\[ָim0摒`Wpe)<ƌo笷@( =5"A7HU 3\1rE*5/Iȹ'%P2ߒI*OZsJKy-h݅;@)=E@/EᄄSz]urH鿮s+a;cB W-'`.¨ǎH@Y *EybY6Ȥ*0\!6B01Q&p"e;t $@$\V pݪB$.%w $i 'fe3peDK[1w8U-<a꒗㻔>HI'2vΊdF(yBCݕ#t9ְ%M4{!l[S6Ƞ6Wj+0aФ `la$-yT(`е 寒p=xA58}=>Y0\Q`com`R00|gAud.Ulz`mZO,8w8-$EhhԛdA%!TO;'$CHd2l{oȡֵp=*7ⅲ\')9!1G:r1X¡08T'.d#.hc?gohCiVQ=MUCMK 2( TR-\݄=_ػ뾘I ΪMUO؉.VRz딧K AT3mF?m}M~5Mߨ*nғl.tX5M7(ͽHM|_QbX]7׏Feۯ7јt*@Ba@^ #ئNŞ԰_r!_#O'=@.T YmGX!6x3 %:ݡ h""S$N'7_.-8R'P]oք:_Ġ5a Isj2^eQ8>Sj:-2v <My䤐6=.:鯥ٓ?{ $)f3$F9M.Oe"l7CPoEk$IҺy# fK(_K0Za}QX,U VLD<]r&+ t|1VPqiNTG!{woRhԖw~@D$g6+nLx (ʜ>g̤ >k|UmxdZ%eԓ3$5(?_D^}FIu!$aT(ă#񂵫:RtZ S.t/]ylTŃ+xЏ+5?9qmC45K A'ke@/1YD“[iu}b7vA)arn0wxOsόMtVղnDڝL|HP~ =VDmFHþ| #_I&B*209(_5vZoԋ/{c6\>qZMmM5uW \D{J#YQ6Է,Ntuq%g :9YNt$/pN L@$BmB y3ԏ&7SSp@7# 3NF/` t*{[+#X;%UOL^ߞS1Z# N"y(CyLM)GPٙy>Ih<\`Q;sşZI rDAuH4]^۴K!Trk,ޞ/װ$;\v>Z쏜~Y*@6<|O /Є4rKhZG|E6GV9Kt*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/UwxYnx*/ +wIf3.$$ipu*inrw ՠcۇȠ7'DL324D\!:% @9_^*w74wN\޻rG5Lov[ˊZ#t291[dB"a ヾ@7;\jX].l$㣒 M7?Y0In~HV+Il0j5d3h*3P51\\ZwjCUl?K|1*rc=>?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 NrWKLh 1d\ Tm3Jz0Y1zUr"MUBJ=!+רx!ETрR]/s޼ Eo'}m+яf* vO4}Sr. R? %ëᦰ7}o5 }C7-Ioi8w6sC9tUsxS1Bէ uE f˕ID_*OCzyXB"'_sF9܆W ';$ĆPI&1^S_yd wHHf}fDEuK7P޳][TsӮ b$\VсŨW qU?Cmy,I*434uɳ!-PWqh2ֶsY9a<3h%r蠺[2kb>eEUF@H k2p 1]]FC 7.$rwGf WJ.wkNV1V:>XW 1S#F3Zݮ+Xysz_X_Y3֋'_kI=;)Ph>ZRڥyvI|6n nID .WcNPfTP-Akѝ㤂.')?Ou'+sۏKք\f% p[?˧ںW/HV=iA4Wέ[+l2,i@ȣl垂OpMcfgHY3W 4²`w襗¨׊ܵWP֥td@dieUuL`棫xBh31OSz( ,806rw5fz oțؗRs U` 8vMa|^[ELb3wf-ﺇ5 fyQ)"c7 {ǵQ[\ (Y0+;?=T(ak}iK:RQkb$/)JsĎQ൮ ne-jIeů31)!]6jG7`AuV][Kium.մV][R:EQ,@h=uV][KixCpt&^8V{x^dF)yK^RqvH^q=%1n4'aw<qVV1LדB\^b<2%XQaUmoaV׷cuOȤ ؍Pom&+Mq _-{=\ y'ڭ43Lj"T\j O¹_Ի;4p4Lu'oH"+/&{+ݧy妧VH9Ϣi g A0'~r$#xBuro1qI0N_ҿ97ҏS'5NGng1_G]S6NOJ:XBRGڿa@P% @gu##RYJ`2auV][Kium.մCy:j'_;Q_aԚ~qNRFO/)yK^R򗔼伶KOPݏY6 h;"aF=>Im*4m`omf=V}Uoߟy>y(뱥4׎dYљ0FT ͐fF0cu-KS v~)JQޞ?3Ik$rn.yseR9ÛjS*YamXdtuY #Y)f=?4>' U ԚD$3UKA-3o Ug8o>5a5a]~_ώ1\ͰF]G7#"N'[ium.մV][KiB^kqR򗔼/)yK^R~}L(PmȐ͇][Kium.e딽]eyzԬkK,Q]iJ|bEi_{F-[цۥ9 ^?ǜh]E:WEgʹ¹Xf\qV%]}C8yf17,V,$tl(%mn`ЇyZȟ53atصR ݽpuZr/vceVAZav J6h[-?::%#cu]z6cE_WrsWr]e% Èn79])am=Ë1aAPYqcQfY:ͭB 1xEz})[,%*pPZ9kV m󽰭_u|7݇00o'ku| 6].AE#BnE|cwo.WGO0]q2VﲃB&ka!h8G6R N=.,/|<U)@Hf$ko+kqkd5اWpS$3gA5Nttun:[f|/*a@-*6$7j;Qބ<S""%ZKAuvueZ$%Z%aWW쐗.Uy]E&6ɥSXO)Z(=1JQ'}"ӀZL[ҳҗ8IDc~ߙ]5eSH~8(Kkş)9l8c3BwSkGFN1x&1ʃUI~~2VNk"WqSA8JYu7zmA)7gFL])˶/ejmW^ xG ㎌G9=C'RHJ媰"‚9:_wd͹PpHoNNY{AξK:f@軾Dz9& XolOZ-DFRzU)y ʮl!, ýo,}fz}H@hV?ʘ9*6zq$*֛۾mIW 1Â]?pK),zћ2.7?^4megk@v FwXI[1 ,&KI[篧`ȿ[8-![_ggaraUUnC7?^wTS1]Qsp`^ڎLEbɕ`cO,1Ej`@qGruTiè$Xh/eѼv=rW9N_eFG^;HumZlQiwݢ:"'^7߫n;NEHs𝔷f'{{R  p=Ȑd׻E^|9*^Dp^$V7T%`N~jϹ[L:xGPOˢr~o4{Cd%~zb GO*Y.+kCsk/JNXDOOw* }IE`~qΩT]_oăk؞ F<OݼZmL 6>XHEM*z4lzO\y';W$` bf؁lktD<׻IY64 eS,L'&@YR>cٗ\ťcJ0̪oGG^p!~ɳ1AT.Cn0[P^L^Q5/ЗxlQh쾂Sh=JH8א oFfV܅+Bw<]BJ0 k9 Mt ¤VEkP@'Ѻj+C %SW[$p)>+./-MfI2R0 md7h}du]_I čxK8G^GҿL71bP.[b%8u!g:׊I;C{0 LL">>'ńTpbkT؄N!a0a!%:1{J!"YHKUp0a!@a!/ #S B^j $%Ӳ4 $#0a!/ B^Z/urأyH{d$%zHG`B^: D #^Kl 0З0P4t  0~`yS% x$0  HKG@0.Q9riW0!# b7[x8KC-J jIO Yb:X;1W.^հH$iP0Otx1h&BA ŸcCdp;O! Z dxܶ~,6}qWʡ/p/tGf0]i! ~vsgTcO׳Y0.@6Ez C`?ҩr ѷ=n郥La ,%JgOO9%<ˑK&7ld&2^0U)=?0x>*-$y˕ܗ p-Z)b mȐP9V"|t﬊P8֍-5i3T#pf daۏ1eT% /<&;muz֭FiÊ&PH3" 9Zax+⸥jBnHN YSjB9a.#D Uڍ_-پJ洒k5֎eKI s GXfe ɱOKf?tW ;v2c憴Ovg3kmB|}b$T}2_X̓rͰj9nZ},T7XԪ- VuAr0hg-6EaF[ke(iL-@G:V:^vZ7Ze_1mS6tVYD~l LÜn lK6'$425Hy8J uyiw9}8#]^qWGG絒=EHJIsdZ SJO''~e:KTpYmiS$qo.;;CCIf?<6nt迚A1cr!o0]N)Z&=Q1<_7ny%0u%`O@MclO^3{Qdg$d`5Q?$hE|2UQmxL;Jp:̢ |maL \ !CƓ1P;KLѠTcjaXxxETփU'<|zxXtՑՌ(&D$T~wY 4mWt9uPyE3JxӁ " j[S쁈)4:h@0 P\![6[صhWK &)/~rpCj`AI`Kɘc+~ ;6(-6dl'={O+B\3lP"lj6 k| R3EsyeȪ>ՄZR_J־VYkQ8Ls= ]b lr{Mw=|] 'z3u OA[K4aT7ĨK x]AC\ufmdU_y~oUq6H{ z sZ*Woc⚨@ewIyV/҉XHvW^z qnü@ǃ R*듙T Xײ$-3Ah K{s4 Ϣۮi Uh6B 7z:Ϋs%FK%0p𝂝z+xp/Ք\le}ɔJ:;a;g 4#`t _ ٘u#Hk],îvg.(gG~Kvjg*]-K"l\8HAFylh=*2PHEmQV{ԞP _hg=~_^Aֻ~PW/ Ϝ[B5PW^hUP/g`q4ˤVusR/,N{Bơw{( RAY6:C8=bJ`yuQ]Aav 5l'ZQӼUrZ<_~,@jB0a!/Sbe!$^.#>&j& .p4J.Ñh{ 2+Y;a11!F-\M^4!$Pm^Zɺ{+Kϗ>#V&6 ŏ2@mӱ!Lv:T|Gq(m))NmWH* ʕ$`l3أyWDm=\իաᜪy|5%:8$Đ0~k}0;U3rWLtX<]vϯ1E9E@(>hnj/|nF}p@ ,vv@lJcWZ e#/j}i_tp}N2A 3{FAgړpUٷ~DUZ M&P#kocl=Gda9SEҧ~R=D" 6ũ1(%D&ӔFK[ew?p1NGne-l8kᵣfͯꄂH9t\spb 0r,x_ An 1{P8'l/VP*߇.H n+T]04xrR>@ !iHŸ90 l#oa|9X?3+ $%7vs$%CHJ|Y0? a!$080 3-dB_Y $%O@a!.f|HHa!# a!c #y$% P54WmK QJ><0jo }/Tz#9 \Ą.n]sgvbc(k1 S/j`AIn sϠ =CuH܃9TFy؃8<|Fa3p?R Z~oF݀8p8u<PK~,#q̛ԯgRL!VM7SnO=RiU/7$C^+xζk,z+xp/хi={ŔJ:mtB y'gVH``G|iTtYYV0P 6JƂʲYђU` [Pj>q՜rۏe9 %9/cϜz|wg#OϜZ_=c_ k!)@|?P`p Ù@gMnkݑs*SuH K L`q4ˤVQaUmoa P靖3kh9s4FUQ)/ȏ b CÑ(w;(}p/>(o 0 LMXe/]58qf4B~z,Da!$KMxGb!-@ =.aA̮K-Fő!,Jo@.VVaT(J:#I[VQaUͷIĦ/;e_`Cmv}h?%ʈų_ڍ 7=#ᨸ4(*5yZȟD>\`^g$#G6;=sZ<_~ՑP a!+<9 $I7U0^؝N0c` dZ a10w q?2{b^hڦF[4eDV[viN}GP=֭RA*cRjO_@o טHC‰E|]o^ }0M00XbP+G<,7& (qF0L42JFyUXI8 +=`l3أ<4tNMEfӇ` 6J?T&+. t_w-TR{B@_]us]b ^F A7*9i,޾!DHBN G1Ne obʋ\]'݆cZac(k1 /~^/Cj`AI`hDhεXC)Rb&px<0 5լSŧͽ>=RiU/7$C^+xΫ+,z+xp/:O_{ŔJ:;`4/O`_fFVjkt>^3 x+﩮Po48T47 MNߨ}E_e}IRON/ԚŸ]_>@~g &RMu ׁQB;=ˏaMU*NS^iɋ%7/XfC`UTܥy/D܋,$=f?,(E5s4-e!#>$#iefF0`iޕ02Xic /6˞F SZsrO9u!U.WU&31?w"0pF~ovb0rFޢ7C`޼dVv(7<>B;_1A¢e{z^'ZM^hJ>aXPme5RK&,i-;+/('qq+Q#YYl!M+ۚ[LSjkYGƅsxcٯDВOgBJN Ja5~{y\z(  ݧjp`0*]ek.T1)+{4?~$(Mlmw/P#[ |/hlNI$DL_)qh=i| XqͺL܆z{uAhyDpG}G|p5K4$ZN'ȸOadz5Wq3 p6CIJ;Y^85Ԡu2]+V 1;Jp}Er͛):ԍgeY,']cgό<{+)r~H\VQ6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%M BAbߍV۠#7|T =*IUʙyT3toxoadGlPWqhxꥃ)exre=D,5[ |&bũɩoѰNHo&J|Hv湟&FЬ{6 ?KѐC zgT+uT7j) i>dA6Bz :lmžWvoh ^ia!{ 3Lޓ=5ef`¦> KfGQ Lv.% e;CVD.~#DCo4Ƌe QnQWa:XJiC+>#'e >?Z:0i-Yg8-Ehxx/v ;Yop.K]goLǴ{ DhlLbT8a+^o4uD/M<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@ ͶA дDӷA ָuxA ƨm  '' -,, //.. / 0 0 00 11 11 1!2!22!22!33!33!33!!!!")?3˃Dà;¼> ͶADӷA ָuxA ƨvm  Ě ݰ        !!!!!!!!!!")?3˃Dà;¼> ͶADӷA ָuxA ƨZm  vv ㆅ  삎      !!!!!!!!!!"l8mk(_ccccccccccco`oItXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmoj3yy4it32'ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ źʿ^ ƺʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽD/"¸ǿ! ##$@&''Ȁ() Ӂ*+  ܆, Á -. Ɂ .// ́/ Ё/Ձ0ہ0ށ000000001111111111111111111111111222222222222222222222222222222222222223333333333333333333333333333333ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ʿ^ʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽ/¸ ǿ @Ȅ ŞӅ Τ ܆ ԩÁ ܮɁ ರ́ 嶳Ё鸶Ձ뺹ہށ€ÁÁāāāāāŁŁƁƁƁƁƁƁƁƁǁǁǁȁȁȁɁɁɁɁɁɁɁʁʁʁʁʁʁʁʁʁʁˁˁˁˁˁˁˁ˅˅ˁˁˁˁˁˁ˅˅́́́́́́́ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ʿ^ʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"ĹO]"ǽUUD/"¸[[\$ǿccddjjk@qrssttxyyz Ӂ  ܀ Á ト Ɂ 膋 ́뀌 Ё튎Ձہށ񎑄񏑄񐑄򑑄򒑄򓑄򔑄󕒄󖒄󗒄t8mk@#056777777777777777777777777777777777777777777777777640'  !ӆ> /= 9_Bq#Ja&M`(O_(O`(O^(O_(O`(O_(O`(O`(O`(N_(N`(N_(Ma(M`(M_(M^(L^(L^(L\(L\(L[(LZ(KZ(KA(K+(J! (JC(J#(I1(I< (IC(IH"(IK$(IM&(IM&(HM'(HM'(HM'(HM'(GM'(GM((GM((GM((GL((GL((GL((GL((GL((GL((GL((FL((FL((FL((FK((FK((FK((FK((FJ((FJ((FJ((FJ((FJ((FJ((FI((FI((FI((FI((FI((FI((FI((EI((EI((EI((EH((EH((EH((EH((EH((EH((EH((EG((EG((DG((DG((DG((DG((DG((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((CF((CF((CF((CF((CF((CE((CE((CE((CE((CE((CE((CE(&AC&#<=#3Mapz{qbN4 (X!D8U+Z3ؙ

׺ y_{oؔs{/uA?8]1ViC2ۜ%] ~|W:(`w˒. Ƣt~LH}hsH:k'{'tHQp6`NF 62RLݶM!Xl= ,t_N-c;r Ǐ¼M+obnWr+͡ E=$L)1Ab(]UE.ti+)Crhʈ`bfsl/8kĿBA3^.Ѝ~)|1g*f`cgBJUBְca,D0$sۈ{q .)"4оV-P_31ER#Ǫ_rT,RGRp+[,u: _G[Vvp`6aa_o dC'n@RͩM<[kWVи/ ]UHaAx!wLֱz?xs1lvâ]εHZ"!1DF=AiJe\9qUL3bMUYLd6TVLM[F"q9YuoNG K7[UQ$_e 癙z(YdTrۣ6cC*I$G[F"H}|?5K,b: 03m:Sx4cjr1Fv s!'=+.Ṕ(Xc5Jg:U9 6+Ga"ȏlnvdV((Kw`jJb6#1Q"7&!_Y|^Kzp'V;6[im |H rQ-Y&A\Y.p?䐈5,Doؽ%[xa5/mR(杷qY"/^pjo&?57.dUq7'0"*4!$绬 Pߘ04t*כI4(Y,)ٵ8-/h .n@~0/#(KG>S]"_t2{tGt;r5G` q&]ӔfBoe X29=!)׵V(2ԓ4>Fu2"cRn.'ı`$G\qJFkXZ- 4v9`{j#jt'&h|RDd;^R%- #N{@AA1 K,С;u808N?u UwUC`beUc/|MBZR矽yT "vJE: #@!)zIo\ެ% Y:̫mGVHwh4<|YS-tGOe뛯E}6ق_^',; ^&m.^<x _7fBGl@bbv6P͗6TB۴OwK01t#g.g?6Y`ɸ5.-rT$9]0;PRxoNv%H)f2b~0|J~~fԶJ)= ¹} O-SRh& xv@GD>:BI0F,^qHRI`RS3̻BÚ/~c4t%^48OzNy܈α"/Lo') #/1~MZ@ϫbПs#s4]v~էt95Tc652`d` :?Eqn/ڳJ{1z, Ջ[cFI G4dn9T*I8LRҰH ,|j"#HaXBni:]&.{L!d8%2SUыvaN5Hbf0N״8lO`Gp-*)1# E¾+ BC#2! -NV+d TnQcD3jbn |m>=)T/@"{_*QsK ˺ `L A%VRX(:Л4$'ila”7PCuNo B_N,0K@g1Ǝ.5.bMg+5Zbk޹ )iP ̔h@fJUt,?n @m$IT G^*H{JR{I$I%tw`oe\,ݡU'egQed%>+򴂆^WS{%nl~XKcSviOp_%*͇Y2]9"J)mu՗kdnSH5K(J`lTI!݄?G]#)XrRza&TP_m5틚Cl*iR{>g?skWH2!4+(a<1(\~PA.M23e7׿V)]>)G v '[>DgVYD|[0(,%(藑/^-&NO Q/qm 0L 7WL7l6.[:k6KO\/J)\kԷ6Ps;U6oѲU*i& Q\/RJ >r涩 hm"}T~9<&tPt☟,#Lrt&8 $27@ʧ(v_2Xx{ݘ'!P4Do%;$.ΉJaۥ5a*S|7)b-5VȆeH.1&W'cGt–xPqFuW ƪ`tNo}YMh%wC@-h(% -u:}ٺ sW44*x;[CSO;ätڕ2%N<`B_[,EF۳|#P/uۓq3T|SV +nuZBkAm [tKf(*ܨ?!JR`-^NV ig%D$Ӳ kw-2_N_[(/JI)u2jsk&RU[Y)t4nݱ8z <2* [uHe_67~|c%zw2 -tKdW.;46"ԕgݳ)ͭLBTRp\ȲCln1$ԭYX6͒Id/t?E}lIY| >1;ʎb[!踪Ku4sw5原}tӸcؿ)P_z~x@-j'K},oKIEي$v;+x!Gzj*;tR *GY6X՛0U^#0;s'vJg)ۊүNx A )̹f%AΪs^|`ł) Sַ/ê(| b<>xF0h4 uG+ #D 2|: W#B]yFK.cZoo;&х&UXSW J(0*U a?]sGZc T'%GԗlMR2j\ CϜ(Br~y<΋\/%щ@cv->FkC߻!wf5Oڈ)kZy * &+BxI)b%Wzh'.G5 ;%z𡏿k =Q`#K PMr'OEoV* ]sŪ F.D9#|DݰI'Џh$UKy8 %&F|tZBrqiه MOu+2m7SQ="XG8^h_QOnl l?b R ,,p|UeYuc|H`M'ZxW$BBDDxU}2K]Jjhh0DY1}NH(ahRApj"tK;EnL|W։֒~p>l l}Q.s e_ ^,7O ]!9ЧZ@ᰧvLT:72l^: EBͯxCZ [,"ńV|[y{s D^{4܆Нj)D^t3`->$ik^dK';fD@zRaZ98@U'~$~TyLY8D le 8[A:^z(+IVc,,eX8yگԭ@ 4bH,|_T:@WʌD-tkz1L-:d$^LsYs'mB!(*??=aMjYc璁t"}ãl\pEMهMb!,mN^J:=Xl5rcf^{uR]$lF$nOgΚy8J2D~> bjk6q >e7 >ýLUPxE|6,~>cϱ, V T[Z. 0,$ 5?pl78o#۰޿I=Q+k2K2{kW>FO*`2a!Vp>з;(<`w8%H b_.Gjٶ (}zG 9$=irX@b/7>ټl^;7NHh&xJNSї򓐝&7!ɄgM RNj/i3}Fs\-(>3F~Kra`? ۯol;j"p7J?AҠ'`B8Sh&ynL9irv%(v [o߶Y=W}eh|VЁG~ Z%850CE %a"mV HAWd?kB`^%ܑy_O?OU˖b-35K$~Y$P#+ 2ś;^y6_4a{hUSsYcsYcsYcsYcsYcsYcs9ύjxMԄML i)֥3X^,~J6v Mߤ-9ԏ$ft m'K6ݖQ/4 &[uw0EO6j #'qAm 8MwD<"zgwJmUAk]jimf))L mmm;A}M#*t -"tFd<y 5Irj[as$e+NYGlωm fg(!LpY@T|p0+ J{fI&{IN7rC=oߏ-/gO8 æ]*a#`sUK1Jt)IoO:7%xj1SAP NrC_# Y[󮘞t'1^]e`@CN͘%B{%܆ӵ! faL&ZE-Vmb{5$qUU|| `V8!Qw,P`yr(UXݦ3D6S-\Q5ҔevL nFڟoO/Xb3v}g09DLdK&pĮЀ'0rAK]l |Ab P?hˬCk'e7'Nᖻؕ_7GqS&O^P" #f\y>^}ե4;Zs%0΂  ɵaf:ӈS'SzQDcs)?gG8Vu/K &?R*o+M3q%<(~r  ޕZCr9&qͲ.OQST "rNΏ_`{i`ɋ7~}\L>t1if~А`L pqrI4+ꪪ$|]=ncd㢦$I$I$I$I$x.bCXni}1lDf-3ryߺz6,!*tǙ(%a]Ʊ7k E(( &Mp#MP_\|!`8c ww>! e ܊ |bo-Xjp*PF̀K+"0.l'JX.XYW+Jȹ`|k#Osd\hg-t;$fX{6m#|Pa8HGga;=mWjcBҽfCv4 ރ+7DjO,;e"fAri 2aaQth)TلB1CmVH0bg-mC+K~WuT`ǀqUE4,U{%YA-c6!%OK0!<뉻f(* #ockU=%7 )lHkw"蔥igOzeA=6MݛHaӓ;–~H=ԩ{^zf7%FiP⯡y^ЅDaD_ CC/eI}777& eUc07Bك8ʩƫR%Ҥa㖘Qz "0ED9~E(pTC#[8F|'8OSʘ҃H+᚜JW'-M^Au-8&̲Qn朎tQxm/J5Aӟ>$0R, ֊!R[F%Rۀڄ@9Fp ..Zm1uIB G,%]sT2L1/038|j8BhMfQȷs2l׋Vw0A2lh_9Ц'ODL|9E< $kVn)E)KC IP"~8^"}-,$0nCm_l"KmΩ [r{ ?\ MMkMW3 Z0^ǡRW~mc{Iqzc_Ylw.$0s6N` -%)#!Pl:%2sZȜvo-Ij̮xvnwP0Jk}WXL=RQ~z[nKCe'P3ڍ \CxՕUڌSIv/H  tҋrF՗㏧-#NHċ5 |BhzZtJ!q-ۗ lݤ#+PNDl'Ի{ǕCvK#'#:wHVvɤuC$Fy--wCmE:K,bO_`DwCF&Pzh0+ՉՋ;@ܭ&Vg9N!Ȥ/fߋqв@tQN`{֛zϏVg %qNJN6665Ǧxߧ0W,|P P`36CdNz- }eN{z^N 2 LRBJ@<$]jTZ(jMq; bEVy*N/ C{H/vZa5y+@Ua| iO@{a;*X[zr6R#8KziIɏ\4d-T0/m ҫ s܌5EneK=Ѥuܕ#| o*&?!&N3W?}#tK^FXg eVtg\_@(;/¸1ȺKЇG:bdyUb{@R4]Smm:XTU4G@OWgIaH·B${/9ؿoWy+) |L-Jz=F_ie}O2t2ɸ Uz(`+􃔧UlSi {?)Go6dr=^ 1x&eV {|7·WJ1Α {HxHeR9ymrV%"XPU."ʛFgA;E3upoH7Ӊ(TRT#HU8BP]Wյ-c}:[|9qOzn{3@%e=mp37Gľ3yQwCN,(뜲 jtveOgUZ4c (z~{a7R(اQ6 os|9! rǃgXd $!pXa1Zv_|ґ Ժ,rԞw sy02Ņ;ȫ},V_E]gZ6 .͏YI+{g6snzb8RMC%hU Jbs$vOpi o1Oqsp#Sdp S$}2ۀ&"=_`9;JZ`6߉Vp=_l? Ѹ $%8%-?Ze^VG~T G9wx~$ wa5~p& T  ,G<יߩ^Va &ĸ(qHr{Ӹ&2'D n> ( $ȷKI/P)~Qs`NZhV sJC'XK:RP\#iF ф Oև4J %<   ]'={{  ]iQJBhl2c|[PH$ƯK=23L G!p"rtWT3̦QXӎ|C;|I6m^Pgje5D)׬q(7?kLxlOHLpP:cK._`'<= ?7Xk}38ʀN6665Ǧxߧ0W,|\BA.m.ptMMOX&?}@S@\rEh+0Q(JGrMK:U\lF.YaI,rVA#؎䗌3i8EP? %14 `M_HZ(B8;~"|?o`BN_(8޾u0)ou(IQ `GQ * 9A9 3::С9 :薋A"SԂ앹}'GiW-W a*_iC=~ݳ_Q\V6[t½*DU>]`(@ *5ȍ' 9O~F_'$lH~eXW[ϨQW9OIZ,[Un8t[EXr;'T[|h j‡:.ssw jvzta|#/Q(麪f LJ,̂M,vĞpVapDQS1?{2i [V;W}))>SDSJҟ*WoYM')6D.pV`M:O8@pRf37p%DykX@9Q()m⨉[85] $ b} $9"NH-r0Ebsh1 ]qIBo"kE:#EolSy1#OiQ5!u|s:.uUXBNNJD_` {m0H_)%G`rium^@ΪrjyAoHljcDb+rSeD\+1K_W' *ok !<J}X|?Զ6.ZP~d*փ X?^EDQ($u[O'cq22 ;;]@Ɨ$3 $uLNCedZRsݣ88ÑN Z?aI36.@ :n/r WiknP$XdNmĉc ^4:p{xK i:ԇ&gfH'dz|Yj8FCTlBDeCsMi\ʖE'[+j*y:Λ9©4F𐀶AV]d\8ʄPCgrP1: y plkoe\oE1֣8ʀN6665Ǧxߧ0W,|P &܈gyV8UA&?0K \;9d*M+%=2 o9#ִ֜ԨE.Yq$pZoR` w53a a(>c~OϞڛkO<'΋ՓMv;_%`A3 H8̯16vC9 KH:BZ8\򾸯3dzT<sPL\2O*bҘϏA@ ™l~<&=Lļl {|DmL˛')\bAr3 )l+ei:i!A.h! 8N~vV_-%T9u(d˺|)ùAk;_TY踼:QпN\X!iu}H~5 z}\[jlxn>%s^[_Zbl,8a!#΂_KZf'젌i:I?*R[f O /ꯔ*HE\Y2"$}egjL )=o1D#W-NWKwc,](֔Q# wH̯.QGl>A _h엠P xLQk7_eKAkqZ_Hhyazmvf b\knl&W1.ts١C97GƋ RoP1{#L4q_~ ow)#^ ԕ`KO Rơ|Rc& (Pp)\6 שyC@6+.cGܯA0Pգҡ 5fry `!"L\gِS͸W{^&pp0p @ $ AF h?tߴ01t@b[4'Vߡe}a4LLˆ7rWTC_.0%tI$h=J*yO1i@>Wu;Bߌ TNa zA>Gzd `%a0β*pY$VYL(Ju9.%[D,uG& ^ĢLSlI$6@%%!f- єቮ7Gd'UJ>D8h$9c;SpBYۼ`@m܉4ic09n jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 Azո|-u DwH$ՆL3+6V_5ۻHviM;35_z㈊":=((:;&~^܉8$ӞKWLU?-eNjH#+Ϗ0ȧ'mEBd0Wf hs업VAЏuD\vœ,3tIUuhs#*v&;#4sN||R= xa)/ )T6rO񽵥+3+cµ%xgm:,]=l;2@w 9.}qG0Q}|YaI f{(uLò KTHu#LaXY ^EOԺׁ_뢩ުk&t1 ُ̙qO`G孲_欔d^aB[iN,_s-Q]L'Q`"_sw'zF94BzDO=?fUw!2ұDw6J9ƈ14(bF/uU2s%Դq'b9N.V8n]\q2c !5(^D7DBvmV+.)"#xmosuC-zUCX q&]&)^&2|e7} s!K\/Cy; ^G,CW)"cRn.'ıg[Ӯ8hFq͋e3Ƚ UQy> $/զ}YAd6ܾ-j'o#0X tRS`n4? T![P(xXm⢃6Y>QIʩhCeP50?ZߤПFYkhe_%%k,ov6M:`K jb 7h$R3 D";ˉ\1_55C+_d)9WYN5"1t82wөYl8S.&t:YF gu`]oCʑ~˃=& C'2^KߎwGq*Aysxځ47eD&j.7kPcsKE1-)!fvש]qmN=f8BW}UTt ԊkqqUy6Dg(YaW6"HYA 3XlsE pDx`Vv]}֕!RBq,E5&sƯ 1:`T 3S_]I$ht9]N2|ix~vň !GbC+5Š2Av8mMN |ĵZš{"F[ĜƇSS 9vBwenRs㭲h9VrKB#g*uoSK3n Ҩd#?QI!ߜ}w)hȢ|>Q_ y{w.% rINQg/\ ||vHZyLWUJUּxϳHeEm2`@Q?{x-]iT O9(6&Qg+m͘^X<>mDA^VoDϓ%|v~l1\c<%vsA@GD襲2NgFł^7_ ~pV9bf3R*9ʶ0+(ҞwSڪn(| 5f3:)j1y5$d"'b|*\z _.߶o>x))Ѯ X(+WC DvdxLs#M?"zި~9pB3r&'s#<xbjGLm!%%k* 6h+Xdw{caYPz6>N6g-/煚ռj5S!;QY_6s_V%rRVeUv@Rq!QvNQc4`oePyܵi#iV0-9Ď;R ǭ;6P Pd# ?~ ྟE"^-?:3FS XB~g2'I#u:02s<[7z]@pape/hƵ1-h](ж!oq(hI9XrZtٌ-tq5VpZ%ƾNtz$4fwZx5庐Y"€Q%p2͌." ;eD'OJ5d_"w!gqc+TzC'-Jy)A;+:;twXAȴ@l{'1q !aQf>$? %hғ*4IlgV1cXe!2>4B$ԌwrhQW6͞ aSd V:$ b @.-@.)@Us #> R)-@T= YFG+P0aC$[5N_ĭuR=HI-|?QrCRI$I$m5dAj$c[d· B"mk6w`oe\,Y 9V7;CA|`:X"]<*;>FHקgvq+X.vy?>#<2O/{čYș+4e]$n I s#oB*)Wq$4'$yh^7Tv7l#Û_7":ŭ&7Me9pl(RLf?#LdG{ZHn +zqUTb-":ܕouC+.T@EC`l;Q7TgOd/bX )RLx#Svi.ݑg‡'{t%ճ Nea_]+oAr% K^F*7-ɝ诧&^bB ;rG x 2c 1܇= >Ns~9Evs 688=i7?*[B.O<]7z]Uf*fhm 5d2/eM۸QHsrNe)}N7vPa8( xCŗ$O暀}G.P՘p8##[9i(z'TVu=X:FtwMu3sD%~9"Hߕ2_m \o=la.d;Y*ol{|b']ͧF+Cz--´ZC31>G(/Bqwb/nt8Ձl!#E>?4g// r2_ca@횟>mi]35˃& Yr?<2ЅgcgYjZܔm z V`NYܻbg^Ɩ0n]%v/s1Na#6lttٵ]Q'6C {MvĤ*ϲm?[oH?@6{4"踡^,L%>^ݏ㷪)WC&M!Y[!l ,dS(4I>/kQ'\@I XF'"ϡD֥]_ ߥ޲Eqn޺);x4WrGA]x*qFswuI@+Gp3QL6'>@fRIjޓtQJ2)iCJzTܤ ƍ׮N<ʟږ0OݘR DAǺD7; SܻxC3IG,Hr ĩ2H N0qi2Zk&I0bb HH<Ȧ~8co)>CrRΊFǣ'^&rIW!Opk.+?QEL$ GJ0|a ;i(ĎVxM yJW3Sw8]c( !U 6P8rXV(ϋcGyqX>E9Ut].>(6_#)<~Wij8k\,@M2Xt +;h `>ȃ=}X xᒽ+vwH|DAJ*٩MH=a10o46_q2|6״zƅ K/rj%c6 ќ6J 1?5@AWQ9c?3$\P p.('c //ʴ7u~6"^VׅPeXܩK>TKoHPE&gk"s6mAm.jS%X-t6W(,V]鮌 svN=s!jc[շX Hͅ~f5:P;h{yv85hiYKCS~V(ԛKASfJVVi]c\OtLQc4 nOOG vu TF "XBioR䉓 ,j FG]pC.M RA DmʝBi948lN7r'FO[Y}}Q}B,{uMqg$" i6.5ωON";`&e#zJQ$7UCUUU[EBSNqȅ _{1o^|=e +&u54hkSeGd'znv~8X=2 &~y8!ƕh"px}#B^YYw '_rS>!\Ų :*\$.wB75Pk[6@p k5K:H0sb u\w4f8Re3:0w5e^DzeM)ys8etųR{v^(~(6$Qӱ { y2K{qz.?R2>] /X}_J2ujӈKfV. @^Ts(k.)a zMNW}DՌEգ.@B9S]7T}HMϐyiiDkH4iV XX?CwiYhi9~,2dTY` uJT Գ2%EڑSR< Ы1]5HLOTaabDB&[$c @ JXw~1ev)Xy6:q{pF,gJ<܏sq w۶;`7 Jͺ"꒙gXS)J^P.B,bLB2_C`â#W g%kdNY +xMR9`W2AmpT}wVQT C_reP溏^+wf H^p;SU6CZ-844`O,Xxe*HVB<"p-Pg@»DJtpa}\_ 7t^6~#G!XMJ(d$ĺmp3P *55U ^.a|Ai;b> Db^giC(u8"E:^ p0Є,<;e0kE@*jڵnltyH.SQ)!ψY YM1-]Ԩnyӌ19u_O,)h#uR@mjy&.r*:]&v6-YB-^U5z+n`' R =UqcHn;5z # A.tuIssD1#.Z҆k7g%Ŋj2Jb:um/`dGS;|*T lιsM-?7g-\82@~mKq`NmF[eڎo{ԇg%":ϸ C>)`P?⠺+L=*#lF[?M]|7]`W,WQhs7˾+,gӺz op'`2 iڬeu2ٞ08VҚId xXD\<ݨ!XS m;JUufm1 [y"'U!W-옿k2%K:]%1kmNäKczVDNAM $ĥ.f2yP!rJ}|;!7JTu43͖ u `ֽ ci3<i- [Ezt ,X3wiM(ph%-̒ /mK}ubl@x Py&yVaTZ#֛u'8D3'ߤY9O*MnBq[=[51y`8 #pYӺfNX˅ P\". ^cëaFbY4uP<ŚR/#X-G\{_"lx1ڠd)ҳf%Zs?ZVPޝ6O6č12d}$VbV=ǫ^ ^>lxcj}`xdEZ~D$Eˉl%<i JHx3 wPƞg5%/hMZY?ia@O=2ܪCf-9 mbNw+y-Zw { NtW}V薯N+T? &$źm_IM>i,n)-%YT`_ߤN{]8,cdW]T:& Adr& ^;]PFZq6eBZN2:T ׆96%/Mpnqe($$;l|Ķ N8BVsE|ڤRB]%9sG&.@' jPEݽԶN*2ʑ?= Ʋi>gĝ i? |ב<,;]~H8>H05BeN*Od%ՔW Ws3εU?)@2avGj”X9&I0SXM>.G1(v(߉rEɼ@z`fN3Pk)Ϋa]O[(.h~>3F~?)`Bom:lQRo7h[?[MZY|7O̐3!ū'=rcoo])d#X/v0|1K:48>"z:ʑdԴ*7f|yטZxM@[< P娘cе{uA맹9}!=}Ru\ #=mR [{ /|> E9OD`,e:G]v@%  <Ӑ}Y0.z( 拡)6ۦLBh`+aB}Chv0FNj' %2ukd$1JTܿy+oK_ 揝MdP28cK$nwjĈSni M5Z2ɯng%@#MT @by6mm+;9y -A}6s慨۲LmW6KrXa ळ6YE:kTES0p̔-ꠣsitHVe/eަ~Z Hj`}}EQ jo\ Wvi6j6?___‹WHw\vڠ&ZvNGb@eZeZeZeH*65/`ѯloA~щ[u|7pl6 al6 a- ̿s^ 3w+*9!#cjz(qԇyRC~|!$Ht#XtAo&a)7I%a7 2T,N@sR)xAOiCk`rI xF~Ó EY!] P?R<%7zTٷiD\])ۆϲ_w:B˙.źfX/<'bmDO!q^]&؂Tbf½xF?" |!+Z&Bl*5W֨]{rXl0cϓ`i sZ>;(mּ>],(xzRBrͫN!uVPR啩ryD2յ{J|G"WHm])l 8=I X{VҦQ"fnA)@Rޒk/VXQ:L d%Er$/$İR)-5\?ir{ DHˏq3 /ͷpPC_ ut=sah1`,qޒO}plV"pȥ<@>aI/-VZ}vtd 2M$%;5pOG]ե1K Eݟ}3r1dVgߥ #ǡCBsD)\wD%n&1c%$-0 >"5OO1}P=oOu%١ i'G隹SXe;\e6Mg/AJ˫dWuhp)+P 䫥?Ge p]qj6z431ɝӲ5%W1/P TTq}Vl'˃VvLDwCes^`Q.z̵afASI%X+ōqtzn(`n-:ѵkߕGvXƳ"? lDQ 鞥MgXwf|tщZ oJ7?|If|jPLWl}OP o]c+ϥ.:bOxwx'|s-9g2W&ŷ'k}O8U۫AV!^JS7^cW&tX  W#L~moH+x*XW6.:r6Elk4a_؀`3t *'kxuD_Jӎ9tMơXTc.AL%5ۑ45NGSqV'pΒKxaуg 4_ekWBH|F3쵽%<ߜQjE??ť3Yb{@94Gn=;0!3zfHi+ ؋-ඔJǾfuZ[K3̤3)vr*n fvt\?# OG),<_"f^ֵ_-fdWWc(g8bx/gv~ȓ ߥԯK{-PSv!{L.a _.4 렔a:1ʹP2:Lȥ1T \E&+sAМyƾ [WfD*SthyDC0TkOX۟TT۰cgZ11o4^-68Ϯit_<ך|yw)?-3 N.#r؇u[X)6\cDͩD`=BLҶ񾶉g@h_DUI|{#j|(|Uuf5F}>:p=f=hZ$p&@t(=trSdeu'ntޕuёҟ/KkkVl~E4ԎNƶ)}g =4cp]]ٶ)s*1' $*B1ҘMNG8/]j>yAW-o1{j{Y/QYwWZ &rI kUCƺ|$k_-#M!֤BړRT  "P=>ԁH<1@P'v #1tUc|g40(DP̭vH{] zaj.Q۟l]& R. 2mH?*mzURI|0ˊplK`cA34oucy@-uYė`qZiZ>1뾪\T=Ss!uL Rk;mw!OQdqRZj:;T[ooO0tMff4ZC\|w',/Fg d?BtaSy혺\7{ ASPNb0$ MUR+AWy9 e! I: o49[pǰ/X$9JipY§ R0&g DDq KD\g4KJ-6b~Eo-AeM*ۜG A|l@a ]P`Ҭ7KrG)3QEp U i,h=,M%H)̰ocZgvi3;7 m~U?ǰZ'$!⢶]Qw/pH"}(Mt%o_ +>:=IC3[{6Pb3?"Ԙd &bCȰG9 _ ƞU  Njr )h6cE!TK5G q_)5U^]v5˝5Ln<s=43nSe랞,W[^B6̮$`&($b*F\%mJRaZ#.;mD_?fنj%<<{7jX~joLd`#C$Pd;)S/`q&~gڴA2;]zȴ)*<=_}9:&e)vg-kv$ؼ[`05.n-P}lEJchNȔU73wBXy @h1ڒ1(7Eu(;P>VR@Cc%})u[A2Q ݷ>E[5P)4L]A,1w?bnJlxV4/GȄD l9Z4w}ƼMrf?uE_su1kj Q:<,:t~5p|uܚ33`Th:LP/pMd_Az2P$W9iiɣ\D˲i"31TjR04s nk-NReW_4RgYiLr~/&MFoŵl|G3P$_X́˜Bqx9}6oVF /u}s ufr8<fejΐ <| FcIJN6665Ǧxߧ0W,|\BA_YBn |c]g֩d)i\g4WbҪ?0 /Wyo ~$ZlpQ(nMUf^84 aTP!*9UVMAu?0AHmYCNAL+{Ģg@8k څa(PtfTt=FׁbTWCG]ֿ]d2xyya-: 9چ3YaI?,(Z=8ٻY-t0%$MPklC\^M.c…%O2{=~Մqv'8<~v`>)^5] H% r~dh--6k@F}Aۣwa}A^~=^3@i#Dl䣆/&_u`"DCMҧ=0m$4PQm,usG'w95+FrbKkֶؕ)7h*z]AHx}pl=$]kyE\#luKUђlY|뼎"ɼ24IR7 _d!Poe  u7ۘxC߶xā=1*JgSd`_G7* l8 kB*w!ig1_A߃Uml2lPױ9cC[vKGA$Th@ rM]>?g!%"*h o N,>s544gM-KxHyT;?ttCc7&O UE۴WdP [GȜ,0{o(t3{U^N4MZ0KЧV9< ;QX(vxudHg" NP53r+gS(e3%UM3Yj3unVC:c# r]-W<.!?&eB=ZRj/(rw]Z%2lKj,;G1%TL=Z_"Ik մVߞB1<(N<35I+b^M;c)NvJ̏?qɂ3ZnA=gIvJ_AC1x7w rf9ߋ3J(IV6dcaࣛW"xh1UX`>?ճiGG7=v+bpR>[ُ""nm,sAh5rTQys[~_L 翲>YXzDg3WVEތ=PFם4H5vSN z}%Cc 6ȼ-_f]m+GyXwB5Ϯ9ƙ.k ,nA/zb1: H;ȯy֮|=Aue.c7!VJ6 NAa,=BZc">P-LdP0)o( R hYnLz/9nOU <`e@BL¡ߧxGuڰ8)ou X" ZI6/^  EVM >/a",\n?)wHK=ߑ6 wJK³/ ( 0]t&)=BW I:ž:pY\{݀SۆIh̅/=<$pM:I!K.H<&}u>ա4ڎjVrikHkS2x2e.D]=6(I Bp3֩C9GDJhlb xH`x"򞳴&o%VP0X\,) 󘓝,e@9KBԂ+o5nlN7-*ʯ^Oa%~$%87)a åsgl.a Z3$֡\"p"rtWT3̦MsQbOCm2ٸg#h[[!}Sp̊lr.0EW UCA7s-N٠o*&Q;Q"FW͟)sz:B$+Ea]TU}^N6665Ǧxߧ0W,|\BA_"3 4i;_„Ky$d"`];8<!' b]]pH},^fMJ!'raYɳw!V3&;0W,80&ךL+u2 a7hWAى#w :~ܻyU4_*V9c ?s%`'/XUףo/iZ*!=]ݐ! \͋GHOV,b P}ɔ0VKuC2<е)V#"x\Dm>}Cm?joV%/H~*h|GPw6(ͽHM|_QbXw0&S2ql@sN<LI+fn2 fS1QPNCs\ƠJv>ms\Oa|0xX[/XZϔ3؅"D̑!qb~]º`9DѬM,TMr#{-Z"9QGQ. Z'e7E6 dQx>ǃ@OŨJKWf[+{ޜ0bmtA 6 ^NU$ nƏ=I cH{6\"V{e}ZefQ(-$J%w z|{w00fYM|} Eup $j…k !iL$UaK?{ $)f3$F9M.Oe"l7CPoEk$IҺy# fK(_K5];7xhr.XzbӎN'xW@ ,r,RG}\ڥK}Q*ўzY䚡kEhi[J\" 3tUmh|a|D{zW@&PvUJ~⨉wN kPBAq؜$ӌ$FC?P8ha t1nP.L+?4H%@" sbsh1`R/.y A~*jgaCkLHVRK算B[.ϯIOPaPP:F8vx# ÍeSŨ;r|B_O)W`,!>iGj@9md+HP!GR eԞm ݫ!k?)a&ɕLPZjIH$V?g hum5gM`*܋fw?#nĭwPvƪq^N6665Ǧxߧ0W,|\BA_YBn |c^K5P $nW]5_Tk\@TB'jB@#y_ Yy1铹 *{ BgڪK;4_*V0|*\l-?qHO(*cRQ¹?~ ^wKL*əQ6Է,Ntuq%g :9YNt$/pN L@$BmB y3ԏ&7SSp@7# 3NF/` t*{[+#X;%UOL^ߞS1Z# N"y(CyLM)GPٙy>Ih<\`Q;sşZI rDAuH4]^۴K!Trk,ޞ/װ$;\v>Z쏜~Y*@6<|O /Є4rKhZG|E6GV9Kt*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/UwxYnx*/ +wIf3.$$ipu*inrw ՠcۇȠ7'DL324D\!:% @9_^*w74wN\޻rG5Lov[ˊZ#t291[dB"a ヾ@7;\jX].l$㣒 M7?Y0In~HV+Il0j5d3h*3P51\\ZwjCUl?K|1*rc=>?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 NrWKLh 1d\ Tm3Jz0Y1zUr"MUBJ=!+רx!ETрR]/s޾CF?i9#ٝm,kяf* vO,9|fm˯t_kx\ G:kS}WۦߴP'[w6sC9tUsxS1Bէ uE f˕ID_*OCzyXB"'_sF9܆W ';$ĆPI&1^S_yd wHHf}fDEuK7P޳][TsӮ b$\VсŨW qU?Cmy,I*434uɳ!-PWqh2ֶsY9a<3h%r蠺[2kb>eEUF@H k2p 1]]FC 7=}^'ob:*'q- vm$UG6j{ǡ$wwVe!XDD_"c"݂$d?"DtЋ3 ZN/6US0fK#x>pCBhIYʝ PgZjgx൮ ne-jIeů31)!]6jG7`AuV][Kium.մV][R:EQ,@h=uV][KixCpt&^8V{x^dF)yK^RqvH^q=%1n4'aw<qVV1LדB\^b<2%Oc *~_GujO y,@0gi/hV! IɥMpo\{5mNš}gU{QIA ~ß4..(x/xUEp[߲gוW'Iޟ~}Ό%. SJj@}dڿ&!^M<3=ǣ[Hm].JKػ+9mܓ[ϼos6V/(f)teH:0dǍve?(]{w"*A4:*輓+DH {Ү 6'5EcjTRVkRHKVjkk \UoG42r\(CX.n*ܷB̼x'QJAaNOJ:XBRGڿa@P% @gu##RYJ`2auV][Kium.մCy:j'_;Q_aԚ~qNRFO/)yK^R򗔼伶KOPݏY6 h;"aF=>Im*4m`omf=V}Uoߟy>y(뱥4׎dYљ0FT ͐fF0cu-KS v~)JQޞ?3Ik$rn.yseR9ÛjS*YamXdtuY #Y)f=?4>' U ԚD$3UKA-3o Ug8o>5a5a]~_ώ1Xq'`֒ @1G7K,$=uV][Kium.մV][3{ltLRr/)yK^R򗔼/m%JI:[Kium.̵r/!fsκ!5rxoմVblIĵDC[00ML?C-JN666-qTː1듙/~H_[<۴ /WqnX(|h/;Ay=i\!í]Y(,Q ToC.;eYxx%@o `s}2lvF葺$[CkDo|?kTS潺9{S+Y`ЇyZȟ5^/u fkQ2yBݰگ:g^EaqY 6e$I&g[-?::%#cu]z6cE_WrsWr]e% Èn79])am=Ë11<13xZ S 2%v0䵌5 on"E5qJ&VjS:ovξo@x10>c\0es7؊)sUD_hڦF ux B Wۑ d|: .;hx͐}lkV][Kbhl{n]]YX_P˫iuo~J0-TuU꫏4eQLL˻9E/& 6].AE#BnE|cwo.WGO0]q2VﲃB&ka!h8G6R N=.,/|<U)@Hf$ko+kqkd5اWpS$3gA5Nttun:[f|/*a@-*6$7j;Qބ<S""%ZKAuvueZ$%Z%aWW쐗.Uy]E&6ɥSXO)Z(=1JQ'}/ȶa^K/1÷(zpƬbNYB)3Q_õ% qRгZsfyN+5cq:/MB 1mg?L+d?3*YZµ3Z*^]UӚ&T{v5`]F}jRk[i7 igק< H!BnGe (>:@ PG-Um/ G~EGJ?^wd"51U|;n(㻄Ιz.p?fvmrɂb֋QޮeWT\b6Ǽnc?oapr-sm!j/32P :@2ʟt} 'aS( ⻽3)M2 [Jf͑R8WT.aX5n4v' U.6$i7|'qU7l5F:|^)Nsg148gbڇ -mNN2 XY"SUAWKK0Ӕ %0jUmSZrK;#\^o*(@S w&6k1Mgk4ym\/ى9 B\^|9*^Dp^$V7T%`N~jϹ[L:xGPOˢr~o4{Cd%~zb GO*Y.+kCsk/JNXDOOw* }IE`~qΩT]_oăk؞ F<OݼZmL 6>XHEM*z4lzO\yfވDcD.B/j7JUsĢ9zG6%/;5%7Up‡"3"lE FS+9`2irx;TYEC;Ay ^v۟H }(ڡM.[䕑4U!A' ToCwc VhOŗC4T[^@ܮW+?[ ֳױuY{(TOE|cIݽæv6O$eܴGRU!:= FJPIlqeÕ1UIvCv2kQ{70U] ?)Z+= |+6 ˚;Ƽ01/w_i=nP@'Ѻj+C %SW[$p)>+jow s; L(~L_Ṃ[p^6t`$N}whdP@P}Y B#|7 09Gw|؈},HFĐDpJ"Mxm$% $#,a!/ BEjHө^_R̻@Z[rsqq@iʴa?933a؎ ϡ4Kp%7~o KZmC;? U) ,=y(v`{\.. z܋I\..3TrBpπI}.ϊnPj>Rm殗ߧhinJH6 1cvC-t,'d!F"bv?@1Oj*%749z.Ϭ'>p:QG?g>0YpOkJa+=Eœi++A@=JEG5:~Qoܜ5ҦH>BZ+U/ 4svm\7@{4[) ৕nmI{Ȍ|{迚A1cr!o0]N)Z&=Q1<_7ny%0u%`O@MclO^3{Qdg$d`5Q?$hE|2UQmxL;Jp:̢ |maL \ !CƓ1P;KLѠTcjaXxxETփU'<|zxXtՑՌ(&D$T~wY 4mWt9uPyE3JxӁ " j[S쁈)4:h@0 P\![6[صhWK Oc AðgE x*,]`S/n+b(l̶8eÙp\9`Ԅ/WEV=$63\tNigYa[=Z>8ğZJ 7Lf  p < }^^uձR`t _ ٘u#HkB1DMh؉G̍gz(gM)g7JSvjg*]-K"l\8HAFylh=*2W'}A~BBj>Mk_hH̉!_'AcwC}}+?T م|䯜ZB܇Xf~'_P-Ѱq!CCGɃ>`q4ˤNqR2F@G} S6`ڨ[l>!<$G{F7#M㳕nVre: qO)$EhFGȁ&y_>Csr_ճZ\ G-'8>7q0ЏJ1dj=$ `nl^H3<%D` oBFX%"nKf}KZtJ1WAt\TsLYnf``*dKZpL>3_*^  l'mPc镯 nK7=8~z,Da!$KMxGb!-@ =.aA̮K-Fő!,Jo@.VVaT(J:#I[N,$M=Ea x\m{4|DCDi!4G>Kmn 9b坟/hזUtkwr*5w!Ɍ[N\CS^0dJDNޓY# OeQ`҃_rz`1op\9eØ5#ԂxwwB /x#02x.LM&S3{=k݂BlKˡFT(5yZǃI_@0]>CkhGܠ&j& .»Eu΍eSvq|pD4"'bJ210k!r?^4!$Pm^Zɺ{+Kϗ>#V&6 ŏ2@mӱ!Lv:T|Gq(m))NNqtxb]`l3أtwj%&NqR3MʀNE9NsO3y{'e!!efYB$R @ty~X,YmUvJoq5DinHS;2:_BFP0V($d8̓WDQ(J:Zޏ&VG:d겄bZIzϙy\f1x}"{|.`ͣQ 'b ngL/{^7D)hIŠkHɺ^FM3ijIu(<{Gcl=Gda9SE ވ)9_ *8 o1e@/#Ii8.z%yn(~KPfՂح&nMIѰ#Q ~Ym? (YHYgI hz i%nqc_&MʥBX,mvd6@nfip:#Eۧg"Q(\VeÙp\9Rȯֽv%? D1ȋ€=7X1o#\;dnC6u>B|;Q#JC~*xpyZw0VąPT8 #z/AΚݰ=o˅M޴N`413$; kyy~,bKF0WԜޣP*߇.H n+T]G( ST<&#v 90?O0G3+9Us$%l0 #Na!'8# a!$`a!#0=P3-dB_Y $%O@a!.f|HHa!# a!c #y$% P54WmK QJ><0jo }/Tz#9 \Ą.n]sNqfżbj-K&׼c(k1 Nqfżar#Z1BS͌-qn+_ioMK l>g9>zr~~ů}u{>vS|o$~p Ù@gMnk|ńf/$HW?|1æ:7_`q4ˤNqfCͻ? y@C@R`z&L>'zex{/<įĢLqlEQRbd o[_S&3>ga'=RS}3.l3'ɿ%SZ} ׇk*X&JwdPʤŒOeT4r]#8cCuPz Gn1*EϜg-9m.eAp42AQ,]אuaB|/yt?~z,Da!$KMxGb!-@ =.aA̮K-Fő!,Jo@.VVaT(J:#I[NqfCÝ1\S ?,AM% X TvaU QhS|%IJbYX:C!hX1/ƬZm4qN`sZYmL #uh1S*;5ſ_8M+7*t&rm'[qMZBN G1Ne .G^Fť1z_>t):c(k1 Nqf {C.Ќ^R@ZpHMH@#NG"$ >mY=3_>ZlSmph~DpRNzXraD*7j1ѵ50̦A3d`GxX qF6H3*S/dgϸ=RiU/7$C^+xN{l;2BPʀN666-q/U뽃"aqC۟r_<s6v'.-8#ѼY-v4B eBO\bff"X.2{6gK_*Jfgr5BkitTyF/Ubs>V[(`_fFFQ{[kt>^3 x+﩮Po48T47 MNߨ}E_e}IRON/ԚŸ]_>@~g &RMu ׁQB;=ˏaMU*NS^iɋ%7/XfC`UTܥy/D܋,$=f?,(E5s4-e!#>$#iefF0`iޕ02Xic /6˞F SZsrO9u!U.WU&31?w"0pF~ovb0rFޢ7C`޼dVv(7<>B;_1A¢e{z^'ZM^hJ>aXPme5RK&,i-;+/('qq+Q#YYl!M+ۚ[LSjkYGƅsxcٯDВOgBJN Ja5~{y\z(  ݧjp`0*]ek.T1)+{4?~$(Mlmw/P#[ |/hlNI$DL_)qh=i| XqͺL܆z{uAhyDpG}G|p5K4$ZN'ȸOadz5Wq3 p6CIJ;Y^85Ԡu2]+V 1;Jp}Er͛):ԍgeY,']cgό<{+)r~H\VQ6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%M BAbߍV۠#7|T =*IUʙyT3toxoadGlPWqhxꥃ)exre=D,5[ |&bũɩoѰNHo&J|Hv湟&FЬ{6 ?KѐC zgT+uT7j) i>dA6Bz :lmžWvoh ^ia!{ 3Lޓ=5ef`¦> KfGQ Lv.% e;CVD.~#DCo4Ƌe QnQWa:XJiC+>#'e >?Z:0i-Yg8-Ehxx/v ;Yop.K]goLǴ{ DhlLbT8a+^o4uD/M<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@!ȏloDzĶޖ .7eUA,9)<̬v_,+$&8M#bG>9A_x~ڸ൴$uSըQ KƳ̵l ۿLsݮ-%_urՉ.ZLzطՐIi 8H)"hŬw'4Yjا}V2ٵ֞++훽^klI  )! 73(  4 ,2.5(K "@`b105*,'zm$Un,),+/$;0)/)/ (#5)#DꅃcC ;pf )g~ 5H[!O 8> Z;)DP vh1 #);]ʐQMofŸ >h*ϯw_"BH>97Viܹ R(֬H1ǴͶg b0UvްC|ql2Xڹ؏6U8GIǭ⾊ '@Xإ{V2۶؟+*횼]kmJ )c8 8w# . xK "@`e/~' ?4(SoҸ wFVYJԳ)vy)6*//. /*3&1-,5EY*6334e ^,//-/0//-1 1-,4I$:-9'" tS(,0*)*--1'2*4JF(811:# !#bcK;jTK-#6862./,/,2{>1430:#-#̫q\?%/+1%7U>e(81518'g H ϭj:$3.!2#:04326-N md-#-3#"bα<+714329 BX6&"%&̠XF.52317,*} ZqPG'uפrPp&9043409$ ؋Vy}䴇6$904340:#$đgɗ\1523409%u :mܨzP,6243417*Y Yy$u鼍D  f}$9043240B QB: ѝh -+71432514e^ |ᯂ- =V-523408'" }ԁēSB~$804340:# !ʼnȊףs .Z(814340:#.淉;Is923418'f H̙b9e^*714326-M nb2w~ެ/#Wz%90439 AZѸ|wurȡ542317+(} lϲzep ʽb042340:$ @} +42340:#%53423409%t <  tl M,6143417*X [x% oPIt&9/43240BOG M q=,(9053232513g\"6514342353408'" pp'E.523424414340:#"5[78u5623 5/< ;04340:#.j2!Oh)Rv":043 4.6-T#:/43418(dI XH==WSr^ mL/523 4281?'804326-Lp`2ޙ A4043 2,+-6238@ZIs ˵(4723 16L}=1423!17+(q^K")%123 72S+61340:$ !크΁% 'H5532.31m&904340:#(KرY?e$3/4341;.#:043409%s >Tπ5]tz';043.2#:043417*Wߝ_ M!:0433262X)8143240Aޗ8 1%90415M543!250lu`! #vZB231138hG.523409&ۥZҀf|z#(%*/3 663,`)714340:#qЂlzꃈ k1O493 4,*>Gz$9043409$iτԸMGMd$60417( #:043 409'aҀTЃ%t^],7150:#'80431EiPЁ~ ?36".423409&mѵw\D43"409';vߥS ("<67233417+WĦjP;,%"%)/3%4308#Cfᾣݾ.!.5/23418ZD3(##',269:97434137c˝Ҁe (;243 2*/48::863101234050҃sr_pY?{\623 7521001134544323 /;!Dhπ҂ܺΙE4_sT)'3123454321014634317"P[Ӄu߲"L+@4434$543110012579:961,334035!mQЅ  1 7.433432102368::84/)$"%->N5408/'عS̉ m#6';243110012579::62,&##)4G^zH+;#3fֆ äO #/2/2368::84/)$#%-] &*!*+9*tZրҁe~Ө& !,@7937'[ݭX͙҄  |),3/1150DoЅ'WA>364423/kυٳ@2aqS(3.21;-VЃ֟_s&Kl-?79/4_PЀ J KL 0*!-7Q]4r۳*0m" i6j݀(#" "cQ.[܁/ιإxZY'4ɵr`2!!h3+*!$'//FЀҁ#wc߸9/,12<<+%#"/#l2%EO=7;98543 yЀ҂&vٛ 0,2331179;8;/SJ!#w[P)3.2/8(c҃&ݦt%/-334455310-.+6{\7! =j'9160:#RІ#N-.164420.-.048;B;}#C6&#:050:# ػR΀Є&߫20*-.-.159>@?:2& )+ " _t&"#:0508'jҮ߱cׄ'܇,+6;?@=7, 9\'; {))81425.HhN9- 5ax҃i4;53& *Jn(VB242340##'-36<7RҀҮҀ> 8[B 2ciiO;304::864/5%۵a߶vِ (Ak `q'@"%#',230130;"ӀЁȃiץaKJ:5;:86434455618%ծЁۈϜ .s  01/00123445420../<hMЄӿPv“#_ $825431/.-.049>>7 k߲W҄ yܳȣQ,f@>040/--/27;?@>8." lЈ բظkG% -BZ :+68=@@<4)!JRmЄĘʦY5 ."J31" 3TzWЂ ٹlH&  a$Bf۝PفX҂ ѧ˨[8 T9$.:*qجغnI(  9#Xz%qΕvaeN4 *΀Ѐ ӻG QCҁӃ_q2cm̩ЁЄ yFHژҌݶ#.޼W3^Ї ߐ  Ȯa<Ѕ f  śuO) Ђ :# "̄  FpUݿ.  /q UC1 (44. 4/025*+3021/34' 5021120/33#  .2120042 5/2120050  $Na 0121008 5Y}'40214'   $HiB 2012/5, /Ve#4021 204'9  !Bi}K5 30103+5( (4j|+3.221 2/5#6/1[   Ai̡vO2! .In!2500212.202 B? .T|ญcA(%:Y  $44/021,2/5 50/: ,iy AgΣyQ2!.Hm- .0'53/0212/12'RGṎeA)$9X W.64,*52/122/5"6.5 :xdϥzS4",Fk y  4-45(-51/13-22.9wv㼑gB)$8W  211/44%/6/5%50/7!3a{T5" ,Eis-2120053"4+40211/ e^y f] #40112/051*3012.9 Z . %"(3021121/16-12/5<T  C 9&5,122-6(4004*%X4 s 5 eq9530221204!"50.9L]dn  Pc ,4/01204)5-8 IzK g 4  ->8!%542102/2/5Yod~f2 $$ &-22.5(:Uj_oTRaCB 1(52#5bh{YPmg~ ! .* *:%$aѪPt`fO]j Y($)&ʦJj_uSTv }  %\B*uԪaLrkWRfoQ %b{|䴇7|=V_  y( dƞLZcfT JڭnCZ} t*/ %(鼌HFx |a C "ϟb2bN f &ᰀ6>UR.  $iĔRb>@qd  $آwuuI8Nwe #絏/PW:BgA ʞW7eC;W;! 3ޮ75Kpq [  4Ȣ }   " Q ʾ; %t t v & R   (x ). &  'XZH  !:  g 3.   u.  '9S  ^ dk2 NW 1 > dYMHPJq_H  3 AZJt ϸ(b  \ q_L"' Ё% ' K uM۳Y?? zn Q UҀ5]tY  o .ឲ` M .8 1- mva! #xT0Byݧ\Ԁg}{#8 s҂n|턈 k1$ YajфֺNGM@b  <ԀU҃%t^˵5 wjQҁ ?LƢ|V3"xᦜT (  .ٶjE$ %!g㿥/!1 F͞Ԁf (  uԂts`qY?|[3 ]рԂ޻ЛF4_s6/ZՃv"Le SQ҆  1   "ںSΉ n#  6Y g؆ ĥN #  %Fk9Egwփ i3 5X~]iNԓރ ڢFN/ $Ej {߸VԀ֡Т}$u\ݼdz۳ԀK|Ǒ7 =ާ^; ~ԁʘVYٷ^ & T[؀ԁf֩ !3߮YԄϙ |)p҅WAlх۴2aq* V҃٠'KJ `QҀ 7 M 0q%54sݴm" C}6k✰u  "Ұc;$5܁/лڧy[I xN8n!h3Ҁԁ#ye% J%EO   {ҀԂxޓ   (!#w[$cԃߨf 8! =GS҆ < ˾sK3&k hԀڽSЀ҄ $1O[t&"Eƚ߲dل} ;`; {)eB"byԂ Y +MrVB SԀԯԀ.:^2cggD" 0 ݶbwܑ )Cn (  ҁʄj٦aK  aٮҁ݉ѝ t   NM҄Qwē^ QXԄ {޴Ȥ~V+fC  ym҈ ףظkG% B]  !MVn҄ƙʦY5 "4X~X҂ ÕٹlH&  b $EjݟR܁ZԂ Ԩ˨[8 T9$.:*rڭغnI(  9#Xz%rЗvadN4 * Ҁ սH QCԁՃ`r2cm̩ҁ҄ {GHژԌ߷$.޼W3_҇  Ȯa<҅ g  śuO) ҂ :# #΄  GqU/  /r UD  -J  v?8~3t'Ei  ] RO  $Na  K 4]tCv&]uF#  $Hi}UA DC /V8ei tGU  !Bi |J5(Dv ! /U߷b?')R hS,FXN  Ai̡vP2! .In/ d@, >RWULU.T|ญcA(%:YE<Y@k_\W3LWUPNQPV; AgΣyQ2!.Hmlh,+PEs@J+BUWRNOQRROTG8ṎeA)$9X BV"YJI}Vdb(9OXTONQRRQ OU:ϥzS4",Fk*y AwEOCT/bLPORRQSL]/㼑gB)$8W nCVPmzSOSQPTKKyU5" ,Ei$ dB\DCVORQ RNX.![z 9 jXH:| &ZMSQRMZ;~֔ W{$%Z@Z!MRQR0 횚 RB UWx3S>VORQ SL\2 4etMcfK-,TORQROXCS đ " Pb\zS{Q_KSPRQ RRQKW4 ݓ !" /:16mKG":TORQ RRQNNTS_'󞘙-!)&'$#% $) +tP}pX-1LSQ RRONQWWL5,!O H1$"#$$"#  "$$w^h@91+'5HY=ˑ md-"%%$,%%'&$+&' *nav\ϭE41TMORXUF2&.BSZOX/㕛 BX%#$#($"!')SREˣQ2/GYVN9)):NXVPPK\5 *} '#%$'%$%[8= q֧j/65I+(2GVXRNOQSNWB_ '#%$% bwy䴇79)@QXTONPRRQP>ё$&#$#'dȚT.0NZONORRQRMY1阚 :%#$#(L۪t0)>SOSQSM]. Yy$#$%#'"*鼍FUҀ5]tՑ⟳` M͐㔛ᙘ9 1ْ񚉙!mwa! #ɻި\Հg~{#񔒔sӂn| k1j҄׻NGM ΑՀUӃ%t^ᮕғkRӁ ?Әʻ!x⧜U (ِõ$h.!藚 ͟Հg (}ҀՂut`rY?˽  ҀՂ߼ќF4_s _փv"L Rӆ  1͏ܼTω o#ݓ!gن ťN # 엘lx׃ Ši3}PՔ߃ vnFN WՀס˱!q$u\ݴՀK}̉[Y6 =ξՁ˙WZڷ>] &ˊ\Ձf֩& ! ݕYՄК  |) ꕘqӅđ'WA  l҅ܵ@2aqWӃء_s&K`RӀpKL 0Ŋ4t޵߲]`0m"ʹ$l㝰ݗRp " "Ӏ/Ѽۨz[|Tvɹ!!h3ꕕӀՁ#yef[2EO {ӀՂ&wثWfJ#w[dՃ&ᨋՏQqz\7! =Sӆ#tU||$C6&đ۾Sрӄ&d`dJ/3)!" _t$"ґӂ߳eڅ&ژNasW='4T{'; {)┛bzՃ،bfK1(Cf(VB癚SՀհՀe=F3$4Sx B 2bm,޷bwݒ '=d `q'&Ӂ˅kڧbKJβӁފҝ .s QӄQxœ#_. !{XՄ|ߵȣQ,f;cwW@5nӈ ףظkG% -BREkO6"!EJoӄǙʦY5 ."4x]B*/MrXӂ ĕٹlH&  )^-$<^ܟQZՂ թ˨[8 T9$.:*sۭغnI(  9#Xz'sїvaeN4 * Ӏ ־I QCՁփar2cm̩Ӂӄ |GHڗՌ$.޼W3`Ӈ  Ȯa<Ӆ g  śuO)  ӂ ;# #τ  GqV/  /s VDt8mk@Y m~eP!;*/ v c%AA2d18=q c0.Sn}   +=KV`ir}42 !(/9HcZbn  2a{@Hx;i 2`  +Y^#R2LEx>m6dX .\Q'V\0OX>H~O8 ArxH1:hdC( 2`U=  *YL6 "RpF-L_B$ Ew3#=m 5c .\&U7OWH~zAr9h 2_ *X("REKhDw=l 6c -\&U7OXH}zAq9g 1_ )X,"QDKrDwZ=lϿn4 5cȸyqi]I/ -\Ͽ}tmf`XQI@7- &Uȸyqjd\UME<3+# N}unf`YQI@7/'  G|ȸyqjc]UME<4+$ @qǴ~ung`YQIA8/'! 9gʱwld]UNE<4+$  1_ݦq\MB80(!  )XcF0" "R^D& KwK0 Dvó`B&5-%  :jjE+*.)"  AtZ?"   %L}O9 ,WyH13bdC(;mV=  Dj~|M6  "56'Dwy:* ؓ[>fYSΈ^TY%[|Ӌ]flBo&urBzw3``f'CU3HJvRC;7F+5y 6: P%^sCF19x?H匄77]ᑙɑ3'wt^#[_qKV{ cنQy᦮}?4hр)0^Kî箁ﷃ `vx謿6 wgMYp6 9QloN9 H&mT ,@ tq Fc07 $ӭha1a SDv$Zzw=`ȡf)*f|VFH|V+9j6L׿%w?- {oǜ<[.<|tJDq-?[ڛP;yog[q6#ո<\ !I]UN˯ >KPoίlm>/olM }Nh1 CӅU/wEav{JM>c\6NThAf7Е( qEW H![}֟Sn4u4-:ѢjC6xvo|O禋Ɍ}%ϿklC*@7/M9\ېy`N 38G\w-[R <-BjQC5jEr#8}2Sm(Zm:!=\6>/-UF"U3Q_\VU<0vvp9R5X}Y a@OZϧ$liΌEUvE{( [G"IiPX ܷӹ3QDՀxu!(NաlC݅6v5 LI6h@}2l:HOIǝP|˕ȊGjcH:YmX,y4A 4Cv WO-bɤP{FH ́Ͱx;T;Ez7 }ÄR"Vԍ?DOwVv; dɥ( UʇԪY]G`,3O!@\mR?K]fJy6U_PWN^?ۚ/0BTmNbalmb'`O5!61$GxFVf>DC _^•!]UE:c<<}E2$ct"=W|bŅW FMS1S u?CHsv CGA@gUB'72]QeVdQx>G1Rz0ھ=ݬ P͝hy+/"V2qF]SAlL+ ( I)[9g+.X@qEܮdPӔK:aQxz`omOPWмZHBZ˭JxT1:p#r:zcDbܑs]TEM 4Be9RۢT ٹVtRD` [ٟ+/}[p0'!\:|79X_ 둟]@te=Y{LD%:_EqpVr @c>j,Am2 Vǭ2t~?2\)^w&$hLYq"\Bpހ]^J]/9#BͩȚa#Iby7Ù!I̱)7Iǻ|3lx̬U-VZ JyYo4 K4յw,pX`m#R?)>10`d1m:*m@'t=$3*eEԯX!`{kot~88 V¹i|(~y 6692ʗ9?Iԭ do?7u@~sEA󇪗(|,AhjZ w\z; ӂz1rMHztQL{Ao[zDm["g2݃qL[78 Y {?LfZ{kuuTal+3ctD_NU'붩Ă=GnQշ:YSty~L)V!Y(L<>=Ma|_[Vn頗= &j8z˽DG {7Mog7~@/?>r8)!.'7&m9Vk;/!pm?.PЂpVljs ,K*w?y%~X'MhSbbC 1~TP˺,U |}"3(:qy),ߥ z0gN: VҺLzS{1"Ort<(lL\0VqTA~b݃G Lfd)?7KFZ2\B4P=[. ǡa.RO)%gJI7$)SPo{T`([< Z[ hn$92A P峪S%QX;[l`w:˭LͲ%rb\ +HKtCACԭ`adVt&gz4lP9+h~])[T;&J1o@Qh*IfEKob!^^3ݺ p'YmlXG)*eqiIU_U.}y理1A&`G dy6X>ԍcU5RMHP}ҌA[Ӈ~|i,^'vd!%s1TUcLufx@T}\ I] Lc 髨ׁkz? Kv '=#gvdP!FS>=z5?n1N3 T͉77d~ UrH6T47}j]_U3[0W4$)tg/.:--V0WZw.A=q>jX\>jSfj{%y۱UGDE%".nk$z'wƛmՉѦ2+NԤ ')&.l͘v+'al̖jȠ* ī3X.Qd l럋08:*cHdO_$-)|Y(Lc"ptx˕\ ( Taſy0u^l3y # ?`{Oq+Im㑯mŬ?(/0g$o*aąM MdͯE׹nKbډ1f+"sn+; w3,cnv7R6O!lZCijY(72.+a|Mbbj2"hh=tDWnyz,>lRNJL-ȢMT_ ̪=`cRt( ĔPuWEb_L̟JF>.g'jޅιVZGB62ga, ny٩5qM@i\}nM%->JlS /4'/ASx3c9ܔY8[qo⋑ +8MG@>~^4d|Z#V_jB<b2R g_MX |*@4h|ܱܘ+ȈX+}YBwi@Wky"\C6N*ēNj]`fQFmU[4jQY6woqO?[c 9]iZBR˗'Al?bvWPqVG8x#Q g+3#Uadj8ֽ>eGi靑:!{GCruKܛDŽ񍩊t QJm >s1Aqhm }z~Ŏֻ|uc$!̈́E8RPW\ait?'Ƞuo(C; ^҆cnBsY6jI1_EkyMޝ4^&޿(7$ ޫג ؙ4NZhÈihjVX6P߃E_)[[-ݑmT=ޗ'@ 'yBMy'.ᖡ`]# LU1E#:ηqt~R¤e_%/ý> WX|j#{58c6rkU zAQg+ xg=ZR/145^9(6Zފ:T\C Wj#=b~;"Ly 8d`6j5NykzWVS?k? 2_TڝU7<Ǯt{'bƂF*H5)~~Mdv25F̈́_nBT7>~[X̊EJ>Rk ^9{Ht7~&du0bϭhKZ״I jA4KmFYP@x19_l5~Kχu{aO"둍\q @"A+)bA׊_?(v=1IǗ"]F퀣;2qn~{^ޠ?U zt _EuFޜ yRMcb?LTR+Ee8Vv4.ze]fP_Kq/ \ j\1a<ɝ <\;]`$[/VhLm3biwdLdիڬl:0t.|ws*e&`S[]6m(eI)ħ @g~[j՜f_D;82#NM@uCö́M$Kx@KPJ'|ѻ.6Oq4S(dU3vMnb1 ftv/.S>{t9E:iĕ'?B+Is -1̴KD/kLfNt5Y5.8U]%Uƪ PT&ƚba< ȭ«S   !3ddR|a0Rp/z~kShp,N9AYG "%~DX^+^߬UՕ>\&Z <40 f(bGskW淫'99ccj:ֺ n-\ O~ tR r@!&q T>hL -y=Ll;OR񦰑K[Ьum"Qfyps`^)K*]LR l 3ۺfг_ =zuTʷZ3 Jqk+?B`=EwHd &NgF%#JCrFgbꒉ},6 YACwp}Zo3y93@˯Bh$nɔ]քD[!AeM}w~ |hu),Qh? 1άJiSyIv@ DDC_9T8qžH3'P}@NauLt KJhtIgd&(F S}{Gϝ>hҲQ5^Ejyk#bZ!D&S}BBEyØ_Ga6"x?vg<`lUN @kv 2VA [%q]-ԇvuޒca'3;C9O/xH#0=Ԣu5`wkfؚ[%ʵZhC 'U IPtPot;H O\G86v ߛ"#8vYF=%]]|m.x|ӭ/M{-9N_ _[݆Fx `s:1jgݓ4l"P6")(vOi{bH!,Q#O$nB7Ziu^&t6QD%+‹X$#3 D0B- {Y(Y(guFa* )^A}t?|AZS{+!*E6َB=UddsJ&˷mƱKh+*?@0@ЊiXWM浐\ Ι`RL, 1M%}nEA9;'?.CmaH`renQiRoڔ <vtjMIeP>Cgޫ`ۤFkiW*~~sc$t/萲쨉`A[|EG 5c՝/1Ck?¿\.LP~WnDSCSS(7lREٍ}mVk8QIk WǑ;Q5L-{|hԂa~,ƕroiKK0G v\mBU5/@6("wg uB2Xs<{BvAD!;r;jrDƿu4M'ic);wiם\;IGU ̮^4OT$]5NZq/*DRCSyk ӌ#mar>3E $ _ޢ2%ڏUW`PP٦>D[61Bw0r,H[NR,Mla=!ڞ)'C)sk!B% Mq;$ׂI$jn,4zBַ_CJmHhqT(XJ Zb }3@'m\PM`0 3r `޺8OX ;+άcKZi=Sv_H;ŇOzp!K(MlQ󵅐Rwjvt ,le8|xˡx8nr pJIvna#_{E0A^,-r/ru9wZvM@h7Y8zl+#`)*ՆWJ2Ïk҂: IpVӍD88lc~>' u6:O/K a8|gpl|S#WT1$0\Fu/d:Qj.SbH&``9WyʠnTi?OV*ġ-f)OB5h^\!|>mήznᤍANd m"Xd C"}C-=]$-4AǞ zHaڅ@6gf,hji<͡3{;C'~8T;6(G"@e??9ƨ7H%-U2_rnq4tE ?f[{lU`F鍺;jvS+@i iLQ {LSK< P u}28n %)D9&i^@w}2@l4svgr0>>Tռu#B.R7{5 xR4}&J[!EOBA?~xTl{ZFzZܪ2^E(A&r O3(ٝ Q/tb*T{:0hE~( V-L0N(U/X1[,knY"{ƌG#`MgeܦyPiK!5t0~IsVPUT@s:b8xiȰzh1}!imk>z(cso5tU%*-d*uV^P4^'=.3nRzb(N" 7RxlEPJ5MNnOX vMUQt^*sY['.WQh T"}@/6,h>NWm5א&&T <2֧A`ړ ۭȽ7 `S@,S ?JʏE5 (ln@9䒂JōwY\,6f88U>κvب4]je 0b[˒-%^#̓n?(fĹ`"ѬpMss&+=RL`c׬{l,eDwY1$+$ۈ+at.`R}7@PQ,4\]ηڪ9 Ca Z]-z?ds:䚥)ZP6ŴdK~[!1Z0|v5<7;oKGE9' Ŝv0$ȪB}_qwR*'o\`Jj"9Agަ)Ĕ!UedrD+80SJrxs-{9$*A2 S2B:g2~Z3L&2rCdGq9^IYS"7OoٲV+x`[*67D]6&Jr|QwXC;'0,ʈ8.D:^Smm0%[=jo,us') :cXnJ)qs#pdBe5]iU+ŰK٩gtl'iMk`;!ڂп)٤pgD$U(kNe,%S|H3v_V=)vLI0]V_Eҭ+~:172tE $TH;êprj5[UY[wnWN(Y%&vcT#8Ў}ѿy 7YL-PgLv_({m -$7r~N @E= i;Uooi-*vkB0dޅvL\^"Q$D[Ni0kr@]N#dFEl# u9C%(Se:%*2(gVN5 7}ƙ,΄2O1aDpτ:Ɗ]?4IF a?x 0vofzL$8M4qBz,a+&'%U<9LfWLU<='fulW,#ۼ>an$-/oWl5LϤ9a]#YK pq6xEd:>OUtfdPR}>M LEVzKhh% ?&|l c7!@j3W‹=182J pk2yQ־X6J8%"6|90񤸓5C6Tȑ<]3o:Ć -{a.!>(l#:Ⱄ`i_. HgՍOAU%y'8eY)(e-ɼ!!IIA-"TD(N޿Ǵlр C;\gI&-TK@T"ur)/zYoݸ nUk7nH{n' Uihwr%e/Vi7$P)F Dtg qTy]Rwe,8i N^:FoԺcX+ӑ/M`eejJ~sb&vZײ֢ߞحPeSPm'2K6/h0~'68:sMݻf%IL'c|$`N/{0 MJf;f?9XdFʓRgEE׸,ܾy_xD:iNIj3LDߪ2Tڊ'_W+GX4wfW^*h"`H~?:` ske '?%}6Dȕ,Öm6XC1m.JAt /-w6*Ohy`tݐC"$a.2# }"m+yyq;P -YOC=\x/wو!bp$[--rk9?\/V,UqFr"q L?;pFƩ] -L@%o_`P@ an f/%wm:fh'2@LYcF-%@Yef 2:|I^r9WY?DOkMӿ"cٜ0 w:cR2τkuJV{ )AߦúPw4>h<"P#T*MA8". d`xX++ћؽ\K2 WEBeAj.ɹyjۆuԧ  0R:̏̂` or٪8Gi=xᦃD_E/y۱,8xxh[n2o]KE1Cz4'egA/ul*G2(5zݥ f~@aa?ʔI £zuJMm:> ](4nf'eiKє`;*;|KjүyTw}O,(2Y" $'YyRa'Z"4bm҇zQ~;Ԡ*e/+`>CTb)ֳ_OXa4`]'2'h\ wƻ3Xu"s\Z~&Q3l0^ ؚS-ydYfss(YiUtP UI[j]enH>Q[pAsR_rdtc<#b*Nja0*Ĵ @諴 $aHJu},<[q}ݕ(AˉJ;RB`bJk'*|}àzO63Dz+Q(Ⱦ&b\KD$3>Stþ|g[x!s&1BO >dzͰ,!CP)3NNo}؇ٵ㩬 "/oi(i촳MWXDb;=ǷBhT\밶w[1iJZ[:kc2iDAΆwa[[+[ 4­>w@1x7MqmG{4!D^f$mLo-͐NgmHf5"ÇӉIT :kIj.n8SIWu\Ǖ?|"<ơVTٳ/XS9 کCcQTb zT6=>9v#aMS#DzQ+@4o|bLی5$?*ei 8HYZWsMD:fJvB7 l}5ZePS?[`vs:`Ib1R`"3 ' ;-VMd-CjG$Rj%ɽviZX_-"I&"\'=.}wě2coěLW6[;\T&फW'*WC$h2rKݡ(1!`y"΃Z#:L'S#߃0|LC&HB7؆h[$vP൭TuڱVW~4ȹ. 78*IgCȈ^'Λ{QHX6ZmG_-^GYa2O:C86qg{H-KeoxA/7"&c?- zt۬O28927 6 ^EUcp37y~gaCymҿϖ:s)xVp*kZJBl} u2 ?>?⨇weqb?SBe!DZq/.<=^r5Z XX[8/vLyucV˜\>JY>*v+'mNT4!Q$)%ZXY`q~_t~ GxʝaGDQ<4j3ߪ½K'xcc1/Q k]#s<Ϗо/CmbB_jT { :,̠NBl8Y%Ck_nO&Ձ!tswP祦l]uw#[_dV<[Cz"j'R&i't-{ed._ )X$[sQ8)DiKNo}Ht ] kBR%7nѢ >S'1\a)/'qΎ d/b4["P>8&#KV\ ;JU#*4cwe߅UFi>vI:cǬjazF`o.5E(\[ \E^Eu_#d?)%"n>h|K[UivgKPQaL9h ADR̯N 0N7l]+5Qg!YTpo!07_ Ԁڝr>} $JL}4@f+J ſEӵ25aYVXlWmS FplRTD̓i(YPvU^ȓrN*rM|_bρD]ՈunN+[iwF8.Dg!*&I9אJJe9G~-Ӷ`@^EaZe[Kd]Epɧt%g٤,eVhka_)wBokz{Xi{#hзxoΆ-VRjREzˑ QٱTAШAA4'PB6\= Zqv6) fێfM?s~\ˑӝsz 96dA!B/s)c-Fѷaۢլ\D#-&Ior<>ьJk`۔ɗG7vq+ک #'p6MH|{byoP;YsEفSKרg_Y 'f4xU 7bhui/B{]F/w[zR5~!м+F X+s[=^;HRLjeK5 y'GB{aٰzԑA9<4 Bq)$/wSV~0\y:k9+l3'}֍bgl,n34\ˠ7tgBxӈL|1$R&u Sߦռvw N |c,j/b6L<~f eeMYخԍϭȼĥff"x+9z?#︘ *Dd߫65xB#^e}g cf9KK_ˈnX@oop5*bwCjD 'U ,[YY8簥O?J98Ȅv7[T(s\_]DT:8*ܔ^O BҐi)4l8΁2W-WYh\)L.ؖG,uڣmj'li 4eF Aܘ1k4b^EQ,4%]]qiSz9@8ՕvŕܕA…Xc WղGܣZepkr Bӻd,#"5+pWxZ I  ;b%$A-WI=\s|Dڥuvى$oh6$h$L"\:( $7H0¢mCX|;$"\=!o<*V%8ThtW-sI 2-[y;C. yPZ󭧒b|G6.?^'Ⳅ-o$Ȓi9pNwďsM\1@dxMɬS62zAy2n.+_+E%SMy⢈v^v dЇcqA&^,%).b7}PNG1E>=L[.j:Әz)(yRRrCSL]+būX~pǥVd]|l Ԅ ftlQdNա>ɆCl! ED-;"C1ucgʁ爓T&<1[(vE$cLoGɐR'lVxʀޠk|TM\} ) ̑AhEαķ~5p QШLd}[5&EcIӛO N,|3E?q'qlGx? LgpM{gެZ.VFf+CٹbgFqM9 K acFQ* 4nA^єQM~/S$]uŸ<ٖhULC-6i[RIiyb9K},V#B^R}s?]GG]wi?]1ϴdxwxR~x8ݮrVFˊŖ C$6X؉jI G3= .ݒEcQM6!sqLֹ -}C<8KP+#@Ёb6cui JpひnK R 6GMRN>bs$=u*Q$_&hopEW DqbyOAl7 uAn'j_n5NQFAMqd`gcA]A}(&n';P %PFw?Y"gfMt6 \џ.sĪحVNPʌVl-O{ďk^y?BqUۮ<'}0G.'>*dj=̬<@<`_xδyCSGqm5RF9Aj)/,oR vEтhjoKVOCȋN\qiľSZ9+V  e,%)Wˀ%qV-v(8s_2+6zbxsWɱmSΛɣ:ϹE4A^W({D _Y]xyswDAz-7+FX gycuҀ;  <DK fڰqҳr>ai۪\csƨr}?.Ws$ G:( O\,W-Q_5J skFl)&g .I&On\`"(Zv!EI4I'h'mrLn ^?ȇ7ڤz?ǬR7wUs1ΪFown+UJ,6& ^'Z#/QOb`l.ɵW[qwPA9*(|͐WX02sEmx(vI.i I6 (ءs eͬ|rtzNP"\TJA#yІG!!puYCRH߁"aw+m$ *[u XqjN27J ])~p7ǁZ.&Wp]cvC ւtM 2^Nlc.F1qE10t g&tBVҦ.)T{G|Y3 dJ~Oú,ພ@?5|sY4Đ-A6ۆD> CAQ:hzThFMIȲt Q.&6nA eR@o.yƇiJn}: Bٔ%]uGV'*)qpK0rK cAEb3!nJ>jj 0^RWlcsfD0B ߩh& Bد*a׎:=cZBnDb(Oz c6ȥ I۹ԕF5 '\F/b?q`oZ<#bnu]0 Q|1ld|%GlCvn5U&/ {tF @& ~+Ɨ{킮(E3)Ydilhy"L6ZњxUgs{}L R=O6gQڤ <`_OAD_ s{ /~psm(G$_HGHF$zIE{ԋxI eQmQ߼Z~WKpDe葫eݴA.Qj_u[ *g2<^ )W-i>ҙ@C^Do4PYYi˛P]`mFHĺ\D]%7‚Ѝ:}1 P?nVp-͍ 1hi0ɔ.#B'Yyyv?tc{m e|iXv+I= 0 8jd;YYCLuzzbMilS'QM2ظiA3*LGVFX ӯ[RSխ?]8kv1م?o^8u &]iwD<L# fPg)6>q>TV@f.~g!f^L$:W]WϹ(NNX?HVPU قiq4,eebĻM2բhec$4RwЧBXfU0E80w1jZF(&a'sJ$£K㽼]"'P1TNjS09D ;BrW@&]nha+d8Jճf!#> 딪.N4^*dp `[dR0ivs& k&Ҿew |)%ᏧDᣁ+ ,$,LJ%`pX5ʚ r{sU#>lo`"BwqF42:{ӇfBFR7@Ie= GMZCuz着 ls PoBz 4oГNvWh|ǭ()3> V YuGKq3Ѕy6f kIqO\R6q(`1>|̈z DLOBP1[1)3P7Qvk ҏR}< DUq@oJbZW; .ǢGh`(F=mfnFqGl,ͫ#g)P2bQ5O_B;DYM"%l12Wc*m3rӵkR$`<˄8. Q vN˻/x\5UvJDhia~xh [}\HF0^%Ջ" [AN( >IFGnK[QF0I}$|X`LFAzdwIѳqRjlKp11H!"m35ى^}L{GyҌ(U]kZ" /)[kԍ1H:::'l%ٸ :R[ٝ$ zΚs!ճoߤJ>hXD}\%v)5}jekFY$ݗb{A̋4xwZa5^}V| jn3S2w]J=Y2~H}ϳ 2pL`^]bTjC[\A?YR'@<.|X FZtt*6a@ѭ1Ĕ=K( `iC*/Hn\Gr}&| ᒃ \2qyX巺5>Rpa||PrvTj-9lWTWaF@Ҵ@w #?lngNTM[{hJљ9~Zss/2Ζbu㴃լsi;  ]X:YW=a/L!Ț3d9|0Ex zhfb4&/^W]%w;l@A;1&9wރEiݻɼNt)@<Qd(&o]s60voXPTJ8),btL^CVNqj~BJ"<Ziأouj$d i2m@2|?49G_vlcħڝ#,Ԥ)rճPI(mEFa2@&R:CO! c^oR ĆEcx)5_(uZCMS^P)rK~ ܧc^xBU3sJ4Q ?|ͨ0I*-05&Ri<\{dA 5OwLbu]xP^oS2Z|Hu\5-U٭(DbSМdl-fm< Qn/r v ƍMkQ$(+2YcSr8oOŒ{M>,<{|s#~/nkoB֘]Fvݣ˩r%|8* ffi.t1]ضaD8*fjI7>,GwԚDQہi/EJ"-o 1FR깿iΠFWF&o?-rF yB'*N܏*XRo.f7L#٘eLfU cFpx?[ˤ>jo&devk~3JSF,8Qϕ)tcEb2M餋瑠8@ynlzF_$֞Z2ѡA4&x0 ,LV6Qz>L ɇ5$/Co;Ё>T1xӰZ43Ay%/ $Vn[v,3dEg%|6PT#ycv%,x $/.eNA)._ p q+7h1hRͱBFWEɉ$Tx_ƻ~ڈfmoڤTOvA3˪dɋmv3iT@P=FSX9kT%Nޮi a|Nc!+L«de5rng94v䗮/D>?D:R"WxVn@ˁ GTQY'I`ou:Nz[+8T343/}u&_8+6`b >TzGb(`{z?'@rAiYxivZ$੨E `n,p8Ykr$]xX( Gŏ\AJ$\'IbЌǻcU 줯juu&Ԁ-ihEڵHr%ŀ{dK J1`ZM{2Q޶&-:)$gܼrI).f*jY ݿC!F}!wR{ c ?Gٱy#ְEkPQ2~4ğammtmMdon'tE#3 L|;@(];Lш-ޒyeaޘCʸj vy6_M, .%BYN'H>v)tʡjxqIڌIӇTc|6 I *'aSݿ1\' *I]lQ'riGa e#iXf9Ԍ,NRpO7jߊ:hXDtN Qdcn qۘ4U(#tc1q29jL$Y<3lePگ> g}*zH7 KD`yPOwіi:9HS>GkHH?FqXMi^j}OTLJ7bR,GgG [B,l(x6Q9^$\%c}40 A@s'!*HzVݗd+e`K U cD$n<_cs(p?&$ _$ B5M_[Åt3 Id|k}!C8&gJu3$ǧfkHGq(u$^x ɐ s˅Io-n -j o}~^ڔ 91BԣwOdijH,QɨTyJeP za{:ʠs}Dʥo$ens턹1tKsn3b5Ž} ɚXz>;hۖE*hi@$gamURi8-J"&Ic+{#ґ!OeH$竢B'ghͳr&7v0'ϰEYY2:#ͫN*jK ]p* \_OeSWj.ĝ>Rd'^ǹ0S1r7D4\t[$6@R䫌]Ѱ 6nkR1$I ݛN{"W[d}͐R8#JW1N,dM,Lj% XqDsK<I5a-gZ^RRb' jʲD@1ki_<] VN6.6M6VCR+-y/NJC}BUy{^M:h! '{NV VQϬkI+PmMpJ.*Ń Ɓ wԖr(31ZWVy$rLΉ]j[0S yŎKöZ$Sf+=@&y3QծI*{P@4yqb:AV[i{&W$Jd>tx\`zve9%MOwx(=KM/yzB& uk2 ޗ`q'EVw>1-e'_-f +`p XxP4m?V VXJeql{JD t0CHTM*r%^,#!YmT];m[4 %Fhc+Jם* "=OINƒk =4cRWp?Sp+SĤͥ䈕rS|7+d]놶=ON@bR.QjwQ!`Qį &kZe ߜylx*!ϕtPM|5ۈG+LJU~ F RELq4!Hq, ƻO7ԑ~cD[[mLW2F'm7oLՖڃxk:|Ya0د\7)c!"I/d /krc 0 ̀7]GX;wdWXc!*&KJ?T`ѹۋ2wBk_[-=.dHxd(_2^Z$ŕ3 8׹< VCByyY6~EJb'G3w LJIDyħ4QV6 X 5n&2YDecHCM彌i);gTA`,nYo1^ !ОRb  U"dXO%,jE_E9.uZ"׀[Ʊ(ZYyNsl}2 ")L՞V[\~'li9JB/}pFFyuZIzw oԗE1yԇ`$oPe yG:q`TyӰMQ!!0b+IqtZf/*U>>#*#Ĺ>p6i2Ȃ?W: WD!О{$q,Zwr7:2^#MxZ??n*oƳv$x :YBf)qIcv]ّbk_,#㕟eMx{#o}4y%C E%N`cAPc\ѹMo,1L6?*y3+WGqcE)7{TAfeD\ p.{ҿ=\= d0O諊' i%RAj _cϤoÍ/ bCaEKP&cӻάbAe`W@,6U޼ZqEcH0$IqFN܈~y? :G< $l<6PCDHſ;rZСbiSm/EH;|tTP@P GIqOJl"E9D`wu ,}@Z_XY_h.۝ī5/EIrY\;|, hFV+̄ąC+z1~8(K .!$h6ȥN_;3-"?De/iY1TBY\Te܌ \.z aWrF\<?hGj$ƧX "bn𮩓|:G6ҟMlW`:S0T2F]| aq7< Y$xh 5?C}ސ 'K >­ 7;m "q'JѩƙШC3l:Z#[_&T(:ۨ\aCC}D !1 e _K"̽ v Lņm:eBܬ8M,2sy37hvGhxp1[3W!Oͻz d-9w4ծ޺ܨ*;% NztRC(a%ZFͻ=ҼyA"+F\;/M+}$~JߗJݐoDSӵD(l.|Fhc}=pڢA,2U* =5XTۍ|`}ոF;hl]\](bKOR37 u+|qvX%:h[ aS X*1dh=x!j<y2ױQ.)= pxSj5v#eq/lR G|UFgJJʼhAX=7genQBQgF͌#EG9$/DY% 5 3:9$vF \(,\e˽KJ "bރY{S_ ]4.\2PA7h 8MBF,:".aM 7>)ObY4i3wws1 [CVƔsӥ“ʴRmVCv";Zr%N|#ӘwFoh7J =h90| KGlScnz]^Ah LUm,ݴ(;v3i*=SU:Gm]`K;%q7?bv?M@(ʱбoϻ GPk ĻO.:ttOh\:5+Fwd^O:O #?g-0Ɔ}F4Pz2 A1V/vnvR.ԧ[G`!HGbMd3T&:߱$v6N@ǯOGcylOX:Ȏ+h8ǪdQUVx>ђW2ݕ >/c" MC3Z K %##i؏w6C;7>`G0ě+C';y㸐pz_R)F0{ ӋJ@8vKWLcc=bFVquZD2_&[/T)+TJ胘W2+aY* b3@>%Y49"5 I_@Hdft\?JGaAϞ2Rƨ ]zJs1E^ws2pfv}f=E\CNqG9&NR&%t.8~yRyٍUO;tLBwVh2F^#ou_Mwf<\M&ܲs[dn+%;y-xfzδhhgX&o\NFKz0d5u*DQgR77;L}V  쯚44ˌb45d{/h6 \:JL1Y~u$p=ߺD2nۃpIwloBER[D,m$ܪ6kE4 |ns-%HeQsmQLyZvDnvIb87t3rav du`'қa]X Ջ{6(mg xa!q04&;z$Uo 9v bWYJ^%C-F X0<mՀ)@o$Ekx[C TU J̗1 sPkJ(jυ"Y1W@`M%x!=R8-ԏOݦ7ǍGű2@4i|-uopCjˉPo(9U8\RC\м սJwFk前ok_j݀5ِR9aϿAlCT%S"&m0K!pjf ߭ 4pW!! [ZI`]ZKԈ hO42ɻej 5 K{!GIvx H0dvSGY7M.7Q^[_G\R02dj؊/`=(n3m6 `79hgnZ@RHF-<[r"Eb9KQb<6xTAj=wO TRDp|ͻoK<o]ݒ31QbB2%ÓB3`y *⋉N?Ubag%d]?5p\ U1\9J}aRj 55SŘhWn)E4˷:߉!եR eP[\ q Ӛ7u'LRf6p9GP'+vܝ <%p,j>MYx3,l%pB#V}`I;NJm ȧf>";*"ёtGbYW>|TG31kΧ4YB9?aoY&BײQRO+Vq>Idog#mG?K I={dk[5PÁ{~;p ^2~IGۣ^G'$ch,wX}}3=jFR\;NS΅Vk-5b]TAlv3ڍ<ɂCCzy- Ɲx, $yU .3ԹgWٹ#o?%>ٮU"ǒ[9ҚTcN?/t㨝QkBZ0]̘ֈ9zA7). `ox)OC%-f?b]SǞJ)7RN,uS~~݂22tPpƜo½MignUJQfdqbxU |(0$kn:[8j3[YQ}­aVaFh(҇:Hi ~(i<YITϺҰij$E!_wpjH3y^2(3Am=ڷNYϪ҃I* HBưfKHB1_3uRPc[۞h@D'Ŵ:9p1h[ݑfG&Ͷ$W~g׈\y舆gZdz DFT9lQ6/cȩ@QN2~Κ=Bu*Bo[r~l=`]Ҁv2!Շ#`}#9aMN~$gw\#K+63"*$ <2*{:V<ƒg>U\yG]J3"38+Wy cRߕ7$5Y|#DJV{>D]8߅hcKO)\ (!%n] i,ꔊ1u\ۢيpYdxY-"dt#: c^)gN(Ha#Nma#{ 4,[J+mղDSW N98uefw&K42ΐ Y%#1u*~#Boh仑#N+ѠǦ%Z*d[&-J8r3!Mg}1:#/+)~jLk1Z[h$>K fFO‰N" i-:7y7L(w庮O[:9&yq '#&\G?JmK_)rđ?hGj$ƧXDe!hNjXRSfu9_aVN]Z *>^Gro jvɇg|74ecs}P.32XF E:5,=>MF] v]yti3DyGQ#' cyuD)]In_IM*4icZӡӹkJyBf. HH+C,)i>}7]˾X& @lĠO* l3kB[j( Yʦy3$>qP#uf64DN3nor"@9$,5 V幑ACUQo Ę,rxIT hVfA^nY _{0ħc񹐯8uTNGoK hEp[8mQU=K%ھou(mIa+0>:M?=qt&*S7Z.tQvʆ!|2˽궮Bڶ0 /Xzhh66"md=+!H3&LXt 8]ԗQ{,%;~xcJ{{[@s5 -R} w ~y VbyQv.΅lY 0Dɾo8fS:!.0#StBGFm'uՖ\&XYwY)MS| c8PB`3cbj]<RQwQ:G_'kf24 ϱS W呛CLU#[=< &E 2ͭX4*W6bP_F1Sܪo i2Ccu_V̈́S y(\,& <{izwC$h /Nq·W]_RM&HB0oMK,a>ZBQPj4QB0 Cux~  AD$3ZlN0XY8&!\b3Д2ꐆ¤.h G_Sp4uX=0pZ\݇/'yW TAqHB㽌LplP̐v{hd,P䨖iZz9˰ hoJqnl]{VG7cnA*%$ Obl)^E|vU\c#L?5rș$uR+f⟅_NT;)BA hb]p5m§eQݥqͺaS#5 % G ׄwԦ~.hRe-qM!x=IX4}3:?[r_M@v/uvEly ߜiqץJ]mYӊ !9KNyYgÀ蛔Jɷ[}Ģt!CMO ]yk8d՝զ˕\YNߩrxc7Hg3ςțb >V܌I(c*h)#?Z&2C&!រS߆ (0y#fA4ߝ y5/4oɸFPc rnq'dB;&4I)wLq7G,oɑ}Tp+ (1aQEN[zy& WcSLtz<͕]1rVO^Pj6zٮR)&}#`&VYgl=,x\=FYlv{Ͳ庀aYOv^6}4}NG{.t 3 -}ʜ25qpe48^J(Q+ɔ2L@CzvLz;5*/vzMPAv(0 Ȕ Q:$A ,MːhLFjc yP$Pbyȟ|$-F ++;&?a=#[5W"z ꥼ6b yk^{U!(P_v\~kpQ? XdET( 6Ǵ 矊{*TΫ bJ$H{LJlvQЭA7my6hJ҈kEԢΣ,nOw4 (y_5!6Ë]y 8rQ‡>27*1hlh8ikf|D,U O- T"(DRx_H|IʹT x/ tR<}uڀ(>V'giP=L;C_kS}݂RxM#-F |B!-:g 62S؇hH経BY#h+u[꓂vXvu:@[#\S@O%z.3&C{գIzZCIڻ-k8o|QALu 2_ k 'oRt7mxC Mb|(ݦCX +ߏXʺjMDuܣN  V^隽V|v>A9{fooVNE$1Nz*5v_SÑҡ劔 8i4 D D9q9>{?'1Sv`U6|=A_b]9^^]k\ݑJq}Xӂr&UAG e0n#<)kT拒H!CvQBu`a[)M =8.Omd(I*_< ߽& P}+Hh/t9IV8MotHmJU';ˊ0H辌_Wr5jk zƊI[XO]L6h9xXR,^aʰ.HQjbE(gmv@mV0T2;BGߢ9&3sR4sr=Xe0(*͐N|FtrZv;DvK9aF!\y8{؆߆ɻJY !4IUpýSޔҹאָv\ n.|'i.%K&0Ĝv~#;gqdRz= 4`wYnﷳWl`_W4"UC]ӏ,JcY噩~Ś5){f+nYi-|5IO)d۳W4D_o>` OK]T:^׿L*1 dؗwnZHp4㴘B^mȬhM@ ax/%T0Jh̫rHn˖CL߯ؤ.#vO?Rzv#p&L5#X@Uxŷk \2N"2kg.r]./!,f&l}v<bglUr .-O<Օs qZBφM-H2!:!uԦ[DeȾP9ӌ n0|w?JωBMܑ<߫p'_tPI.SS&ҊW$iy2|ފ&q_u g+a8wB+2ZK$6(Cr#y);xJXbCG c$*S}'wBH-}D`9  o☫)3<_#Cq6MY= >$|J1HUX1%`x݅DpdQPG4V\ 0Bnxya2Iuv5_+ "+0b]^Px0螑SNsLǷZ?yﰙYNS̹٨%"! f/x8+jo"Rq,0" 4'KLa?NeC>f^vmgFM9fahvj`1 exY]JT oQxjSLx՝u*vS/HxWv.,*|88 ކPR #Qಳ5`@`WS &3UKF'T ,&{{oswD gzӥj)%eE_pEG*62n J-bBIu{}u}#!85,@Tc!?E~d< j JbHMG#|HT噥 i]OQFdy"8'hv=k)sdT' kaa:m%7$/::C'ϱQ0K4tA4\Ŝo? 1@db\~O6+:fF|O|Q> $JKsrU7 ^/P֛5X} g'Ke3H 7h_tl9>`l/Ѧl&8 UtH*VwҔɺi_urK5bD\s~{6>;Ejzn%_3=3^Ӿq9g5~QS E?yлPnn!#e1A5A_h$pO,Ԟ$!:"JKQLOvFZND"_|@%eF'к)\b8˂ o˜7&;^/}t(?)%Ngܳ;㑮{yؑOROՆ9MYִ!m1hoZdzӹp6l$s,^ASG_̳/\*GilYbi|r'~8trPŁA }c )&7n i]i5Ak-v9NZ7:bP6`0(ZOTw~GX>͈5(4 N._'h^ֱ:+> ,26G @wp'qA'F:i Vߡ֜vT*2l)C3c&xvW)D5b~e6p8-} Yc7옯pI +b*PTF+CVFJMYÆULJgZU1/L~gf(D,%QF[Rgz"YqŴGZIcSߊa0TO'%rk W>g%-C`ړj{gj?WKc5ɑGcק^$j~`9Y^Uxed7;lj8!Bc.K zꮮ!.f'9 {Dа=z)a%6Ma}F[ 3A&+v /|krmxARΙbt=H#diˆ*rG-7ESY&-W9yrEZ{JNIW &D![w~sN38O'-EN8DI\iic09j jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 }C|WÔb 1Xx9*Wrfn)#q\& 3r> ;ֿ=R gg`0/4b%Α_Ӟ0IĖGNL[3DayMs#v8ډtk+Ea;70^,($Akf9ZWWX nbŤ'ޘml EX̬:>1vS_@ΐ@7kNnFgLkkTj f&Vg«M"ܝ pk⽰\Y, Tz<G`Z#5],琉T}iTܾYÈ턵J|GkD0Y\uLG ,R8%&-(m[M>V:2f S_KHϚ7ߝRkq2qk᭯;=үiOA*&;[챨j֝>*&٭M~`E6e=RI4rHp&([B}㬐 Ӽ M:Lx`` ْQK^%^ld)VtTӆ2Dj4TB=54E]1&ŖD_|X_6^YVE=U1cK [1=q UZYM5# 8j]u6Ud9acSڽ3"JX U6 y7n\ˉtA@ XP jyA\T.@r<ډgP1h26/5]1[cAIdvž^Q;$OQieaQ_Bj7'ǎ[ pmC@M }Nh1 CӅU/wEav{0VƜ׾uR!VX]{)I"W\&{S9{1٦ouAV폨`B`jspq"[/h6J8h 釡#m.n8IPrSOvRZ~՝@Y[iφE_DP3]Ȏs,[މ3ԑ!& 2q7WώU8 A,&ˋbuQAiQj9ڊ҄X`8k<G8%טo!شג_ 'YWv:Z[;{m! - ;+`27oOM3MoJ D5W9 g7C$w:}4SUw8`^G-WU-*4?W?;5P M\\wU,]L҇JZ]T(򱬭`Yng"{i8ѝDO2K[LJ d䒭ϷxH(QpIw:ܮZRGt[O)_NFwxCu_ t5Y7'9HK+1Mke@8U^4R+܉WH>DOCSQ %oǚ_ !?G Z{3'1ťkٶYֿ/!d.j;O EXS]rֈpmѣMZ-jz-wcLsݝ7;P|DDr^QioK8쭬+ ܏%!KuoShv{l/  6oDaBkxwPS/Y jk{fPLvUQy]^nq,k۩`6@Jf .16+fGQ*zHq1AO;:y03-! 5QY&`&ֹ"Ϲ3)$?XHE O'EU(h^ 3.ؖ Y~16>P`$ AUuMWɗ`3ڈqζbE,?Dh!^;;=%_22?  =uuw]mASQ^X]p_(NqjQ/UG/܀SNE0flp(6Я*2S)yݍeO;L9/@#ހwaW{}OYh8ML#Ef [;c'}t ~Ҽy:GkPϵ jZZ0f#! cC}]&8q§l5l::2%;qJ/2P~Jyy|e"]}VCA@gUB'72]QeVdQz+:dL l)Q9h;D](=D dcaa/:+WC Ǜ{X| wcAĎvBZ9A/(2g;lfΡ 6"9K:a?Z't[<ke [!DLjV=:N&[>Z?O1rib c%^ 3x=hN;eyxk7O{>h-!q#T ٹVtRD`:0aw?@!;gB[cVlsAd(Z녋P9,8hoUblB &\<,5㧏fϩ:ϩŇVɂzn\v[4tw cwtx*-9xXra};}"^+L_VȚ<ݓ˅hC(ސF$^7DI u5BlHvsפKq.ؿ)T `RSw jof<|B~bPXМԕZcj|(!RY6Ћo᝸7`Fo޻LCRZaKҍPY撂jS4iXp%"sv˫oIhH8be=Y!5QF].ʗK+g>@[dRd*K}:ESn'5,fu7ÜùVvDaݘ{i#WPTWE?H:BXv)0m`>tAK 4g T!CDmǿ*T$ĺ)>>Bz"BV#ϕ`ǀ'ɽv{ulMʳ)#pxh[l_x%8 { 1|`oru]ΪCZ*71զ)[0etgO*T[]G AbF^).6&c &aWo ؕNQoJNWcѬl\BJxjŻ~qzR/_6Syo$vA-[SdKN-Rlw DV<&"BŽ92ó_,lDRWppsU,ծठPl W5 -R'6<[@EQ$ OU?26x\Sm<w R ~o~CEFe_FzzmJskx֜잭R3ZYyӭ;xF |>۰gTT-i 25A_vw'{%xƊ99 $Fk;]BDq~;?,ljQx̜BJ:>"$j+LԔVe3Fy.#-sռ>d+?NL;$^s< KaTg+No>2.zAiܥЬ"5gҠ@l%# y3b ^8u4l0hc4)%M@L^Ew뼟`D~'q4ld;hs% cc/*w$tU!z)S<[?J-:՚m뭟r$rM-O5ydSHp:z^i؛vƄ늤~lOƻx2zMYaS'2H򬷢Pm͐'+2oA]rx̻XK ::'rKY2mGUA'!$7gD(گr;'(2*O3~'KV=&# Eړ2sF7$ A!qƪD*ЙQK6H({0vÀWE%@>A+]cމjGT 73q%lB7L(][4ZԿ%;;a|OQ[ XrX:-a%^'^Z)w WQ(וITc<Om99NYxQc{YC!TaV-7nQr۬x;\rVFx έ>8G^$6AjI39xhX})ϳӶZv.oЬty2TyZ|pMkЊ~jz*m$ Ԯ?6Ia?:ZS'u/Te 9uN`pST~RҠj/ۛ 4ђÞ5&d`+'-|K9|o@ڣ WZP!InBvNTP "dFlKrDyƭ|^;ֵbUsS4n(}qUՁcYt]i7;tZvTLF8%W fT첏?al<]Z 8g>r3(K5ݙ !9͕{'{u F <8vJ{CaWO}..?Y zH n2!ebEP$~rDKVt HƳHClf4`8jmM֗gh5%ϠN$ ߮ZFnݲ|LC6u}PJʟec"ޱQ*VM} yhaz_P|FN}ڇ CG6@4Ml׬HJrDK+0C`%YOsTm4WMyMIltrOL>0<0°t w@ʝL[1AWtLat-q 4levO:`;.Hf}LK3R7%ֺ|ak)Y7L| ˹ onR#"3Lks6- Csi<ؙ,>Zq1* cetYv=5؃q:j?\@?*zS֖噒 9tC~H~2_Tֲat-\ _%H$3ދ59vBqXB[9(N[*\9%:PA:6Ru{P x`ǼMɜØaC_ .Qո^Fz>F,x4ݐx}} ~EwIc]Ĕt3- %2q.j i4|$QO$S;Fi}@YH۬y~ʚϝuB`JXyN^J gv 3#l3Ek}ߣ̛谟΢ >ʁUvZj Co."$c XUN*@ﬦGpEAOgG%EЧ( lth> rblTeJE Pf&ҋ' !@ QGSP]iNA m% $al]gOG̣m>pҽ/+ׇo26k.Gb3|eUPO)̯([x_(}''O#l1 i"RfNWw6i/P;A,- Gl:|u+NU`CL:S[s,T`| (]RI3g@Ugiŋ}S"%~DX^}y]7Vxsם>ѺU'L@1%+jAGgI̕ u W. 'Ux\t!l?Au*P.p|Q'㊏ ?idvCgԆ节@fiL0't͵" O}C aا%$@ʃFYYJL췁UD8:܃іLb\lMP#0cHR0\3mVBxk4VF!8& ޑǍMKn< ;X)RnUh^yNU{5 bNq@۰RPVt:,ɒ.'4ۨM%A&%,6E ,`oV("?\= 7}fqAq8Ll :32_{r3a|*8,-?:̡]^S~8K'. d}7_jGn=)#P53;fw%"8U"2{ԆTZR_-&l A_JunW)69?(x {-o X.%?󿛍s,j͖n%Nj%=(CꄗT@Q9oXBb%j iVQ\D5{Rʁ+o3|<(g}# !rZnkubP%F?p/t )l÷dCE!Xn^Wm//zOVƢp0Ze0x!Vr{YBYp0tqQ->1XP; ]$x,``{}* rw{=^j.h 붛8޹Saa֯_5Qy!зLQ4^Fsd dF~zeh[ G6qWiBAq]iYyݴ5 ^O}<<ƈ;{GOy\/@ceq!e]~OZQЪ   8 Tex̍% LP{+ȫK,3ЕmQPKbEcbrBqǟnonlJ_~`goqtqJ)1C .YBT}m)jFh*q>㕮 F:8m5{ NqRx0*}nݣfGǙXl+b\uaP.k-*F!(Åˍr CT.68~ZU~DKP5[05u]QMQ:3A#n-xgjΠzS KpMayEě2F82| oz~@7CL.o?Y-l7" oh}n3a[/uEN/&Z M[fF 9riMeffĶ/RaZxi t`rΑv;PsA&.Z 6$3W7H<6p>#S8.B*On>Nzgh -,45e+A`)r_gTq ʿ>/j}Ѧ|]w)kL^Ak˲澎` 5 t{%FαQ8se_0DJ"}dCh~|EH4R@LPX'vh,GPҿu-.ėy̍+˺mp=Kϑ /9i53d#ٸ|4])V@p)@ʯ*uK\y+yDzL^4pR-C#8%e\cQPr (74LZQ~(NAǷ]b`z"@b&[Lr*qVxp U}zd%DN{7NK!ok}C[Z?q0\? 6{-Ĝq)%V`mzgη>H1>;3oh+A38fztj %̘>f__ \$.i%h1^ Y2\ }l] O0*126cH (f0՞Aͺ_&ݗ@bafO&78K5jVk]JHucȘ Pb+vgM|uHveT.AKU%" +]Qb2MQ|œ/!M]᫱AGIVSҼSDe¡ )zĭ2+olQw)#wվ#XƫcG4"<\m7*5몳 ϕM{ކa{Є.NX`fĬƲ\H~][`o$ppJwA ^mᨒ|Z|#= (u߁ny|"ӵ(cwf%&օwSXץezg51 )Kuhukݔq[ɦyy N/^O4F(忌w3LRҙ`TGf"5\@(8 g{nh:aw`NOD 6?lA~Q- @L/Kbʲ:xP3o'`oGm{z"/DR"‫.c36_-͟SL:lb_93`AτfD#~G i^݁[_ϡ[w*R&Xwy뚭w..'J/1bFU@4%?`h퍐#|=0#a*̿JJ$&]Ա) іg_`29: nD"3v&ů4U_2A  X҂aV\M:k @`t\j(c sͅ)Y5ZPTTLR%fCJ{'vU)J(AG63 {?aJ{]0Qc<]W7Ñ#6~O! REyggMlG=8H+RhW!GH-4V"4Mh3|~c(ąĠt:=6,j5UGgqʊWx^_N F8XȆ/G$Xz+*KAR%^F7%!$hD]Q7 ܬ|ir &#6`D 4A=H lf'$EkmxU}!sU '߳>rYrBf]# ۳M+Y:TckaB.j ~aqÆ%`}CyA)w)y%/n了$ fJ=h3槶S8C4(==8kNZ:+-L[b,__ޗihB*3n{xoGTE#C\>^, Hw~σw6 eBNwocY`Z^EF98͎jut'THj>iCZ^闎 /௨Xt 6efeI5xcfnPu*t0[E(7gg!;J3CE {0\ဥۅ\`]ž՜Qj^5{jle.؂ӯ>[:M]^-O][|309ߝi6zuڪ~*s:0i)\;P\>!vE012M;$[-6N*ݱdoz];$K̟6l%ϴ1ŜMfl P""3?1Ǚ5CШ ,/UFer0:bUOˆ`U3$T q>`iP; BbOfŁLC/ ,` IB}0AǬbUh76nED6qwB L=?Cέ;g}4Mō #j@U2I2t}c2O]⛃K؄X.% DrkݟOTR]v@V̓{wڪ>ey!v[_JO?;;ZD@͞Ϋ3k}^f.o'SyK=+Bo4_jDA>ZSO֋Mq݀!tdTC AGح^Nr)AîK OgZt} W-)`P>UDY Zfj1DW:@nP댾T۵~Ur a" )4SKs+m\!\ȄHms 񕿀@q'-LkZQ= sE?GB7(qª%Qa$yH0\bOhS>RܱbhjFi~Mv.tz/ø"$X6c65drZ;>ଯŞl(aZ$EO 2 z*؟D@ƩR$+53Ns4y#}MKscri9( I)㳥RuksKč\XHiek| bm>^^~ds83XCs/OE=kefO^o")JNoMMCi6R3:{~[`h0W4B(W:HJ'.0ۍ/t\ VzeHzvBRuy]W<}ôuFxR9$X3E}vc@}Y(,]=BQ@YKBl]rQl*(QgPhP"r_2Bo =3(1KH~Ҙ&wW/fhTbމi}\#,#4Դwp"-&Yv?>r^әM@Dؤv:0G.۬ݐ}+ uN[< L:(Tď%NNn]%ꄗLec Fl dH[4H_D I`STߚ7S-x8A!/E9kOM' PHCo<&ls8,S*qPsgAQ/six׬َ83SƖeɂm[;WϸыO&/}P}s,ǶϥRnΨ6 4T&NDY a?tbVF[}tQH0^hk9YwB'af΄SB'aU@d&I=W~Ouh2zdDؐҽ<7PEڻ~ByB)FA6JTEEYD y`&I*lIMopV쳘~Bd+pVLf<\*Fb氝: bj/7*CAu@&ۢ PG; h3O&ᡊ`dч,;l.̓\´!\7Qp=*[$0p08e3K|l%0P}?Z(Hiԙ|ʖ.R0 $*Uzΐ,9K0Eiy MZ- v* E=,bfB'ATJp!Ȋˏ3D E2Cja1gs)(knPBuYJDz<R[sc* @h?ӥƠmlvɱRp8ϸ÷Ⱦ6TS=AkzbBy kнB ͱ䰘4듲ɩt:yB97~MNz{}c-^C`7fOυ70"|'jZG#+o ,%2൦%x9Yt ^.cI,O-0~bӣҰAe9Gx)3?;b>u9Q94κ=UH̍`zd:Ͻ܈$71^Dz-FS?Ԟvъoie5 ?9FFȁCEY W_q>HN:q|gk˛<>.][$ [.W ܪT!n`@ ǽui>t w @O/Ҡ a=@.QF^Fc\9A8H7ʶN2QXwԻbdsQ'o#.eaMOZE)1QIowEC<_Fբ,?8$XIwK BN\^FΥSzy5-ckn6tm21 n60ЊluUgZ܁9cj tF@;n+CPzX:Ht @gh&gRkl/IE,4;dM-{ K;2{$̖͡!ZXͩ0:1%';R~g#pv F쎞* z&=,g/|F.# ~Aͱ*γԏ%ةg9N)kzekdV;q(G*M{TW{ЩdWvZ.?9&ǭ'ay$q RZ1oew3\j3ļ?GǹZxzdc`(eE-yh>sqUm; 9' Vk@aӽX<A1:,iAI<,[2SxH!qt} [(TӤ..p6f}LeMIX`b- MR b@mim3WiiLb fЌ/z;7a:xB*AN:{qbf"JdDŽ_4~6]Hs!t^,,Ϊo FQ%-&k|38N>ư/tK M0G@ZәrD=T46QZ3aGۿI+ >rgԘE͹eM'oL?; |Vx2 b:ԈdܷM,r&k s#`sϯ_tJ{૬ T^ij/Q1#ʵijiߖaPp4@ f},%17M l39#vo$5K^h鳕;=GN), 1Xͻ_ywK4= S, ZNWޜBg2"C(Uw9b>)337W2ʑ.4\9آ M.Qce .mb]+e\=ގ:+*'zVU?wGXsS~4WY =t݅}рdP]'fBU:3?#tfuONDةd<HJ<5~~,uN.OTˋGMmT Vfs0!쭫vx\[Sje'*$;?L``2נB>ZQF[_NEra*RqAC%:{ʠwJvj|\!!zE:1) bH.6Sc4zR֐z_&gFvWӯN-n[94"#[%,ɩ^{ XDZWD;kgB+E1I@IJϤe|֜_ cv-rGۻ.n9=sʟHReAtp+,~8Y "՟O^ͻp|,9 #1Ydh4HuW)4yOm_yEUY=/*Btʛʹ%;H~AR}mВP+)}y314EӌNf~Qd $Zi=Dfݺ;, {W2$# (E1M2͜^. )B˫ι1&)Fg=ۄuSW|!d]O痰ʘ nq )sV h'ӿdJ[n-}t)&\HiU$"/YN' Ot ጲZㄿUn?6poQs%{a2$`#HͶ"ӹܴah`hz9xYخOv*F^G2R?Tp' c$yLsx(HTPCa21VuU>=gE[!fhK+p%eL9@îQ `υnQLLV5f ZH{9E&_k${-h;zb];CJ>YWr?Z./gz`V6'dp RTD̏Υ&oka%dDkV1{Z'"IM^S?%nw:m;s!;n?jM1߬޺apESKľWew[_\/1kT/r)DZ)MC{M$5ݡUV>Ǿz!L~Rv*?q1NЏ::OOHkqZ>i14HN ys Dgx Z{Ә{aQUuٗBFO ˕a29$s"D|R F$J`ȱOKI,cW>Ad6X6p'U$4) 䒼weB@ZG^z` oBQ5%13rhp2qntpC3*}}%2X[ m1?dInu}M4$ QAbܻDbz6hΝ \H8w l(35ؠ +nRsӴvz#_ 2\3H?&4M wDM =Q-hN:p'_ddqĊ]N08kcog;05i4 I ΣeӢt9bhT5(Opj#ّv# K JD+ 7UC:@͏+uSh'LT>4&$}E"\g+>o8=:M8^J*_͘3sŒyz߇k7Ivo;M>OُOn@ŴDSf6p|j9fq/JR9_׺T7(9>͂ ]zG޹hn0uo36oq@d0BmBBy|$$H*-8cDo=#fw5Xs'BQzYJVl&/g"ssuޥ+( /pvۅ3zc]{*udD-ytV"rYȶz) Ώ?BcDhՅ#ݏ9G_{V'ݩ,g2h9#HӐ=̪fYpL{6)!}EGˣ[Ur< L!IEJQ٭ _M[cf+Ղކ%n'd46܁<(}~Crq9Sԓl֍Lj%5,?PcxW֓Z=̹|]VC w$Tt|zх"P/m{M=zz8KLd0lwJ;DƞZg</4heFGjٷq(s"ga =%$rGίo Vʔ Ġ &e4fah+)n8cu{'Ye~ Hs1PR-~*iXMm~v{Lzw$wޒ8]ې;={L Z]PH(I/ցC 5u+tavNށ ᩆ9/3?b#yse=:pHIIP38֞2([ z|;ct|; ҾL.\¢wCEՌFIHtyL2Bi2=MSer/rʹP'Dwl1 lt,^)# b ȫC fÇJ!ByǛm 8ţ=]LU|7>*,Ϯ0[AB X@3~HD b8H;llo4rˉy7dxPw]lzgǧhx֥v_v\Jݑ}}b$nhҌ2?(e ,*6ug2KF7m;g7VhLλz&WyjҹhSD(WN6w +o1Lf#=ʗFʏyŭ!;o48dBeȳqʧZpȅφU O0&i ~~en?5*"#BH] {X'[@Ӳ>I`bx^7;)%MzGPQv5D(VVXfOM"xD%a3OE-=u-MgC/SĮd%LAmX W=^ )ZȠRnb"sF~S"i&lۣ79 Iİ9RPʂ+sylAZVz={k9 ͉1boHfghrU(lH׀q4&+(dBetpp&9ܿ;${ھ>cghuN&02WuA?JQ.QV<%9( $]SH8Q#$vzxM_&uĢ(K KHQ՞ƌԥ1g"Pұ%{\p ŏr5wBЇ'q 0]J[,}𹕲]XbGBЯ=,r A,{&QMO;=pA =|HX Q,\4A,P?k>y⿀E%{fEj&^N8l#+-P.|7!oz`B9I!rq-`N$2vl5Y݄'X/a0AO  R}JӍ@[& ބiB7TmBU[[4!|ο)~bHti2^0Q؄Hczv!%]qxd?5`{u3$h!|捛z49tOOi>agfbKUv a'Jњ7Õ+BYLߣ~'SZ2KQU3>k$6f򱬏fT|HD46X͹Pw/-̸*A\IxӉׄʲzbn"$CUXM]*M9:}y Lv [D0;]QbV3~ֳ1t$"H6Lm~Ծtќ`q-?l 1p9iPc=q#ŕbry_;:0չw}%h (uUvXs8 1up~~`h;Ɖ;RS O$d&:Z4nyg82jh Gl)s0~ͭ8e67;  Lև"4} Vz7;k Mjomtr.SDrQ 'e*q͙TƉxvd$Cה=wjf&c4F=䖼•=ڮ;}9",N$zN.^Aϱ{3d1 j#8\m}׉9{27G*#/7#1͹a"U*.),`8TXI(#.z<>)Gr4zɼ'ZVk$:$F2#ǭ0r3bҞJAnџxD`GkZQu OH4WzjME}ouH9kwb;ߠdRo;Y@$if&=ET7Mz|%CYa#"Qf;jB2]:;+ NJ (PAfQ J+όwvVn^;%|d!$9jnWύJsSd'G ƘВKG}ʄPKi#Qlo%Kn'f?ZR8Rv6clN֔eI;NNx4Z72y PfJyNBE"X&AZ6 l&p!H[T~"(x[0׌T**%eT@&ce݂ϖ\6Ij_+ޫ@Xy>p[Ei0~j/e]_ gL"wMCmԂ:IwpGGiU14ۑt7StHJqTz4h\} HoH`& lJ$Āx;6l5(\baNI2#YNC߈v'slts}!ҳuӱ(p̻.2(9<7 |P<ο0vL9ـYvx gZ:G#a <5&=らTG#6U"iOq(v~BE4"tE2,k]irmaG f1g"'d,SPFzvרqXyG::3k389[Kux FRMd$z Vm۸*>W15qS+vk?Fp//۬%w$*a [Ҝxǘ:%ןUeNΉJC ) zB_ ;qjR_ EB/__sA:Q3ر]DjL痬FxP/>0LuSbQ'&/(GaFjLDaz_ xl 3CE|X۲ِe󎸵lJ剴1ZHyM+lcM-Bh#>=͙I[xGGq|!SU]״"cZ41^DUQrWQ:.N`F215 HavZC9^ $L 0@Yz{TiV' IrU$yw-NJb.WV6É2{س6˾k_cHVeũEoF#^ڄP*K)q?O]EfoB:HņT?9Cˍ.q\n[XB3V c4 y%ATI?蕑][TbAR`mGP 9C6>A g޳oR=O'PQ;=KXTFElRXhGu̟gӦʾ3o]psՉXs`?@OwNNXL)h =?ИM>%OMv[ y{E%뭕Th$ sEK13 @\#—e~њD 78}_Ʋ ^PFYgٿ(K\ĎuΈM2:xKWh}oKmoȏSQ ub28ȅ$^C0x!nI@ԗ[wu*&5evwr' Y{^w1NI>-/w |}}g]?A'ZHig]>Kx8S%WGߜSWNZ$`gYVWe8:ª)}q0FKxMkSSr'%CttEn1kKϋ857^ ظ9@Wt@^޵a~Agk5`=n}bO%F nC{6+_yR\WHyࠀ#{R6Y(PK_ح-=^?< ppəR|FY mW&C\Ŭ~߆ѷXkz`ռL o|®[T:f:6M?+J]Ѭl-/=9ϠO@`rgϮ[20>)gV]hLsfN~Gb0uMiA15dA58@c5=#7 vR\@[wcݾ)O'<6O}p|:b!Y ["Q3:7cv/;Qntys0sN{jE LeOAeEr ᵛa|6@ZP.` zW+Jۿ-@~/R6^ /fnX[ryT [(U5;Ո7le@ O)Y`llE>c.OWQ=`vq@yPZ[}0^ k nyR$VSj2ZX|FQNэa8R'ޭ@w%9@EhX͍W? ǑNӈFݟ^KxSnM K¼=#9A%DʪhB뽠'/.o&`Lx*eln`"3faZ/R/Zcw9i aQU`v[[U>uo(')ՂeYW-C{|w͗ :e]`u=pZnuK#?]XZTΖwXVϟ[*;Qw`o`;sS2?M!0 O4 &aS[H꭬qf)D"Oqݺrndƒ 3#]%Hkz:rJe|bi`ۓ{ˑS)1.ˮGpQsg`F "L;KT'RȖLՕ(On1! ]7֑01#׫ X;r0TB#;Q{!gG! h pv9"Hfɦ@JY\ȄVyzfRCNؐ/G#2%`E>,8MV#˭'d"i@*j-9%b<đklK3-G/=ўޱOAT5|*8G jĘAY>0 ndvŒ:Qz hK Zw8M䴜U6bVv.!Uif4"W_2#^>a<@P|)BI4F UOўI/:14^A7Ӏ-ɍǑi 9݋x}A1ls%p;ڑ|Hxa?RoiyJ_̆#`` n0ەcKry,MM~ESjI(O֎S}n(&w5 aQ%3  ]jMŚE?.p?cR778t^N'^#7 0!vB0e_@)α6_w^Uoy1C1t QGM}8-ѽ:mn9Lk[rؤb~IeQ'' -D=<1C3w)9V;w82qa3oCE=7YRSK@ )9F {*z1աF![5{BSJT1J@d'Q{ H¹ "=>(q{  0\ ,PjcCMux?s{bnU 9G/PaǭRTr?vc8{R儜?u<"\mOFI.z8{ \P!p* xPӰqpl%Vk]N5ip9pYTHEhLHX٪X 'aZj[9CiΧ;fg "Und T@nUF鮇֛͐(%&GaO%/C4ЬQM@2IMDz}}[ۻ~ޙ7fn~zzFؖkLq@oW_ "D)Zw+V£KblF hGv-H  +_W_BE#^Α)vX;Q([VlQ^A[ߗ7{3~E6S1q,͓agp!> k#/9#/cv!0F }(w;dﰡWf;T w+MC0 TvS.x+ Drwdnծ5gtS 9;ۧFޏ)aRw[fM4Ɂےvd*Ev+W|[0DƇڧ a~XnK\i:%fYMF{j*ƍ̓E-.*ik}IF{4:[F}r:G Şxc=oj2(&إ?'>ч_al&k-A2 F瑴Uis^Y~H\<=i(~ܶMLX*gHȋ%xړxd&͜-q.Qٯ '-2aRRUO@0 o[dD-&4bwϖ`״keL81}!p/Ia>9.e}kHѮq*_/lQ{]rjl?kA>TTgi*"ͱo;I4 Մ5:}YO;{a0i4꩛ #}׊_[crZ˯5-,ӟhw5'j%PS*- q%O[i3j#P1&.3W|:Z=w Ta.c%\rSbI%~jޢ[cbFfh-18iTQ|ӜTTyH1Gv`;4E,'$s8u^ͮ9ɲ"b"`k}L8?4#qZ)kSʺ9^ZH٪<<#Z`lFBnm#I ܲiHdnd` &,:ySmI2eY.+PA3Dx -\\S-pP^^̑p5\3^ӛy6>AkvCڐ:uN[tF_<2{Ų:@r|C㲇u7qOkou$Q Pt&05U<m#t3X dt\-ܕ}–|f)dQ~zB~>_B]0$o[.Sbu2VEi΄ <ϾJF9a?AҌIl(dNLO^I[Hb+˵sU_>g/o 4sۣx5)p&33Gv@Dboij\L,!w^t]2J{.ƠQk_1G2nchoF-(~fcgd2xdB,YMHŋ>-MzHi xܩ\Vɿ4Z6׳0cun.Wx=?JFJx\Pǽ?vO[+UbfشP|Jv/i+3 JDxճ(Avd 3kFG{~ՂiY͟E8ߌ$2蟋ؽ0hؚ~,k647|8:FQwudӁ)zym|Q LWlmU~$s~ XrX(XbOTEʛzfUHƕ>[o=2, { c6/p>M/H<zJ=+1#{14 X!'tN q5Jkۤ;jL+0Xy<*JՒuPoyȯKéF.MɮHn) (ǰ"x_.i #tgܾ6B#&2F"KarmOdI+(1o^KhE3b,yOgŎc85ˠM+L(6 l{CސGsnD漢ME b^"+%N5x>`՝~<`U7[΅+ @ad4'BA:˒yh~ٶt!??B̐ĤVOJ0ҽw:{A=T'Y(qPz]2ք:ӢyEkpW=Z> ;z`'K\u43}h3ܨuFFDo4;+U2<< RnMLO##$}1=&kP^~uSn6o6.'n͊ tqpؔfg!y\jI(uܪ A)hYgP#ۛ}܀*!(̌7ܮ(pbKn 8aͩJT) Nf@nG;c=JzU$@X`Ia FAv9YBA9ۣp jk n(FHSNꄉDbxٯ BI~Fpn^Euir v0cYaMiR0.%ԀjBa#U !3PM>OUՇϥYXKأ3`װe!SD,Xθ쭈6Ys-csG]'h\oc&zJt&|x lϭX1$Ů@2Njc G!U\Z˯KT$g۾D{g7IH F Pک|{NP9p]b! (0__4MZ[{rf&M֜@6V]~oQ02w_p3'0yQ~`L,tG4soGB>P2'PHɧU'ܿ}So*U_g+Tz+9bTax+i 㪐3FDm :u%Dmᙼvlb XtC.ޕNI3G0Sy:ok|?#dh n(ƈwD] jgaLc45U|C&華k9kIc/h$W`[=$=6;eŃnɻ{{'|%34vft>wurֆݧgFi>M.J?!'N`=bppXyJ1ڻ=FP]a88Ym}(4]F cenKh&ݻYsrs"ax@D,aA / nبn'nWoQ c+j @ߪ4fdz}9&krîzvCj UEl\/ZmD*_@cTBN%>A@w>*s)h/j;QGWv['SD_emtw rm S F/Mr2{kg;vA#ahֽe2wЊPiyG1ǁRQbJJ#Yӎ͆!w.^dzj|3N:I -I#_"QAy?>R*9/nKB7~+"r#<Ԯ X2.?ΑJQz:(<xm8nGUƓIj"Fu%6x;߅HC:ʦ'[ep?^ uE+}p]I橓Tȹn=^:MEW@Ӑ%p|`7]b:. 3\(NvQei Yeq@ $a {;>KA{hlAfB,lí.}s0 }liX=b5U矠1"},Ir>\h~qz.[8k'+5kQxGHzeml4t>wMcBؿmg ި\~FGdA,#Dr̞B0\BLa x; 3kN捑[qS_ĴZ۳EQIcSNY܆_*iud s2b*r<C=JA ߉ -.N>{=2\34I%B$p?DYb-"Bv$wktc[a8:7f zpʭlLP.UdE 1eʐF=kڎ;Y[ k̾7+( SEPϊ8.{u:W۴RϫAoepK_VU}["i @cѓlgBsm)C<7eDY蛰5Q_72y ,@,I]: ?wM@2F63?n;aMki:Njz֨ !ed #hkWOډg8 G9 R`hjAٙ3Tw݉agv%Ɓ(j>jĵBBzT$S"̼?ҕA&9A="'B!l 3Rq-ojMGz!ESѾI5κ5b3,e@9\T˜JX3"fSJADm7*J K@l "S W6refW|× ;CXVx(0[W: d?1/Dt 3NSS֦|QA :\E_㐫7./IjuQЏ|芪(~$EB Y8TN8qh !n_vgֆoO`C,Y҅Ye-qDtvv1bi #΄*n\CNeI. R7 yM]rQ$%i,mt~=b#, d] !K0$I'St֐U2H&=k"\t Ͽ6XQeIi$Y.WC#fP\Q%NH@QIoT>'Ce%YS,3#{N@5Hm?JO/h󊵎S%IUpFaKZh*)!o,|<}zM+9:j#9 FE-tr,۞&\Yu| )5ˡ'P{Ʃi2 lDAtBaz|5&}4Yh=d[X{BN1,ۿzEm[*f(묂>e"߃,Ǚ2\q '7'vxG1ÏaHSi)tOŖaGj cacͯD _,^@{/_O&i#[ y?k帑Czr>ײ7]}Eer rzPX#H<s3vV JSfP9`Ƙ ́ wk$,h|w(ޫjǣO`90NzuPwLu&3MCeqAZpJVdKI8>G-="b|@O#Q55L(Yjc)KAS9cbn6& 8Q)W cU/Uԃa'2EsnIk@Qt ٳKԪAtP~ 4wUyO=ELgZ! ߤrA (>tŕ@l*@)ñ FUǢ2"vQM94:ףXLB oК LwYD$fwk/ɼ>|+uX*:OGZc͉@nKW>ab_W,ˮه[5Ò푞sQc+8qOY_̳9B> h,?;*BiźTKϞHzN*1 XT5H.U] 3pl#~= Ib1v3έ920,W.)|*&|?6 [ ;[mN0! (Ьg>9a"?ﰽMJ Y:1pQJv]J(FS+1a{wS׿_T8+!KXTb돇n+#$<@wll3AHsؔL!GB:|/*=$.k)|'\F~4.݀%^T6Ɖbz5ٺ4 :ӌWCgZAp1:x:o#b1@,ύ!m :;-n4cQl+~ITzw;^=8²QZ2?:i\}L Gv>BS ᄘ|W-z? ΊGn2b?Vyiۻ'KdXK4(_ξ^\u . Yv !VC y^oq+}(vIo+1b8Fb-R(S;{Kw _!OtÈc2 OAb< |>h@9|l5|a7j ڣ'nw&^-M -tAIMT n}~+b,m88DV,6;U}OXM<60 Iߙ:Rض;~O꬙ V?ME<!io((/O8{T" P _ƹ ꇑiSbA`Giȭ!) NnYn kP^ON/?)$Լ؃}mJNWKEvwΙ`RjH!N6 w&ժ=JChyU"1z] @gJG[kt^MLL]ᷓ6yMIdƍ"iɲM!a.Q3Rx4"s%`5Ά"e %?cԖX1J4IaOFQmh; kĒZct0}hr'kDBmgǡI V߸\$mqaͻi-g&)Y DNpIj/~t@^-W_ߞa5QƣT ,`S WmDs#A[ tQvƉkNт0jN 9_V=ylZQ~`N+l~!>ŦxPC-kk l·(P~Խ d<|xT'<=ݡgFqq>GoMܱ>QyAw MH~f1+A#{bDբR$&{^JQo@J=9'/j/hr&A,boNFDf1fv+ؒ@ /hY(2Ovu(-%c4z`mZ chJ`\u8rF0˻>|AYGUGk-'y)-iP|Jnz1kyOuAL+VS}F^>qhqSB[(q1Wu8p#``f?˗EQa|(Uq3Ecaǐ|K ]tY:E͛ Ni C@8Jg9;2bD7gx3h~|UK4 wO_bݰ:8O(8pP04#^_`G4' 48' өυ !'aB"*kHR::Б'dTu942n+ hGolK#;砳Qj_UՌtncD#԰ q`>>eyQ OEyT::KF?z~ d:[O{f8PФhs[ 3!0Mˆ`-aVi* NIfO`;ifCu)R}m#$-TcA_렯lc@vwfNV>.O>ί(i?S92QҤ/F5aB$}z~iX#9$؟0kxx TO:"EN>CQ7GprItA$*!@>u7?Dlґ33Tk|ԇ Re$ Ɔ1.!2T[{gIwQd1#጗=!LfnRP%mpi+%FЉ7_*DG[=s>⒓%OF!E1L΂e#}ܭRf^0PxU 쭾_ؿɝRXy_M2tD Yʺk 2ͳyaH6d⵲ =ҐbS1XS*B\)lOj, />᭟AIa/+!@*i΢_M;R5)7L[;#5],`ٷ$ &/>y-Nh_K5,Bx b*E\}w47 Bs64udiyNwB eT7S(h' Ҩ0郳xu`PBN{%K0+Wi3?] 3ܔUʧ}AN@ʗ_vimX-qۿ6&TۺfK 7w=)H!@*ex1czm  ڕ&=X *i{|CK8VD\}VyU+>to(?`^8Ā+8a本#gRݤzoM. 3Ȼbո ĔX Oސx8ϻt.O c$f?NyI⹪h5a6Oy)Ȭ ܰˀ%`e3:Wc`X6Ž~?`baR K9[?&[Dbw(IfՙXiRd Oc%CrB8Oƪb: V,\ju}1csp,'eNهc2w/^qEAFghf&%+RJ =: hY<'6U͉L} (:g_4N#R]|d3rROW_ٞg ~\ə1'r4>HS'442i#[I/Uk=;:j֙}%3̾~"p{؅7+[&Ð5dPSg*'!} H6^ȮC˂ž m H}N:9 "Ӭ,6^:Q#%c+ܤBOs^aբ>nUߵ$3/nM˘SC=Ġ <5QeP?7yTTWeWeT(4 >i`0- H7~ɱCCi 0n<>Ky&)'&@#X͙"v(Zz!rRmD1p%{f*pDs޵SwBq{.@:LbRyGQܙCmv#@zT抅99 p1 R;Ƽ/x <q7ڮh1EҖĻy)wu+xs͉,ow2 +Vdٴwt)]]t@yl~nEnU$_ӢL fo(hcޔ3w@yt5I@$rVЈ\ Zh>iaTQ[d7| >|Ҩ:g_<<>!@ȘWϨ7U^'L?j7k,j#LѬu[3rɚmC Q-ʈ:fE!JtI b@$Aoc%Vd qgm}j0Ż1LJ;(KO3<! ߏKC$XҎYG+/G 8gvإiv<&1~͟BVWлޔ,% XW[m57l%eE'" V28jX:0ɖ[w_!ȓE`n m}bgWz^FHI=ԫNMxDS bs"-Y%Ј^?o`ֈ}h N=el# Ljq_Rx~a"G(~$M5FMI}RA㸄*_x=P+͘팛^c[dT )9ǀßs)L忐+jvZsuKU 9.2*Lׂ-TRf:J)PS:F8Avz43:=nWW۷ۯa5ju޳?kUo/ởGC Cx_oI۴wۯWۻ|uph?P\àWuoO _}R`AoR۹s Y=ʞrTG0yc xپPH15;?wtpՒe$lӶ0z *n(_Τ%j\mXh[z+yUwtE':y\$ـxDBtd"d>: fLzNL.zN*ovNN) dM!%762Vcmo tkY ݧr47VJI mcdή_eχ|"65rA}6vvO5|ԡTrL-/+pˎh%CX%ի*;'k]5њfsk FyvW1>SPW3}˯AP%ǡ-R& adc!Z#Όk3Bn,=-jM76]A#,&6]N;XB$N#IK}޼@FZ>&"f{E]"0ø&&"M¹EEYܜ&[B$=arej4(ԩ[G"0&E. ?ͅi,d} J=d.DBID\UqS@S`5.HvԲu\w"$me:wHí׫a|W/Υ[^}@ P_Պw߁ WkN+Y,I$Z˘`/,{2:6| g0c&x%T~^ã! Q*M^wT`} =&u"{N{9_7TgZ 4EQCvO@ C1+_+J>ȯo%=:j}L.cr<0Y0״lE8rY#oʙ y\|f_QD#W%;/Y7e&.MJ@~8O՞ &A<;7y$Mmx!D>Hj7V39j. X'9Uf+V%G$cZ^jYəv4B|KebM3NGs%J=xᏫفY*'@hSV[gDrۻB` 誎Cx͚6NxuqHq 4sP&'0_64Y$E]S}WG8d֩$RK+n4"I+i䙙0CV0R}*n-Ou{O?ȟI q|݌\:kϽtkΣ̼l0.2$tD3uy*Fш~{Ԓ<ZusQ5Nxo߈\|͇̼voj+TA W(wH;Z ^񷅆;oӽZo0ϹڂQ*1 娟e3@Ks/u0H#& r+ A-cSk3/gDW>| =Z9$r TRM̀tpՂC~SLD1Mp8;07%s %{BS]P ,FhYUBv y ݢXm0&] q1E=Z*_A l\Jiv "XB,佷Κpۙr[3wgw3v95ȽI5u-~Mؚ3ڙjL|i ֥E Pބ_ Z4 ]ʌA:p֌ >-:s+@Fz;{!XųሧjlǾD>&Jj,Aa~jbDDe|2Z򖹐۝HxeA']`mt[ \ܷ&oΙi:/$t}X^=0uҍѐSjbb_O3& LR/8X{p+KzX8BXB]`נh?Woc&uA`8sC kb'\ G9Q'f T;A/u{Uj~93n!mASti!ԇm"7w1Lf,8N09y޴tzdkW-9(vq[~M}TF`YuMy݉fKpI20ˣOx-7ܤkι)qX l :@Nϟ^Fm5.]dRF ߭9 %'!,$BV@=3@s89u$ĝNW-xKֿ%}_q' GN 74!lfJs:U$*d[~D MruV3XT\|Se8LnSƴvKxzPs4ŢU,1dF!'u̒LǐQ2ZQͽ0.W3{C מo?6X/}0/1 Y*Oz[=`va|+Γ0v#^9py-tqIYj۱Hҵt[ dv{&J>jQ5Owr5jC7yt%& 8YBMWMr!dp^( tۃ=T'?#C[6Q52-Z1Bj ^)c ǂ~E'1LFݮ P+vl#I S%h62 U iMPxuti(e#?2,|f(Z~eob}Xz~?y6+א>ݿyjMX*8C' g& n; /3%kib%|菃 ?$?-@.Ge˹J?(o$$`m᮵eku7*-x홄$[,Ver5k-i@à{.9 6yQPb@~ϑ+=뢔p]lpA+[5Ɵ7WZ6g\*ڥ:דC.:[!&/>@RPѭ;L%W5i= NT~~2+80ƣۦZh[-ׯ3Ej}iJY1Kԧcf %ۛ6SA$P)tS$oYyiQGz-yotr?d+K?.WHz;0X9)cgVBU ~yHFuD9~@z|H֤p- %i 8=3g-oP8jEAH`<*"^ù˵!snUndsI*!,. 4oyS\CL G1K ,6i%hp ve=糪3DTDN(i^冚GWz!T^}z??"|i6Uq2PR "?SyJar7[*a^W]O tXD\X(@^7;ڞѥҚǓ'{jikz˟B a8">Dce>ҞbczK9|_ucKBX\l١o}E3{Cu7FkXyN&sS~_4XtV fI2KV;ds1Ԋ{<5E&YOeXH^ >T!7-$xu"VqWWoadX$d5*wL$huy5K&Y)&Qp 'JmXy^]1DĔ*~OvYu[HJQ5)$&Eph?>_7$Wj#ҷNq[)`;*c&"kɓf.wPꖹ;,{rTf%,S] 8LM_l!ɰ"*9h_?;jds`~sz?ri>{Y9=-ty/VTPz ͔*Yd]P4Fչ>L sC`'T$FR%"LW5Uޗt 'Zf:S!Rb̀ 6@<6@+zw9WEl1M)2K{=2a_\O_LKڤ_M,AC++ߢ|[()0.Bz#UT e- `RV`29xC2 y!Ԁ]A!|Ū6nnc<8WV7+9[9Bk"0 ( ց WoC(̕zml<3lx v֔;ea%(W8zS>Sܥqbk+gzBnH6ڪ<;|3r,U%f!]p?5Mj;;{du6$#OحFUų5ދ~/!BR;P#sT6yx @%biN?R_󿼨zny [JT0smZ'wFirY/iL7ViyC@z256j,#=!=|7wDǭG~-fy>ܿ?{n!ډu6vf$K9}b7&/3dRΩ?hmS J.My._zq,/vv| 4l9UD؞PUyqͣyV%}A2B2,(PI ޘIs]=V}EUG`v6};h/ AJmB%w?^uJ[vA\2ɔNs+Egmk֨_!9zLJP\"h(*~VJ9ςɺ'ԝf=/'n-̛Pi`b;N t= ;ݺD봕5#j,GˈK49QGG,jeVB˝ndwW^-t{>R5W #af5ǘ }9p̓jJL,]bI%7càO%mx(O'̡,o8*' {Wl хh4O޷ySz*>[{RbV8,Vh VZ2cUvՆx %=-fk=)h p{ҝ$$G6TY_^\P c&z <~>韍 VLByZs gjơEJY0y4Xm.ZGў+7H۩L}gͳePv}S"X 29.*Әzaaܒmuyx6:{bIHx`m5uWj0gb emN- ;h !/VbCˢ|6Md6kNA&9]k=u\HD1S|d#@jl%% ,kpT [m5kJM_7(OY۸S>Z&`D{k1 8B7`{ܜ <{EL;#N`10 WA/FNic{M;Qlݦ21JR!b `RA;vaeQ6 B ~Pɱ()׬eЫP w%pD(S7. jL -- 0ì`^.o߿ fuf 4;[|:259SbeK Pɮo OH+uqxgDrV$ LXCa 1SO4jm;ZXllGvP3N}ے, b)BRօ?Zęo; 5ۍHΌ/ , ªj'碿d'j|aֶߢrSDiW%P-Z L@{Opƪ̼sv+P!>?P4 #M~{{ȯıu#=},ٽ]F!8#E>&z,*=`LG̑Sd Sjr$ 6 CdV %2O !(IKiğ` qγY9޽]knPP|OBNd̩ ۩ꞝRߤmߛ$Ug"l-)9@ tg!U_kr^Cˢj7jն+Hӊ.5۸~۔[cxrmdi˽%2xq|һY1w.%f7Z{ӷds7c= Ngx_YA~kމZa) dļx5 e(Ikq,~ w:R :"j HchU咽li@$` oM8$VѯirdE|jSu ֛;E8:b{kmY֮!p6_]9A|Gj<@ry̗UkH`Ԕqי!=A wwS4lUgVǘ,zKf٫W$,=("7yuy /${я!z귵rLuۏ|5fWh\ʛVW;{xLv#de6t)j5XZр V]-]6J7,-(D9$8;Rh0EAnQß}4%\ U; J$ZָX-@(-Ow'J'T >89/POѺy[ @}ȼCEEkV3tƟ;'_A4jf;LRn4v4:9$A'$(d=gXER]@kU=zp ŭ2r/U_YTS=ApB!TZ9֙Q=SCj Ź}Tk6)X s`5 Fn7>3Yv8U WK ś :IcGnHYTN/;tĝnL VkùʥmݓD)îTsdžYi Iɦ׍e('Tfwז3C-NL3gW_~0jū,t @,eB?[-/GnMrz ٚ^ɷtqwPGAt>hydSzfLZKrLQ\w_ iewł%CBԳw]%,|iYwȨ3|=}JG{[\ԪUD4ڠ3ӧ1hR6P_|-wQT5ᅫ "4]OꞩȠL0]B=PIل{@2d:7e71CqC](piEPt,)GjtZ)vPaŮkʥFs ?u+Js7@LcbgV_2TZ|*brnfl,;$ׯk(.r119N*eO}h%xߕkݡ//Ad _MѤOPS:V2[f6FhޔVa߫_|A: 9&J,"Cw6$y@PIXQHvJLYCjؘJ]xkXBaܫ[tus{?5a-`zn-a㷹*V/Zvg ԝ1y|j?피N~SrRzʊ_Si{VѪ}K#]tv"(w2c<в9uIkhmWVu} |IuNh wڝE ̃wP/]oq쭬1-Q)*7cS:o.$nK*I){teD,({!-2k75T pAebڑਞs\/~Wr=rb!ì*}y7ԏ"}:i4.DI'䍤X &t$8)[Gjʇh=Bzz+5_B i WVyp*BXowJV^ZmP q sqTgzHN=_ > EJ*Vr0-LEc@c;xE)bNvPߴ[`NJ,^ _EGeStr!@{V7;7kS /n*c;hSzo)%X}/,zn뻢Tb:u t^=H]5_]NfFtE N}'EQ2,{sVgR26=ؓ6KM 恬|'۹5$4Nr X\;:zU+gi2j9I oТmuD38n|o [D>K:ӡ g3+7my;+@z_&P,9LxtfdXۍyuB ⥥)K ,-v;8Opj*چxs~NST,/6Ov]$BkZQ;X$W$aUdhb$67KDy)Yj~M[9Vl6DGdzj~?Gϟ ;E5<5&6EF0y䮵BF¶HajyށFKVsyUwB]坿="|UD/H7mŸ[Վ ,3kFIAX3D~様ʣ R ǖu\\T`hyt}l5C>ں̇]͸7*kA!*pb,~JHpb#C <:o5C T}Qh>̻Ak>k(h"@ۗٗtl 2\^rˉ8`NqẆ*D8m}+ -;aEU(:0^&۽P"ߒi׳JđZjFBy)w< f >o)6ok+|L632k' FXC[#!0bEg&Ei1ͪE4GQ\*-d@ȸPcaOQ:HU#TFLcv^~XH?0j+~ar! oL%RL;?0G/|5hWqoWVü4wAXqSj_/}/-IJJBOȚߧsh"ҐJQSVf[ޥF^kn-,,`+p4I|!/+*`7Si0]Zһjh3 &dZo5RE%=d/Bu]ZܳWvXS2xY8]\o"qq#: ]hfYU\S:ĽAF.q.ʹ 1C*Q_>'}ѫIyB x3qd "\ T" !gϗ&Nb' aTurUiB|މm 4W$@6z*I,j%ZU {63wAYs|E А@1[ uQj3=n_~C26ea0x?-`D>d@=?Sa-,"_6 F9Aʔob6Fn*ĐaVd3[; EX* ]8p g8\NuHWc 3~u`BT sJ\]Dq,[yow5p~iKY٥o+|`3ł%9M6h!}nQl>=݋q] grfVG D DV_%c&z l:S7 JAVvݷ/{QY+:tH/Wn*PaΩ9rIG@g)Rݡ`Oב\Uh=JxKh9#26n֥|í&Or2vj`fi+%[QU]}Æ5ZxYp~ui4w&!"--o;2ڼ! yY&.調sska7.oȔdX) K5֘QVbvFbr-!!X__0ۦ[E=^n}姤éX62Q}e˪ iKjnLҜ!öE䇊pCˊE bQt'' BT oVĄpzd ~LHml@'Ђ`e9L-}S+G`6pLRW{Wϖh@@xo@H<~n/Ijr[K/&Rۊk[wȼ;vsN1)U*(r[I>z/* @®BGgvùg'UJ2^YGr~l!P=YKYGBcgP]ztc7@lÍ]SfVK̶lw+^h!t;x[Qeϛ+m/P^,At#-G&믩p?Nd1DZVX,Dro K#]>d31_D3hB:LD٦+hSA Ҝ& `&$΢7*GUz NRL8$s2 *Uz!TS{&D)F&iD[W?jd;MB$:D5>78baiW7b6knj9S}Mw= 6U~}+bzMـoR46F `xcLhxD# d _-;-cl LDO°xSb*'?x ޶5Tqd սA$}aΤ2<KӨ$$ÔT0si쩊w(e{z]hvhz#f3M=Շ8vk#( #bSzqؑ}Q-+K8$wҐg3Z8xqˉ/zY@R7 ˫1.(<ǒћNWMDu iQ$3 sLfg$Ibyyn󏗟Jgew%+dT-C{!9w1[;ǭ @m.c8i݈f8rջȲrdg`C1N_"ѮCNk+r"+&=o$?O|xQ|t"P(]ۘivl{RH#k )XYU&QUe;Q| m 6?K\N5tۍX}<'JXD~0|{c: S7$ }*kY ¹iD9)݃4MBO&FR|jefh"5Dva\If ]N<%(]qvZp?3Zl9a͒/;k>O6z_%< 9?1A:I뙋jXURBK0W1_ǭ'L;-w vYE~[͔Nӡf@$pR>pIg5Tl>ķӊXymz1b͡|տ([j] D"|E^i$R7ǒ;y.MנOM}-O:!x̚ѽMDQqX i gm_&*Z_|'i XQ$?f9a 9Ϛqm Ϗ+ARTxD&s5_o#_N߳@tMeuHp>H!(9M|5}:k+Ҋ8r6tz$u _: O^-WvSO*urN;hp C!g2&`{g.ɟ=^Q;W&Uޮb|k)Q>gPW}*lhA m|:4J "CvӃjk8D'B oON'#ȑ=z X 8]{D,_omoֿ{Uv|Ghv(9';]hʷ@ : ɐ_~}k|v>*#l2~SI$ȁkDST؂Jhh)FydpK=6DnK!Q&{WCjR(5"2yZM&$w U>CCaM\9U07b ƕ\AZV:OS^?F< frLp),g~ޗkk [6^pjQz'I'6 Nz͹n NTUU+/ _ ye"KXx]^V?}!ҁT`r{窲`IEPV~n0 w}Y3Zoh0D+\r̎ngt7>F2N6&IKO}-nUHmB4=֊֟6&b_acR:K"qK!r@ pp`7kϢdPCStO@گ%ޚ4Ϣn;8[ZS:XfWS;tykC +Gxܞ,z9XwnjBĿP ܗ5Ү$;eG MPі JS B}3VZ7 Ӽsb+LQ KmиBTb+0Cz:dxBhE}0$=8+W* oq:o$X0aՓʷkCA"_ym0 יGܪnx6IӉæ0>46x -UNvB5ez62hr-|nLJrR_L"y{z{+v2PŤ@=/rXwo;t P&?&J&iZ_T~ bm%2'qզfM1{r7mD" wY~qfo+>`7%gF䫐Tܡ;K~/@уp!>ҶgM o7޵Bfd `˶;pmP~1e(葽OIupi* ik+i!NĦtڗ9ZZQLqcǬVO2`_#3 M4_3r, ~Z5(K3۴ P2q3)z_tDTH AH :{ s-^|F9 `q=~b o,'TѪoCKxUH=xRzxrf[DL*B-yaLDf*)3h v'X^]S., ē2&9G"bx?BIZ"!nWeCԨN~jɡ7 XCǩJ{1f p4VTo_#Ż?z# /kOqkCCC)$:.YKew24Um²sJ;ޅBK՗ơL>NKIKbbCQp}K9ðIº&yO'Zs1oǢ\n'^r&Ai[l^2{.j'=:V2ῠz-bތ E]vUWFkS's_k2Rzg891]SKPR.godc^?Ǐ5EIUk#7+7U^[G8AιXʀy_ ~CM,۝LFvX+T?i@WX(VYŞe}S{Q\4֍u,HThML DEOQp;KNfr.pR{*[hѾTq์Q;S zesNv7P Bi_›:L  xJ= Nr1Iq x(ю:pq3llE$N v>_kDRmnP8;u#⪦'[qx$G d>PyXǃ}!epmgͧᷦyD㍟\`?!`=~hz3Q)51AQ/AT5_2:JpB|QŨQo"XzWi'Aj )Ghy񾮖6You )t>K}}]_UϞh?muf{uMt{h]>5oۤa}hw(VS d*?]`tvP(lKfߝҊI{E&ڥ:)oKJxRQ;f6z8;dd.@;ש2zJL̥ @5B7O1 `=ꤔac` n!:Z}m~, 2[i; 01jCe;-Ph/YGH>k?eeU݀'-R>uc6n{e'gb=,8BMh@OlŎ?e>+mm'~%:ӣ$Z\5rjwWC;q5rf=P(z(T) m7SydDD4S˜I׀#0w$#`@sI[y=PAfFt|Urxo>B~z+==]5tTO̠BcNZ.oy+ذ+zW\4c6oW(qAhP示gs(tnseg\rE~cZkN=TSoAGΥ90M@ST.JߐJGPJW^}U TTE5|9`bl@ >P Xi8Wn+3B ۟*2-qgL Wƨ~!Z墑-"$ob, i9<'EҌ -ԲI]x^;t1*A>o$ߟla;qꖞ[>Zv\oH,"lp.(%Iw'yAI8VZydnX,8Oѳ ?^EaY%F@žߪH鱖; uneU{Yh5·Z=fcY!BVth!L$<"3@:e*-%U5I}a]\Qf(@E3P>LpNk"ke[^w?+oU[-Š4"??p\ ~g3.uuĬ!hY :c G^l @GD 38QNlnZ781xXfY`1\c잃`}Ѥ N͛h7" 'nlg*ѓC'FjH|YΘaɋʪktV$WP4gz)(JyhY' ҈hԻZi]"[v_0ekS,Zqg|0?˭C\ara}D٤aZK">S|M;U-I+5F *PA /|D%]u,-v`M~jxkLWf= O d;x\vBS.urUW OeM`r:Q|˝Eq8{8gf-O% .K3r#aʊX,clcN=k&u'L7ЫdpI $ˡ4JEN؍dnK=pjn%n/¥fXrgqtJAULTX~%RbE}=OgTl}Eދi*AF|-W91ʂ>X).u "ߵ 4 繯|l4-?B=AYuE:{Ó8&@Փc2c4v"c0RtK [.sX*6;Y4Kr?3Z=6UE9)t& <6xgg4- i0mSJ˰Iq0(W_`|.^j_ ' &NߟW"ޜceNVF+Qv`#qz&N*u A41X"[Qv8/1RbT̈́O961Dû.!0I]Z1BMZz1?ϛvaazSۚ.櫭S[gX@K8 yqoo}uҤ(oƵd|lU6woSQ|PMhO-:nVL?qhX,Y[1k Ӥ|nrM7vH)vZ7D'Izwb_cu.\oU >f_T^ǐ~7 $vʻ/ڢBe?L-:*^ؒmg[-j `+XCEl)ꙔBjk8QXY[2Z[Bs&AvyQlm>/q )4d Ӥ&fTlZ[|Z_BFbu'QdV@' ֎չ]asK2yO#{:7m>,ؓ3BTiLcw@9%IE$<}[xs̟ Dc榢.ĔuUq* 3j4D94t RgZxߘDp~(mp1\v:,Ԯ!ܿ6> %7h4)g '5?{%5`+1T15&$`lM,*|k[ʻ:++#ܼdMfp\ǀi#99g7֩*Uok 1Ӣ Z"D.)t' LLy5R4 ;1Hz_Nq㰣K-m3JTM, s2ڰgb)9xy4g{P}*q" nk3I g>b9ѾQG| 53c5(Mxrnڞ${o~L ]|}T/V <*. Iy66̞PAx+_[ىMsIS27ֹΊ Qg0\HȃOM߰"_M&)% KFÐHZcl# EO](4"Pr QI=)Qb <)B;;Z[hV l?BYD, ғk:xUUhM׬6gei +a?ge(OQ[qQtLȖ1U#^Ʌ#ͲB^>bKG#*dc n3ppch.e*E^h$acbGn^K8eӬn>gCr Z!L҈2E*!5ܩ#a]Έwc0^կ&$Z*5V]Vtခ3Z V^ ^t )>O:4;p u3X˲k%'kPX457mGn*U _1j{pԽ정12x7[{9I_ڍ؏R$3Z3ݖ]0cIU2?ty` JڸYɋ&K{pS}RǛnv~٬9ʖ7ӻ5  #}8*=/5Ūۍ$_I("eDoSo@&zko,EO989mpv7j82Y@II廂7n Nt쥬.LW#ϙn61XNaqҠ7 iv䌙Vvb-G"t̫Z(*hI^iPY>9Œ]qYAU?2x0XcCpՓuЅ^Am&w$yGt|Zc5^aɁHR.+W/k,BX_:8ȷ'!ɻ-\>^:n q0و1wnmݷ\tZ8bpqga~'jtݶ'.^P0(}i` "KK#ca!_hfT\@: g P.:/*ySGK򨨣'<ߦ$1)k Oy3 ban7DH Nr7Ͽ`p$IK-kz..J1P)t㚅[^Tv]%GlTRގH# %};Nܹiq/r$S%^.hzH5lL xXzcVp^.S!ATU ğTqc4 s,1o>Ӟϔ3JǐJ`J-<4Y>^7uo<;RQ:[ʲ۵*(cy$5)!)*JmEltW_C\8ACVHOX I'G@I%F mZʭmO#e.*1N\ä~ICnYՙPѻپ-6xZD>ȶs@Tx &_JXK~(MnsVEg/ibɥ /ld{pMqylUl 0m%^N[K7rT0-nȲXůL$g_чJj$rl^Hw0 Qc#5^xݷqM5&v:sH#P͗ \O3ȷ9zJ2mXxJ]ktu&$Y8K*/^z/{"}ox[gYztplȗ-fՠh,!t[GGIf,5;/1X2hl/v੸ֺ:"'ڋgj(Cc?=J75T.hh7oEߓ`&QZLc9.FTkEo符Obc`e܊wWWb&Z/%W;} xHzTH h`̌Ð(zj]J S|ȋ7,So'B"rJj&%Ry[-6ؖw|_-qh{B#9[Zp[q-ħ"8Tڼøc 9d5k^9gcwE2`xx ^&i&M,-{<Ɔ6U5gL|v1ƯpiFhk\%&̏ pwT QhXo7f6( j>qU}o*'}ic'ٌ^Es q!kG4'l*\iLGSG -g.j{GAh 2#ꐨF %G?Qbu]쮦[ IVm I4m[lĆq0 m L,^u]Uy“K,:O:LDjaS3~>řܝL $aRMD8Q40`.md^R1_Sˀo7z^k<-`PZ's) u{*?]]fVxvmfgF\1Ot6&dٲ[K}/Busb# Pc4v i|vHy2uk1>JP&NŢ5P(y,PWN/ײPQ 'SؼP۾,#^G#i?UF4SA]f·W%9:kr0̝ȪGBp@R`ho˴JG唦c֗`!VvfRMt|f{+.v{ѥ]i Y|]GpxE-[gO'AIHdل96sjd,Z" bokA'זeّ^%m2$h#sLX(0q@GBzylb&itGǚRV af֐hEu0G3>za,@>b8v~J`&rj/!Ouc.f%Q=0FNgi'X.ٷU10tIExC!B,?x>ϡuǟ@IpB%pO$MY} ,>̈́w2 {y,I0}dz_sG,B+^Û̳x-jBEi^aOtz-" do=}m%Jfm[$ p[Ûdgh!arh)DON*v_Pz֝+.<"=\Hp~ٻŮs`AǤySbp&nH\"TLMr+U Q\lMh^k6>30tK,ubR&O曷cIaZ2%I4u3Lt=<~7 +[6800Ȓ+;kH7TtnIWߗ;_ÓUa-^]JȐC Uă4$^H6x{NCu.+::QB @M:c?C;v_C6pݽRb^nvY$ySA02M&Lh5ި+ޣO{mP?#U;|1-%% s|`ئ^:Drv!#}^(y)?ͻKmJ'0wn?OB4vݤ㟩&A ѳ|-=G OJK\J (8^T7G6XQyƩN+dyMyY8c~.Vܤf/~ triq( Y\7Л*oZF{(HDd֑tkC)Ү]=[ɋDlC [LԻnf-M_X[/cqÀ9&x&?ߝN :mH/j [0Fb:nϓF@_LXOJmwTZAc[?[u\NO n?%0p&rJ$&9; %տv9TeLWBiDWݖv Ѥ*Pw,F_tE!i ꦔG r,lD$**4 Ҫ icb0V;ng.j!V!٭JL.HvX! L,A*sLR@b3,QwӰq;,.0nMO7-6~իӻܐ@GsEooOͰ{;-:9 Ez5Lu<6"(ǚ$׫w?a>+6ufp<5a+BH_G ݍ(VcбݛA0ϏNW} >.ԫpeNr1( `3ΰU^D|=+ܤ Ė1BC3g][A֬wEq#Fr-Vbk/_B|W-"^;$$9i6_b@yy\^EKДkŬƘ t /Th>"~@uiCxI3uIsX Qpx. DaR l,v|s2_ ;x$/ca["]v0/߮lwvfvp*:)"N,M>T[bU؜Is2+pXHV3^K>^Hi ᩮ}}?m_nGKOK?:oϵa?Ǜ?ԟe_n_m>Oߣ~ >Ծ{k&Z[zի_޾}:g~~D?fϒdj/m+ɴYݩIUlRRŝ/}X k+ʺcWH:]sݡݮnOplY6nIc\;;PMkkj j>or8 ~jz!{a>(P7pK*G3̌n Y N)(aQ{7`ѭ#&G[ ur6?G~T>4NrBk˝@Utu7TV6kGpiNY}ZC3i0ēɾCFɖd=l11 vG@>یNR-S+)U$|9`b\/ԔE)!Dn[-Ԓֈ BjbSVׂRry"=5vpER A;>BQMP)do"5F4QV9 c>aS9Da`?xZ~ڍauhIKǔ~!FXlwgU#0^XQtg~@a ;9kې}rDPu/qܗcDTِkk 8Wl]Ĝѝjfn[O ~8!=oFO{ӓ bzk~IM;L{0.Tp80ՅħC1`3?_˜tBkNj,O_|6m`3>UߔVkcR`?8aPW h}\nx &TzRԌs)y,8hq=?`r|3hҲ 'x%/[4`,Aj-Ol4UKEJcꐘ˞::9)Ht%,w=Ύ6e*qq*_RK9c(YR9 2t^m})d |JD'Ŀh"d5V+Ǎ~}>f-ETћ|h-Y teV\a{mw Rd1Z"e F_M&^}?%;R[%)w{ݠ3@1Zgy̢82^*X60Vye?Ɩ#=OD ڑhH87&m󞦜;=+>Cr1 `afʉeؑXh3'4Ԃ۲#m& x~$thFC2>67! :3,5lfc6 j\)) ܌c]D ('."զ ^х[mEG% ޢBRY$D{ [ӡP.ue>Nm&8 mB4ԑD"<>ȻrBf픴wZrAXZ}*vgx,BLrvi/OѰgTGAL/a> WH9Rs/@sPr"_0Ɵ#}ҳ[Buvo9 6yQPb@~ϑg,hqW qtV|Yw޻oW[3W\ eq"hse s9=jB3?`.i\,FfW 1Ct:9W|EfPo JmbZzk1 np;ݴkW×ҍ X}6mm@v'N!ezH֘d8ܗS"'Ufj$ K&ꚣ[ k9Gck%[~{QX,jEh}Ѫ}K8K, '*{>K-RYQޥwE۬'TH11Fr0DlGQ "p3s /@cU졳u.)\s-`ަX֍[Q$c4ƫ+=Of&R3Ls[mD-wd< .8}3(ū&0$LDyetW f)_rdM A FDܴm0)zYDEkU(B]kέ{@ l_]P v$JvWqAK*wH9" a&l i($ڋu8!4j̟٧ m-3RV_ Tf >hE.{6kբ{xI^KʆXfp}9HGhc(c!#4fxi1Or=!4n;q5aX w;u86\ Q[ {gse+l$:En ywB7Y-3r 2!4}"&ESf>%Eai] 5Gl, ?ñЦpgI$Xv1/C83S~NF3NXPGNxD?Ie82z%E`x{?p6dnjzF.%8ƞ.H 'I"vԥPJ@I k['[S+QPiumw Yz}O{-RsCK/)H`/ؖ&I͒nwZdfe)F0:+*ݹ늒ՅdaXӠi*Q(lAa Dg*zcZ֣ljVcwJ}U*ch6gqkXod(1B&y|y1y۸q!puG(ȧȊ4?Z`^3o#-~1#3?$>  CNpA81@G׊We @@ pYtt\C0dRܴ1S?ߖ4$U Ċ$9  rIW0^T)V.KZhe }9%: c#4}"oI>>chE9÷. ~dz$*(xinS;>*5>06Q vY"Y2j"Z#gߟpQ`vF ^悊 @y)n |\'5~溹+*؟#}IakDN~ L*$Bbe<@r@S[i`9{E v7XD@ mԞJZ/3ûN vS\/oKNV "Qn|zYJߢ9e@-BO(xd%WmS<_9Cwqq 5K2Ƅj*^0Ard 7 ]w crS[3)RHkqSOa*lvHp_;Fsmx>D߬m ]# jMGa*9<(BvYdW+{ mC`TUr7R\,"N9sLhtiEWֻ#dveT/#*Tq)g?B*;> j=%"PpBuWzx]DN.~2b.ARHpv2}wKgHnzhL,Fm3R^"%GE4$8&ǿLG7'_>9}|k_B\>}W j5kRT8\ur]f=(ukh4(vfg,߫>gEbTwq銍`7m_Ul W}C r ;+)죚cn X05nc mNt\?obݷtс)icfhgkʿ`ka[Pz95[?h,@A"CsRǨxˋ9m_XiV'V2̴Hm1AwKT5(e-yC גƻb,5dѮJ8`3N^䘅 咔z؇"ʰ}5:B/Bcf dF4i$7@7Rw7.r*GlP˖T&x6pOlFKL\j %XU,\rE$kimq00\:[Ak1]]-)G?@ՁQ1SbM.- :v n7טim_Τx\ ܜkr6M/t s㪢^VxQ(v19hM_Ե; 0`7 Z)kĎ0& YC9fzK1_"G?% KɉgWiZ]h\~&o&-oϦP o^<}c/S51{ox.`gU +3PXK1̀{rb +YٜRӯJWEhCzfAN>i̖wqL܊e-S7P ܵDh2Ct.۸U;IOpI˾(x>Ub~', α,NgνYysftܣQVȇi18ڐ˿ua>^xdOe(x&d(r4yjuP݄&58o'$HyȾV 0Z)n~o {Ffx^퐼2+ /Yjir2ߚx<,`2%DQ]OE縳[¾P/ K﷘[W6} ;9RHHf3֖w*A4~x>qeg5Ŀ+K21r r$.B^m']IZیHIX^,k8]R5No[Eʥ+:'cy!|էjJHz;iB{ AO y6׮ol@Gcn.[5FnGi{Y!|-')RF|u EU@PYPf,Y~uZJsL^^RTfz͝T:%8QzO#dpY{ f0,^F;[3_. 䲸Zqa}R eFqi:^"\q}M* zAC|7qT-;-e<#1sR6 8 -BiDWݖv Ѥ*Pw,F-TP N~A .i,_mu_z.I3c(>[35* TPZJ/C;G)_Mw ű ;;0 >]i.[lu+'8$*C[a}Lzd:Vbgʔ4kΓ'ILm%0ޓ]牖iFpUt'+euDiڰJ)U ,nTp.vvR ui_A/MQ| vH2Xt`Ez& YR a0-&ޏ JU4'Y=C2՗,EU4< h&g&9M%A :\tndE_lX)ю䚳i(C,WȬ;ˣ !'{y{}?ȾVD2) ٱ.cD9HއǍYÌɓClaC-Lf)ۿMLlGi!ރ^d櫪ZUۖ^=g OvU4?xWĵqƤlҳ],]im<[sIOp^xl%:]?y}Ęs ?2mbb<_AbWihHm.0 # XE24hK{<,w;m?lh@5=i%jPjqo,w)\WruqC|"V^:=& Ih 6y> ҲEmo?i7.!0Clgl-camM @e!GP|L_t:Dd(]W\鿕ߞ2xVFPW-t;,C,g7;{5"j>}!j;OۤY~]߫EgϮ6tןm!}W)tOV]ZW}Wxmj.BU~OR/gɱVU}UhyZ'i\,'9NjT|K:KFq QΩW}_ 9 /eu*A}Ԣf]CXl^:ąjz҃k]h: 5_ppum7ߺ_pc@\H HńI5ٴ]uS߶eב6}_ZŹV0?૪U{9Y NS퀒*jt]ZjGk"t]M(阞-Aq$m*̹͟nԾ0%Cy=\,8[Eyݴ(M>L.|?6q̠cIY-?&Rq2x.a:M~wKSUX?V<^ 3Ul̲u&&BH7I'ģTw| e4 (O˞)%mِ]CՋNrZ&rzrK|`O,"%lOy.EIb\ = .ʧ2Ќe G]FN R^S|V{b'K¹NWJRVKZ)MI6L3 m޼nv)dFԆA}i_-ևR#jнd:}P{E7`D ǹj3Aa24RpdDNoz)kҁsKg5g1W,~h!5:#<~pdOa{LԢEf0qo&?g _Q CҾ8+ȮGhqs!E gB>G1&B:xrvU'_?`>E}L`~-+E:6bTʇqL3С53|-@a %f{mҙ $!Rؠ'zޠoᕉeXG?u5EA< [@Io ^l Emo1| S/2MrYFy$Q7Dcbx[ };(xWW<) dޕdGUT5(!*x e~SA(|Ff 4Sc1G|;o8ܐ$T ^&ȌĞ4em'KLC19@S :;ƚo&|Uu1فAdb6#`u?'w 5&)2a@B6b3 bd""uˠb(ݡhvtWo܁ 9wWMyյ')} HiV .*iC&[*/WƙEDMڐ&/ˑ/HPpT,@a9\ߚa3fzymٲ Q[5#|ѓP_N`UgI='vJh:2  t82.5߄ _1B Pba0U܇)TQK2@I)ܑ/7E0ũ t1٧IJ:9lMfRta?-{+<dOi"vw,3[\`%p۱ ,l=d`*'Ƽavn9"L[|jx۲Fi?`Yp.-m`Ǝ \}a;O/ǩHз4ǢsdG- mb_INHap)轢;\t*XbK4*}р[*z;G/loǾ5{{8 BJ&W2;/* fTMd奍+Ǹ;px*IښG1"q dsQuHqDXl+ݗ3~ b=0T-@brfJlq=X. qKXpmQRHˏ?D})Crb%pgIh ]ewE5ao!.JɲcP7\fF)PZg5KaR :896 E)F eP%tLsqk^*m0gLƵq\8<8oU>.B9H(\ pN[H[EIjEFRꕴ'ERXgs{3Hig 0px_K Ec9ӌqW!Kj-}%7lzrY\ XC3TwWFI FLZOPsX3fgnn~Tð*B1ANtta^.>rf+y(t xt!oleV/ܛk3w.q8o=bCoڴO@`7o"_J 4n)Ω` &3BX|u6X7^gpnʮ6άApaߟ^OlIe<_V5"vL|ik89]^F%sEOgT2r2v ։oGe5u8x BM>䈍W3"-2po1axib@TRJ)I/<2u~O]u)m,-*+H*As  z}Ė;7Q:\5y s7zV: gׄmJ ]/DqWՔ vN#8^FB"l:lul{i4sWuu>^DGfqp ]bW+yBd%a$neN9UtNslQ*=h9)b&hq7v4aⵖG^_l/kҔ0ch͟}dAۊjӰSXOߛ j@Qtt}?Dc$f}gOow.bt=nI#Qk JAK7y='u<Vc EI$-1 Me'+c+Ɔ!zIl(Gv ,T)2%jꋦ˂tsI#5c)) փ);7I uuj UhǙe=Nsb,d9=N)k5HR4/Ed3g@SaN㻀l꭯X.覸UWؒn{}ب#Wm BHCp UKYsA~}$ܺni }ڧQ3ea[!BJ 菞wjXh;nvښ4:-h6n2ru xnR72JkzΥT xzӞ>d@{y΍yBUEcTHSgni$4cxqw*.-"L4pNAcbpYC'>XV/|" ՟l2̾[xtفexCiC`i@]O!VwuGc/"Eu id>?gz8?αR頿m$yQ{](C4̈́gR󊶝+ʻweqG ǵ=Ew6BFm1"Kop Z:՝ȒPCw^&O9*zuoB@uE B%#ؘ֮3IDGsnW83447m{W~xv{*4'g|b h:W>Y'˾ l¯[1U\+7d:ͩG([jb["Y)cj iwCa/ŌϧL(˽:tu+9 |˩%qO5(UuT덇KxrĮV(&i2('\bˌ,YeʀS+^G ɐvm3tfgK>:B)qX`dG xE{ 5d#>Qb-m l;C)'H`3~x"4"pD8&:ͻHl;19':~7]^WAWn@nE5'.<:=cHA0ђIUdqB-=Gq|_^!q.=`kk/l+ZV~xA[hbٛaYJ(9@ ̈gZX #lմ7_Kԏ3f{ZXC5ryC.n1Q:3ҜeJ̻T g8A@gs Vdhz,< bAV]N;tI:R?f߀y ra=pr/M zSL@#vعt7ҚSV΃W]- |fyׂl-m--XV_-Qs_B;W9e2;ޟlCߣ=iȹ)5*JW:ȓOMwu1@yյ-H )'%*BF/eFp_`382"ܤ**Y̻0H<93_Ptay12d+sT"8&v2z:P &QtJc}(u@pR"F^UCB)J SIn 4OOͦϫvEⰆ{ koԏw0 -$(1}-`NFK<ԳXZs4^@ju) QquoRߵ9B@ n:4j_ʚ~C݊ok=B1KuG P#͐!D)zM;M$y|xHzG-jId& Q y f eέ bݹJ!,&&(w!_ `v-%X Jh l|>x& ueu"QJ TR({k:!{<H` Ox! C!9տ,Cx(=o7P]OfDXݿAkeتɵT2:+TZ٬ j%_ћacɉ)Hr'.>sX ˂Rh" >Մa\Vf |2`~6Y~:3)7'͒Z=6Fq-,ۿI ^V,1egc)UI1,-y0_iwsh8GZh-]+?PEyulx8IB9;jWPGyHz0G4Zf~*uߒD-T|M+$ZSc3L:4!n cA/v)"|aӐ6͈zgP#n%uOC\$˧XI:,V JGrBΠr3R?2: zT뉀^+NF?8yQ++ U+ԩ>͵9$(JZ;\ `e?)ԍ댲C~k: 1OYD7IYNp0! )ı'Ħe U98((,1NXEp}9$x!.L/, djo0V[ԂpNw:N C;|t!ր< x^6U ,EK즁ha?=6~%+x)P*N&™b$h2A*(7׽ uFCkIM1W셇7]::C͢SxpAqp&C G\A-0݈ڔTЊ͉ L" icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/kbnp-icon.png000066400000000000000000001506231506470510200232650ustar00rootroot00000000000000PNG  IHDRxtEXtSoftwareAdobe ImageReadyqe<5IDATx} |U՝NBB aQAL- UkvQۺ3ZmmUKAmSje_@@-!~ϻ弓s.{d}&yo#@ @ @ @ @ @:% !\7Nq^3N-]@ mI@ s@yy]}}T38t@*D?ht @ =gfaa?V{Ɨpiee֭x/@8kׄ@ ACNkX~~^>o8 B Gd_\< v`3Z_@ P5v[Xҳ}RGq ؿ/&o{~}@o/- (s@ #"B kD x,bÆG[֭Mq4@#ף@HF"e+E GGR &@ Xm<=mdEl OD !@ O"Mssc^^14*(@ dMwP !@ i[UsmZ4We}v087 @ (84M 2)|RDنX6TXԏ ut@"=My~ @P\XfFF&@o&Qһ6:1`.5F 5 2 ѿ ,~@ H8@-3)v5v @gi, hb@ $Y+|dcͻ^Pw @ HHc'aAz hb@ SrH7b)1:Y6t ?q )my5#Th&%!@ | $H,3@OM L:]q@g# OYfW*JˆvC LA`IAA"hIr-۽-G:Ls@2Y@-TԞE֧|lh41@ xyyUߥEnq_"L C@X; :;'(?\rɘ1yyylܸѣ &ŸlbbtFMEz_K۷o]aaaAUƙj9O}i}?,Qȃ! @Du;טּnj;rV¦;XUWE`H@"7O 202oi>Hފs,YR7dȐDEEEUɦlͱ5oe.ZiO>@s??@ԏ>ӌ{Gg?[7hР1N18Upmam8NKzD$in@5ޯDք@ dSi>ڼͣ6?F)\%قCDKG/Ua .)ХЎDh`ܻtxoh>SD;w򫮺jA%%%ս{t\š7i`sM卑@܈IԂHC"Je\JBH>}9/ӧO򪪪)fmڈG3yPv_7?iҤ$HءBDHkS y#ۑh @ O$H]D}~W6h z6H'e|-@XSh6,~nHhdiYby8J"-7aÆhLG# v{שˬ@VA]G[߉n4G*tD?Fk^dڿp#ИȬ Sl)q}PdqB keƔT7Ѽ+P+_fVLZ 9_RDe?m֭\L$wKF֯_?UDuh3N]xn{uS@Ok7Q2F*.* U#$O8m??#FF=U|0tZHnlNg6)i ,FB@e5%'&gݺuShF47 3ڢژ-o5kkjܚo3^~Pʥ, Qg$eOW!zg}ϮF=n(OPLT,1vmq^T16EQ /-Ϣ/_dfqfbѧ)ѣ6?"6O|aFjٚ7h_V2/WX9gq!Q_{Bu4 ( 3o oI}\h~>@n_s6s%*tIE,m?7`d:y/@-xB1#03 >k6ljDX^Nra#^*|B}=O4^ƍ7VpT+(a4 z"%ߞ@_ex!P#^@0IWsH_ /uǍi?x1F$_hDd-%#65oq6j#$_So"aLoD!Eڟ=,g͈~N[/62B2 ?>Dވ+WN\4]@[Z"0OD/qo-X`̙3WS ,5|aI{TԚ~y 5 7i? "9ND|5y#hgѼLi1<Vv%P]]]e w?$Da]/[\7H0:A=5AѷO?+"_cX{2^\^#N{D}+))wF4?*͋4H~}3,- Q TEa_'xJ͌L&7̓2Y/_- C|yR Y $W1}ͻp;,_ ? 1+ShCnnyqU^,1n)y4ۥh)PQQQS |ʖx$S9/Rӌs滠T"g"y;3E=\JKK/N D XC)֡i]=e)Кck\.Ob=@D-UZ:AﲳHbZ֝⯍!iAV }Y[]}:t*uS4d Fo_ o߾,8A` pyl-'CxeL#021KK~&D@'K F9촿/\ս{2*4BD:x,8Խ`dlF`E#~ne}FԠ> Dn 'D yb'_'v2]_ԆTh8d+U\.A}YYYyUUQ7yZEְ;=Eĸq=2(v)!DY y!>>8!=[A[~kh<7zdjf?݀8e<֍EQ|III5j xs[c zBxF_q+m2@#mGBi -+hf@f~f?@""f_F4_h^A //5! j?@(,@5gV\çۂ0:(L vҙ(-;n0bz &r~!˱%]tEtv)РA0 "IP E/ÿΣexttEf$"JO7DbO)'C %%%Øu#.*Kq?qAub1:緉TZMHf?/[0 =h.y R%@Dk#$ly2~(eqSa+2 -Ѿf 4-(abgs̡x9c th>)ۥ@%%%!Dv4Nt[z~b"G?_!|(/3<=Sh>]hAbVed$K_R/~lQF ?T%KQ'As^d RA=Y Ÿ7}D^O7cWm۶ӘdyN6! 8zٲeWM:0NydDY$"#RD:KŸT5?*|SɆy`ܹ' BZ׳6w;KR C&b7|A11 b7ͻ^Z&H w^(*`Yl\ x^P4JQHŸqq }XcY-('dϻRZ 4x`Ĩ 0t̀1l &L[!Df!Ֆϣn  珉;C_/Ah9[nw EKJKK!rC#230  @e&0 |~z\cXbyB KX UKT 7DRjqC3bUm"sA1h^tS4OH!k_?6j)Pqqd/=wy"7xd ~keCotYR8 -ND< rf@D"'҄o~U^#N6 #@f¯VKܠz4'ޖg~Q[>/CL @@B@ LZ %=L,AEz%<t)o}敄?ǯwV+ϑ_%!'͂[!@(&d!L~1@hz}%|A|t[~j_>Ny d'@};c~!]v~[RRҝ`w0@Y4GzzRȊ_wdW?,@D>"Onڴ/ػw|ѣGG#Y?AL # eӟhv2@"e  'K4/ʉh< r,_娿_~.,,7ԩSs_'e( 2>Z6Pi &8t!_MR@sQ8澼dɒL@Q//?uˈtvv ?g!gp/۸Eށ?oߴ~s$𩧞b]]4VLH_W,J wL? Hp K?\{oذI?YgqL5`ăLL3ȆCW<0eFpף7 $݊_w/\ DS>j"@N"`ǎ pٙg#tAXf@q)2R|}M7Gł͑@@H }) ^eee aK~nbw"?N[[;s3Fif<4 fCY ĊƏg_ 4sfw8 221D!VjKd46Kb5f_-bR 8---83BDHh5j׿f< U6#Ѭ&8d l+MOj$݊_¥@~# @ȵ" *wP?8I@!B,0*) ̙zŊ),,dv|0Uwg 50!Q[P2nKO*"~fH Xv0|(y YO6_3 |~LҝLp؟) gEPX NIɊ_7hnP{3fL/"  U;('wamt^-(DԩSͨP Q MVNAK?ɚ,q`LlZEĹ>|$J"eifW^y%:t('qqugd ZDpDV0UK,}`z< Gx#bPM7 @[MW]=aQJȖ]vYL_8Ǐgf?jB s=+$7L]]TZ:ڂI@\۷ n qYY?ν ĿX !e`X^Qԧ>kI 7 "<p-:xSwPC2j@-[ x}ֵic˖1džZy^v14{y! Rᖿ}sv=袋"q_%&E @ǷXWAKR {P`+^3ƹ8|_- |;}kpb-5@!rwtk !zON Cǒ([NN?g@0ZDnWf_^'$ŋ'[d/ I'36NI*7g)DqeA} Ǵtbq56F {)Q@8A GY$ۨ@RbP,Na&$ϟf̘A׃<2LeR%^)^ DH}7O?~[WP$އ38?5&?pqfa]a=V#1}CYQcn@h Ā(ǃo1O/c@ g@SDAAɮu+: Z  (e/)ydžlǩSvlg)߼ɬ<)_;3TBvA%%h0>p 4ȭs^*b9mm`DkN gL\lٲڵP I8{"`&! sOH>knf;hPsp뭷5 9Rםn4I,ź?, .z~ dpeaPx0Η76< w4<9fw; D !ЧOHB`ƍ4 m'?ߏ !+~"?ʥ@>h7@@-WVnJAx g XQQx!߳g@C@F B̀S>5zQ" E6lXDlo < Eʑϳ)A4D'(B뮣2@ؽ+=фץ@$@ z%en% Do('a}oKµ/=Y\8ـ鏮/;_dDIDX,ct_3Lp1Q g3/A#HvJ2n_$@E^E! [ubFeO>P^@*fD;a^N"Zdа=-at;_XR8r/bŲذsGRre_M.HQWS |![;FE?2>ҹUKF@,r#z=l$d3P@< P {bXd(QK`L/TK/G#& Կhkkc'O"`ѢEx)os':",!X}}=b̠o3(4KMNPRR2ZC$)ˣV@U =ܟ$}b |-Ds\uU|A? ĉ#HDNHC:#Jj?:c H^Cj'RH^ L^YU: ĉ,#8hN,UEY\D_F J1$=v?rf}CM2ƣ ܹs#cVza)@$1 XF0T 8~O?i)kfPiY@V@ ,u Yq ;m X1@ xƋ_ G m 2FJB -bK. nm}v@H#UdWGY!`׿N.H?g`a7тlE+q]̀p$X_'P4-b\Xn* :+EljO@4JqOPScF Vš` a3cB$2.bNCW-b0tSQ 4C{ф ߚY(Yvĉܸj_鄀 =z L07"u~)}9şI<<HR I,MğZ$, HMw-<GFBX6b1cﳾl{ե?h @{OpY9Ă I03H˻ @Ynf?@ ZZ d& 0?E1H0@xF@ j@alE@Y|h@m)3HJV?7&E}*f2455졠2n)?"UKQs_ R4B7끤Q>l9% b ?,[+JXEjYgM+OJotRdI߷$ɃA Y24_SGT.zG}( +֛ bq8 {Gbj1Mb1 `*/@  ʭ" c"r{"3qP1cFL/uZ ] .2@28f4J݃q( + wH_X"j__}81$h Od[t Pʊ_ŏZ Ç̨ ڻ{Lf@/a@nлwQ, P@375@筇x{׋Q;qVWWs%K#G𴿌뮻vOھU)@|,䷉;l0GvvoхJxu}E;0 oҠ< ,B G 3)xP3Ǯ]{FÇwy-[[FּNj&?YeBylժU$"8.8˗/>E*ǫ/UOg[la)e> DھWaQ'>PկS`)Єzr)wE]ԠD0BTk9QYQ$~+͚5 -mZjS/.3ΈDvA좦/! @Y Dq_7R ݄@< 8*N4/%U{t|8 yqP.GnXѿNe5 N;7.r5 4$D,nG^^Ajtӧ0FSU߰FM5"U"j tD J (p],<(P3`nмշ=U~eeeUiaG9hӑZ5ĝ,[5N>@Ve$,g=;B,m߾uZ"d_ȏA@H K`rd˖-IBF҇_Z TXX y@dɂ2%dk%!'@3*f3yObY;EKialH2H=^& UY{Yě6 /,Hu c?NC铲KOm ؟~mT̀Y #N$' -$z NJmq Dŀ8tEARx[;H̀ &#<񪫮b7x#;묳,I_\{{ ݍ. Z ] o$` mTI`"84jV,-[ BlflԀH97 /2M;e ӣKtQ?͔WF C }qQ) 6?E_&\7Ù!?ͬmPnX88%\Oee%_$/ptzdEd/X $;Hu`j%: cLaD B,f@!2lpD/cDOAƊUX4rH>|xtcK:"6vτA[ N8A޽R\EP * 0dlBa(fZ99x7#iQ1߸#&ŏiѣG;/Y5pH ۋǟ?@YB BVwPA( F>ldd1+ɓ1M mEA ~i#بQx}uj,Y\6!#Ұ n3SBZ'A ~{&lg l5kDjE^D)~% rgF |H/Z#$!_:@H"mM#@rn5K0 ;:"nAdoGHPذaC@1_]]xjC<PvA=fsD4񕗗,>-?_f@a[DHHg_vB$,|鐈h_HR *)|"Hs9È 1!Nt@d|A gj3HK3xl555?xuSu{{jCj"e#n)![Z`g6ѿw+(U]1@UeD *Mi `1?x`Kǁjh2$5eN ǝʥ@ .1c*. $;LA;::׶ĩ΀v%50zVZ3,@hCm_G]ď1KѾБ|_F*S`$F]@K۷o92@Jeuݺ.jjK`lJIhe4 _Yp+D ĨD=ti{C}EC^~գ򝐾I #65}%R `S A[3t"bUayĉ=K ћTqp rA/G?H3Ж!"}}_g#'\]Z Dd@tp@ /7^ss]?W~j Ý-)}̀Un~v~"ܺ3*~D*}K_*/A Z17_ DAl8:~4eay?`iSdȐ! f@ 3" n|Lܹ3ffď Jji@GVV+~?˴'R  Q̚5 , @BӺǹGsN֛bJ@ TbO@DcLO0!t^U!G@ܢxzvf_>5z;>xѾ4OOѿ@ۥ@F0Q!"~Ԭ˄  ˔! t؋rT{ :|d2V7z2~GҥK `_[هs=]oM ߗ S>`[2h)v)h#Y; ĀN@@TI}">š ^ØPud,Dh"ڵkyS 8V6QOj@k} H@`sqƁݸY U@uErB:!H%7e6"n~p(>M6]xᅜɂxoԗh/UC~zF#Gk@-H^p\GhDv3U-Hv@㑒aU ˍlj^!dkS}ُ}/!d:R ,Z̨ r_xy_x+i0f#ދo (Zn#|1P5MyS < {ޕF2?WKp#u^3h X[ #G +eF}rM_SOSߟ jk̊ "P%JZZ" B7nuWeD:*ft*) -R$@AE#dbe .D'=^7R_l,..־8X ,x>W^seS!M}]sVq4d\ t 7oBbf!g*[?~ȑ<B߆#9P*.I$ڷDމ>qЍ=g>Rٳg~?`0 44 i~YXoѩN.7 ]A(_|?u2I.KE/.2o}H V;FhQWy78&?+~+{|DDem)],Kd A>}h  .h'~@@I2~&,@GWוH۠ƿ5 @nзoL^@4 G|0ѿX.nOwDGY9YzX  @K0} BuTz13V#S Q")++D7pQU+a~z-{R M"6$DmΞNsݻ-LUsҊ"r&ǝʥ@/8Yza=>DB577[3N@<?K_`mP_V+X Ta" @/8@Tgg&,Y7`ʕ= \*ȚH?x8{|/cn'̥@TOA@dp| 7~ɒH?Ӱ`;_ߗ" ,"PPu~#n޼ْ" H+ľWch۟X@nPXX8̆]\;ַ0P6mu?`ǝFsE~l @"`vö(^jtL**"P mHR/̾ f=8812;%@o6$֟T.5kh"~g & n׊,@E@b +®]z,!=}ٿ<] hK`՚^-2v䏳 4D~bzVc2  h)wf n @*eS4ToV; mh)7L_0k <@ 7 `) v${B`@[/+7s> @>(,{@Q@6l)? ǿ???B G9 P8'9Lf/}DNhC ^./-Zpa#?[Un[y $tB\s5Z@ 4 R ƪ F/"߰-R/--elС1_d m?h)c M_0 !+E4+ԗW_A[Z c)#SEl{ ! P] $ 0jԨ@)@ ,2bz62!bCH:T~+++u| *a_ T\\b´JRXwJlQNb-  //ƕŋ/@0 &hKd@Iw9fE96wO=U~=y1W*D@E;4/}<͸%0. 30 &D`̘1OSs:/e2d&~,8 煉 X;t3΋?-3lذ1/3Xz=W=#m__&.̯ -1SZ!AUR9!@Ȗh dP# "AA2P_8(G{gu)۵,݊qr;54.|~~|߻?]0 y`"#A'Mr)%W:? a# ܢeyN@|=Q/.&d5kUDFVyT֖E"V猆N? T.P|fN 2O/ƛR\\yݻ^X`3gn79S"@r$]i~W;uX,p^m)[JAC A c>JoGK-av470KjjjPX|2<y]U' FŎ~Ƴ?~KqmzM؎N% n>,v&(< O寑/ Nq2S}sڱcXKK ?af5@@< `Ř566XL xA xcngF@X t;Fë%P34~/'}x{3i˸%)xVE@2j :I Ϸ <_$zĉmd]]]tvvF 18N< H}'Nb@۷ogWF@?DH^=z_G*.s6oC oYdS$?6Kd_3X>S@&w|gW^yuF$|jjj}Gs]ZDEX1PDqާ|ow"::: @ `ŨO޽->g=28ƍyH_jD>>!oW%Z3s)?~1* <c/ 9%fgl,ܓt ] YwݿCy A`Ϟ=yoY'@MPEc+54}!i)~XPmYD>/շvۏKJ37\~礏E6s4oSߗDā,NX+`55"6э І U U3  d3Ë=qvg`3k]>-R  /Gs)6o޼1$yG.|]YOs H{ _. c };Fuﲈ;X]Bэߵk)S urS Б.@%B G&d(XK oooj÷W}1<3Yn3vb@'Cd D$sB·r@v_nr&@d m|=Y=Z @n4H#V6-J 8p1cƾCۀz9)pرM;(rZD@nۥiqtPhncmʑ?ԑ#Gˣ|88l d'9@j4'=Y 1jd2Le?y$q;w,}۶myM;07Ջ&A>,C&AI|nITt PD|dо`r|dQ ?q_N(F@]V[mYm۞y晱[Zv-|ٛa5.Gd]$" XetSP8tQ]#|ȟk_{dP# !BD@@~H^5Y{tm.9?S,7/?gsyy_XpKy 7S?CJX9K D^>2 aMxU_5F@*҉ ݧۭ.~_c-~X ,S{t[E]9F Y~g`s`?R@ncN4ʍ| ^%|ՙ]|DW6wk)_SX[k#A mډϾ}wɳ^/k)^kNr4+k׮#rGٯ _&xX-"ҁ ݧI2 WTx{چ?Qͳ\;]7|zs+VY|p*`6+V8 nޯ{6 wg tHufg/*c}7/:Ouؒ}9?.^l6Q۵ oM@m۴iK) we/H?hΫ)v͒Powkeˣb gq-~X|9o O>?}fYvޤ$L`5kDH9z ?|7e@8~^ xm)SW1cK/EýGNrokkg |^i63fxg~O~1{?9oY26ХNFٰaݞD0nĂ I )Ff J$tZAhU8*f{C:@ ~lS 6^v`]77tfE)lX u׍rc-Q?t.6\7'! @ ظqxR?y{/ YE~5׍M,z5DH` LP*JKK_:$/+']W싚R ]l'L Q6G.~tWvTKfOUg '7U 4O=Hx2 ק:?q?0kW:@vdk).寮jW7CgUғAS|L #K$o@3 gy&kش@% ֟i0;KTWď# ieIcES>xh \rcɈ?Lt۷/+/u) ݳFHdv)ޯK/G'-,}aV6'F6.\:m !!01{͊F@B*.vd. \>y.h)Pf95Oq }/ 4AJQWKy]66yg[( !9gf; tM7W}ӗ1 e"YhҤIՙ~:/݄!q웛Z:iԵˡ~|Y|_8|NM8|nVz`@!\x>}^ !́_2yO~Nu K B8l:"0^pK*b(uD^7ۉ,ZC7ҪOmS>6~u< Ey[ta݃Cvk`QZZ[7Of@%b[lZqR /_%ߓ=0Sh~j&K_?RXn~>sTvy?DDh5Fa%2d3g]/ۘb &@G=j6R @ψ (PPPpҿ>K,(%|?7|3+^ 2YŃWwdT5?]7agJVb 𑕸$0&2bOɴDii$('(NLhii|F@3>WRV#~-~ _9m4a2"hdH߈?~D~q˗ 4JY?bK9vkӑ+X1 zG WP~TV?ȃ ˁPEKA"?- _J2$[@4 [B|?ëW c =wZޒ^P_{@f`Ո\ok?}RQַ،Glj7_<`(_u=m4s?Oj\F,ssSK. 'L=⮹yK>qq(pM 0.Jk65H>aNƝƉ?,q,~a$.o>]Y-a5 ̸&ԡb 7 ٺ2e6/KZ DR \^%\Ɋqmƾ/o͓Q6F1"q %tO3߸WKy,@n3j LKYfqΗD@/lv/+v H;ZUś@w}lysC9{~/●=Z@:D@s> }ޕW.~My]wq%s)PG^&|ØZѣG~DG7WZnk\v-:1w8ǥsBB|V'DE &`F zӑRX`&@3ڲf?;FxQ,"/o;d\ ܼܘ("u/B`s#{ =_?yڥ,@̓MW ҒH!Ta@H48 Ho OHwI ko#~(]1w{ x|0 B)加䷿6444i__NzL,_5wo %elGD~a=OF"ŋW|7bF- 鶍+gU? I.^ SAzwWo>4ՌVwux <ׇ|pD8!Er*@WxΆ HK 31# yYߥFT4?طJ7Ce?|:{]Ͼk;@OJ@`Lɘu,:XF3 @(8+eLd tE~FXw_IC\y(vMɽof?{Q_vݣ?NjقM6n[^ܳgAM/ ՚)ÂVҐ۝;wf -  n{5׏uJ￀a)y47t3[|9ﺿ[>/{ :siwBӏ5 p@cYXzuV'ПJYHѼɿGڿzd)񾏰N  B2">33fxQ|?V)?#~,vTxp˖-Y DB#Om懢yͨfqzEds/B?H,ǎ~?ql#(/nH|Z-#+s߾gsS'_8&/Un:dh)!(4+e َcc:9鷛N; )Ыwo81·+A=Dy{Xwy1Iץ! "XHxe)X)K6/wT~҄ mmx[&W׿C>$^&lȿrסqK\ 'N @ Xoc,GO?yFɴ fqGN6|nGX_64]" Ѿ:K˼/8)tdP,A~>~ JYB|li{lѥ#Co1; nweڜ﷊j~OMM?(9 XbEVG)  xK_6!X{gfN²> B7RA$3"׾z-~IoJ I_{5,Zv-AX D/i:Ghʿm`gz`il;!޽{>o}|PZ.ol` IR B"Zrhy !I&z@lg#&o;Ú"edŦMvٳi#{>r2`?1n@ @K*wkt[*ZBFz_qY ď cܽfkE ׯORϋ-7)m'2KR .r2N.OEoGo>4 ? i|\{'7=D߭Kid+~BV[!~܀uS صkWV^&@Kي Y' gT{8J"b /y̍]0p&9俙l30QMpjժU@ÄJ <;bn}Xv +^u؀k&a ~+Wl?}Wׯߣ_%.T@E0KF@Y2w~'Ϙa>a)!>|9̅F0gSm|UⷛOY?m'XR^R&.O#N~#ϯ`i#~"rE*" ~}y.xn?Ѓێ(B*9%<fX[۷oJyH#@HKhԯ_۽gg{XBb-n#Mwя"@K:7 JdI,}_66GnS;,)Q@ԿӭYYN^w~_lηx-}AbbvHqR CfG%Ra0 RzRMN[埬/F؄F3.? _͋X\UoUjsmK ~&v" l=hZ T֒ !u/, ?UX~[[oծ%8sKO>ٯ-[kWO+rc-y睬uR ` CGV^qHnho1.Lnܳ{G8G,NZI%:]X tر4%de@pOˏT.aG@,5AF[[?_'-[Hؓ( -ߟ.Bȁ>{S(?ь*#Xo:Q7anCMqA^|=ԧ; LϱKC?YY @6y~-}nqnW+|1l$hŊh{\0)3ݯ7i@d7WQb43b&:{'+z4'8@D'NL\2QD[@Mni^izޫߩ:UN9OUWMuu~/}K۷ 5!Ї~R-|)~rL*={֑M9@) $$y%Ab?Ux8> .~h󗾞);@'@5`~=[PTT&M*'VD+>I/ւ(m .t eB2Ct$ IyugڛPnuښo?c$Ls~90VLDWWڱz{{B Cǯ~674779 @[ƒK?!y _sMZ0 cS/ >6L> e+a?a'<ӦM~<TR!0R.oڴU5kք>&S @ZX-#p?E|g_s׸5ƬI> rPYq'?? Dgj` 4Ҳ SU@˖-#6pd Yټ V'#AZeO_>*@ee@+UoΚ?޻#J-ƌ3E"~>,gz`6h@r O;!DIPBo?R/l{-`ъ/AT&RVvU͝G92--P>Oaa!̝;wڵkğILzo)ЬYƥ S w!"au8@l>V.k? ~4~g<|ܾ`z{v>u=:\00{l8u$,/ً?8/=W!?+Ӧ@ǁL0!uUd͏(gtL+/~R-||(U?.˧Yf&a:>te"S'=uX|\$|o4˦W6E @3$KL!~~̇~Oc~4SC2,+H]7uSve<@g_'/ ΂f0/))(sǓGeUO&[̀"":MM͛Gl0d-LACCCp_\0)o,#Ufw7,rY"T6U}o N3Bv^?1Nx`رڶ7-l Fb)Pqqq;Epe[6H|&CÙvc;>uAۤxP``ñM??a!x_,#cߐ-iK1*C ݃@N )2i\)K"s?TugZ? |[=d}-#'1i+h d?773B"xWPM9:@,z2]<+ϳy^'$e/f_߾2/\pKb=;;;֕lM |o/#l$1F "hHx?''}/&W)p1͛.\=2lYG+쿯06V21a xq(WRم`_8zH/?Si?SePu?LqQ6.WcQc/I/"Cnƶm[h1[DwoG|\#Wime9#ѣo̴?NEP `ƍ1C2-O|zdF%ǃ䏤۫}샋'H53W:VƏ QӮ]~owZ8y$4z&^?'~ˡ}'$~~}CK{7lH7rᤨJ>t5U)S+( ȟB rv@6)! Cg[T:UkYW 7ϛJ/P?2^?9h@vBW0Y>ުt1 dvɟvڙs-t5*U2<ԟ]7C]u#cҏUYxr3ɛ@`K @wuf'kqꂫLGC/\p(_* `i1!xh0l0X Qͦy֏@ybY8Ĉ+ ,`> ܝpmVؾu #n 0d#n `T(h,x 6m /cQW p) gvߛ>/|_~~ZND] C\hFXH过Rq>'%̹喸PWzz#r L-af1O&@Z!B_My0uh Mf;(ç܏g@ 3C3fw͟U q?σxPSs6mܠzC+~%%% T~7)L՞@+3xF~{߻2h =X)?Z*$+#ɟ!?)0a=n ְ5(_~,1ǠC݌䏙zڹ=f{f&[`J@"pYG *Sl]De= _$,^Fi[5`?~'O1 Xp1}OiN8yS}FuqC>?f%YWo(p~\^͌2=+A@QS :M}p>WQ0U?l lAXDS'am~Of%2~A!g{ѣGPϦ \ FÀCNfS \=$8KtX/1E`+p¾G{#<2_qӈ"(n0=Q OJ@-ZU h ꪫ/::/jeQW$^6GQ7`5OP`򀿯?=Ų(#?pjscb0M+APCC#@6{ARCV?xߓkOބsi[B[ }Z&)U_%3 28gzu (e9v#2 wRjO&}6寝aQ/&j׎Pe?X灀X_G tѣ XO c- $EW>/jvHPվ{ᓣG%_%+^?/ `v7@Ȗ5@ tĉ~rn SԐ^_5(NPWjEkK l۲LKJ*$ =ωlUL[ok(ZN*`J_APߟ.*@ M|o~WV2#[a^]$]O{]O%j@6AS ')S">M˯p@-ddc5?~?[MsV4hGKVJVqA4XmsP{*SD6)y ;N2rW~yoeId+X @@ີkh}mټ *+tV~~=Tif@(O [ W੨huI`d įozO{Lc~]Udgp&A΁hmma.~h+N4/gf+~ @QE$oD2b5I`2 @_&#?^G?I59N"%}U~zZ*?qN?zZ}=m٫^tEz`@ u@'Nz.XWȟ%oee2~'SWA(} l}ˊd h>I֣e99_[s R?:]-yO%o `H.Fd Zߪ/W۸q#wU vFfዒfr—Dr)|G)*ide~y8m DkoDVV~cWNݓs +wª߿g⧷of,GL)\;WP (0'S A@{q{zzIBƩluGx^xn1S<0KF_D[nI 37 ?~LgoEՏIʗ~hqH׭S8M"A'+ࡅޭihW~q2z)cW@0P YiLu@Pg*W;>ˏnbOc`tL ڳF/gaBvNUF>v\$EƟT'OL)ފqV=ޖr^ttk"^`2xr[kgX kL_V`[J2m A s =Ij@ee# A@$s(`P1˪~Fe~4..HvkhWœK!Gnj?'HB@{FNf-X`l1lYBmvGZz@3Sj2xG ~gv_.#C߀0#8l s>1cz5@u-gMQ@|}n߭Ϯ:@v\|i=m^oV`y ^G=1y|(1)O\oǏ>/sf<ӧ`8\z7ɾ T?4G[+~Vޗ5`ȑ! Ā\e $e2pEx63RyTSLHE^b0믨dUXaנfk ><מ?ـy5 s ?VbD=t7S0 6ZfML5ڿ:yr{GWkeKU?~7I| <ju p}+1BBNW\hk#xU?r/?D[<v僑Nkd[i _Oi< f\Kh 4u S3Hb܁ǬW$Ɠ:+?8?8 H&1! z,v+/]U)Pp c 2"jKW~. 2}'x?N}4xa?C/P H?ǀl(f "IȒ$}@w?t-вyF5!݄"@'O6A^@6@uu n81+UޫU ēJO|5YԇߟϲT[y $y?4f%} >8"ra%w##i t=!P^0(?B;::a=S G{//yqXݷ^&T5DNC =CBMz~*]9V]2eLHCIl4 t=ȩ'-9d/Zz_Q)@Rw[[)XIA}Xn& 崿jyUߝfZ Oih3"X`رc1ڱc3)uWȿM/b: +[)\4(nTxϓ~)=Z5B@~0pHSQG^e2񋤏}^}k} vm 0OuDsXpK5. amp_KFp(1>{AS ]QD&9Db $}c\6Ŏ@k@G#F¢ŋa[cZCI'#Bi__ zu-MV@$D/9` Lܴ `G~3k/jȟ+~g%Ol5.]BC&`F7lI5]W/!~G @8DC[U9D@\~XGid dʊ_'׾&7 VA@,~wn7aůd_Tܿ ` %g/[x[^^ԓh L@VI~9g+~ " gp&r?"?r?Wg?}VbE\OMfxG{9sakf&&@6KsS +Q;DS [*4b+޾=la\]to~ RGBGb>hfdď@W_~5lYgJ 3L4 7vˋ3b0 Fg[ 0߾洣D `N,ʰ_ߟܟ8 TTTիctl\[ /<^ߏd.GHֽϕCIu`ϩ @v)ԯ?LSR SgF;ߏXU,5>ղ v`rF8DfbƟA+#iA{4OZ6ӛ7%-E,>t60Sh MR(=.]m}_VJ~/0wU`(io!@V`g͊A |O]w;53\y 0V@6  / uISsGG}$xy;[]vܹs׶5 0d@ˍ789?Lq$VLbm]0m@fr5>)뮛:WVVX>]$}tLBW25h 4ydlCTP{ Y 6Ep+A@| )ہ9+~bυ}X_Yfl{7lt"~ۭ,@%Epɥೊ~?Ҋ_,mټ_05q+ qp=p 0 B@.03GXbKWpɟKm;u|vE"%}{:}uS yeŋHٖ۾Fh dÆ ] _ 3e+2r !RW{z{~?+\=u/;]V>V>E7?_|vr}g-evpuQ+࡞C0y1‰M `c@NB,Ho J&.~HX >v/fue c^#B_h2'j{F,df|W>y;R8%zmzZTTt#Uҋ(7h8 >#gp9\CJ)L8YQT) *,|~i ک.*Z"i<^/po^!DVDm sS uE5 'M0(«8 'xFo/_zW㎬69;:Xo gԽH#c{Щ}tNmNvl4Z{]vկ~u;*U &S 7%.6ix34AKt_S7`;?hcB%khWb0#=)O1( 0ydvS,--u̒.Y@]Cb9Y5f^*ϏxqYfCp,¡d]wͧz:愘408PeQj +ˡlܺ'}g7V+P VО='+ `y^RK|n3x<^zidl蓐8$ȣ WmP`/8n7l>EYa[o##,#a֏o8OnnŸnH#yZHU&'x`P1?3gDx+#S $y~CL*AV]c ] S6[K [>< +~+++[nq-[U*x <8 #fBII \vel7p ?!v⑉_;$ٿrTj@'Ob?%m@fvQ/~CI_=aDs[]*[x&Ԧǹ!fਫ਼ax;a;v,K\s >PȀEHCD!@v+_jӤ" ;֢E\(b W/})!tʕ+YAY ]6ٚ-O-YȈ=ϳ~/f=H)^.7Яܐ-(JH-lKfOG |7S am PWW̯ؿWXȑQXj OSV@, @]s@l Tp)P2$C ՝ 5Il֭ڤ0h*l_%3?]$H{O@ @_c)SOX^ "5ϳ$O. M|&LHbkk lp=H`F>yϳ} ȥU/D, @vG 0ip:9deSN`Hb*px7GXo2@.nĩ'aӆ  J*'w/h t3 9F o2%?Ag{6{#Nտ^8ѡ(ޏeg2sW?'~Ϭ @[l #d! *tMLH/?}B?@CuE+|-xk`#? "Ǣ+~==ݡ^V>W\)̂l tu]]]۲e˙o^;j2P P >S H?޿c0,IŁ@4A>1Ė R0p+~dD-fx>~DGg>|{i/V8p}ԾdW̾'`V~? Rzm@-@$H yoOn(C)bRԩ,_ Č_<e {mjoo/++k۹sgXε;A?B I]Ywjk ) "NI`xFjgD o\pՎ҅j5@꒿0en_VQ~Վ{ݧC BI߶^?'}|\yg}/W6_[[뭩񖗗UUUumݺEތ_ o[8B 3C8 4.G|)}Ѿe{*۷m@[l^$Z[2zȟ^ AOAPf%TYYh #W߃'04p=rLJ?(~rJ;;;;z64_[jUL^u*W9F dJ5M69}v ,\ |PDZ4?n}v"zVgĴF~(?(]ĀcN9wWTTVWW{1{5!y=635uW!z_ }]AV#F5h tENib@ߠ7 U_f7khd;Shb (--eZvRn3]]]kZ9'OI6ߦeZ6߯H>V+Ǫ*@G] ~mSS 'y 1xk*S_bEH$W_|e ؽkWԊѰxJ_63g`6ߦe]l^/o?o:q_ ?:G AH4X:qZh (ןgP6_̈́{V<|`(Hc=r*7se?>/ Ȼ=Op^˙| d A H֊ I>Ǥ`4 zω񴵵Ed1LJ_Ld6ff&/}/Se p(3fLy=k*6}﷑[ |NA 3 (0bi=JKK]ө f| /QټQF5kL0>øq/f6>_P?}<]7D$@3I_/垿!?S8ii'Z6O&![퐺Ձt) 20pSO@Q#v94388]G9q(W~F$u$:Xr _~F>^z'Ol|GGG͛I{!<A),Ja籲Nh@V"XE%p(U<<$qIޯ9?CCC!Kx! o:=A2-8,E?+NB6؛7#x2z+xf;7|,P\Z:ˏ7)Sn)dj2Go>=#E/gx_]] %#Gȑ#]$@=h[6on7 Ş& |[e>ތ>B}`N𛐽6Te&ob.1`"LTdx>3HrU#K_EGǃd3$wy~_IIs`@wǶ1@$f.~T'|nXYq>U~L q ty8'bJJoo]ܭܚ}@nF rW@ g\EAG7?S *G1g<7풿~?9?@(nwDt =_gφ|D}8f>?/LtUQ( @Y}ƍΙ3'b$+xf/"V1!/E.YvX(ŋV9Ѝ튄e]]·[w؏ |i _ޛC+.ϟ?߿e˖VHyxUYYFGfCxVV},dO7 N0(p&b?;v-`?l?*#~O|Δ?,,ۍSs>hsDҏ1r/AdH! f`ݼJ۪yM2[%Xo%$} 9 @Z⦦o d=O$se1g~?ny -ccR |c5譐b%:aODO@ܯ1 JP/~i…̊ضmsE6Ȭ_zzzXɟ X}gge8pGRAkk sߛJՏ*9_=@GUԛOD&x%-h Wmlȑ##\Gqt%${H"GKbo"X xV^MR ƩS'7D$o-|E?Պ߹s缍}Õ:4Qd0IdL^q,xG刺8y]6Jjx 'x${4r o` ]{7^毚'!Nc+WP߬/%'C::tO?jV6tjx3zd q=O%S c1iߟ3~:mLO508ۺe3twGXb=7{~${655A}dEo5H夽') +AJϟ ⇽~ML3ƆߏٻlٳgsvtjM3"VD$k&)*җ?E-Zp뭷'ȭ_=q-E[:@ p!>#a֏~w8qBn}  Tט@rkb%x"z s #͈?o~]_STl$\~?W~3] hƸ~F^;y.胤> q5C:@"⓱Fg~gE 0yD"`", 6* r-0:x_|U:e I_/ h'θ툑#\fxԩeK>|+ HAYv%ڼƮ= FyyyrpKU>܏?n+̝77dA8}~wP{Ӕ7xݮS8n;_#vϫ.Wďӣ8'ݗK*O*D]ozH䟦h|i鯪ө'j8 G~(+a_O?[?~֢E8s gNk}ݯZqR>oJd^fNNAj.7ntd/jUj䏻Nz/fO}z zr:drU FFDoW'[k ;wˉ'>"`_xx8a@V0Po]oi_zp0(hnV1ۅ[~]­xj^.+%{F,ET'P dc "ollܤ`6dz~?l7f}G-hiiO"~YOۨteT^&n[& Nlzٿ8~M8Vҥ6lwlcϞ=  ^H@0gFI}}#ZZ @ xzaY|9r=wFՠžu^dS&do'''P@%SYG11P666Ž]dͷםkj:E@#GnLz{{yDCl#|k \If2eeeeSO\tKuVuω_y'N 2qho^|oݺ*PX#A?؛''lzMY&L8{<>{@]]{q =y|a|II qu{D'O0Qy g"tC閳9}t_'2Zlc/5iommػw>ɓֲ|?6?xh~`sϿp e3gx7o<"< cݩW?< -Xٱ}{ُl3h@C:ODO P6ğc 6@ ;p7$hjj644t۷ eee;wl=@'Tr yƌv(zZ[.}*NmfA. A|mmٳVUUumݺՠ*b#YmpV,?;mڴK?"zcG?"KxA_g?"Ltω':zHVݻgmc}hK ' hಟ/= |@g˟@t_'kJ*%?"~/^#&5vt@ h޼yl[^^ަa&>p'y'_~Nx_/g$m߶ Dz_QO r%u 0`X;؇[<%^;|/[7/ܱO zs>@E W @-Xc}s'6#ohy_jOE~"lz8AiB0R8#[<Ï=:o̙I(;|O?k˖-3yRcgm0L |)7+l~k/{ G5ǝTDBfZ!b@D Lw|EEEkuu{}F]1_'kWeF}`]գ`p߃<_W cǎoNcTAtW ^/D P@ k>DŽU/ja5?vXNڷZ }ӇL2zټYFGVF|\! ݐ"K^0C?}Kl{bzpk?DY?@U9,@//{ǫ;wKZ߆|iii'b>R'}T/f9:X(^"2yWf˛t u˽~q_Uhŏ@^+Tޏ.9,8q[nes/ Fkiv2XIaźU(^c(~ytL~sbWnz׿~}̟JZI(VҐt D_,YHo<[yF9rQ@q5A??XIFf]ϗ.ykm5٫x >DkQs@Hb.WSv Xgy葽Q/ P `"v@e]6ro\TTIoӧOouCCC ~|`<DB r[q rXg^E+[V[e'8VK˃lSINDTAk"xݶ mLy3_-wmWW*Lv+Np+ߡu''( ,Uuį!NΉ} T'dBEJԩS=kt~b7} -"!2ZBlj_]Sˇي_"cU}c"s׳+\l<|BÁ` kʫ7\s (H@~rF+~륷.JG"e CU#{#W z@=0 }yb3V~%݆g< ~\ћ򧬟@ B#Y7%Z"{lPouFĮY&7 #W'R~"*^ Wx[pcy jՖ˙o7D'?!A3zɪr_o4xg4'徼^^ǫfC+zYT1/iAZnզA׈{`<'ӊ@ AU2`mNoloP=@`xK5#TYPcSN-6mh7Ѱ;^,+-Ⱦ l|5?# f"Ȍ` opɓnsT/XZGRHDh,^5s\0DgUo3Ƹ kβp`ůG'#'qnz+ #?(8֣[uf.Sy6y1EV7`kmy r_Sy/@A꾬 `$~Jj:Du*%eYpc_|囝|C%}Wo߶ DQɟ@ Df<'B/@H]@etOD[B+v_VvG?\S΃~O$?D+e@ P__kG'Hȹwر93g'Uɏ7vuuɿ+x+YLjO \AT^s8' =?Q lܔ+~9΁~2'x!rO'+=@ UR42Ӯ]ͷ|/lԨQ>Ѡ=zŒް~?@@Aj%P&ZU[o J~[wUWWWDţG+~$RP)3@y: pÍ>),W6,]-ӣC~E'' ?-Y  w\zMv/Y UV\hŏ@ I s@ ̃qE ן+/oyz?eaI?d Az=Po^@4qt=w0G~ Q62/@pbI dJ@5*9<oƱTHE?"@ N)a8s@ od~@ W  Cx @**} Bb@ D sH )ӗ)') x)?O8&+N<"Ǫ?@@H{\9P }Pdhŏ@ P@ 8< UTb /@@p.y@`H A)P??@x ̕-0GErn\ژϖR-IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/keyedit000066400000000000000000000001101506470510200222410ustar00rootroot00000000000000#!/usr/bin/env bash java -Xmx1024M -jar /usr/local/lib/keyedit.jar "$@" bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/keyedit-doc.icns000066400000000000000000001346741506470510200237660ustar00rootroot00000000000000icnsis32Cr,ǐ ՠց՟ Ԡ ׿r,ǐ ҁ՟ց՟ Ԡ ׿r,ǐ ҁ՟ց՟ Ԡ ׿s8mkil32v)?3˃Dà;¼>ͶAдD ӷA ָuxA ƨm ʀ 躿  рӀӽ ӷ ݶ ص ص Բ ϵ ո ! !ӧ!!!!!!!!")?3˃Dà;¼>ͶAдD ӷA ָuxA ƨm ʀ 躿  ӀҀҼ Ӷ ݵ ص ״ Ӳ ϵ ո ! !ӧ!!!!!!!!")?3˃Dà;¼>ͶAдD ӷA ָuxA ƨm ʀ 躿  ҀҀҼ Ӷ ݵ ص ״ Ӳ ϵ ո ! !ӧ!!!!!!!!"l8mk(_ccccccccccco`oItXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmoj3yy4it323ʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ źʿ^ ƺʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽ/"¸$ǿ@ˀ Ղ ܀݁ Á Ɂ ́ ЁՁ؂ہكށԌыїȄ̀ɃɉɂɂɆɁ…̏̆̀ʀʀ̂†?Ç?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ źʿ^ ƺʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽ/"¸$ǿ@ˀ Ղ ܀݁ Á Ɂ ́ ЁՁ؂ہكށԌыїȄ̀ɃɉɂɂɆɁ…̏̆̀ʀʀ̂†?Ç?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫʽO¾eſOPQ»SüTƾVǾUɿVʿWùʿWŻʿXȼʿYɿʿZʿ[ ¶ʿ\ ķʿ] ĸʿ^ źʿ^ ƺʿ^ ǻʿ_ ǼʿaȾzyʿb ʿ~xspooqtuz~b~ywv y{~a"Ĺ]"ǽ/"¸$ǿ@ˀ Ղ ܀݁ Á Ɂ ́ ЁՁ؂ہكށԌыїȄ̀ɃɉɂɂɆɁ…̏̆̀ʀʀ̂†?Ç?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫt8mk@#056777777777777777777777777777777777777777777777777640'  !ӆ> /= 9_Bq#Ja&M`(O_(O`(O^(O_(O`(O_(O`(O`(O`(N_(N`(N_(Ma(M`(M_(M^(L^(L^(L\(L\(L[(LZ(KZ(KA(K+(J! (JC(J#(I1(I< (IC(IH"(IK$(IM&(IM&(HM'(HM'(HM'(HM'(GM'(GM((GM((GM((GL((GL((GL((GL((GL((GL((GL((FL((FL((FL((FK((FK((FK((FK((FJ((FJ((FJ((FJ((FJ((FJ((FI((FI((FI((FI((FI((FI((FI((EI((EI((EI((EH((EH((EH((EH((EH((EH((EH((EG((EG((DG((DG((DG((DG((DG((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((DF((CF((CF((CF((CF((CF((CE((CE((CE((CE((CE((CE((CE(&AC&#<=#3Mapz{qbN4 (E"ɰ[FzL!CpE{.Ȁ8 ~haR } E춾;f=Mg7Rb%J ?>׺ y_{oؔs{/uA?x@8~ԮGE"ͦp&Q{;- !X,Vj"/녡xH⏂z p[b x<jaU2×t9@76s(^8Ӣh+SmT/iz]ChK(ڠXPi1pV^[?d"I~b?T̵s 碯?o$&Et<䢩DcZ3#Mݎ> ,t_Ns;A3uHCCkG9kAPJ F/0 :Ǭ8~E|: vu!B `l k-iy(;RtVhs6/BV;&^1 Z(4j1G,ok'ޭ'gģh|а'4Q]cb"詚E_zf?M c dmS`V/R4> Uq d*$`0L`@ k x'+>E0Ϡ$/8 2Z_?7T!K@㊂A ~iuɧ)޼W!V&.%T\)ަǨSOUni2rIo^L sz+ gDHAy+K@׊ cXwhqòUGh q&]ӔfBoe X29=!)׵V(2ԓ4Q?,,,ev!w="cRn.'ı`$G\qJFkAװ=̹M"sE,2%ϰAd6&383^|*H/x}B D+Mi1j?  Kt'[W2qؓt|C>F+!~B:+rHh<kxA+Iz,SŔ8Ot~WM\oGJ^zD"q~η C*B׽l"aDl߱śyѷyňor`rR Dι#(̾4k g"ShDT҃pvuv퇢)W ԶwˤB.\2_98J#O?4K8(1u8JI Hs,D::)+pq'R]ͣ;ѩ~I}P[Ƕ'Fh{'38WB[E_/u" ITtW%xZ*TNa7whW)s+0c춲x-p:`gasf5i'>j:qw'}?>@=C-\]ol .+ OIBww`n|ųecvS ,ket4^Mu_-)nP}jN,^wRL2&P:}l'o&-60f5Z}p&v2Z_. qTUD&^C,v "Dढ +v1G]Q_x-k ⤃,`@J3ъšD#")䆷/&5إ^AvM̔¯}bPtLȹjt+)GCz%hғ=gX7CցEӥ3ؓ"9'jt|f&(H m+T{ 'FTOR2]A6"n,[0D1bwx I- z+6LYZԗha e/1Ǝ.5.bMg+5Zbk޹ )iP ̔h@fJUt,?n @m$IT G^*H{JR{I$I%tw`oe\,ݡ6#MQu]AmGoAh- 1CV3>(;Ԃ/v?`VtI0V4BF3-$GjVq9+0:1;]`^BK6N][MUr]N&Wq$jE LRxJs/ >4*!/ޚV&zYU883N ~ʹ2 !a*KZu_TRzL`Tm+ w06..u 89uճErEIa..dz#?,]HxdddRʃč-J G;C{?:KO3jѢZfu,vJu)@?HXbzR^o|;5M6%g pB_D0rB~׺iM7ʝS5d~0e::h 2V[%6oYtiUo錉rtb8Yfe@%d#2YtrhP`Y}PV^˕#Cg7>E 6 nt#lyu~#>Ň#0= j\JY4_do+j  +{|U^<:=:w.MVFHㅩ;46"(^܅zp*b^A:Bw UDŞhF+u5a_ ֚ «Lb&F Jk` 0c΋zKْu>+3αR,ZrbA|d0enR,%W:΂j:* PwzU)#;"M26SAV]t 5k!Us8=$_64}2eB_$j~LDr= Zɷ7ifn)e@x*]QC*dw?OcCd?_${ҎGf1y`$ǪiىT* <Ȕ\N:~}d,v S!"Xi @d7GiSvN GL8NpU1}U~|>V[`:͗~,)Db`b2mJ1H,^pB֨7Eu0fM^?@r>LsQ!ð8JhЍ喝 u.Cl@wѹ49oHq=e(A[]K!{7b !klX3\<]27[JאmٳN^uE3h1-Tx23_Gh}9ZkZ(~EM##;őd٧oyMBâٷ XZmx5W\I9m4C^T'#=LS )k\+q";')H|1M3--~V_H^k WPXpYt*cXT'1_*BqWCg~.wƸ!{2t*~h&ۯ2Qk82\mZ+^ wcqLxf7uwP."~P#wA}ڰEҢ-;}Y7_ [aw`g5k:7-V JQۓcj_[)P@͏3> "[8Q*257ξ<ϰ[J˒| @;OqcotI@NrVudk[@&7|jM;jsNIPՋ2Yte0rVi`Sc~Mw`K̋2Q\&WCrv_ؔHە؊GOfPP0Rk F>~| ΅~Ԡ߹^pb^Ρά)]Z7w$|IJL;k*CޡCw4l*|WJF5ԓg98]2 h~n Fi_ ?fZ2^l[ QHzthJCrQgg][yg}^wAt5s*bH(Rf\ L{U/0gC8yc7c+,3ƫb9` D% G$9 >us0,vIqE 0q:]uʺ>%-c$ +Xw^'ٸذbgɤ˹0 1րcD]%s8*Ӷ-pӃ*{RuKFr-( >3F~Kra`? ۯol;j"p7J?AҠ'`B8Sh&ynL9irv%(v [o߶Y=W}eh|VЁG~ Z%850CE %a"mV HAWd?N EKXq_krE}?O?yTV[w_.4~f?8>lE!$Y,<)cɲ#B~pt\PL i)֥3X^,~J6v Mߤ-9ԏ$ft m'K6ݖQ/4 &[uw0EO6j #'q8b LO':k!G!/=úSB"Yj{tZ[[8f8;&mmmͲ!A}M#*t -"tFd<y 5Irj[as$e+NYGl8//Y ݡ=૎9+x{U[IMπ-UE]]E$N|K߇׫e >~HKr` MûNL0q6_JOVY] mlu[:lfN>r|_XͰA.d+陆a?$]=L{*5:~JU0e + m*3|IP OIAYWp <;~h%|/)yKfZdRȋf4fCjQ]fUV+&ɖ?- JJkj47: Vs; WpUNA eŸli[NK.VѰRxɒg;E=}V@r& /‚i'׻[Ay+}:B!L v,iuLC"=id̴c^!v, naMAbr_]VVPXhsNT 6SG|RQhg|oOK\+Ξ_U+Xjo~g]_&az,`E ]&ŹҒɆ[ / 5Pv 1Ք%J-fqfU[m;>X!0mgWmLB-6!Yl#aO _CK KFl Wf__l8A‘ߣC= "Cr8j+) ])g8"MY2xiO{5]5MJ B0{^]DplvwXyA: -5)P78 ]$]HɅ^ WdR.WǏeobp`~ׂ:,~Ӊ/欯 0Ӑ1*vh+RlYl 3?֮JDٸgfY66! ^xh9a+l6 Pr}V0%Fd9;N|Κ<ĤwS_ٓ{!Ģ#VefFELL ϝoܙLHD++X;04ۆ,/!i`ɋ7~~;9G)Ԣ߷z=ШaψyR,ZeUco{/W -| –g$9p|Ws$Jf5yFg Pڜ[MeSE=D UUUUUUWG9BKh&+!νK8KAwHPm$I$I$I$*ht+g+rm n>ɪ.n*H3pd#(hI|70WDBk |?:LY7ɺq?)S̽7|Ó.^9=Vh%{tPrt) AM{q pw@9848)Mݔy2ckm O6' d.rg>W(z܎j9T)(as1;/q -!)x@┞̀GQ C|OAV&X7V1 xr]DmMBf'}-CfFSxœG2ݘ'\:|Tt!a蘵0/>i˧uHbSκYg(EKy%QR q.ٳ/FTƥ&Z,gu7o\d'X~Iy0bXpCïg6AMٔ/.Y^.q0~L3y"}fޯraA5%˰#%r[[sy~鵌/i|2g|2,ǃ_cD@²Ӏ@k8 @ *IhJAͥ5O5AgR}lN &󭼤fiω.UE^,74),X-f`X'u?ZP?|gC"νu.x(gY!Gش _͗x 6u #ݽ150__A![4pZd\F߅' \Q*~)G{[)kY1+:." #{B٧3DL!G,hp_Gsf]uA6q mˊ1@z{" 9BlH "5J ^5 ֱ۪)}tc;#0Z]Ra"ǥ~r>OR!d'xH6DmK^ wʁݤ3ek_u |1:e^-DlB0aH B6 %1`[)1C| >FhH,\sC['`ϰ6^~(ܻ &JS``oĞQk6:ՙBm~kS?g6+YL/`FɈ~t[+o-8U>H/,7ԐH_jł5],GSs.y> g?P;[^_+S8; -&XNOTRnCG%M Z[NU~?7!႙J ):D uߐq=$"UξpIfc`}&¿A<,$YӇww ړ4`H0W~Sifa!5 V2_B"x Q ZF:ӥLl5Rn7:c~x ! 4@+nhl̘Jţڏܝ.D/Wa An/_^f_^t+'lpړ+JUm'D2;ͮc.J蛓#w܊Ze ul]mI6Z{Zic:i^bd13|ڌ9~W]_-5Va!/ϓstb}` ^ OR48N^IRc Ix$o,$‚9u U&6*{\/ @1eF ;Z̷-o2(@ I90*5zE' 'BbJzfՙF,1D0():r1ۯZ- 'r-r韪Aб.cELM9  gz]H|~7YȰy aZp?H(=gxfR ;51AwP%iPː0ʇ~K4qbbD.xN7| w)^Ce;_dh؁h gJJ]MxL`xk,Ǡ])Vy:)xKzt|CϜyنkoAjnTN]6"; )μs+VV;0_6b,E2yR'ДYM&t3|z&f}#0Bط>i=GƯRvct?&w>^ l0M^: }a{ೞGFvt*l+r |kC?<.$c`#S>_Zmj+'D yB]DODQ o*G,Β}(Z!-aUvd'.gUrBdFzK"h%XΠjBܱm?zIy~;(O -wy¼Â91"J,}C:o7^L5Q b7/y%[p=4pq0䋼PLI)x7Vucm7|G޻o ‘NݺDRV_/&NB^/8) -Wѻx⍤ҕ4OʘMAF,^ų-+7.kUGF$cR)>g~zs:ƫ' YᩩKΈj`rT,֓)/v8!ղ^bVM^9#fTЛѡK&Pz2 lB7MSnq8}VG܃l,\&\mlCmoںPrNゼ ?L+QKD7>M:L Od"َed=P׳{6,Im2d>ixV8izW@]#G=[^ݿpy[Bo]08 (H=T[3e0KsuNvI")e(@A=߉? O# JPd_.Djvzo?%s^[_Zʣ)`0}5m-A<, ͺO)#~:NDw㙓[ O /ꯔ*HE^>+8*}CO8UugdΗKa[mF&Qwc,](֔Q# wH̯vu#8~NoQA]) xLQk7_eKAkqZ_Hhyazmvf b\knl&W1.ts١C97GƋ RoP1{#L4q_~ ow)#^ ԕ`KO Rơ|Rc& (Pp)\6 שyC@6+.cGܯA0P02|* VnSDT4NF.~Yt b*hڼd&pp0p @ $ AF h?tߴ Rn((|+UPFa7-qb,rWTC_.0%tI$h=q&wWu;Bߌ TNa zA>Gzd `%a0β*pY$VYL(Ju9.%[D,uG& ^ĢLSlI$6@%%!f- є4*uNR9c;Sq>b [@&6b!icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/keyedit-icon.icns000066400000000000000000002542721506470510200241460ustar00rootroot00000000000000icnsXis32f.XF`J>&FUy' bv|ÿؼ&ǻ@⾭aհaϭޘCQ%(c\vH®yY: I9(^ :?@f/XF`J>&FUz' bv}ÿؼ&ǻ@⾮aձaϮޘCQ%(c]vH®yY: J9(_ ;@@f/YF`K>&FUz' bv}ÿؽ&ǻ@⿯aձaϯޘCS%(d_vH®yY: L 9(a íIJ!,ؿӺڵ頷:ѹջ͹RŸǜղļtȻs÷оݤɺʧYλʸľ>˻ȓb-%ʸ\JX˺EǽݖLTtc˾ɹq$NXxrQ=ϷìxWC"=_9qï}_E+Qa*XزjJ4 4XL& K_5 'WX@]DRZ%4[+ j( e   WѸ5|^ | p^1Z" 5-Kj_"4Д@?cμk ߦB1`oܲ³ՈJ㣳ͺzϝ^۸ŶƘ֌˽ >íIJ!,ؿӺڶ顸:ѹջ͸RŸǝճļtȻs÷оܥɻʧYλʸľ>˻ɓc-%ʸ\KY˺EǽݖLUtc˾ɹq$NYxrP=ϷìxWC"=`:qï}_E+Qb*XزjJ4 4YM&  K`5 'XY@^DR[%3[+ k( f   Xҹ5}_ } s_1Z"!5-Kj_#4є@?cμk ਰC1`oܳ³ՈJ䦵ͺ|ϝ^ܸŶƚՎ˽ >íij!,ؿӺٷ飹:ѹջθRŸǟմļtȻs÷оܦʻʧYλʸľ>˻ɔd-%ʸ]M[˺EǽݗNWvc˾ɹr$P[xrQ=ϷìxWC"?b;qï}_E+Sd+XزjJ4 5\O& Mb7 (ZZB`FT]&5], l8mk s+s jW#p - R0p 'Ar'&9 <`d%N~T} kAv_V)6Im rM1,Qv翛q#ʯѶz\B+ z}hֽdH1$K71! JK%w{ @it32x= Hn_YK "G q< $ٌ$t#5ˑMvy՝Dr wsMՐw>qo )"pݩ/Lq +" =|M&}y%%b(KЏmH$ \F g%l^ ε( ~ s{z;'*H⁅w~#8Hiyx ,"a[ "{uT-!<|ww u{{ -!<|wvûʑLuw|l'! *)#csº6{yc'-!d~r- &ekE wz[..!<|wwC(oh> 35 -!<~ywûĄrm) f< *)#csÿx %\̂27-!d~rzlE ەH !0guu˱~lE]s7)H[uûȪ.9Ӟ|~quoQ7"WiTUkؾ&Scy-!d~s|qzݳľ=Ptč|%:zxw̩~'twz{û߀(ϽܢxT폛zՌߐ}6 $0|}rs=~ޘ/%{vz#ڡѲ.'v⮶Þmח;}~Ы¥}'"zy˜?}ۻ~¨e{?}}}ˎհ}Ā IMԢ{~߅ōܶ쿐x$|ollzLȍz{Ȗ|}}řڏ(xohihlzyUᗳޭ}rr}+.ztyܠ>ȯzuvǢʥ'mzתϸ}۹ 'xeưҸ}ňÃːÛhz~þΎЊѯɥ㊲ڨ܍Ѯʐ糨Ąz=ۍ纨͔ȧ{ʛǵzx&̡ǒ}̾氧{,ߠǿǑȓΰ׼~;.nȲΟߎԏ̑נrdvӎГ±%>yģ˺ڐ8évs|~ᑾݒϬ=z|ޖʻ禨Ǘu쟴횻ۧȁzfغѤƞީū|z'׏̐Ŭˍē֯u媭ƴ̀y'܏Џ춦ޏݒ˪~ȏίȸ{+Ԛ̹韭ܺǡzϷ.x욱巣ϼzѱƳ&zyƦضʿēqq’ѭ>BǢޱ؍֓˓#վoyϘٗ ާ˃ze¬ͽ闶ٓ˓ξΫy~z)ꭥίvεݡꟻ̃&)Pʨԯx全ظĭ{,͓쭪ƵΔї˯ŋɸ0îlڒДμ֦ەѼɭ|ӳܻ'zzʧݒԻǴ쟼ĸwϘԮjzȤ⾭꣹έ}Ϳ|zݪΆh<ũݬɑə£}׀ڀ ~N&о֜ޗӕ˙²&Ӽ|ɔ{/ή띺ٕ㺭ȿwџ-yĶԢ²걣øɏcD9T*z̬줭˹ŤžɒO?HU_>Ķ+ }˧k̗г®ԕΙҠ{E:R\]VXNM̾mzʩٗД׵♽ܙٲsIHYVVYW]Aƽ͊>ǯhɨ쨩碼iFGF[WYXXU@Աҁx&墴ȹ뤵ϭzBXCSYWYV]GiƸĿѕy.ĵϿéΗǛծVJQCZWXXWZ<ʵ쵬2wųߕۙә̛±š×qCUEMZWYV[NRż*x~εꢯꤻޚҚŶ뢁hDVAWXXYV\AnֵC,˾ꥸH瞹ǰΚ較LNKG[WYWYTF˶ˋhʮeȲݛϊ@YASZWYU]Ebðƺɀ )ɳ1̙ß籩±0ەJKPCZWXXV\=Ǫ˼˿a )ø,ؚɜŶĜ+꩷࠭GUEMZWYWZNKȺsa2-ĸ"ʷ,뱮檨YEVAWXXYV\Az̼s`<  2ȴڼכ,ȼuGPKHZWYWYSF]A" .Юڦ%ǯϽiBWBSYWX O$#ήĺвﯮ驵߀.²ɷlO)/RMEYWXXYULjlţﲭƵȵt[:!BUENZWYXYO9N+ùϗМǟʺxdC% #OQCWXL(H*ĺڜқʝξŴhL*:TIIZWYWYSDA.Ż椼ޛ׸ȹnV0ITCSYWXXYN27̴쭲妺Ш·½̽t\:!2QMEYWXXYUH"2Ӯ쵪쯭ɺǾzeC# CTENZWYWYP= ,Ю ƵjM-'OQCWXWK'%?γ˲ɹqX/;SIIZWYWYSC(̾u]9"ITCSYWXN32Ŀ˺zeC# 2QMEZWXWYUGǸnO,!CTENZWYWYP= 6_2!'OQCWXWL';THIZWYWYRCISCSYWXN32RMEZWXWYUGDTENZWYWYP= (NQBWXWL' ~N&~{'&d*MёnI$]G i%n` ϶(!u}}='+Iょy#9Ij{z ,"a[ #}wV-!<|ww x}} -!<|wvûʑMwy~n(! *)#csº6}{d'-!d~r- 'gkFy|\..!<|wwC)Ÿpi? 45 -!<~ywûĄsšo* g< *)#csÿx &^̃47-!d~rzmE!ܖI !0guu̱nE^t9(I[uûɪ.:ԟ~sxqS7"XjUUkؿ&Sd{-!d~s|qzݴľ=Pvŏ~&:zxw̩~'vy|{û߀(ĺ½ܢxT표|Սߐ}6 $0~tv=ޘ/%}x|#ڡѲ.'v㯷ğoט;~Ы¥}'"z{Ø?ۻ~¨e{?~}ˎհ}Ā JMԤ}~߅Ŏܶ쿐x$|ollzLȏ{|Ȗ}~~řڏ(xohiikzyUᗳޭ~rr~+.ztyܠ>ȯ|vxǣ˥'mzתϸ}۹ 'xeưҸ}ňÅːÛhz~þΎЊѯɥ㊲کۍҮʐ糨Ąz=ۍ纨͖ȧ}ʛǵzx&̡ǔ̾氧{,ߠǿǑȓΰ׼;.nȲΟߎԏ̑֠sdwӎГ±%>yģ˺ڐ8éuu~ᑾݒϬ=z|ޖʻ禨ǘw쟴횻ۧȁzfغФƟީū|z'׏̐Ŭˍē֯w媭ƴ̀y'܏Џ춦ޏݒ˪ȏίȸ{+Ԛ̹韭ܹǢ|Ϸ.x욱巣ϼ}ѱƳ&zyƦضʿēqr’ѭ>BǢޱ؍֓˓#վozϘٗ ާ˃ze¬ͽ闶ٓ˓ξΫ{~z)ꭥίyδݡꟻ̃&)Pʨԯz全ظĭ{,͓쭪ƵΔї˯ōɸ0îlڒДμ֦ەѼɮӳܻ'zzʧݒԻǴ쟼ĸyϚԮjzȤ⾭꣹έͿ||ݪΆh<ũݬɑə׀ڀ ~N&о֜ޗӕ˙²&Ӽɔ{/ή띺ٕ㺭ȿyѠ-yĶԢ²걣øɏcD8S*z̬줭˹Ťžɓ~O?HUa=Ķ+ }˧k̗г®ԕΙҟ}E8T\_XYOM̾mzʩٗД׵♽ܙٲsHGYWVZX^@~ƾ͊>ǯhɨ쨩碼hEHF\XZYYV>Աҁx&墴ȹ뤵ϭyAXBSZXZW^GhƸĿѕy.ĵϿéΗǛծUJQB[XYYXZ;ʵ쵬2wųߕۙә̛±š×qAVEM\XZW\NQż*x~εꢯꤻޚҚŶ뢁gCV@XYYZW]AnֵC,˾ꥸH瞹ǰΚ較KOKG\XZXZUE˶ˋhʮeȲݛϊ?Z@S[XZV^Eaðƺɀ )ɳ1̙ß籩±0ەJJPB[XYYW\=Ǫ˼˿a )ø,ؚɜŶĜ+꩷࠭FUEM[XZX[OJȺsa2-ĸ"ʷ,뱮檨XDV@XYYZW]@y̼s`<  2ȴڼכ,ȼuEQKH\XZX[SE^@# .Юڦ%ǯϽiAXAT[XY O$#ήĺвﯮ驵߀.²ɷlO).RMDZXYYZVLjlţﲭƵȵt[:!AVDN[XZXZO8N+ùϗМǟʺxdC% "NQBWYL'H*ĺڜқʝξŴhL*9UHI\XZXZSCA.Ż椼ޛ׸ȹnV0HTBS[XYYZN27̴쭲妺Ш·½̽t\:!0RMDZXYYZVG!2Ӯ쵪쯭ɺǾzeC# BUEN\XZXZQ< ,Ю ƵjM-&NQBWYXK&%?γ˲ɹqX/:TII\XZXZSB(̾u]9"HTBTZXYYZN22Ŀ˺zeC# 1RME[XYXZVGǸnO,!BUDN[XZX[P< 6_2!&NQBXYXJ':UHI\XZXZSBITBTZXYM22RME[XYXZVGCUDN[XZX[P< 'NQBXYXJ& ;UHI\XZXZSBITBTZXYN11RME[XYXZVFCUDO[XZXZP; 'OQCXYWJ& ;UGJ\XZXZRBITBTZXYXYN13SME[XYYZUECUDO[XYX\R<)OQCYZ[YSGE ȯ~v{Ǥˤ'mzתϸ}۹ 'xeưҸ}ňÈˏÜhz~þΎЊѯɥ㊲ڪۍҮʐ糨Ąz=ۍ纨̗Ȩʛǵzx&̡տǖ̾氧{,ߠǿǑȓα׻;.nȲΟߎԏ֢̑sdxӎГ±%>yģ˺ڐ8éuwᑾݒϬ=z|ޖʻ禨Ǚ{쟴횻ۧȁzfغЦƟީū|z'׏̐Ŭˍ׿ē֯{媭ƴ̀y'܏Џ춦ޏݒ̪ȏίȸ{+Ԛ̹韭ܹƣϷ.x욱巣ϼѲƳ&zyƦضʿēqs’ѭ>BǢޱ؍֓˓#վo}Иٗ ާ˃ze¬ͽ闶ٓ˓ξά~~z)ꭥί|δݢꟻ̃&)Pʨԯ}全ظĭ{,͓쭪ƵΔїˮŏɸ0îlڒДμ֦ەѼȮӳܻ'zzʧݒԻǴ쟼ķ|ΜԮjzȤ⾭꣹ϭͿ|ݪΆh<ũݬɑə׀ڀ ~N&о֜ޗӕ˙²&Ӽɔ{/ή띺ٕ㺭ɿ{С-yĶԢ²걣ùɏdE:U*z̬줭˹ŤžɔPAJWc@Ķ+ }˧k̗г®ԕΙҟ~H:V^aZ[QN̾mzʩٗД׵♽ܙٲsJI\YY\Z`Bƽ͊>ǯhɨ쨩碼iGJH^Z\[\XAԱҁx&墴ȹ뤵ϭzDZDU\Z\Y`IjƸĿѕy.ĵϿéΗǛծVLSD]Z[[Z\=ʵ쵬2wųߕۙә̛±šÖqDXGO^Z\Y^PRż*x~εꢯꤻޚҚŶ뢁hEXBZ[[\Y_BnֵC,˾ꥸH瞹ǰΚ較MQMI^Z\Z\WG˶ˋhʮeȲݛϊB\BU]Z\X`Gcðƺɀ )ɳ1̙ß籩±0ەKLRD]Z[[Y^?Ǫ˼˿a )ø,ؚɜŶĜ+꩷࠭HWGO]Z\Z]QKȺsa2-ĸ"ʷ,뱮檨ZGXBZ[[\Y_Bz̼s`<  2ȴڼכ,ȼuGSMJ^Z\Z]UG^@# .Юڦ%ǯϽjDZCV]Z[ Q%#ήĺвﯮ驵߀.²ɷlO)0TOF\Z[[\XMjlţﲭƵȵt[:!CXFP]Z\Z]Q9N+ùϗМǟʺxdC% $PSDY[N(H*ĺڜқʝξŴhL*;WJK^Z\Z\UEA.Ż椼ޛ׸ȹnV0JVDU]Z[[\P37̴쭲妺Ш·½̽t\:!2TOF\Z[[\XI"2Ӯ쵪쯭ɺǾzeC# DWGP^Z\Z\S> ,Ю ƵjM-'PSDY[ZM(%?γ˲ɹqX/ 6_2!'PSDZ[ZM( (PSDZ[ZM( =WJK^Z\Z\UDKVDV\Z[P33TOG\Z[Z\XHEWFQ]Z\Z\R= (QSEZ[YL( =WIL^Z\Z\TCLVDV\Z[Z[P35UOG]Z[[\WHFWFQ]Z[Z^T>+QSE[\][UIG =WIKYMFFKH LVDEJS\YD  6PGV^ZTM9 DCVNC1-I5! t8mk@Ont1aKF7(WXm?*  ~&D! ,#Y) s]A% Oq /~+1 (R;%fK ;Lxl+ P "=IV7# $ *?JX`( Ck 0BK`1! 3  4FMgK)<0HzJ !5EK[Y@2r )Cf $5<;1 > "<^  %X6Sy _ .Lp!)~U35 )Cf<8˨zN0"M "<^] Ǣ3 Jp2 6Sy1*pG.-Jq4 ovPEQ\`qP1Ҩ oBr) j-JqC _7Hef#/ .} /J|oX87RfyA( !<]Z9# )CzfN4/JpoF.7Rdy?( $=[Z9k#׽w! ιnT9) Ӱv_OA0( NI>862+'" zο3:.,&! NucZSZd7$ 4Ųzf[RHD@==<;?T\ ɷ~l]TKDA=<<:8752.+**3Ej; ͽp_WMEB>==:88520-)'# -= ucXOGC?<<;98630-*'$! .G^Ʋzg[RID@==<98741.+(%" .pqʷ~l^TKEA=<<:8752.+)&"   &6 FϽp`WMFB>==:87520-)'#  *W2.udYOHC?<<;98630-*'$! 0 Ųzg[RID@==<98641.+(%"  *EWwfZSIDA=<<:8752.+)&"  .p:tbM?9425469877520-)'#   &6  #'+,,+)'$! +X2  0   )EW.t &8 *X.!2 *FS.t &9 +Y. 0 *HS/x &7T+]R!0E)H1/xםX) '8ݲ~]H5 )R~_QID5 .8C<-  # ic08Z jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 m( 9,.}RWoS1PRK;31ƞI\$e+=-c`[sKn%vvq|'_>(џ:}4:(YÕ( -wKk:!eFƆ/x:,ϋ 阧 P>Db\=20k!%O{n?4~ ~y`<D v=˘v#aD5LU5sRG0hl1`{fmw֓-dm:U_u!cXrR*. elO8?D@z1=6܎X^"r0˺rxee?pfOcw GPÕ6pt.v汅 c+sksZ8j{G:8YSj ZtYݝS_~gq7A3keduRפ)d48ޢT ',}HE6Rk(7\öF~.6&q~/Èxazc|g_~(Tپ!A_qkzr[LB1L^L !s6!N6){Ϧ!ף1H#{$ҹj'A4i2ER!!UdbZ "kБ9H$ x3+V?Eʕ Q*ӼRFpK4aJ:)Lԃ 7 G1ݽY]H 3vZi7@q=3PN뉵M48?vr(IK m $i88Q`u#ox*h|t[ VΔx֊H V?:cͤ:Sx+@*> 0Dp\sZw!g:S~ܦ)bv;1}F 28\:clNW_A',}&~R\Ow ,wEoUVԛ/B/"7""Mfގ`5&qҐ Y hE Q&.s΍”F9j .CH4ε2y7͆G> cZ2ޘp5:׊1(*' ̂gu#QIJS%hzk9h`qVV_ϞذUS=hFXB(g1(ftlΡ2{yA0'(b5 ϒ}6!siMr @KCӃ~_d$9W$`SK f8nSA0/0O 4d~KC(MѧP|MUs 33?<7 !r m )Y秅[}濄,3~L{2Y邰q1TY~`2*W_{o)t`;tU+r7.PŌ'h`u951y=lnDfZr"+HL.V,d>\pfQ\?šRC$MU8Ҝ#A=Fo8piJ .<:2V +DG_}V܈^W|'?Cw2CْIi<ARdRi50?#Rn8#-q D_e/k`mc~E5Z>@(vYV7 60 ;W=嘯l'骔Ay%l ,t\%|FH(ٜF0ZJ^jlp[|#\$ϻD&)Zlŀ(ba:2Hx Rebi@07 rQ.95 P98fF^ 8V$rBT-/W(=r7fb%mX#$8v8Q :(Ak4^?uRAGD a"Jdo=lՒ!"{|㒸DV.~O;ȎPUi|"" x&'1̂[IaJw'ԬE&,c<)wj6pV14O02A$x_*H"EWM;AkRȠrG[esqfyze"}(D ` 7-tt;`lx5\5*J0Ыj@ƹg ;3BR}Fp~/#<kתjZvyu*XСI}T F avA!*D &eV0ȎEwaG{ZXD>.pê$0 VhkGmo%>1b7Nyt/_; Ӕûy#itd㔬=c[@2vqUtn`p|M㷫ULJ08rJBt6S0E~YCA-3rS:.N-@_-!)b0IT:j/Ş%?ghV <Ձ>IdzG5{;U;t4Aax?^J_zgs(3NNA4| k3`X`H6egHG`" zxƂsyš F\.X޻0-/u-6٪+eTw_7-(.T&֔?il~& ՔȰR(ÉPX~|g ;/I5LM%k0ߚb3@pS 2e-}\7 "g{X# 'lHi+0~ÒiD #, +Q(g=dޟ@VҽnU2XDGLZaڦIw' >umh@.*e$q/# 3g6>q@2"#W3yFŨx@⽪cռǐr͖V >ZYc(d !8&lNuxJԧ1j>0ªs];@ 'mٗhхlmQ#2* ?MZfLp$~N_X+Xkc戗9; .M| K۝e35IeԤ.T,; aJ{fL^!u /s !uuoVCuEsm4G a~m,%ʱ"::0yuԳF=v=פ*>=~G]1㞜JsJN]ۯ-KJ~9gC ?{RA|jX;{d mwNDgB/jliPAu3bEn)1dIмX,V}B1qoV=GEcXyLhqqLQKBfƲI0K$ָזKZCJ/ .lJ3R#HLnCbQcg$-篸2wy]1T27D$.*(㦝sg#+EְRXUM~\8M% : bK 2&n'8,@ڪ2k=[xIy Gy.|cZ6\#iQC+"vgo8$U *'cNvP=M{ћ E:ct>gc,u"OL*ʓnbvWvƋs @ {qj-`GJ]TnyMk!QEdKF umYxJP#OPgڀ=ZH(ڐ:BkLSx'/‡445@׉vmX~c{pS_@6CZy8h 4;M~{m8'Gl6]讻aթZ󺅱_k,,mXQ\` O/pm)LXvdB90rwR趶!H=YcEaiW+"{8}鳘3H:i m08 $ib+<{Ѓ c8K;pG(+](:h"c) KD)7gG"! 7#pdg ؝ff }"1߱@ˌ*M dIDW <8@+6lB(D~s~e$[}X >kAmo/~!K(/5sd۹OMc^˂5ٶ|<Լ@KQBeH.|h;1ݑvI5 a:n B~~d,CP8eB$e yQhAglp.`R>qm sk $ rAeFiYSfO%@#vV)7MGU36=tfkc&~ehq= %D`ysԈL^V7}y?\$ZD[g6|MPDMŀY! aHP}X^ASp/1^3hm93IѨ@0mpd\,_.C~aPzBOe9OUU7KTA0`T3}-#_j /3iF^PJ !\퉅&McQŐ¶;11+c@)OYObdCʆ$m\.Q[qW撠 ]Dž:06 L qk! תZR) ۦ=c9m/ec=M}c|)S/Ys{R L`߈~A]J&& ]!~w3D]i)zJH>w9'W{y#$BpuEa)p#4'O'@"ne76$܅q]hI^Ţe1{쩟f{O]z_!3c I.}ԪOy!³ޅ\Շ ̹ } l |ŽL##iyK)`Lm 4aBC"PgE[f`1izR1D7KNcNrY(/ oTǯ{ ]*qhTp_oo9@S5kwӫ2ɳ7;SxKKQPG^;=9x*S 2~,*o\ȼsĊhp:}f^}u֐]{4O3FЀZp0$d#`(b'krc忮 F/ @P|_1izwˋ(Ty(^ h,vh ϣm]^hL(} CRjRA 7'q%L#?g)Xٯo \r'RZ|@ZMoP㗇ϋCgGmC_d,;y_xw0wW#7\?Ig>6w )>  5uCjPn|"rKԽ*/%S{b .<߰O$Fñt)T;l]-+1)cío0}[443bP:/>iH-{V5Pј,KZ{ Y!s|)2 3/)}!G #DX)!KeL[-tVS1јj&#N/yBan)g~2(-5+. pQ!0αztu'-Eӻx>_:X vʷ=iK\@g03nV{m%$ƤWϸ1VsNd1m6?|c,EN":*`h[}Xuu})KR^kG"h8 k*/aӍV1T+( !@9zP]ȱLʱ'}b퇜bIh+>ckPlhݒs[rCɽMI7MmAЯ̶ }1!u)UR{"6 1Z!]PY/?FX4DXhiIqcn.|eh_w zhM8c45PHo4*ڼj*(T1r)5 kDAt$]F/nA >wxb.JKNȄIy:aS@} F4oi~h13azJ{ԖXm{9فo%d>bĥ-%E FGOp+ђ<->~vFE$N u#@50A^c|&;q\nֳ( MtfK 2Ao,Z\@BbS7l[, p_jA0#&Ka+lv(>҈txZJ0 *!BZc' q6mU8ғӪQ3l!4xCG1=Sr5|ޤ uڞ$"[]J_o&rAP{97/?ù\Gi[dUG ys唚B^j VF96.ٓU^C^g`1.ߝ-Ch_Sn:ZQSDbD9{3(|33"+w4 ^c<iґ;oRCI9FOAbuw+eIPGJdRJ5֫WU I1Lxl|w@o:V%$o]rJ<Ր}fZ@oB'.KbV,)"2Å1QvŃωf-PCWW\s=aIg5X@^]L6 ؜pc4?< dŜ7xGsօ(~SgbG>#32 &%!dBѐ0߿3+#lۍeWXԁHOC\ʹ6e Spt/\UcR "s,_mj sG1tehTQQjI<}0cm8aԘU>Bfdq%kr'(1{H_3p0TmX >2,>mTQ=}CQy93q?GF#տOfEC9}1WUm@lXTWy˒\af0Kiš+ޜXd8Ȏo0lH}r1G4XC#YڙgPU@7'KGgNP{bnl nkCdžw35̊ Fur׭ t9檘B- Jd>|=GzP b#_wɷ;H.{ [ J@ Q.~~RLFӫ-" }O\،,"x~\}xV/!t;ƪ;\j%;l6\lآo7Ӑ[Qcc 3C @%}MP;-ȩS) E Pv9ܺL6[ќuh;NٍS!$r֚{BK>~ `[Z_m~=*ոp?d:>닏8+жVL1ݾlzΏNBRGC-g( >q 7(%bW2sv;v0~ ד dwMe&v yT@̬f%Fb7q ]zU3c2rc;: T41[Jty ZF,/j._@<xT)'%jr9Ļ}fe96< -XJ9۵ m(싂 Q.v:qIXqE]m]|rkG{'N5du=Rjr+,k饫ڝJʛPCD.XQB Rx4u)w*s`ZծFTzkPu.peTBLiYwvjj`Z€7 @Y8yN;ٜ^jBf,?Q)pϧ %c&). &…}fUIA0+5C3(4 \16nUP~sd W!$y:rj%^sYt_=L[}Jǫ>=5YgTWD\JEs4*)+ PQ֩ܲ3Cs% wMߏ&= :Fd0y黻z{ګDfH9zN8 /; h7*b5S$ P$؈qJ* p-a-` a|zI2akRtйeQ9b*oR%OR2MBA]f}׋OIwpp̀?]L|[b[oHkL-0ve(Gh-~\k}J-U-1G!jeX3;FҌתI`MY)H9mPL#[LRZ%) dSJ0B:O~$~Mie)T1K3 wݫIibu>k4}D'UIy߱ǹx1娀 m7[d0kiZr"#pe:] ,/I6p`ĤӵApA-hLS\/dM?"c,5*Ig[Q2f~ŔL',ecl屽z͍pQJFȬE_+^_r{@ۨmm#mU4tƟ)+4.6$5=[>W@~h6^u ddrZՊ"͉LHS9krbfd-l (:o J17Q4_ 4xޢ"uHκ/;:Y9p8U!%ɪ5}Du؍S&=B{ {!v24T[ԍ"3_3hJ]mCx#ϝ˹h9_dۃ@ maS7)'p؂J5B28أ/܋Q U4cl;D2XTݫ!&~ Mdy&cB1ucû0RщMQLƞ2Qd'| Ytu:i*= ʀR"?clW,g'uJ|Coq@]>%) "ϵ pt(F<}W9\  E |V/#,' 2EYq,G|@_o)Msjs1\vn7*6 ⼪my1j\TkYvN+I{S* Ը:Kr ۹VU_DEÕ̟}ETx/ .M$5H?@`&  YȜ0S(Q_7vLVҢme%uq/NO V|KEu\0<;=B1- \_E1ܿ,I_@&yCg=L0/xj%Çk/V`ġ :@^bNܕIkj9j;t*Jj@^0BQiA_hV~8HkiQnq;vDlgjh)OSlz1e.w(Աؼ)<.5sRu{ī't $MY7X\CZMA1Vԫ3 hŕr*󊆨!K<=AOO)jumbW9ՋVQO]2 ▐_r,~oC8Om>{RO[=T3qG& *,F"ᩙs l]TE= ٶ}򎦰BSK0;`Hu3Eݦc%$e>.+fʞ7YV\sK \#lJ ݅)|Z-\h!"lloZd$fzuvR34%d+(y_d ]B)9<93QTb}siua9|,P>7jL)$.]x>GbBDk{pdhLI/ɇ9%֒4g>đGF*R.%ӓl9ϥ7Ӛ`!2LsOg&i# ϏxʖTYްCw\dl_Zgǥ*!׼4~tFfӶ+?iF# }K[ !9`eC&`N N6xin.2mA:+K'Yt2;^c~R3/dOd !vWV'Wu?vu|/F]T}(IJB!%=}wS|6iW̬,/R5vVscu=f6K<<`@Lf,z1Q9Ij<ܚkGhQVr(@86o3^q#IemEMQ6 r5saWELd7Qgk@d" J7(K H©0q{ 1Yny$p1ZxF*k\3WNqsCtne~ 2@7$2at$,VnIr;?~7+]o aJJ\ͯR=[ .DwA4*̡Ǝ/tE~ .D]?>4Ohʟ ݆dǓNn;nTY.cN p+\uLYV'~Vf^4NL ҴJ󏔻8XOVy?&~Kr\/ RsG@t&SMI))E7s%Pͅ퓠0 W7Bܷ ֋҇`nFi* G;b@p7̳:P}Yӂ `* >C\b%T{!\NAһ[ _CUN^ ͼ[g۔J{ߏ,,Xom PC. g0"/L:Ԇi1PX^ar [ 3ƇzGq+ ;+7PlFYwjWQ>yۺh;ڪdҼsŭ)d(N,hsdSf>)U=MPf?/!Ny\vԩA t(jX^:`EiOאGFz3@x%A>{ eLdťDuHMo"`%޽4 ܈JNO;f # g"\kD-S^A9 }'$kWoB5rhSp<͇[[zA)Yg1G"ZFT"ҍ/.xw ,KTȊ:|ƺ3Ի9`~4W;FW^O\bq#hVx $k4Vp2QhG,=N>A"}\?ڣp.ܦqߠ-ޠU(sQ\/$ q;SHIIwiemqmLL1BSmFʥApjhm$n"Pc?ҪC7cQ~͜TkM~*Ɩ;>JnqլØoal߹@Fqf.geR$x`ANP׭¼ikιfv0w7TwM=ܛ\BTƗƩdΆKv%f%+I!4_7MM-?*Nj DaamƞH k]>X c,vP)xX+`/wS^w7(z iMaLO=ݻ!·AN!å]t?+|+6HLV):˟W@^a 62BweWdNXuxmRw(*]޿0]IY٢U&Ԙ$_9V_q=D];ՙ. =63АX#ctmh}Mwp9n?#nv0OԠ.'M&$nU\2gq]a(\OrIIjl2xd..  W^DA_Tؾ<YjoU#j(35e R'l.֥c/WCZ}b×0oLj2A=; .h}wJQgc5Yċo7zxHWs?E"ק/ǡ5mϙT\["lKXp{ y=C3؈zCMra?UA,9Hv2D&jYH rQyDc'SLB 'ՂZvK id,wQ@0w>"-b"5b' >KgGoet@;ۼ0}7g,aʸE.U#,M&Z$<ƥ lIkB2v1^=.oWqrY>|.ݷvPRh<;E Ulڪ,b|D5"kG,X7ΌJn)o<,>T{>1Nz``LP走M^K5ڜ'AaǮ Ka\}C@hI<\77Mwd>Ȍ4 4OZw:i6P^ w:$.H+R_;)uG)uv6В]tƦ%`wƒa8:my՘R5gP%0"1^4€.4';HN61T0CyT͟ia(L:^"uTόlNZAӐ)(~yBy6f eeRNN!~GECK%Q`t`GjE{f\Oo>憵ɛ@!H c)`UԳ dC\NrC|FS%1]!( v2펱">p׻X|LJK5v2[1{@f׊ݧ>Y\"?SPF:Ng ڱ,lgL}i^:vUab{ V3/D$~ |ڈzCl~eϸ )h5~L:t|G/tȀ7ˎe>8?RHiUvH:T܋ {'u!Q.ң1M`-O$-F4ґ8g+um0c3R7˭XPL27+1!DOo9nqؤON|2O9 2JE;eө=Od962; pЛNEqH/bZE4pc=tFz~XV:z M;%T{l•TIc3+PKʚ!yToʶ)iҺfW7 f`j\JH"A:" '"jN.[q3=U(W| "m62uRDqV]"U{Zt ݊]^!A5v_VK-淉:jn/]:SqFc|Ǡ&Z0WgQj<{=vL'.pGV\YZ8y1-[pnϲ|]M3/4qYuwzTnMNY@%ݏ͈Lf-$3>jbfUi3yK}iC<##_HH_h'c>pX_Oަ2 5&ess\NN|m$B8H,m$/GN@-e\{23tC@vOR @gӕt;8h97 7ʰ"!wÈhU-pwSTRҀCCL;V(Tc<} \V}6^ލ O0-+],!wnn40ġшASH-!2O:I? ^1 RBB!\9.H~U 1(1iM`MLR\kw2 &Ƨ R #m9d _-C0ID6൧g40HoUܦ7 Κ%%[$EV:3X9;-vKLh=  4=#x AbJ(fxpƄߨP^tGt,y}cc?#cKjzS4-*_緒B 1-'Ph9ZZ]E)%Y}]c=!gg&Ξr7k))'9 7oѦi/M c-<.Z]B2ɉFI*^CVovQ4(Hu*?i@)#o>jVeS( aWkflR,r-]^=%Yz"sV=pe{? efG |,(3O@<=_Ge33Ձ`/q{ek^Wˮh{ylZufO܉߁Yh xtx-Y[pS/4oPC k \ߙq 񞟌(D(N拏^D|FH%![J8[$ڛr@ =S 7t|6Xb|&B]Rf ,Vw6 AO( lשC j~WI2jHu6dR,p+iW\=2~8|iiG@lEB<ɅCCL7yx(#:nm4 ~;*77 E#.p/߲Sl4>X 2"!?AʳY]WQ@Ġr0x~w.[:m͖:bO _Ykzq:}Cew:[b%D^6mUK45DKY4̩Eʡ   ;ߏIFqya9`IHB4k&)n_>9 {$Ŀ~/SD b!ɬ}t}C<`PϏZ ;f/Ы!k!hrДDⰳ"Eи8>4<1 ,6"5h`%*s)xbt,AmlG.En>g"tlEk3>!LpYmU_A lG N?jڴ3̦{RR]x% v|8L:`+9;NHe~4J,0Ɛ9^O7;/8Pr;A .-IIm^MOOIy(hRXA*m4 %"l~Jb*ף\/sAMhF$tX5q|$CzDV=4`%kў4@ŭ~) qV.9C$k1W&vg5"U&D6X("\͐8Q߫?R?'zi-} h&#vWoP1}p~fKDԵ;vohw+t4И.@!9/h1ӱW2NLS҃8CJ4X+~AnuɪkY(,88QY1Dڧfd:$vͳO*c $m*t'J-Z4eako\{TZ`' r݌gD7nVQY>fCWt,$Hhm'b)up̀OmQ`JmGJ9[o%LU6q%fǴ tW>Ehhef@6GervKA#|9:N*z ͕%Q/Ys@քm{.ˊXiXKle16Y0h3iv6=]SZ /=NOj^>c)%w +:J{8~tn\Wv-Or|\ UwrU[>.\𺟪N+]\rsU ;WN$>B$S_5f)[ ]=jٛG2į^oPB(HCp[j~NrLB-ɗE/)f, k.8\,װ̜cpG5nijz t+Ԝ$dz7Y,ʼ9rtMbU1 J\ b)Lw5|Ғ/?ELôӠw+Fk k ľ6JN[%]Djb$ e VB:q.Uz_Wz5&pN/Oyn Uwf3"\1XE$ԚOu!- T>!>G09B6zb"cv;%6|܅L}6`MB{+A!td ) uD@8&W/m2iCjZ/GOfd/ڊv )kVidiZpjUN4`.6!:e+ YTԹw~-V?0~5o#u*S9ֳz#/= iDtslT#:}ػ$l+l;?t[ yEh]X-zQ5 CuCp3??_f h9Cn2V?NFkttF1?tp Nس駶Wɼݏ͛ZK{gIsvŸ)28ȡiZ;~z(0ƥm%*KՑO'F ?_IҠ?p>U*JzϹt˷XRI274zj4&aoqVu](<:RgSv٬uhu gQI _lOts=LRCڔtp6b(.TÑ]hDM}-8Fo+pxኝS֭bqr6̂djl{緑 TIrYO!˖!șVQɚ\ Lh.ZAh>؟0{e\V|_fTEVÉg.w\0Yd&H[$9CpfCC32*K\P֡sQXMI:Z8&^4t}{F#>0gx 5 (j?<~˸D*[ʮW X Hp:we0 izg7}8S R08ѽ\R'xYi|JDFр(ǙFF%F`v9Gqs,~[ٸ X=(-u5~ ZF xFmFW7ɞ 76޺O':YfCF]s_j\\ CW\BZ˨45|ǚJ3G/ RB404D@mI.a㠻@}Yz7)!vJ+gamz#Rm.YO M_QbuL &* #-b;E S$C\})6P5;#" eo!s n;(3f7d۞Xt#nWZ"GDr"ە4/Z BqLd`Eq. (ƮP{y W,ئw?ns'hf;\'^x*9D9YdŸak$A6?& 8%^ʶ lB`'Wf{N}${p-h;Jlχd&f5Z﨩~XҢ5`+}@ȧP䄿 ZtB4t:+]NB+wAX[lĬ=ٵe=$K Tٝ/X:յJVahq[W6#XdH\r1Rn{D[}OtG_` j{]Gퟷ+pzׂ7RWYǀ@m/̖urC.$F4Q-ʷ"́{ ٛ'WOA }3m=Feø}U &>XN-|a"2ǴC_ܶ2 E ֤(!`:E܏dp 2#J2P-|P7#@,u0tR>n) ~qz<;fE$uѶWZϮgDsČG:L`e;"}( W\WY1T>_Q=[s\T2GpK͜szt{a&eVw_fFmqa?lG7ȇh*6]%m\gι[ bzǷj5gw͊c.n?ք{PKx[a g^qn* hQxrw驴\lwJ##\.XV/JB@ ,}ԛG$  9c^"$*xޖ1ZbNN] 3@xڸvt%f@'^OGEens.~(M?5i~f N(ee/>G'wOՇD0`I9IE˟?6_גj'=7[*lT<D_k޵4Ǽ>umEȎiZ&B6Ɔ?:<3mOM<7B0K͜60B*דh//;XpuGꈶ9Y#ؘeςGoBHp纋ȠNAL߄C Emٴ8 a5H*$q)W62=$~̭0d(و{H:!I,TG i\v`B2Ƒ@]niRW7$O>5JX^O_Bʅ Ɣ4zXM= S0S:lXf#:-uiGbj"ϟ-:ݱ7%zxߤJšJՆ)%RҨj)gjR]ª\_T0JRt 8mTP1ufo93` NwCcԻQ?m=)M;&!%yNL_c\&bF~:b< ~FdӔav!KgqԄEUiW{ 4uNhD{ɀb؆CiisJU*wҋhv*zz4*1k#MЂKm )ɘ &UALL.5Aco1ׄtPj' KcR>u(\PѨH@ʳѥoWxT=BiT5SM[s?,d]?2" <%ZCGZjo8H9@?( MUsy?ei}qΈLUnm9-(4ߢg*^Q,eB */}DEm)/Qеq~804֙˅}VYR݁q1',DY̸Kڀnpyy:ADp>o13Bq2͑; ]I13wCB.VJU< p_[`uT5o՞p}c!aBJ<`@œUdJsa?fؗu<z=_u$;d-KW |Q2T!?sc6TBeMh$ `+i,h׆PUK6P<+oڨ\5Tp(?c=Q;Jc6dMOy%r-h,Q" #/A|`cl[0YVsw6^'*ho[ox 7cK #[S]~Z<>lE"ΏT?f:z&muGjB>oo{vW΍%c&HmyL2z}q;lX3e x !!kzBu}7*ҋ>X6. p* Gңbݳ2M x(w0C>Ƒ t?&sWp8iԔV2#H%z6-B]k2gd&X tO>ǫS=GqG[.Q7WB?MbM1m>mN 1D\f\HjC Ab6όC[0%~ *8!flVgpB| h2@2zQ!3|8>Cs7(CgѱT"Y sD}XQa]-DVo0[U5qR#^}۠φIyi nT@#j|7BQDuPK{ َH7-ӗU7pgUp^obBRK|>U~jD8)wTWHn(KI'6qµotymɲgfO{vDbUs?wP%I'D+ibq@#~vfoL V1%SuL #?0bT&]v;{IȽkuf\eWbKЍۦQ }~-:a'}TJwW eqΎG8ޝI{šImդU^d0<ߥ؇e;5&|Ev>)DUq^Lj{!=E4v.l,Nnfl)V&F U'6 {bf+C /Q̘%ZF_%i*~{@ÌcFQ>qkz%4m 8~c-Ef_&zYf҆uҥV~6<- Tȿ,hJj:w]EGϾGFBZH~dSG'QSv,Azۿb1w dowU'熴ys%n o'495/@dZ7ޓ{#9j?㪾S`0h7{ء5DzEI[Fm0#7Ow|Q/GqU]mQ_ɫZ{@ `&Sb60/o92 wѼȢNg+)dĆk712r^5 B%ƼK̑%tE%) +$`hȖGҺ`?BX)`k O8]HV}Uq%o8u+LC1`nw;F:pdIv bd]] PeJ M{M"ʵClur5cC}Z {-\K>$#Ɔ:ϼ" $5Օv@,Wy;WW$l1(:2M}@+wI+` :GkwbjgB)҇7&,/bOn|9"1fτmW$,HE]ot67KV5 nh}E O 7!DJ)7DTA vP,Qѓ3Eez6Tud#j"w:mdw@kB$L$WE)a;ŕ! [MQj$sw׳}WlZUrsn4 l'ctPp?Is"ewR smS((TS^Ó7bf_랯4юc#{),<fff$GR =NwIՈ/)i\y݃N\#YJdV>B;I4>Lu@T!m#|tnnX'+~Caa))>=foߒÉOO@GF_o'hEgr҆ D ZZ\Qs҉38f\zmy&,xzf BM8I?Ww<>r޼GP19t"\zvX7ncR!4a)?Gj_{Ո<5%2^ÐRP݀DX,ګ]Ə\ưڲƤW:|\u+i͘l2Yɱ* _ |w,K8j+SyDB-1d:fG) W9DYԯ-G>#,ė1Ww﯎Kkq "n}Ď}M %;B"*GP/*&%Ymv)0a*ٻ?1\JD6;輽 +8V t[|oPSIpyfVr|+gѠe=u4v]z$b([Ii~6wf.M:x2q 0&\I L禍@[/m@?Cp:U_20 ri`GEl&[@䚗l!E7G_OG >HcԔSy 4^Kø%wgU֢'H[;Lk) 'VGF\44> Sf; tze2B.ۖ|h1|`Ȥ- 37͋!\|R  }NQE,QopSq5Wd'?L_i4~=LL܉~# |D@+\Z$ʥUd<p/ g?k,tI@d$`FGd9#J)Lb$1}'LRmjY_-T&%GEB6^ fxU5 Ye˷Ghb߁tg X-oR̥ CY=Z3Y3kʐ@|R1VIX8',;OȿE"4+ |u&1/u)+O8F?U" $gzURl4o6uGS`-[\J(o a0ӀbkOk=+Q\eѭXRt-ZZ v^{ǂ#)]z;dՈB[ÛoD,4MĖ:]1(l!响ol0^} 5Q8hIbFlI~/Co"oL;X(:+Y 읿`Uuyt?z$^GNgK43p&mHf3 *$p[ť(i ( gq页8pݿnqܝ~HD'm Z"tE[~;QxzSyojSTNhpǖJnCUIdmݶK `"R r%{e~]f5Iͭc8-Iq!jNj+W*CI3 49:_Aj<թD[Ro ^Lr'N0, /M򱹱ry3w}tvea4]0n?nhObt\*Zb4x[m][\ , b!}<}5$۽EA&'8&A >1g.pD-1YsT\lE7U_a4@:Ĝ[P3A-9EAm QOɏ>{@$&Rt=d}^LXܪu<䘒7ToOCAY%=Z~@+ y- ̕q=v )fZV##7$R& ~,S㥩Λ}X%(AE7Q xue^WPSl>n{λ:zr ݖʑz(_ !_ex["KkT\XT +`*2oåktLkʸa %)lUfߛ>:`jMh)&wth=;A!_υh,p}֥g=Vpm^Y2<;d&Ψ#hXp}[Wrb<L%4ܓₚA|G|#އ7;#GܟSTog@q9'K,6%æ/WqK@#;?/K=eWX>g "8fhsM7Z'oe7xsz-'ّHğk0q<Ѓ)d„1ÆM?ssW]sM<Ȏ»;Ȕٳfu2EZZZ7~#/+3fݻwg%Ȏ}|׿rM`mJ;v,dG.!_{w}|)/6MMo-ִv!jAv\I_W_={׾2 W#1Ȏ49ƛnxg|dzmhxƛnYv 7YnmMVȎ, .>p'>͝|ۓv x `Jp.j՛7oڨ=YȎ 0߹ /~s#˧O$W^ikk7tTεjMN|dGvd% sO~v {LWWW50n4{ʀF ǎ؈#ۿoo{# fϘ1{ӡƻ>Uߟ>}ڼλѹSڒޞ׽]pެ*c J/^Q: |w?渿p.H,` G\2,gG2/ʯQZVewDNzHu88dȐ8@eّ QI&cY  + :jjjLGG CM6Z0;1_Q\\|3錘?-򘆆P!j@m8vjdp{?%"/6}.0⯫;O# _FMG 7}s l]h ]$;C2qoy̨ѣVNgf}r՚ I8U_^aK d ;.1PU,w,[3fL C~/:R85zaűz, 2$e퟈26"{.rBT!tKD#e2oXQGYA5s߾\H.2׬z?8W ?o|7?77>G彽5~ūdfC e~ }JC5z أG i7oB'Kۇ?/aÞsp;TNj5vx?6?' q%J9R_~b>^ P@+?qQK,Dt2NO% sHk{9bl@G\Hø#o,9Cς[MV"@3Xi ??GwԐȎKnpw9_rĜj81Pd}hMD};wnyP?KOCy9s}.//+A7xc3l՝{$`cCϬ{O: |Zc1 ) "k_?y&B ἑOh*?u~wVȎC3L$Vͷ–cÇ]VV6,O?ltuu_[[ٻw rsGn%/r?47`}ˆ=_үϼ_ؿ;˖ͽ]rJ7).}{4ĖgّW `Iv"?^t]MW/DiЧad^HwzϖMqPğ5{9 /ǽaҎf|olq%yװcGڹc]СfCS@<&1KytGQqӦ-\7 KT_~Ώ~2~„fϚ}{<{ػoU+IKȎ츢 $XUw{e+VPkmfiyb݃.]J襗w5Bo6=B3~zM>_ ۷;n&+1՘Ȏ+$ %'RvmٲiGuUՖ^3duww9q:]AFq֭77mg~&N$s{)S1k>qJCHWRp6'vB-ɺ㊓^вimMMon}P(Z ^WU+Js6Adw5KE.f-l|5DdvdeaCƼKqGjOoxݦ MwU8asP'pM_|/ )Ny͝ t [W Zy&k ̎+rB[̅U]u5 2c=VXZZ/ @я~y啗ӧ;<Sw?Zq/ʖ3H /@Ee/YbHEvde/(On//~ܹcsNΐÓ1@%կ _%c/z-S!Z q<ĵnrUա3&ȎB1}3z<@zcZ[;wl<^3loZRC!B~Z޿}up.aɾ occW/jr:?= *WgCή֮4}C#;/G]jvTlۺjswo}N /;n ߟ!R;"\pLYYmC @ի;0;8 Ы@# t8[6o?te]{F1<?TUuGϙ!r 8qqG՝S R`ܾ֬cSn`>ّ;Йm9vs@?ʼn_ݾtN:)OskUUO?=3W'h}:^ڲye\bɊhʀuP = B'N@qI`!O=T}[j_W?}  VAUukƌc&L8َʊm?m&1߿cpuiJCS$^phδHpr8Orϡ"$d@[ _؞WUuɾ|`o3t_=֜l ux} E5ڔ*w-|'e\D4N 8>#//ݩL~~qb% |T6΋*@@&0 J+|rBGQ'P[`]ُ;]oTev\"N^&ƶC>l07ף @Pa: {$@/v&)'um3g}~XIT9s He躉Fqß~t^&m\r% 6\;>7y w| ÕS@"׽Hk$. 7Tmw$%}t@Ϳ'J=s?ُ[ͅpir7(x]q$vwatwwwyg+V"zL_ 57+c3ISGjkݻw/ 4~qcj7~,xQ@;/!YMS0;qa(@2@x'TcmGM>ˆxTgx|7ޜ3w/R @U&N0׿GT\ 2YW<~8]M`?9^ "@cmc$QǎgO\.&q {P |ďc}%?ٽg4 1 za[$t9.?_R}oq9!`'yj߷ě$Eu'MiII 9 Q}y%L@O9nP/P'Ԅ-ݻc?8ߕ_n޽~piaa܇]5V?}ya,:G:I?W-^ذF륵-YW~/W4_Izy\&z-tuu-Ǫy?EEEaà бF }jok[\O0xL^No7 vU2XQwZ!^>Hzأ%Ú h'>t}8zh3_&D`i\ހvy\j3}$iXVUUUmz|\~dDNx~u~ Xh$KPVd8Tpzp3Y-[7ҙu㋒R/NE/IKLE/O&kPHv|qE0ВE<#ׂVǏw/pW^b;Q/دu;Lt :;q3g6ZBH҆= hѣuu'v_ު+kGB &jLE// }z96aN-⾏ %D_ \C*DuモI#zn yY9R/95&0%NϿWB<0ݻw=gT,h 3M_ \kh>w2Dl`έڻR@G9rfIgCPNt;y3A ]2j [on[-MЇFx535U U'ML6/y ƍw%bK,MKQ4^Ev; W1kkM푣 8sٻw5kFp< A媗kOFybN~'|RK/)) %pu^dLMn7$V̈́aLKO˩=6XXpaYyy)S>|xaYYٵGع )-$RSLZ/:$rKB@#*sلs mZDC3u@ "rУ"2%>Fܼ2U1 }Ə n.BL3:x^:eW^>>ΊԱ];wܾ"ٳgO3fX:zԨQ-/\7]iMS۸$F$02O1UZK盛9L43g,\46uJ^>CH`  `Ps<Nx:;ruGMT9.L:yP(Ӆ2(t)\ۿή߯I~ z7;R{ԩScǎt}Ԉ#y+Ƨ"čx 96_.]i|/^ vu'M"cFcǘf`gg]9[Ts_Nz%K NGp ?yUoɒE.0@T -W-TW6'rL&@Nn{}?p]--+j9ڜ76m{T˧/7F1/F>7<*gD# ľNZL1GQLbw [q=$|GQ}B3fj0w99:RߣGN@fLԄ#w'N4WboMZu1g!J m}`c¢ع٥O 7i$D)bQH28яb1$r um:Jj->Qe8Ҝ>`?nS~K=娗֐tm(+5/42W^ iwy~n2._lT4X8Gh%4IcO55,xعޓXW /=o . )~3TD}c`G!Gv"O6g잻|0@J]s.#ޞFr-xx&HlVrqIK\^HKjmO2qk/O.fվZui4, 5Ë @Xd?ܜ߳"9柌j 3<b7Ť0$zt]prQYu^g"{h'-[2".%]\/\cǘG9KNNɋAww -:dHSx ZZ j@ݜ?eF,<rTO ̙3 <:'N4GvǏ9TTT5c O+07EwG}(8,x @B Fu 1cF}uޤq-Y{*r%sܴNu`űnXAO78_R]}D{Ъ;1|>.UsV8wɌ N1s3f4iL2%Xahd 77_-:M h%Dta@ l+WI  X㷾ABP0A8-IQ[o _{rS>*YoS qTh5w\9-,,pAȹ$6+UťʠTK{oFcv7x#8q#xSD[: &J]ե+0sJ@|~ŕ"x6l 9M>QJIT>- ^4WNF>O%ȥq@_USq(\~"oz.B'M@ u-:yyA< D*؟qϷ?%Q"{o 0tĈ{ bw'ǃq<{ BTZr JMYYYPC͗/4ZT"&c/`++){6N#HF~*$]hש^^HN:cAfx) S.] *=z9|9 oGZ"ǃPM бU b1 z= , 1LПN?{q/]y+-Tr)V4UTX@_aV<=昞*ѽxDQp. >kXom-x'.{z9:/8aH|p}BJ xZ3tR yg3Y9hwb_ٛ*5Zf{#c/L,/A@CƵrQJ#a]aR/]xm޼98H{Χ vNJ$  TX2\Fw<[i_h*:ujEfQ/k? ~| ܇REopF<ټ88Z[QHw Tyo]~7{sB]@{dQ** ͢-bC.RP@-}6:7A/;z,娗_j߇8 tZB-՟v룋x9[ rDtI*,ƌfN'c}A?.7pT|=;$Ax'O z7lt;r V{,gof|J?H 2@;y1vRዖ,హ|:_*—xDihN>z{/>}I<شxAZ=zqFHXs*+-Y3͖ k B}ĉWğ 1KW a#Kl#߷o;`^þ[~}VZON_xŹ0?%nA[v 6`{'xa0.݈ ϧ:ē.JH2G:nJIO2٥tcR\;͎Ph;q Gݘ a%@$;636(.D`YfԂE*4|c w @2W0.N @7 e ;8@ 3@pHƋ. Jt՚ wXGX>rE~bP=ԴaKik);kF+IM~AahiC1L3]=(mELN<)'UUܵ,Z ami \i}qW_u+ p\I`{@H"O%Q-m@ cEZKdUjx-O$ 7%ؠﴈ A@td7>~Er4)D;޳!HB#)qpVDgC<6[oJJpI..pך.y!P@qR/H\pm' kE\9 d0_?k11mı#ffhn^|:c3Me>߁R۸:|؈\&&$W|Ʀ^ӟ+mx<\_+>/jb LWGl )Kyaڳ9v+Pb|^9x'k Y)u"8ɊxV ub{'p;FY!:&@z-Zo[N>K=w/!8OpXx Ԁ"NV!|0PeA^Ϊ܌΀# Mg&L"+l8O1ɬ4b2A4bOC\^2 D{9"-,n;`[gMDF1ݖ*%݆ģ1AZ&:C!aR3~҃Tw +=yҥ)YI!@,*KQrU3 ,Uu7wF@x>GOP0z9)1}Ҩe~9J wf4dQ4= N'DaCp @cL{GW,߮8uAa pY9s9*0^,hپs9YL<9z̝34C a(1J 㞨Dg eH@g}эh2Lp/~:TyI$>dj]d dAM,^fJ;~gMؚ8/+-M( ;x֗^z)(] 0|;٪n91;v0Z eJ>d@ |ժUJ/Ǥzk}- J˹+ Vt/k<0Hre@ʬ40Rdܛ)! u,*slG\>huDbޡSZӓDXqt?~z BkNUʧnIb&\+ R1ZDZq,3j×B/C>#_>(4]Tqڱ d,]i?}CgaJ'q0p`9}Biy. 8p 1ݸW?z%T]3:x^||#г^D" )0;1o͹I2^J×%ع}aQD5PW@S&[0dPGT#00HVZ[g醘t1zZ/:- ľdɒ\i)Y[~SJ&g!{dV a::NZٙᮐ&^6=E' k,{ .:$k]{4,h9@@o4E0Ⳳh4ez,‘LHaH>c]qX[.;; ̉Ü=ض'Yj5H]@r (ѕL:cX+v)1: WZf1{bVޱ}qZ%"Wb l3|DУRZ}+ྑ;w17^:u=j]<B"hAd 3>E3g?LT(r|/a@@2f;R֠`-q<ތ ZوFs`J&v ؈뛩eI,/] 6:XxSuJKk 6جMB{ҘMMQGBߏ[/={%^QÞEYBb2I;[qoK|c: uСC`C:_3V܆L K؛n{kli"c 8vp+-n8Wu-ӕFtE^Ǧ%;;{dLPI+rPYh^>HV0a|eRgfǮ=.ihd3gLjB3:y$LRzl.VLAg sH-#@J1xD9پ}{%q,gNt*qڕF 81N d [D||VbXX_ZY{.2ixh`e92XڂMx9WZ$f0 \= a^+*uLYs"Ud• (̕+DM*xU VuT駖 +>7  䀈y"XR&&u,qVa2~smt䃍3`r !\hX$^Xy[F+4xJ0q`BV?T}5E3*qH4 {s2X's҄CἼ.w>PIXi@zr>]xF܃Kd8/הՈ@8D/·W'J/HIä#J%]R4L*z>Wi}űҕ~4jmFqR6QuȰ@ͅkVrw{VŒo#I,،(7/a7υz|XAx'рCP5Ku]̞UOJ/@{oOptC }\ u=A /F&i8F1*QZ{_CHRVa??+] c\jWpzqԥvUt(t/'X\}1aRm.Q6 KXFT#S1%&ψ߇؏P^-Z`6mj[骬$H΅Śhp)zP%N_[Y YHӗ1{LWk.kV70zT΁!K,SN 3:vD~\Dݝ%& `1:X] P $:ؗaGtb3*,-g?[&ÉҘ~Ib3QGG7ɥY|?_.U )A|c&*XwySـp2C /ha*w2LAW%X v!5vFaш 1^o'pm\9LJ4ɾ2ϷOT Ʀ]~T%p3Y0Yi lCLVP$cqY+ , p~ /_݇,wo;r_I,BBI={4d_Š _sOf AljEpQoG 1Oΐ\z ן5uu 'AGMM\u~"sbq 5EP(my9?s=,%>O*24R@`d5]va}ҤJ(cbŠ/!(Ip"R5H;L\GQg:oQYzJT){1Q;<&P(}%GAHE-]VW# ?tw6?4c!a>p-o喠 Ř {rPYtX)|Ӓih}/\d~9|@Muy 4t2^(}G*Aj!+:NψW'U;Lj"ybR(}z7U"829JVq.<`ţ'8c iHzJ ,҂<`NW6YGF˽ǿ[] ΃)!J ],P0d䀁U $.>W#]:qZaB a!U VajrYư!a ]h4X޽;&`d7_Q2W(Q^}W{Hߤu E~}#IhƍA߼09Agx)J&gŋ&H ;v1Hxt=rԬZ˘Ki;68# h@ŋޭmU2]x'YC '|krz/oМ%b3 bdF *!#݊ZeY.*QƱ)'@I"-39۶m *4wHV#+*8o6m ˢ!lЉF1,{C26 # г@ OէwKAWaT=$*[,D&a^)ed:P|f%<,xnrzı'6u*nL>9Ϛ/w`ka[!>7~H6Jg|0aŗ_K=q64@1H"3AXR=1f෸GWMe:Ta@X\Oؔɓ.|YH a *)cfCY4J_,Z`amdK"bn3$S#`RF)D2(˺n9KXv,%wA(>Vsud5}5օ%DsCgC 2OH|QWkI> h7lX/fJ?ݟ?TYfyI- H,&gS8󎝻͍7\ '%4{kIB̙C !HɥP0X.EkL)+=׃KnEawNֻy #eL [''u_N#KBe us2 +:$n\f͚7Hq26g'~M2gTAAH^! ohRURtz|$(Bǃs{ E̙ߢfJ5vHL /@OV >kDc=W7 ᱾LdW3>fȧ$\pnDaDe|ÔN.{Dyr HDS_z5X'0+90Zd 6RUVbw1 ۥ 7d.l=h[/{~J:oq))xq%E7#x… $/Y6,k㙘\/b?nl"ߧk}6^kZ_O#1NQ " Qz9RS1 )F# Pr-+qoLr%zӑ4ZRz%9:#@k1T`'M{uǥ˪o>o!Eb 08g(H{&Di Of~!KqP%ξz<.IzP>ӫǞb9;Y&Z[ wb8wDJ V>Û٦cĤ`l/Fްx.ƥ5E⑀C_~@k$ &)8p]QK9ud/m106dW>uA'Hub%lCc 0ѡaR*789ĆH;@aS6ȕ|iu^ +&K+ֲ߱ _c(u„d۵!P徘n4oMxAG,FZep4S M " e00Gڈ)V<( -Iu ۀKpӦ>[U (R <4j8Xe5/ `ȓ{Ktq&1LF݊-RaCF5yJD~O< 5O o܁>^V(FK# 8tX`_7C >>6+rx;U} ouiwT7 +87l/ހnmm 0Ȁ> >⟸'G8%4|HӦL2-k+? 7F`(hw0.k.%=Mr]} Vd5X6@)>|sbNVmL5a" b2A~~\  ,D} ZaQri,c/z poJ1ƢԗVt>#\MkI0sF[`K|Ԩ2g?um gH`K}o]\1c;,`c޾r9ߨH)MN/\l)zW/ œpdCKXH&4b`3w wvmṚ! P/3$}+Vr"2(D6}κәjQ԰,(uP&HS{]s8_ J7[hmmyMN@T'SbBg/0F*MaxQaPn^$(6a;i'Ъ+\n. \rtVНt]QrɽB# QbYxRos!^+E;_V2QN!)`ȚyHdD@XrMKH' H!T 8'1cL HrqFioѢEn^8{9L/gXb^W<߂ … 2a=˛E _KR!r?1'C<3d kFQa>x.ɃF]C#QabÎTazD$]RdH\tёǙ:D̰)Vh%ڱ ֍ r@Ȝ#ZԙOšHfp E7e%A)~4cke0@wB'jUQ.kD%~ 9Ď9#(jܓk߳] E^Pq^ "07›QroIg&$/0U%](Os5D凍+W(ݐ)hKX}%+b5˹Ks!1 Dx(J48Y]>/.m- /6 DwfDuu%tՕOj}M {يL*rN1_zR#2shdfHŶ 7<ղ;:́Uo>uzV|%BM)s>](7Tn\.<$L"(m&JXќiL˚H\ar)P:0`_^ć9f4Ϟϰoܨ0c@Ւ@[Vu`wXn39^T`)l9p^瑹r d"ud?#dUHVatJ'_NmAn$;v3%0Q *}x(D/uq=i{`'$Üt%mspØxV.6§wz %d>'iWY *e'\tr?d~>/xW][q<և!+; 3FIyt/<3?nS@\pGBiy9T]X4itRɘyJp EPbX44 x>^_݅Rl12q<49M34ג +cdՇ5ÎAPN2{-  >/ӂseYj]#Y0Ƿz>HXe.x*9DiroI'|c@Dt߰Xv#'kM" Fy**w`8 Ma";ut̃l.JɔYܛvCQΉg*u%H cpY3}qv՚[M.Dn1,AhT$#3{FNB[p |yJ޺u=_iw\_-y >l(mG`>.&!",Uo Zl̰"X`Uf(9E6+΅ 9c (pdGp!%PdM"3q>\z 1<I $qf '|XnӒC@q$O5#vd|˙. q侺~m2L,ƿ AZE ޝ*݋h {C -)~b/f}#`3j, "ԩ:#I;ǵ/7gݥ/\CA1OF:U`4WE9^ |sms˜ ?^g:uvvqন3u 8iw!gH#\_+=2Z㥗^*ԧ>0*LƢnMw6 4_.98Kw1YPXKQ+FO$w'SNXaOge<NpD,LC%/?ˀ+D&9`d;~徫;y! N+V`#x%kHWx>z( ۧX>$l毰BKk65&`j)tbT"| V36ȍAR=u%}rc0 {S {^i,qn44J>A,tuQ͓B:e 6@է>7C5&JzdX|~)ߵ83o`ΜAF)RJJGܼap=\ DBĜIR|OF0Ŀq_J]be`X,$jOhX(a9| +F*w,4VRm@\Xl(CCҥKVgZmVe7ZVXXCO(b0JOW^@Sl%eC%`uOc\/k%jGfG e=rk1&}Ԏ %qYj$fX.L1 >bQXᡘ`  narm|ƣa_&HƁXkGDwaQ Rv1xәpa%pVxY_, B{r92n@ՈN\sM]S~ejY3뎂#nL[{jT'Ry7Tr`]7KocS;&+u[2ۣh J3XM=-l(Cq搊 L{PWH $x}5HEŠrQp|m̵㸔h{cIa)JL5hAoN(28sMbF'Qxg\k24` `llcּ>V~iiIVЋR[ѹ˜ ˂/>LFbF$KC z. ZDFj14L7_4dg[L=1L'PTuȑ" o'Fsɢȴ-ݙsbݵz7}$07,MlSP큑w%˵yU\Y[H ,a9_G0"8;&Nh$2kL ȣs"R6HҖCbgwc|#RЀ>V$&p 2=j}\ ^).3*tQ˒BΙe*roimw@YYnjH\: >bk] -Ȉ>LPA7*Ki:] '=2]EƠZMqg2 N$}_.9[ddцR_İ97Y'c 3{i$ SL ?/I>{թ@K-'~7QeD|2- vQ*Us{'/+(C"㻰 } Y 8l&j ̨ @nk seaCpV]}]% @P!*G9\ȁ:#ud[#*p}RN;2W1H;EwT/?/c89^HTTHWvd S)Y#2j}),C;m1xᇫ JR-fA" D$\[sh ,LVI8=Ev]iYg{M`vS.D`UҪ4~FEiέ//W0T|F<$ zwήgR7F~<skݬpP @R/Rg?vgs){KtG2)8C x#NA%c 4r|~n 2[rÀeE,F5 Y'HQNVCZLm k +j\;Y;<ƱϠ9|lD12+M }'O\2-湽#X\2/j-0QeE hXwmcL|_@4*,bӕ$gk"f0'Y2F]q-shԣoX|iXb0ӱI8Z7rYѕ!KH@h K m|0d F0 u6VtV[kpy&@-U 9|Kp %㠭u4Yu)8oK\x뭷Mrw~(3"3+} II@z*9tB*d*R2A8/CE/wLL0u;vs@*u"SOH4Aܛ<6K#ԻLJ)4G͵~}5rINl'zo ex=/eF& @g75z1X`VO ;I:@._2007nW_}u߿r%, EH$)Jb2Rf F8LY]O9DRF RƄro1yӤE,G7 n+ڀ'n)2WHTn` $w/e_m]>1čWVVIa B{9Λ: ӨAE̸}t3kFi?b35dљtZeEL~Iв f C3'z"p{\h/b7#P=ê0k*.M {a1U}zݒF[O4Auœ1?gk'GךLa,9&1!m9b{@Ҩw1s{2! AEOT}@#U2I9%0W R/@R.{Ax /:c nȍ`l+MƱdr QOFU x0\荩 :ra@2a  ]sKp߬J4x!k`ós-At\O 5/!50MEΝk F1uB02I H@IUd@eJ0RH>׭I>`Fn@nvM8e 3x"~nJ8hG3qk;,aE '}\\Jv%ky sJZ2+ h- MF1ۦ4Mbl-FùV)Y=!tUsCXBti–P8/kcru,1''\n}dzx= S0#| 1\c;6+'Υ.ewad6ҤZa70ל?پ}G@13׿o/^4xz/Rv}!C*N*2vs5#(,ΐN4^8/b6 RR/nl apCin]1%|A|[ r3rt) dbx5% f/mkB? w)ݤ>iMF2A@_psPY& w6;#@YR/ћEԛA8\Y1!c;R .7l`褝k@{3Cj v&=3 Zr; IJC-R!T~#n_}|sE%\YE2G?ˈu/gl֩5p0WdS b:)uՙ1rX@<`2#v s;tLKV)Fsۋ) exӄCQ]|/*Ƭa +yp_\Ap堗&5VXA(U% q I0ɨA|ٶu?ä/ t=UUUղc޹s)Aؽqswpw lJp\2D[Aə0!ey.(6ڲ0.Scl O"%R%z?$DoTӀH_ ؀ >gֶ}*QW"G@‚ &iM{.aE;,녵^t}G!> $4Jt߮^}̘[9rK[oU-'8A]q|A0,;)@"fzIB-|):a\ƷdrlBxn)өZ/ŚעhBDӛejqClƞ>}[dtt_]q{.a'O q( lқp=N^۫D';?wQ.]=JhFb mt09Z )G ӫ-varf1al;ZLNGCMUCth+ݷW-KSZ++1>tSd}9eꔠ6D4CT܍箰5k)&nޭWI = ,R"UbGSS}TEJق>[%s)>[^jBׄ-7(Oq Qb˳IbrIthU]GKKscΐޞ1>`t h욥X/' !2}TUU%"/&gm|tGJp2)i4@ EՐzwYehcb㨮]7ֱ!NM $MKbB hKJA_>T}!*UZ}CU ڤ;m!cƻYw{;;쏓s|㖗D=~rԞcB>/ؓ'NȘ6~y9)17 rL(U#6(9$ĶLGGQo5g=xV/M>'@qUsŊ:AZ 8* _7wGrT:r:TI.:` ?6$ `D4Y^,W #Yb#BBJ/?*(FlnnHxd <.X°:/ &K)>vMen< Nykђ4 }`!kg BޠzrS(ȉ$ >e˖x,oK}kVa0BCr0q'"Xe,m80*zgci! 6M645Ș*YX ::s6Sc:%bV^йgn>R{{XT^Sc0\9v Dͩu0m߾fZbˋq F:Bàuq$:NW e=8GӦެ9<2λv> +~NUbԯvx`(&FW04 E8Q(O$m  ǘx9D1*/: x>MY9B?>#g{B=/Al}~z$r?x7( Gpx(NzE^˧"0?~.鶴o;n D΍p97|ȹK(6X`R/KQчk;w^yjwʑw *;c|}_߾ R ;v&ƐvE@#1lQD3pDu:k|:oyu /:/!V8uMx=gޱLbĈ`AE^G K=|N N*MM;<:S A҄p]%ևÑC{a4EA}8͗+=Iryt)]rv\KrzBLiBp &:ם>N/A\>wOCS~ŵ ,B(;,.*#? cs<<-.k"KΗcVZ !hy,CI(]rv\)Pni"Wr w*'R,' λ^Zs" "q4 d'r!hysP洑U8(X5pD!cQ]RBvI#.x,QuN<$yqJxe+/ם>QC>ys 8Cp}?o5A#rhnYoxT3,4_;X`X'^`/T ^f^c`Vs6 ׷^ IO統ظ׬xǎEM71|4D7QL q/wy5E ŵRE`dl(yKk 8M. HB#bAӂUqVa7k׮]i'߫*@gMia{ﴤ^-$Gd`:uj\KY]>/2/_ӼQ@F0F'^ټ9C A7 D *hvxQ@U?4 7)'G|y엯xy"\:1O Ec|IL) =-ɼA( BrЙ3tv d TNOMX([{2u]|ꩧ^B[d N6:}9ѣG?@K-(W" @u3bP0Nqǝ;^h̸\VwJE! UsOA,$i7! mRy)#/_GnltŖ_r#iU_<0+1 hmi׷7rkA |І\AТ|>?sv콑XD U9 rDnV'Dqt< Ί=2$QvP!XV7mCV,_葷l NT9@,A?`[^٥jujz$rMݣ Ϛo9r`qD86KT< Մ&''#=~#Z~6k97\U<9>|M"]WFΜf4$KZ0ޖ  5o\ M/FNȘUG^3Iu|ڈ>m  ϖ8>i4g6tx,G<8uŴ +AWhshKɺJqSR3`^Vg-= ]z]ꁙrJY8M3]*c# †tN&y9[5it`Pn w-L jʷ\ټ(LYGѭ[/y"2BSR_}6rj f(fh` X.Xւ9^*NCvjj'PIA{Sw.@D L#z l~~󆈠.VBT:9K\\@nVz@! A_kK뗼ۛ/]=&V!3-@2襭[Zmkm; *UB&A+ׯ_=<>, >vllp!ص+dTձgF9V}cJt`c> 0EC s+yqܟIi ;6:q L&k}vZQnZt(MG vll5 ih42;tAU0׍ (i{mmG'Pvllu%fNeV#UWrUӃ~h HBAr AME`I=%Nb{B=Kcp La"S6 d3@WˁJ2!(`c|@@!?.FJApo[k+qQBdV]= ԒQ[ D Avllw+Cj EU "Aж;6Pk8T*tkAd&~_\69b;;:[wz- d;6*9}-!8>1~n[<{htb[}PS2 CдdX4V5e3$GOG%VcP0h4 MEWI8sU+64z=HkN`s?U̽@2jOF"6=m b@,$ j5ؼrSS[mm#.&6S?/..Z'L6`c#ݨ4 8=pHvaQt=p0577N~&(fjCrD HVϷz:8=ia,M @B d `>l[!~[0(6n$:o} PEX[Q 83 뛚 n8pʕ5Xyll7=/ AH刿Kx\,$LNǦ_:{ r4xr>llu|=}@۠=xwr߈'Ahlp\naf&~r,9>11|).ܦ@ԑk]B3䝦o_TGϧ;<2|\cAi I\ ;6h 0u ͛CI*Ї!?X2parjߗ/]BraΠ%mNRצU}Xڊv?޽{ע K'c)QӉi2Ϫv՗W?L-(v ~6O@Ѐ9`c_*KKq>}QRIc "9'/RS,)Y`c( +r QddH6Z vQdHԀ/VE@63c@ mל՟A 9Q>_?bccO'GSO1%-!IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/keyedit.desktop000077500000000000000000000005071506470510200237260ustar00rootroot00000000000000#!/usr/bin/env xdg-open [Desktop Entry] Encoding=UTF-8 Name=Kreative KeyEdit Comment=Create and edit keyboard layouts Exec=java -jar /usr/local/lib/keyedit.jar %F Icon=/usr/share/icons/hicolor/256x256/apps/keyedit.png Terminal=false Type=Application Categories=Development; MimeType=application/x-kkbx;application/x-keylayout; bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/mapedit000066400000000000000000000001101506470510200222260ustar00rootroot00000000000000#!/usr/bin/env bash java -Xmx1024M -jar /usr/local/lib/mapedit.jar "$@" bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/mapedit-icon.icns000066400000000000000000011571101506470510200241250ustar00rootroot00000000000000icnsHis32 bA) >El*k=t~첄x/S<:w-19`ھ}R͘Wí6м è'Է̫Էg>H02   cA)6uTi"n@y^u {Cŏ v;2oZ֦3{RǞyXݽ6ڳ ڽv'£ʬմPAH02  A)il32 FB c  - 6K5V{x  jk?R)If XDuLeS8hMKv ?T`NrZ0#P-Z"-UA >noc8a6}pKԷ~-2 qB.Ө̺v ĵܲW_Q治ԕz >۩ƀ& ΪuB㸷ښybک˄ƫ{qܺtL漺Ɇ~㾪,籸ÑնyW6ѲT;R% 㷟zZK^a  C e - 9-5V{x  olAyKeUAyIvָ:hTԶ >'?##S A؃Akla,yןcdYm͋z}0ݕZ& ːv\C汘fjbݛZ|Ɩ~]q޸laL粗Xu侪,鬫ȅoշyW6ӟ;>R% ䷟z[CON   u> 8% - K5V{x -ꡐ+wLJf!}Ѻ#}mI >@pzǧZ#V~)ipQ^eAnph*Hci^!QQW~6AG//ya{TD,(d[V E%4NfH/锤\ 3epa [m*RF_SWc) Y >q_Y& `cH +B^d5ObX] qoaR$q^g@>LX`d侫,~}.ӸyW6pm BR$ ䷟z[4,% l8mk ؄  b  ) $ 3V}w  lU Fg]Pl!@e- < Aj+ G)-w,1 y"WB9e g_@& GpO2,Ğʉ.cS2uG it320 &, ( "q4(*(2|+&(!j*%&  (;峫a%&$  #.rR"(  %Nb  )C)"e;35Zy'"&h A"   %HeD'T ~& /Yza(@wk8'5 $ ?k 'f(+\y ?o"&3%(-E.#}=xs,$2/- / EZس/2uW+`! `!  04,Wsɤg! 5`N) #$ G !Bd.d,,!"?N%*F7 }C6ӭϳVf4'! "F#$DFX׵| f*^L$ !'UH"kwi) GںǶd:  /G/%/M[i" bBӵ߽c"L2 ",(-Q{+ Y β f!7w$$IIJ+fD /IݽԷ%j$+ߍQ[+&u?v*#-Bb!5 }ʸChA#Qyug%$T|?K_" ?ػdj ]$1ZO9"1(w ~S83VOܵyjtR+$)d\N!(MLE'<o ߻ջlbcK;jTJ)'(=~+51}-9}ʲмm˪rW3 +# #7WlT  4ȾmЪq570!4~) ֳ1f,2% "[ɥ5 6( ںL 6`$!& çM%~,˲tn[s63%iηکq aZWԸŸ"؊C|}{ⵄ(FB$#̽ұkďYǕIa^i"Լ obiFCDδ'prĝh2  I=-Nվ8p;ɴʌZ  p=d\ Աep_}b֫l/[Vaf7 5¼ǘܾ p}bvS%gQ1dڊԹ ĉsڈv p'A 3OvЦк%ߍt2E'Pdy۴𣣢pș}_嵬c))& !'1!tT%+  %Nb  ,F-%f>65Zy'$) j#D$   %HeD*W!) /Yza* Cym;)9 $ ?k *h+-^{ Bq%)6( =D(-F0&@zu/&511^  / E[ٴ)!25wY.b$!c"F@ 4,Wsɥg#$8b P,!$#').k{"Bd.d./$&BP(-I.UOӮеVf7*$ #%I'%GH1~֨l׶| f-aN'""$*XK% nvpcŬةwڻȷd"="!"2I2'2SU+ƝjԷ߾c%O6##!/+0S}/şjγ f#:y('!LLJ2\ɨT޿ո%h#,"ߎT^/)!wBx.$4:ȱ̬NʹChA&Rzwi)%W}A!I-ǥ۸oټdj_ +6^Q< $4,yG`ŸؠȕgܶyisK%&-ibQ!"+PJxLܯɬjּj :vcW3('9{ .74Xrey˳ѽk% !"8'"&:WgcݰõnTUWɾl1]K@!  :3#7dgzͼ]Voh׳1nR̈́|W=()9&"%[̞Itb໵hUaiۻLn yn  #)"ĥ?l^uYYt~̳tn Obz C.(iηװaGsjYWgȑrչƺlƭ@[=,f Pv~{ⵅ)}=VӶӦ_ξӲi#M Wĝ8Xdɣ֜eս n8n>1@^<]zyϵ'p Y$&_:,')$Ğg6Hw𩩨򻙾bֿ9p^!ʵɎT4cϽı5ղep](f # c֬i:>ſWJýșݿ pѩ v"JwSüb4/XۋԺ l$u:!gG!hڇ{t̻sH8DoЦлn >\^-! z%OYtC%p ŠǸٵ?P}!Dm ؖոݾ:pu5: kͳ~4´`/6lոYCF j ̵̻όA[w7iI۽׼܈5yceb% !4ضCδy=´`I?[fܻ׼KHwWA:V&g»ʴҿ?emQ;HYiԷŽʍ5cI9WiɼԳfpT@G}cɼj"Ի᝴״У6b_J8Vrٽ8h ~͑;¶uYGBl׶^gѶѽ^@kTA?oi|ܻΜj_McNKt~ʧpM<\e|a`ƳuXG9`Ǘ®h;'V=ֹ~I̻jUCHm햨ԋҩY/OהϪ?թ`O>B}{mH%  E ԈԶKsǓz^N>`zԷX7 "؝GρֱnT@5e{oF%  ;ܾǢDePDY©qT9 4 yζğOjlIE7RH0&  0FəΝ:ŰX<40FľƳiD/,בǾ򵚁Q2|yñnI, 币tJ*RZ\|H2 Ұt[= =;22  ŜpB-  !A%6-#B,    -N  wB<Η5v*Iﮖk ⪕` U͒ڣO  %Nb 폌ήӔK5Zy'`҉tG"  %HeD"܄HC /YzamuFU $ ?k *ڏG~v  !(-F蹶ݛjR2BQO / E[ڵ+dF0'>IHikQ 4,WsʦgY@j~Ԛ`_ޕ[8HIWS= "Bd.fRIqBJ 0AINg};BԯѶVhY~NLy̘Z`ص#=GJ]FDٸ| hBwKRG&ciYe/ۻɹd"lGYPo樔I^IMR=Uչc eF]D@_CSPLQ5е fkжYIص1n XΈ\C3!' -o_|Vˢ?26Iw[E<6337>Sm].ۼLn~s (SR@ŧG3/GZNB:5469Jpt0͵tn !'%Ug~C%;eѸجj*74I/236C_5dֺǼlȯ$G`D3$lQz{xⵅ(:)=AS˫lQ:F@Դk+TWƙB,1M_ǫH?iR2ֿ n@s#$D9Bd)-9f~BFF_+e3з'p _*,e@4.0$$(Şh5!=SWUU{7|o@X9p "c*˷ʎW2HgDO|ZUB!ִepc0k ,e֬k4GZ_zRE?/?ĿȚݿ pҬ${ *LwS Fl֕kK80"0_یּ l,yA)mN")iڈx5\oQ<0*6JsѨҼn"*Ecd5#)x,$^ND5.1K_zܷ𤥣p -[}"%'ʙZJ1-:d`ܜ鐯½/!"h $-(&#!ǝ%(U]aڻӴ§{[+i$'"!'/ݐڧ{WʍٿЛ͹~ qt\L9& "*NϟԻڵo䚢V>&')8Ǽϱ򾳬ĻnJxrt )Jٵׅ͹նo.ŗ\F=<)޿̷&qfA))]# ͵Š׶IqS ;ꬶʺƽdq%(Oth!R׵ٮ׻ӓn (Rgio-aОՔܿǝޯ۹ꬥj %*%*ϸϽ瘯ٵi! ۿΚȸldXJB=:긵յƨ4koxryԩʲÿΩնZ m̿չ҃߸ pķѵ׼ٛȷ Ou< q~һԸ~q9 rYǺѵ-n\I>r5Դܙ۾ڹ GkXG4! pѹј̸|cx_P=*ou۸ȄؼLˮpVJ5$qƹ#˻®P*! qѺӶՀ Oû¼› pjеҷhIĹL  o@پ׸GXygpst n Ţɺڷjwqyr|J}|  k ٘׺ݿ.ysrsrtH+v jδaG{otrwn6(}[iֺ3azouqy`(#%`zh ͷͽԀruqtsxO!%(LWgIܿؽs8{qsrvr=##!"$@>h4ٷжYT{otqxf-%!"$>hݼؾ" gxptryW#% #" H&gý̵ &ytrstuE## $ yZiոƿtC|psrwl5$"!$7i˽յC]{oury_'%!"# FʼgZ׼ǥ˻pvptsxM!$ #" cLIͷәj2{rvq<$"!$#tj"׼żlR|otqxe-%!"$N׻3h ٽƃԳ byotryV"% #" Fڻ^gڽ׶&wuqsuuD## $ ziӘѺi9|psrwl3%"!$6pgyߣɒSY}otry]&% "# ]tǞfWg*nwpsswM!$ $!b} j1̹۴Î.zsrsvp;$"!$&η'hеڼa I~otrxe,%!"#Lǽ׷Mg׻μB`yotsyT! $ #"[ƛjiڶd)wvqtutC## $+bҙi ۀŚ;{qrrwk2%!"$ 6ڽgc۪Ӵ׵M T~ntry\&% #" G뺴طjDމƇ7jxottwK"$ $ wh˽j"ս឵ض՘'xtqrvp:$"!$7sھ8h ȀΓH~psryd+%!"#X׸^gҸӼ?Z{ntsyS! $ #!ei~ݽϜe6uwpsutB##!$%tgxտ֢ 2|qrrwj1%!"$GӽͻhVɸ̳湮oR~osry[%% #" dԵj2յ۸8izostvJ"$ $&^ӻݐػ(hϯչך$vtqsvo9$"!$5q̷̕ϫLg޹A~qsryc*%!"# \ջ頢t iСƹgW|ossxR $ $ pצé_cԵ/szosut@##!$*tʦpN<\e}=)iqtwi0%!"#JȘ®h;'V=׻uwu\$% #! b혩ԍҩY0OؖѦS## $z}mH%  E Ԋո+>'"!#F}ӹX8 ?܌]&V|oF%  ;ȟ^{" 0}©rT9 4 yϸš20& SJ/'  /Fɘѐvl 40dvy}oP+*דȿWWmwjQ.'币tK*[.5Ұu[=  /   ŜpC-   #  t8mk@Y m~eP!;*/ v c%AA2d18=q.Sn} +=KV`ir}3!(/9HcS 2av3٘!Hx pM;i4 2` +Y4#RcLmEx\>m,6d  .\/'VB$ OH.H~rG-Ar_A&:hR;  2`}J3  *Y}B+"RpLs Ew=m 5c .\&U6OWH~zAr9h 2_ *X("REKhDw=l 6c -\&U7OXH}zAq9g 1_ )X,"QDKrDwZ=lϿn4 5cȸyqi]I/ -\Ͽ}tmf`XQI@7- &Uȸyqjd\UME<3+# N}unf`YQI@7/'  G|ȸyqjc]UME<4+$ @q~ung`YQIA8/'! 9gįzqjd]UNE<4+$  1_۶wkaYRJA80(!  )X1y`M?5,$ "RֳkO4# Kʺִ{dL0Dvóvohb]drسxeUB. 5-% hxfcVG6$ *.)"  "/@F7'  !! ic08( jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 ;( '_9`tcY6R60Y[N{0Z٤ԣF̏Cņ2Pb"MŎNVpS.r%rjn$Þj4\`Z䷰SߧhlHyIbP 4t?;XB$匄77bt-8?ql7p[)Izi WJm=~)IH%`N`0~hP`*!7(w8Cj@>UAE>tQ%!I%' ׷W^{kmSWHȻ*ax\ʃeOQyq%'n´=N %V~8aM%YKH["=x7`Igvɺ3Ota-֚҉u E-҅?^)ܦ&V_QB/5 Lhw" UsI`o'QI}%>0~|MO/`&̌LRSI fս׮)ս~YA~Y+4PC'&T \p.@ͧi]=lOPBjh. =>MרAyߏ4-T}WRi_FP=#6oGQ์ >_݋Jins~g0 @]pIf cAW^IlF%oҢD|x9~YQL YФHp 'vl(QEYFmY\mBIlOK[@b; ,r+Ԕ|m;X lUyM~`t$S̝aJ#_oX InnGp)4δ;%Pn*˗̩t!!-LlM2(u }4)nX 2&͓"ZYekgޡi-ؠ札?FYݒ]ͻD5n9qɗw2MK};t[REʳxR=lܚpީ#R|q6E<ٚχEK?6׃{PMoUEEhǡ;ḽC{Ĥm MW#ćPмzA!Tn G[Ihm^7Zg\pagwp߅B~L kP t܌ǔG)#5=l^jb @`$EcQ[% ܂To[G:P+EOd^ 2mV{;8++=Z7ؔ(SQŌGMnA1xd p v \?ZsC 6ZRM|gGoUG7ORtӖJ"6Ĝi"<^ʒzOT_'Xt\%ooi{l6+m?aR#:n]cxBs"02[&Y%o˄rSx?wR g_Lغ79+^jDW!'#-O4d-I=#IpyoIRTJޟ'q#ZR^$/;q\Y8XTm|3my vfב!=[!&kUrxrf WJש!z8&4/cg5sQ%h>I}'ejJ|7hW;[CM7=BmrMBOz 9A.W{XIP YǧYSa+Xًa)=`/ӳǝ eieel7,i8 3{ǏD0 qtS &Q~lsXrFp`[l+#41̎csOe-K (lWaİ%4?)9ZdzB4fP46z*[=ճ\u#X㸺UcxTn6v5n,8;VD+63= W.icHVxX4S˿C܂0ڨn:Z1!jY,! t A`ޅM<+ݥE7oj@!9 {KpڪU'9|8U,4V-~ٕoH=Mq3qp'"Ԡpn%|4 xQl΄„R4KX_:(@ȝ}E$;D)P2z+18D@/-N,bsV%SDhؼʯ4OQ,49m ̐QC=|eu.K:E}cIw }(B~ӭm^8?pdܬ1u2l/_;T&K"Ojӌ1ZҌ1>}n6:M,z_i;蕜r> phPzO+aXӽOLHC"N"!h*2`nJ$?peKz"e4P$E8kbZmG!/4l:JN³S#׫ Ƞ)xsD>#|GϮ(:ϯ/$㊫2ϑh),-wfySf,UUyyö$:C$yNw(rmin< \&:RwSa^_9;^.BZ|7݆ϟ^{iniaE=ۿ̒ h5>-Ez?$jX@MsUY+CmY*Kyn,^5]4H(R;P:8_% *7gnqW,ᘣ0ʈ!LT +ݤj9sG`ABcAHQ3p yXXW>$PԖЉ pq I E߶Ԋ`2k8 kϴpM`4ki7@1p=u/ a+OzZs#Dpf,TjtY-c|Cٞ}Ϥ#&B“ˠ(د/Y#bGyڬW[,W:嫡b*s?nP>]_dW`tf]*Q !` կր!=AP:lB'%FF!X1ଢ={6=\5(T?}HQ+Ώ;ydI:ӧێ m×㥐DzBdߥ~9)#㈳)pU/KgAFlnq,[qnɻ2qR_Egk88.zFc.6:_?:hTb[aF a*x7tǠA/u)y YXVS$`T [|&+’4q+)cZ^&4dDE"2c4(+-XJru0' 'O?|PS[Gm P"Cw9syc) { F;[h&h };a+,Qjg}k^1:)JLA}!5]HwNGGՐ" 5SJX}QצIʹ/1? f1y"3CSǝ?i+LrRE;z-"-d2u)}gQ6RR[l|P|BFQx&ﵱd"-}0qd n_܇IH0!M8 FԜ3j{m%:=C'puƀ.l[|ʟ1fpEDr0md~[Mf/vn^|OUe* ]w%#Bad*–sRL3F1% ɻeCmB_ qL3`wA4Yr},"CU.V2䨄f f@˺:n Jd{cG3f_@KjSAIQ(;KՈ#zwM0q15x-VUٝ &D9>1EzF"3xek5C!XakPFNki[O?sg+ EƇ1 oL'IFG[&L^c`J*{13Bޱ`YEPi]qw)"VHjذ'm0X25KaPN@)ԐO0*0q@3uJc6xXr Mow:Bx]OOOMa6,E?bF((kWp%֮D#LqP(k4~Zr8\OlyHK" 2a&Ha+}Jv%`KX1+k{G"eߠx^f3S(AM"ÚzhGϸf $)k xL~W㐃!u3$!A5$ ⴋZwdՖ\̢/n Y O%a>dÍ㛕gr"'n#U&&l bN 4-Ad gRZ&[(AW,W^?6h՟zSvk*"/F `G؈'aBI^!.T| B`0<0lrkQM=?` s:OYе^f]}IJ8_tkjwZ8ཧn$N/6ž-+N@W72ق^s ڐ{3ono &Xj-a&XdEŞɇ<}e0؏## NĒx6 U'[id2m0r6lvy[B^o=f= p5JNEйvOOFW;TI(55ʹ^a|h5GFuø.Y8opv̕LNBIevoZxLWt `^L+BDe'`5`r}z]s2r,nr8% XYj;o3cՐpUjwR&}_ӗ҈gp@G~G:߯SR;Z؆031:<Ċ4ܒf/@aUIS草oMSE F/W{”xpףD4@މYՂr麴؆5Ebj`RƬ;zDiHpUZ;T(\b'Mrq`ZI1.SO|]p{jAaP\>_ h) EEõAɯȕu2? ˶c ~.((5Nx^ˁ`r=Iv،b-:x\@qHHCўD.?<1} J Y_dl$`#?XCݖeiho,3E(^-|PCuLkϘv+7Aq u"ޜj~4$y=np<фED.cꛢ\0}@`'/,EaS~֐H#6VV[>-^b~}Vb K /^g#;?=5ؚ/GSM" 4x#&]x{%I߮[ݝ,oVPv,DfD@ !jk| X!ܒ OfV_5#>d`f/Ǘ-X(/j/r~b[g mvw =r0/bNpJԿbP+V.ZE2ZvZ_ǨŞ!?zپkwDž%'X=fh"5 m? nZ&T7xɤۣ @j|cRDTGŘCۍZ!}uHaMX2{ڃ"_]*4@'./޸7~.b;IXPEb|9O@ٛ66ʘ#5$*$kL8$U%KA؛GgbUARWl-|W1kKA޷cq'{*Ȯyhi%L: ~YTG@>"b " ;}k?=:z:mYVB5.]iη;(@$;R:Jl@&jvrέ^XeDǔXTLqNo i3b_QOHǙk pYԋ8F(W?0|/c31Fہ7KCӨL&@edRI&-KMqNu2woe%~蚭N::큖=E`cP 8F_O4Q9J'OH믐V be6DZ|j ʹL~^by'Ҡg/ς|nөBIRej/W%-&XXUXOđCDH;ű-ʒ71MA yv7(7oFɚ>ӓAo!DjيW5I䭘ښ4% tqHݖb`#|1G9ݔ /q)<8#ö&;YvHpkV!@;* bB}m!P,v}e9w4rhv^^RB<֭d8^Y!pPE*"o jeYEp?j!%U`!ľ\VR. "ӭm'_ݯ.VA-wת]ܶjDv˷ 3d豧r.5l-v,X}b-G+l p`N Z>2(sV- >Ar٠zr̩%,@_cx)3ܨ\赸jjmEr1)Νk^UY&߂GNPIq>q!!mu-:~؊fu-dSoga?۱6=*T v􇴒5 -PKԍB>p_nU ҧmFja8B/Ϲ,m*EJ.l&/)u^X?0U 1z,~YD "t$͡c٦FЯ: UlT1@d]$]x竻|X^L+~T5iYM,ʯXVY8 Z -@}Ѽ~۲ʪ@;$Ա^ל@bu80`#>?rm<|($DP,Cwzawn~ڻeзuJ2|SFTgluEi[k%3Z0n~hch~8̅ppз"M`Hɵ3O]TQ;,jN[t7RqNZotNpBĸD|R"|H+Gn bJ8k3%hg\(6|6T9Z+,pu5j)3tcř8ē",>SLqgd pQS(/?m|10ZJ+)aB.1X8 h/DBPV.t#AB) 2Ȃs<4YBc2mQò%V 1܊u .VJ -}zOVs/ t8ol;Yms5ΟPa Yش,f9'iŭHAm)2thVodx$9]N Fn{8.#[yb;6S__CCZpL/=〳~TKw:#~6k|j.TdJ?7m`"jfʃ!5IήQ/?բ7i 37 (ݹ!O"wb#T;QeܭQ|ie\Lw.djV.^DJo2L~}i<5MpYڴкˆp.O mcLluH>։CîNLDڏelmYR57N{h_A{q,$٭ZvS/+}TM+pȪcVcud$3.nul! |*,c=$FM]׭Wfg拶$_8:Ʒ!Wz-+I\F=QT6LD{r듊Ov @$5\y\l+V ͰIĮǯ]NP}ZTv`AGq>F hÑ<.81S.jr[]lI>ޑ48/#si} wށeU^:];Zƅي߮<|[KvYbdA2+!%"{roC6t18ܡh#U`kbQm bj/Jlr1G1~k6ͭk.:YE.)Hͮ\ O0_T̙bLbiDέ R\_l磛zF^tVwg9uaP'3?r2qr}b 9e4Kŵw2l;dtdlzc6R;*}W +͎H, wMJJZȁfZHUiHѼ6_/3K 骿K,>]I${c{nIU9J7!kM,e m7evV' :퉠n㯷UhZ\7f3\l5gWd5a!٘m;sf.cvۘ\hh?sKv lMnv`철}2{'TZXt8TN gL*pSac|Lȳ;$-os;AAcp97>6x6@xbQPG 5M5G iwaVfNY @,܃Ͷ{jRĆKqP`E=^ǣNVBfI )2y `DS 7Gh.FGl4\ty;̫c)8ial# .ZhT&&mQT3r%@̲t5Yck$[2F:x+rxUssZ\+鮍%. RcxKɸV7"&w $ج`1'M0l wDN_\¤2 F(?䵑K7# ȕXMpKuhz#p#)Q:Kܢy2E+7f$*SZi^`՝l1eQSu)P@pgW,kgI}OU(bVۏ׻^xa\%`vo;GU8A/ꫪl~f]ao$ޗJ AEW; xY(m/KB AZ%A ;PTlL{2ȍKHs .8-g#u1ѤӚYy$!4k:{'_|;%<)WO.;0\qMw{)ip?ez,韏h<Ӭ N/X1>=ذ d j`֯VDwG.") .k7|W5ְR maiIȒZ[ =nDJGL +ݗGh*Jex+8/lr8S&"Msx̼J>f!gD553RWs#dm4&/! $i3]494i hޚ@L9/ÔIMai;|3odF.GG_^;mMd Jc.+L7`z* %E\p sKK]ƴ4**]OуQIz/`;Y?[I9EtL4Avo3LiP, g%ֺzn.ֈXqG%#!+465fFKG dNN2p s,頭z=-)V459&$T.0g &(,jP].]p9I݌3iB#:0%-2*ི {zSgK@:jhI&ѓ;VP4$DQy d9XxG7">ҳ`b!b%4*[v&e|9۪_;w@X t^`\2imj8V@s9d(QOG(}SW/u BJNY 3#%1٧C J=GDaG&|f U[4{\ CVJtBKIR7M)Ga sP" 9p> Ul[g`??] 5^oEmņja_gCeQ͊.9rQkMJ^#UU|{Fb#(JԾumT<( $XlV!Kjcz>K[jEhh,\EΩEkP qjxYaY? `$D)K` O& J?"T4z'9ɾ' i$E0`˩MȎZCO0 R!E݀;`mj'3(@p.3eSvhPZ+Nm |GcH#qXnq`;NYt_Z<,FA3/ONӅOFL ,\%Ruprx=Xyߓ*>gYsѤ̢.7X6b㞉؛tF:s%( nAmf++a0Ws]XLK=WV8nKmQeQ$#;&7Pя0ot.ɸ1LS6zˣ@*PH?9(B1u }}``ĢPuco)~"0#)PeUj!A^2ܤHbcAO.3Z CU8?2F3UeGbkhTj<L H9W#/ _3üK Bx\Aptdɠ&*FU6i&"f+([3LeYȻ߷7D\gV{P us}I=b&{8Ep-Ϩ>WZ4s,oڮ}l'zH=LGB2@q~M_LrJy.pҌQI[:ڜhu괷#+\/eߪZj侙P/N1cG6 R?;| k桭OSiv:lJ9tM 냭Yn,qSO; u47L+x|+ _X 5p4ji>vAD:zE'5̉U'*IV5yۈP9kP ={]9(H v6c"kii4CHށr/Vj"ԓuR7â 3:~ K׼A:-}n^)/R5mUw@^R(Y9t,gH6M%.Fwj&{( /+4e|yfx|Hn6*70k9ۆyg4=6}JhK-T,@\!gs]:7!VH MLqQE+Gp dQ%Gi̐fug9z*QK1-5eK Ta0+|V'جu[BZakC,f-Qg`d\Afon&gh&Ǧ^9.طu{,N a!D뱇Gf([#fߦq|7B[ !Ofn_['>IS09֎En] db]7!wmVTI\Rd[ ]Ree Q/CB p$ 0;ZBI 'Ib^uz buMP!"4~G,xU7zi4 8장CgPz}SYO%(ԊnӭL%xIsuzrJ>9Aa۠';L̠H yC7MMl2 o3.ҵoexgN&ףn&d֐m{1Q}v=ʪ59ݧ |>GĨ T$AaA "57'ނ17fG12~Zw,Zug*9M0c;|c كz󜓼f<Ts ou"2ۋ>cR7D eI֟w-8ϓ7HMɳ?-}w^܂-, z@Iy*hBڏPiMM!Mb~Q k/Qu "gCuf[36},$ ɫcl.0a$(!bceZ0 D&q@#! Y"9$k1h Zft\ _r!w]GKUWA}kMZfoHQ{<ix4,͢= ȁYw' 0&nZTL6k@Z"M(<Z]r7-}̬e&SO)I@To9UY+'\MɄHj宓0*O |v1q{ynuMb=2g,t#?KuՊrQ^N%`J<ۣ]39TMg%3^T/4+lt6~ԙ)Ӓ::6Z>y%|^v,>B?{))]Q 8< aM!^lX8#iѯr@pXTJNTG>J✮U΍HQ "__JM*$:px5Sвk-+Cxhߨ]Cʕveܦ ǖJ)5;fG`?e25OM`Bod5=aGavP:(™ç.KΝUF2*19߈MZ'7 AYJϳJgV]1 &R'<  sHc;~x+1Baﰉ*VDk/Lgn7AVfӑ\*riH_!'awq 1K j{NH =Q xI;`a'+8], .Y(uQLpk40ITqPrN̉*tP4IU } 2Bc\?vG<յfUkЏEĀ@xIJ 7KA\F NѿvmK+=dǟ,!Qo:βS>Ѥ,bP"&b$ȝO"ݢf2* \E{2~NB][]#>Β J߂Gpg`tUgrneg@!IA|LPnB$sc π^j9YA105V5T+d#P6/H-~n&<}ەKK-x:9 b9>ѬtMF rv!3j[L#)V]`+jK\ɡWRX4!ŏcbVtt])r(}r*'S"8(|a z.Y$jlP_(:UÕҌuIU n@#d|gW-LzlѸN&(VlMtz@ZJsX@|O;[@/SΔr1L~9} 'L'q|e%WxaSejy&Kmq!Ԝ2ϑ,dw2AК+rI>eH!FsoڠK*WK%s ZbW}V5 ϠTSnwS,bINQ]6cE'@f* OH|zڎ畘}„hA,*yphM +CCt~5z+QVIOƄwg98,ZݞψZe݇d?AB,|0TH!3l߷Wgy&㖛Zh/A-w}# "KGh)(B Lk T!cqn2 PѡU^tZِVhXZQ}I3) >ŕGwȼ䛧@rP$%~ ]B^73tUW[]tP^3_W]96dt#a`NdtCjȴ>8OM gyٞ,7zO#ȩ re_TO /-6ǃrlNOJ{ Hxi5݁"սݍD@ǁ 6qD͎ߝ49&NSRpu}tEs&v)jl̂ImxҋNђp«}bb覯~9Z:>38zmO$K/:e.g޼y?G^W OcHI0=&>-f̀fDԧv+Ǭ\K8XJ2|r&O :}_PPdGXQ摣[$+ P1(G'pAr NFa5{z fL;im/a]'\vިKIlr"P 1u0yZ8. \)ʤ4rA;ݮ+k)7oatjC~~Ɩy@1_[/~ou%ɗϨ=VDe 7.9zV:h0a'!-@V5޳FoJ_RTD̓@ЖmX&ʵl(2?wtft_(C<'^AM;? ۯ![[eYRVTRN49[g->!2 q5c(a6GP;j5Y2'x xA_HYd9G7S+@c߫޻6-AB{%s.p;8Ї]x@ n=\ 7Hz)8yEYv0dm?ᙱ wRkUَ usǟƻőŝM3~i kF1J(A&" sai3_ lEJc)}IG[7 -l2㿀ˋs,+^I"ϚlFjn8PSՑvI3/D*'obگ2/S1tg#6dS,&~WQF +0Mg:$tLfhGP#5+!L,.QOtB?VCjxTؗs*mS臈=L?7Q,hC;}?ݿ?ӽ}S}8JW1rLc;h729ގ:ts9 =c)Kr%A!l  i"4UinDpjF՞-*/5݀Y0=M ۏ¨`C 񺎊J8ĨѵjL260x2갸HC/usV473)S~ qP7i2E[m/RD6Wr+6a}vH/BrOHN=( ]īw^ ma/oݚgjJZ"?怅Kd0z$c=hN_WD2-^Zfx+ p 63 7D%@v1ASOUz'5vǒ6CƇM7N!몄5iثe_lۺfL&̹^H!/1wnE9~/ųq&4Rbk6?0d]k(%=}GuG&ۓ:T$ʔ; Bw@v_' >o>S F-OX6-0IqW.Q BEÉj^U{YfZ!IZV::hHe%JS*\pU2_nxF6Hc P@v?Rb TS% _ܯh G)M"xW=  D=r5涱#| ǧ[7[+ C-k/=@.[WXp8p}\URKTyWs:`Y!^m'vOtG>t TtxhP6Kh5c{ k)N^i49)LދJ;Nlt| QPO09Go+(rɇ+t8Jv':rCuS)x gZc4?9hx>kJWxt/@f Sgy"h"'q Y[<:o> ifJI%\Sf ٜ.OPlx ;8"W%#txCV!yЋMW>Ka q~NWX摚KLwB*~DFNcnuTeN 3G# '$=h}b:M{ڄ2Mq0\Or x-4]lfHMˤ hK),Yjvf-)-||i|R,[̆h S=p0^k/;SQ+Y"x=k/>̴Q@MjSw;sj,Ýsz k&C֛Oo *J$5_d c&3JLiKSM԰YɴGy&cYn_:7w$^;r{M,Ev! ph;v sY p)u#ql^,[Bh" :G0eQ(=cg<x2?DV'(S\|0Y(` @ӀAeJ4Os[ޜFK]aqɉ&L%L}-9^(#F8XN o2D{Q✄kkh 9p*lsi*O`{_"QjF o<| $74g2V3/T\ؑ.oW5p>&ҹ UHT@)n%4o6h[)_,URͪ,'o<+[Ǔ$OC"Zj@~ ťvKo`\qRnW0lA8t:kɿ< nhQ ,e/WGVJqEa3\@GЈwdY_YrxtD_\&&2ac&6%Yy%lYSD:JP ct`+t׻)g?t0Vf.Whindx0*ֹ\6!XdbmdN2r[SSl,R/OHCR*pH#FpkgsV])"-{?OtԎҚzEeqmerȊXB9oOI E&Æ[rb4b-(i&yʃ5= 8G Kbp$*$/ Z/0J/f}yg\\4jj[n=Hii/ps_F &Bjc5S9~F 1@gM;_bD% x}ޞ$-F&;]6FK&}P% ;o>'[@xyR>;*{WUSNE_ߒNC CGXZ>Rc^ri9oUI' o1q=Wn:'N/WAϐF{'B\)Ѩ" AnFY>q&yR˸o-:͏=xWNNHMq|IʡR}Z)$p f٬|"Bf0=%WR."e8\qC^4ʗLѧkiGM4k< PZW[3+&(N4|2s+o̼$֙چ@\Aye!p֥],<4SgeϨϐJdkDNwB W-lh(=4?v~@H2Y=Pb//XfcDbȶ_g̗Bv?B! >V. q CwJFMUuL%$I_B͓-}^}+N~'A*X (#K! y|_ %oS"0N\@!ӛ/ݹ>LaçmfG肼 A1yyC倗L˫}Њd6u\pF 1_6lt,sܣTONdj1cQkS|c'ߔp/,IAix#n9X65eaHGR7R:hN T}gE˼ f k5ƚ*-w!ˋخ%%?ҧb6E>׈Kz"JxژTeXb0"<,h"Q7g I}WW1+MN2\îČfXZ.:vxߌYݵ4'WLhГFtLLEoh:U=ޝ??3b_ZsPc2[:cShpdLj0TWoW۔Ы,FW< RvNJ:C0/fXIrU9yJ-Q8{~GڻSUWR=JS wˍj$U`$KiA;m9z@졸+By&Euiw@J\Z[/ yCWQ# Ha[@ԁ>qɠmAM{%l&5bZI* }(0,"u|gu 難](MԽ''9>6uaaM0Ha9Lձr&zbg~g3y@]͉~,`Fc˪ה}.Rewvu.Uh|OCvL@EݳΫL_-[Ip[R'R>2/mD " P6k3_ xJ T*)8/s%UL<iĨd=(M1Z j#QilvEDl['HFZ*A27n?2YLMCفEW"dGD5hYavdE;&!NC N)Cr.- @2StN dy A9V-~L]*e5zZ9[$K#r%&˰5Z23uQL1t8\&u,msf ,i.AP$##kPp6Pn _Xxɓ=)Xmv& #IU!.]UJ񟡱TÃ]nT `QրR)͆l,+n#V,-n9{+B&Z-[^az(p(_wxWWa˜Vu>Xe4${99☍1#l&SD/*i@#Mك7[bp6Ty0MtalAж)vj=#̑yEV}˦@+yrAEd&?@\@.#|t7ݠrjqY i)t8 `e3Li{x\~Sc9U"G4T s.#M+ypQ&'Wj~*e0/@f{ܠJ@oT#}sU.)cK0vĔ(P;PaaRa'y)4] nUת K|((= ^c(X T![l싴nJ2aCšdKK`~{|LK|fR\F 3+:rv&AC4;7 dmX,%985{(Qivs1ߴ9{k8}5Y* |KIei:4L8)UnZCֻ@TGy1`8y`V0eHo?ҕ+3t`5-]d~|D$ "=o<ѶO821+B +-;Ur0isC}޹jqgڒsЃN_'pcXǒfI~t)\f7>0{n06h/wsņoaLBL< 7D״/c^R73γ' ܛȇ5ߥ,UX+Yh)]>"vdeE.}n1%T>e6M5pOG 4R2ɷ?K-*,xjl7)ItJ sپ7KI .,Xk2੦$*\ ûw?PJGO5䅒yi5ՂD}ocKL12mnZHg?]Sh7~^\?1sMBa9ʨ V%ZQ(GD_x[UK0pTU!?H156ICVs6-=9عX}߶Ćqf?_;X!/Bc'`jҚ~dD*f+~W]:̇+A0;S]X;?U/, 8+-;oI ZJEe7iz m;e=a*I&VR:n9 Vzu1A[85FUjC]W.jWA(X-[DzSwF})61Zk3䱎9{g";j6JCƽKK%^8")jMUͦF;PVk^tkٲƊt@3[+OjmС+梔֬րZR Vie:[)KFK WɎe=0މ|TRVVN4#TǡC1'ʡho B R)c5/Sz0Γ+)|lhx6.{` AFوVdNoζVgї0C_ޙY_*jQR+X-;!!Y:Hwzބ2mg,J\OP`a M}ΐymiCpDB3yQZ?LePt.5PҲYʧV>9ʌW|q1`V2c %/dWaiGL(4/oWF1(7fA}+SG ȝM  (3o>R0^x #P}tqr`WF ݐpV VWgm]lESsmXFIq.K_&Jxl+zܿ?yp-nWfKCw10~7ىlMp2N) 6cπUgAnٱd#VB9[lڔD~P7^6@[c-:C t36wͰ(*(0 )h2iI9~=ʔ5p_&NG:eFdzQVk#]!~>pɽ^֖RbY|ȈY0O+٬N)}n=0#*[Qk9#( /B?n.p.ud[.'Gߐ^Ñb9 _EIRݭr`ɒ č!L gUAaW=tw&z룲ǚu w h"1tXy/UQU>18̌YffMCh@"e}._^h0mm >,Fy(59^T 'Vl(lHxVZD ?16w9@qz{3Z  aVcsVVL ;bNsNH) "njɭF2 )zox Uf y|">-#v|̘$M,5}d)'ULs0: Z,ERDIA8r-k̲+ق'EfP߀3+hΑ@B<; [Kз9yQQ#zD:Ry; BwI"ɇ,~_sm&2TRO!6 X.n.9M AH߁LY#ZUbEMEF bA$`T/. ɚ"Eb]u}[Oks6lYWI=![[bZp25nə|Ú4f}E"mC0rrѫHW+c@[($ gPs~R63XFW# = @0:NvՅH:?h} VwzO((;mH'|viIU\񰂢1*5n:&5v2zm"ODtuě~GšV3fl2sr]g]y:*ؚ}KFќgYsf76\!ؿx{L6gd{ޭo‹ɑQƌTʾ0{+ ]840H4UHEY*L|10ԖZ.wkٓd吼1lkh/iCHx˘G^}c_icC <+=@l:\ !:]D=d-T % `hhp7Uzn,nb&<01y{e^ Й)@U^vmpٺ3GmO?oD=Ѥ*K}MꥼII?F=B*Ϩ"L>`'_[gAJ2NViOϝ6߀ĞUţRuT.T>8c=KC6DE]I<kל 0d Gb,zYA^%Rf("H8Uy](Sr=ػǬݹzOK/ cp+I}3FTs`H3' bU%sQ,V%|$q)X٦İ#fpN꾭 R6fZ6qd  x{|VFA.LZ$njlhx LP4hd's]GIh'v][;GWlUۺvbu-du 6.to|F Gֻ~l`%#I]Sl;R[ a`!1,wR]F.yGSbXA4v\R'f7_S;t315Р!P䃬p% >Q8ؐ(>8R FU:?u2Plv|!#Ȩ|_@ÇO?y]qcYlwOS'?Rg/N\!IN!0xɸgopj ]7GrͺG51b2 D 8tsGhЙxZSjC5[JHTJqa/ ;)pnjW [\ozq 1gpqpWnn8W¢_h{7~_f\P]zV^RGA152SPjh%rcBv/c񫴤F}6I'!AH fU?+k6:JO&x qldvYz \g4Ӌu|/| mz{3GN*4QL-2Q"cp4` w9<蒩=+[ V=q(Ip&H&$ O,<\IM*z[`ƛ> p%+ % sIPNw 5!hW\Dk~gpkʲ,6 6"aT94WJM͢uN"Yj1lTO78%Lc1fjvLCqmƴTDlt"5OTn13&0AcqT:r(d¤e~x#V_:ZëcQqYQoؿ4,ոE>U ᩜ{u 24 xnh셩Q,}e>KOK7 cVX)h|KԳ+lYԍnVAB{&vɻ&pHX]1JQ*ڐ~ dT2|hְx@_/)8QfJJ$`gȓlkkڂB԰_.Lu$rih],hٚ01D36'H\ ,G d 4w ^ϯ]MumU 4kի' </+ bq<"ּ }ڹ:8C%nS}hVf z%OԞ!-<ԣ}x?Lȉꉦa2xŊnxɵ{B(ړG|LR澾"*MEEvԡDRݮhמuSgrNFP,\hwx>떦rS%y[ F!|{}~ýG#qVvy^>xG/zRrw`o&:*;c.CC;m+/YRDh'MܯMNޢ"ł6s-:c > 8P$氘a~ĀnxInbU 0o(r,ALLy}UEb)$(k1~X2Y{Z{g켣q5X"y<ەPH06bJ_3=8m yݶ+-_.dzͲGIF8R$n7K>2#xŁrwnk3pOk Em횕,eo= ({g'm͵k?vAe"-koIl/߼hK>~!([߂j&QP}ߚuO*n.xzVn0J&'g9Fȉb%7Nաš"씑)K_%dxXlo)MNR1r0yˈ4Fϭ(W2n&Mj e."ٻr P^]N\8_MsvX ;Jτ9q A˱emБm3߀fαTc&)N}6{ і;FM'5iw*ޓXL[" o46ê5;P(1hr! Ӏ3A:99,ky oSWЏ/(u; Dj(hB gaO_R^嚺%!G=yo1KqF6HMknf4wx4T((oFѠJIL"Z;\~Zh*ہm),z<I+? }WCeяةtknlV F+ǴMC4<0$worx'NԞx늃嶌^8Z$_kP$ p4V+W::q)#2ܝ@A #@t|\Rmg.$KBh%."snܒ3n>.ɗ?&[Auz6}=><} rQjP `8]'#CG!\l@|H^qew2z%{hWdFVb6 qDenKQeatle8>o8u9d3rB*!vx%˿K2ۊ\I$?DD1+?Yqш״Z*3`p"A{eTIk\H9W}e$Uca8%}b\WN 9p.O9M4$GhXx'̊& hTX!?Gkx 'K74Y !3;I)`spRpZ GfI ðfYL[sødA8M׹}4# e#vHmmxw2 $Wh|d2ytm*{zok]țd{ESpw¦sd^4"lRҰ=\ 'F? ByU >--V`ɋ̜Mx7/R}dW-.v]Y/B|ny&eFB2αqrKK6C9ŏAx3yce.ܔz6/r5k*%[-ܞK-ʰ}#aSM[ưo,ª,{'CiQ :LLXs\S Gw$Y ےG*ZB햨4<~Ύ5kҘQ8kUwx*^\RVMU2xw*i߃ǘM6[h08tJM{7 )``XoD0f}tq.Te=.9j~)ΜLַ['2nwf\Sy6%\5m'aqtk rw9/4;| e5dqE8tt(ʾpƞco=mW`n>)-wå;Zq ۿLRݐ2Du &n+x>HseڴQ._5 ~Hn:6%eH㴪%+'k!~Y*A'1O9Vn(BiXΏUO 'kkt~?' eYvL!΋XBJYEhA_Ȳ~ؿ^%=VE@IaJ$t~ d%Oz(aIp{ȳX?뀐0 mj{x!s& F -bv4| 6\Ȥk撐0Za R3bKQ֎YdmZNW~Gj o Яgl4LGJJ"Vms{΢78'hb {IL6ZIk} "X !*i>˔s#e ^P"zHqU'rK ĻVcsV?Ee91=v/vBlVSv3&y?Bqh 9l&?tK\AI/5&9RKCc8q425 ^fpM['鐙n H)kD_%,F!?MiSLYlT5?|Iq[*g1t=LoI?kE&^=aE4Q?Jk)2`M'W [˼4'Alۦ0A?PS'ks8`AEMaO=#77RdA^V2.4wspSٌ&A&sJ$x uaB?\7>jgxLN vñJ{\Wٙ(k`_n7~i9fkViW`*{VY&9xwgd:p2K͓sQX^ V"Z#.]=lK:o5zX(tTY㝐&r2涠\M @pcdV rZm—=e_Ӝ}DnjT`֎)pͧO3 @ꂅ5Տ^9 ?geQ]yxC& H]ӢS]TZׁc h$d=*ͱ@3er!4R_CT!8мhd݌ueo<+GEq\&$7x.;81"v3Vvn-o@!? GĈ;wmXn>I/&_Wÿj<)R=5ץo窌H۠}0S3۴;|ib͌pk'[.[Zdas"㡁1ݘr˒#'[lks m%garn%lP?rikPڲR)a.إ8%v*b4RiI>o܎DkJ| P}G(Wr5FtO@kA;8\:Xސt:)/s\ EyQ]l͋ 1:+'GO' gP/i(FQQLdZ G5A1T*oK sIkGö<<xx ~͹<\ŗ cG+tQHq#\w(_L'?82"Bl+q /ʫf|=gJVw C du:^Hy@C3`$~a M+4Soi@ FȫXsJv y/q!A"Pxy9Aeg)_xnmGzlCSU)(#׮f~Po!ouUMaX L-!uwv½9ed˃/6ca!TWaW~I &kmJS>nQe)ث=+ӾߖcW0,(?o_KSbȭI1}M݈qg2[ںrS+U`waD~:F( uX19SJxƪ. T̟lM8o?HAxV`+dđ/ӟ$/k24:]80 @FDa-Eoe,RKi_Zi_"Y|;) vJG2|P'zLQ,3ȏ.ca 7eH B̓)swwo#sNL12v •Y6[kcIibY-M0MQVycihu i߳,g k8* ֕+ƹ!Ft*I=YD:&ORk(g7ZJJo0Æ*%^ɮ@mΛ#u:}uTz>pұÛ%0(tew_J40"gMS.d{Tuk3 ZP;)[,/cs4&\IDB+$Y=*Z^4P u/XsP:M %\a/Xǜѵku2D`hC pNԇI|BTw(~27;0ҟ0ރZFtnQs}f$gOH8H]:*α6{ܜ $]K[e27jq: ߉dA5pDvZ\K| .~gjRA\7,ޏ*ѳG *\/RrƝ-R֝0zdcēkP@ג9 JA׭G~抔鸖PMt—쥄6*&^{-jD,[.)SjqRPפS)ɞ5Y]!}J*%~e`ԇ$0iL@qq^86]KG~gxhuMtN4PSAggF0ɼB߅&2fVD#^DVk(NjQXN`ڠk/IxWljZr+PY:i9xJF?lD' {R |8VI 9l&{7ћհ0p5K>y#fHm#րΤUysljIIw0ZM+١n+֧hQ{$#˔067{@ܪ՘$?^S{/gBb~Mqd[Z4"na4> w_,oXe`aB/J`aCg\ᓴS,e":ޥSp;l(׃c߂Q\UvDUTkdtk"!AvUTVK}3мSy=|Y.ڊ!c_"](:0LIk!oXɶ8:Qܶ*]-!@7Э.DܣȴF萲+%f_8?aQTpC(3ِg^z!뿇FxshU/*>ے7jE p'}g?_rҌ/x87yB&?/x"P %N'IM+:r$XɅFXEC,E Oc:jf@saٵ :j;'Y7.3;5dA-@Z:s>ʐ=eh@@|8.vmAv_D,cUHWGeNQ:`\2 UՑͯ*շhxZA '(gk4C! >á`J`Ȅ+5 ^y8ayjuÐK-]I'^wcbO:d{{":A.z'y} ?+m=S^u8x cx;6$#q x N3ʚf8v:DwC`)PC~va*X)880YD%P>>|jݳ·N!|%ب93O>/}# ȑ{XBWl6Ϝ#TGF^Ui $;: jd澓o۷(4Ga莏Mu D7K z@#(a[?Q?s )oQ0hVc87"S,l§ i(Jٽb2\B.PdBCGy]jH_7CooWg 'A:XA2bωGuCNפ-l:Rf0 ƃ!r)v'w d KzC! 4fOw FWTB1Vj|.;9|1~AJ1 qáѨ1E 6/}q &{Ϻgª%d`MM;:oo&o`][ Igb":++Mc.נ?xܪÜʸRf{!²@.CKՏ`gnnZ^z ZF/.^Z01D#I١癍_a^4IA]5T-zņX aXy;G.jax^V(`Jksj%o܂_QS7s"vMBGSm0/HP96T=a,BCI❌(-.3rޯiyg{RΒ vo0R !ə:4J9i+eW{ϛk;^(/+fz<$G#.Լp~jbd/+(OO|`,J?W g:K0⋄Mfhwez^nF&SsY疝ɵBTr]P*Ϟ `[r V%ϛcY W"q`r701Vmfmf$Njkp}+s,cwh8J}pP \C ,3D npb.}ht2)HCơa]ՃWc1P,@бQ@J|Vٷ{z)ӰuU?VqN Wȣ@Fޥj@?S.w15(~%GԈ\lӷ7nx)n͑蠷c X;c4P%^,m$P!&),ꦉ}I6䄩:Tԇ7{ JcC9$$1dZl2̲5A#n˞(a$L^8[?nrTu>́ouw oVJ]l` sQKj-/9Et3ghuƈtDFhko|l^!4J[z&Flyj,\h0y7^hH,Q2]ĸUG9R2W!EIa)cP ǫ[S&CiX*:-7eB_|)-W{y6{ mvI*Ao}ficDe U{i8 (;-/~ODy]+F/>c㨍1aYNJ:HY=|b!7802XHү|G: 0qq[Ў=UwoyԹ|A7qq$ڃ}`[' tTP5S,HJ^k4-* d"?; BV5ӻ~A^P|,i;;g1Ն౾S)ltU9j}:ED[j8O_+%GcSZ$L:KvV.i=O*,n63&-2;>YXH-,'iFd^9SUf6{齇c%yׁRǕMô[ḟcj|Gmal,,fh6;]B)Nc5uHTQR== z/7ܱ 0=7^gpkl1n I [mU>:a(}gO/#)HtNvG_&ALePC\Ӈ 9S,'~CGφK?Ae2ֹ07|>KbdWLBH"Xxb؀=9ߤ0gTMƾUbK*G\ O M]-~%J5`jk)Gu) j߱V5Xi,dI7^悫{WV-'"S:a0lu"fӆppKVbܡҹƓ|Tg V l~X#˶EQs$삽iSY{U*liHޝ2{j=T~LKه&̪9A?6Nw.Ol~g!jsi.ŤТQZjځͭo}-CXǤ%<0%;#Ag~232B1]y_dF K2#{={EFOtvn 2 !jDN^~JfW^p i @sܴu)z UqPGc-8 ]op3GW3+~.rzp^,Jibދݻ0`wb>?MG8f/c`y,% 8Jx%5sJt?/csK3lu̾qU/G>6Y?6ǹ>A bOw,lS&٦Ff%=z$ Ckj`HGj2Mŧ͍_=%h21KAoVαuE5I~I=;{71S90-) 7,)=i*d7/Xw`etEbbjn.Bp,R%bpBsmX;4עܢuǻ֣o(VCj2@AX8RtIS|#o,$Ȋ?zg]#Axn>"= D r;I^x&f^#j<,KtSXŎHM׌A1Lo}twf枟OQ+=އ;S$^lf8m YvŹ '^^~{ 9AP[B * KIߢȇ}fή37tM2"dE]ԅ9rh,9CƧrh⏤7,|3Uc@) k|^dsZt_"_h>`^`IJʡja; RM4,WAI.4/+r+=5bDZݱ[wpkQ6Oʻ-$~O<7}?AMbֹٮX<,Eu"՞{Hm_órd,{em: !K-.5vHd(Jn8I9L9R59h{pE'GؐR<% ل;Go%)!1d\[o#4arُpk.gN<*Sv+A=sa"CS$ `ԆQ C|y_#og&ME>UpG9dv5 }z1FBکL'Er.4>ڸ>nZ~0SYH W+)( B2Yn4Ln8#BkFX㱒 LВH) .c2Ia[sQ, Y,rj IszK[4L7\G~n/0C\?^=w=4]1<^Y{{u&ESk>8*MH kp?&*Iiy=yw4^Gc{9_PVM툢b"[*3$VOjx߭pdSiyd)Y(%NzF ͊={j4-5};v"50b`4'6sIqGہvo.mzcYtˑ9(3̎dA\+6qIBSQfwK-)fj(WSq閕 ʖT+V;db*<x=$a\q'3Yux mVY*裎NE2NX=|~}jsS8ҫZpK"㳑;4d8-|eh~؜ATYNEX>k;[; XYjp7æ$iJ퐛PueV2BԨzZV̸!NXJѢؐ%o`.٨Ÿ Sy&؏s?,KGU2\3&hgs:bW`gwZ2UXGKj򩛯@L p02lU+nfW _ EÍcE_|'z Ǘzz&lID?0Y-ྸyLKuAVs''+!bd:tRߍ:ko0y))'F]ֈhaC*-%1>SK]qXBGKn gذuʝ ~qy\V7_PbX5 L_Vp"aG\/1$'BJegstA#<ۿHVTѓ z]xj?yuD%ʮX:氿 HemS9P[1R)x.G2 pcv+V&u>Xe-[̈́D=CLZY%G‹G`’~fGG{>b,ah)^waOВ*%zG}WKjz+#z ʲٕGiQX៝_=*>Gil+' S_L|QK$VCj#-*㪼m)z yM=? D gB5C74Js7) ϔeT+#E*!\.[JDXdC/N;UHo,Z;ӌ_+&r陞acv819^%pz2kXI |bKf%B? |eC7 ڠӐ6Ȩznw2TW}r?"]-r 0 3|a1>˦)W9+%ٛL= [:qR_%I xWW"d- 錎'S"Y8X9mZbNNէ>הK] "t%eEmCIT瞍QQ!y'O$ĥ]֯Vf)_ 񕊟ۇU(cxOqb8ʩ&Y!!RQX0):mAVIF.=j(~/эuBq&EdFExgtqqӴ``FtWr{v_fKs\^C(+xvJ$FO$3i)> ~g 7yZ ?6PVjB1h(ώQ,{~\˻{TE_k׽TWc#rv u2KڧCK0> txĥ8 wiDuNr'׀3.%ąְ۵ |oRaR毠T>-$(H;՝1\LlC, Kº4JÃs[I[ά+t[)2n2>2L(f!|3]#I7 U<ۮSx++rA5XZX3]AR~GD+A1;gYpǟ8[CY R݈LNS`5UJTm^ xg CaNjgf4N .,LLQFtP|~c G"Pg{qVY*E!a]JBf8~zT.ɝ~*ϩۂp< BL_派a<墵DCemG0w}Q9l="Q=>~~y2@G&bFNœȎt%C"ɰGIy0_=!pZYPs$%mFkl5p^(G7S$_]rn놖CSFp>zuFf|-gX^1CT Sd/t@⑸!mzЏvCiz?[9&Ҁ޶%t;*2Q'e*p%c,CCҠxb!xb22ijy[ucfҊh3mw۸Ute> .41nʯ?Ї22Z]]Nb¾&Z¬mBC;:M%Wp>CGđ6;$ -Gr WÓ]=8;20J@ 80AVdί޳Pf 9&P[gPp. qPC?.[W2 @}9inI'1ɪUG|O p|VjLg[DlY#CoZYz!`1 3 Kp~k)hymxsN_E!j0&Ƒ)s88RYa'Jңg Hi{?ԁYyjnQ@ 5?O~I")q.hEڶ0~ױd=YKqC( ;5Et\f6.U 8}?,4y.TѴ9b?3^^"MO+~nХދ΀wXt/IDIzL+{ _ޜ|DOWp{f+z"oC"2&^=UaZa* Jb*97oͧȖ#m}GCW$!Iba{lx!vF^Y!&Wb㡫Zg'H+N8BYIئS:N%ܖL_.ꘁ]捔qQajʌvOgeJ-|sã(7kH7'?A=-NQ "(+v`4rK3R" Պ;B2qNwH``vښ jՑ&-kv٘[=s' F3Pˊro+aԅʭqV%xo ZS@M ;\W@¥[R\ df"ʺ/]rƆ:@ZS" s"[cRad;o?Z2yȲ>4XX6z%FFwWNY}Hx_U` I.~{d>ȓ%8[r\U3~kҜ"9I|>^P$@^^lwJFS#:t5_smJ}'[Q\DX"Vh"keS !ƓȎ-ry S>t7KrPoq XW_Ai\A1}SW:q?RV>)OnKyNYoPg3XHgz <{-!Ǯނԑ,R(${^90@sb&X#ݻʍ"dtL'bًac1K+I5j59\Ia8xs˱,|{RA7mvAϚ8̦AhE_sZ J!#Å-Gu7k}rSWC ?p)|uy2LPERbƮƙ=55U_]qr-᾵7/Z`ĿBOf-C:EV.p 8ID9*H<< +7W UĘKi  OT(;+`V`cp\Z%AyB>5A\N .1mcOÝp 鼓[a=-S]vh.c t{]݀pD(L UpS])9Y-'{[ɣaW&֘%$6&אp~csn<]##ܮR6qlC3OCRFu'!*&SFцN<:wDmL-:t8;_>SnȺ? L}!;zOghz:/hաصfɄaM5TiOjY;툛iA8(09#oYX=`b^A:G5ae4S_T=/zuiuLsO;#,Qǻ!HM,vsy痂g;?).VPZ)G0Rwdq^"E,EU] t]onhns5$H-}Zk;F#LUB3 //P+/1AW+`c~8;)[x3jf)&QȻeD;7S\Wsc?} A?p,N9z ނ^?~㩯oƆq*NE6[ڥ(%=m7#L:3`c^銾¾"9~A8KA;X\ *\1 1BaU1=YyWȗOx VǷIqOE(: n,aV^DDQfdc4VSl{47h`2/,êL&G_^7f+: I#v:+VQ;-'/H&j1ԆOSRя+-0_NF!$hALdBEC$pu>#`tTMmF>*veŝ⾴jbpN s[DA (|$xRw1;SW-.Y`Бu~~?Jk][gzW6U3}t!t)XK{OPhsd@F|ϪM˚ZM!d} ]*:P" #  Sk'fZƋGތ6[8Ai` q"Zq%YP?hHE=C ;%G:"EObEJF%"}cЪ_QQ!<09++f7R^^'ai4e3菻d^r+[680T2"gami^;7EK+knj,kw}IЍ ߒT~WmN Zj2Sယc!pjQhR!64qdbd/>$'G [e+ ;qY(QG5U=bȲs)ye(ڃS@:m فN搑k8@Wtqp$s;!wy&9om&AΧ& NoHc|H1V h&,TD*&\Zg-oC/ÜQlnd@H}usZz[mBZ.gʠN)K[ o[^hsai,ٓ*,Mm9KohߧR_tVhޕÒtּ d\rvYZ(UKDXAX:}E)Wm.3X6\5qP>1z{g2hxi vꊛW4gzw/*-ۍ soegxjQ;~ ٨'[3I$鏕-̔+y.NS8>#VѰkF^rPTs#*:ɥz۽JAO?1JmQb路B8+_|}(E 0$iUV}JƜUb5~{xtO4 * tFIQJo.0#e J.ZoWUY֑Q=5΋u7 |҇&z>ck>pw|od Pk޸gқ|8M{  O#P:(="5+VJOwv_@ɱhn%5J P``EcjiW( &.;&b*KFw] T5:M[o~:W5o=>nRS|Z/z- ? L^8FS 9i=IĆf]骮5"˽r>ڪPpMT{d`;C/1Elؑ~Lz\> 'ǵe "rA+Sv]xphO"T,&rzf> 1|H㸴(^S_kDgnJOR=*c~jZ!ۊ~ \$2o(=~#m1#q,}Q$YNevuR\ilč4dqd] k0ɑXKL eUe9m}lwiӐ׊3grs0;U9^Jحr7.P \-ҀGGcݏķn"$m6 û+sԔ4RJSb & >]'Mo۩6hBCc\ k 23Ř ^lM _Y)Lgϥؐm i.ANw>:sew.q'eq|nSB~d>7$C:ʏTClJ OGj\Y•hR`72Ȫz"˄u9-[J:?|8ց3WЉ}Wim"Eo dL1WmN M&548J3_7#Q%`^w-~ѓj$!a]!+n+O1|ym$nW҆b bd"ݰ=9m5eDOޅC iT è_W CoVћOJr޲{w$?s)u?6{oϿ+Bc3벯T |e*u( *wȖ),W`v\O=gŠ%*.zYaW3(y8S,/zoSkATTԿ.'nS%oG qJS jhGg]:[AL)]!.QNUw}0$knZ^=cK֡US:?/:MȘcb< tѴgˋyU=)M̕#ːm| ,+ŧ—ByY-8a8*>+_afcݹ9~mB9 OT`h 40Qo.jEf٢T?1hed.!žD: Z_k1fuSC O>QDUz_:y8?˯`v'}:yevz(PY]+P;v ë{0c^uÑgO EszNY)*L/I0BVmpYUP.P[n(G]Ϊ yck,M\hw6wc,HFs|ad碨r1薎ROW_=̏Hu Uƥ&X4 gGԔp6`h:֥^ʫZZQJ#5*EңPgku.<`l)._*Xh*)ĦH ElΙKgm.6#M֤kP`ѿdA]aһB Y>?ava|ΰv͑aK芮sNJc9l UYND覗xJ3̇83LPɹs2Dr3CO\3I 1u5˪qit -OjGMnBAm͟:[ eo{ m^fC,IRhKC [uBy{澀EGc47Zm%@Z!VF)Gl#65xmy!${у6jA%/Pbj??3 U`H BH$qlg@gX^N}d irh+VccIbAc@(b~ O1nAWVF\8'w8qEGxig;$6r=;JP@F˭Y\0 "U#WK(7EA1p 6t{9fK3{A}Pز#DiTfR W eAkKKƺP8t${UU1S]<9Xt}1`áXDCؚrMH"ODNKGRe֗-giX%6cdm Wk<+u^ '9Qfphq'? yDA%ɬh4h=~OlA+z A{ `hqwrQUڱiUk@[A:M!- {o?%^bܘI~JKz2A)Y1{Agj۵q3PfY'ȼgm?4W񈬍yz)ա#Њ<¡sJ.V4}bZe+6ܓyz W 9ø>5g;_ƺlsLZڐt`"/NL8Vy3Aw6&Lo[CN|k^BJ5eGREAR; @6{. 2-PY)l XVr&d^JEGC)#87@%&{R]%5ԱI4p?$~䧶Ԍvi0%u߆e8U]0lG/ֺާY@ɴ@\r £^MDi@$n4ah/t& ,:n1S$s4x ['9{V<`\lÒu-ۈEdfr5| zO6a=9|GAbv_B4vEƜ>DvSn ֨j;6[ͫJ؋e%r~&1]ٓ1CL_y 6'zQ̟\`鬦%MUA~@ ˒J#@# k4XGeE9|K:sG` ̞"=pC>V21c?}ǚywJiі "tFJG95 I>ut@(hm|a={\.؄hCC3`H ͦE>uh1k~n>Oi Ь˯҇EJ݃Q|鈴Pu bX9/9aBVrڍ%'+D2)_[q S  ۀ[y[3V[X7}g6g"aV`-*o& zc]h= ";UYeZϯ[pN-;bg?H3btL5tr%C^wb^w&)M}%蓱ܢ[:Pd\ ;!}V?'W,Su,T  l%{;~(P*uHH/2j`C f! m~괥F@.d='9"p<4\wo~bsvH}dȕI!/Pvߝ2B֌ qQY4Z|]pB"0a_qp2+o*C&WE|a,Fⵎ dq@F閉dM:\R x*y>4DEgwXd)`TZVGʙjٽK]g$6 5 crޛ0#UkR),E:rh'_ Utz.6otVyT]U &%ŕz ȸH3rL@Q1(u\f"3cO 8  iKȘ/7]d S;IX#  Iғ̺kP V^V ʐzZ^|c=GKCP\$-B畿+He:AI NNS"K oBբ_)_"~?󍆄$@f+x]2ؤXF ykrȃPm8w S? \h(\`,P;;6a5MqizTfi8Ax'۠7J|Z2<ͦZ/zFfy4`#AǬvEIkQ1w!c8R= އ<:rnCɚ{JmVkS|XDٸk +kYC7¹bƍ q:[Y<̻莘"BH7RlF@Wi-Zus~=W^skviMHԙRKFP%WDz+!4ܐ@w0\s&,#H a;=-sbqLI.F^qR=`g !׻lM;bA*j;+K>liJ_z݈8_3!?lTC.&Gۦ cK_痶`fR!skx܉eU~T_ryE zd-%1*6ӡRP&>Ay`:SnLc^:#5)ݖ=ձp2*~NLjU}u +mU?=+q '.-uiRD(k]٪{eSKP?*dTaO(+ M:_Pju`$6}P"XA &:U;?4źO $F@Un ~ @V{KW2|yA\}BOK&3V &d.(¢}_5/^!d]kΎfpldeNuAs+EqpM&%XU -(al ZK?Dǰ {錞ܴ:ok2P.,_pJP&Ts_o=9 2 /+3b-M*]snAy&뻨 J3Noxw'%>!G('*ls6Ƞ.v@H0TU]Lc/  68+s.NƮ-P=WZYX̱$PY\%]M y4`U glK@ԭѐ* *x]d_y<JJS(%gjpLfwUjGnx_@>P]\ 4<`F:_x•ˋodXėB&r(6xCFy $ЈȬoux7xNQCP}'b)mv)-GP fblTP 7mАtW6tJDz2lAW[;CQDDnad谯f%~@WǛs׼H<㐀( ϰJ=83L"fd*RaP?q DB 2G+ubQZgp5DA Ęh3E]v4 Hr)NlQ,б4#V/Лvga7ι'&ˆPV,z4 i7n*>8G/ cUUi6l3x#J&Ej_'vYB?HJ[4"(g+tfFr"v@sze$wAJ~RHjpJ߶,3Z{ؙ~@]?z!ߞ_҇ E=nͭ#(,&n\R%<\R5lĈ%6ZL)}G^hP&m=]U 4=ހr!T0 lq/T Rx2V*B$*qY|a\xwXj8Urt cKд-\.u4 <Do;G^6NIԠ'#TG4:$zs~%"f y…}t6)ncKA}ACji=Z^Arc}=]MZ]+y7c d pjj{ ]!$FK8Q dڤXkٓIPKkI[PVa1@5り6m\,{CP.IDV6 'Lz}(j= bdA e%t_?cHJǴ㛫b0)ZmV+eBF{efWh- mVfre[|8-? j:7+\g-PAD ʫ86\/E-h{!6}hb'ѣ>\P)EIpž^CtJxwR+qۊ̔\=J$_Z(n]r ܸ~RI4bxe%nc. 87& |mw*vGGP)\+ně^NcK@vKȩm>ioQڵ_hJ"KJ`\7}"B";/&y?L2M m sg Y#r?LGkۡ;t?n~@a.!RFy[Z`GدG`>4"UC]ӏ,JcY噩~Ś5){f+nYi-|5IO)d۳W4D_o>` OKKNd:rc ׾4-F0Jޏ~ ᐶg]vc2">ڲePԅNbDž xk>#J^oApёJ>&tsFt\K`iGy1奆"N`BuK!Ud\]XbCG c$*S}'ibb]^Px0螑SNsLǷZ?yﰙYNS̹٨lTIZLy8bIKإp-B1?(r+3WKΤ2rʝ'p04}P\?g(E"x]Ws1׸}w/{fŀr 5aޓl!ET"Uj9h`ӮyF /A o$"'f^BӺb$%oQ1AQgM~WcMlXOI ôIuPwuJ8a&!n\3{:W{fcrޙ?1Խ+-WچjwiJ]~uMPܯ!+f 3g^G/q[j}C/(QFdy"8 *!C\cܙ!κ5>luuoEpY;aA9Ѩ=iħ4娬;NoO~VUVQH&$s{H H:'FUuUas VHx+#aЛ Cih2׫@ LһzKڕf7-; B`NL[SbwQH,W>gMkϠ<o( JJ<`ҢqtWT^]P&DoBmHFOu> Gf!HFA6A97;+q/@F,ߣc!ufK*x@Lv%ܱB䇧U'͜P&I$I*^Eqd4/R7įU\sBnFX͌kJQ\_Jqq@6)oFYkgJOkt]jF(b?-nH# B|i(c&aʲ;BA! %oΔl6V$!c9R{?|)x5re!/ 7shWʬl7u3xc1YnyZV֏fʪUwK|#P!#]uACRO4`PXAˁxGi?<R&N?닀L Yp28mΐUXXfسm[$_UXx@}L[oǜ"U3q6V qlgaq({įbQR*_.wj(7xF|%\'_vު9&T1$d"|": ;&^䧘O^,<}`A}c{ *Z,u8i%SCaf2uCDر穹;9.Ik8>E+Rot>5N>yڠbIށ0*bLY'=|X_6^YV翪9eImDΤ YFBH&e/rp>GBLpԗ˦p9@͹{W|YD5>hXN츢UaEG0 EY7) Nl:)\_lʡlޓ0|PT驺8=a@.&Jɧ~R5mDƥEY./0_c (oGpGr)4δ;%{m7Jq9jo\&%9Rwt؞v9Fa &<Ʌ0Rd<{'B*eVU"_go<ӄyfJX6?z&:*|){gPH< 噡Z4OVN>XƠ Dn"K/w !I04Wb0S>ց֨TQd~?aGT$aɄnyv e']bZ΀}!zY |*δ?F6gw]Tn%#Z&HU9ǹMDY2?:k S"#`@kti Y/D+^bi/ \$sW%6?Zs1iQSIj7gü BprFi83(,;ݠt%Ϩ[#![{ULs6DSpݛA R\*pJ '5 ^4xZFX~? t^+{d1ɶ?lِгvnX Z%ȇ"52NoP>I[4?)9ZdzB3wn9 `1BXZATt Õp`GEfMҳN@TrjSļ +6KV.icHVxX4S! >uUGX1$߃np%eU8K?ˊُN97]ZB;`:8+b?A;& Oe{j@!s[@\!]+j|r6^_#s6p7Sch|xQߚV/9PϢ4^ -Ƽς+8UV@g󼋑iq߷OK:E}cIw }(AXq󌲅,# v9eq/hǀ0såЌ*0x9P8޸\368c|^Y_S=9Ff:d3۠XT5bԵcO: b>^1zO+aXӽ`WfdM { o0 ~ hRE@eP\Bv`,T rMpL$fNܳkw]Tx<9"GϮ:ϰ/$㊫2ϑh)c5cЊ7φ[s caa@k/wnH H=DOKM5ffM*@~۵c+Ժxt=tFE&61Դ`oamd(J4Z^s`Zu{92lɻ] &,JYF*ƭ\dNh.ӧ7ˮlboT5O#vH6bDz.k [fl;}B_ɭ!C< $ֲ!t!Aa0dw` C#\}DԌzܲvaZSk@Š'2tnл*$j~F-cXC\ @xNY9-@QBiHb>ԉ4QnsDPCƊ=yoC8Z)(e~t듂bFCn8R]L*nH>4؞ti(ڷtu-֮O7s9Gp0ye41]1\!>WG7!>DŽn턡3/oHSnQE PkNG֙fv}D]>ZYJi壱J<*v| oRj4a(eKS=tUߟ<{OȽkF ^QIZd+;E@L?gDǖtR,hS.g&27SPҰyUg@Q6{Oqocږf$$TGW`pXuy͙47!ic Ӟ${ةW3_2?=Ee4j_Rug 7%eJ2E~|4t Kw{L[%;2],V ,nnT^hDU?®>4;pg+ԑXev{H%dLҼ+?GEWF_Svg^K#dׄԔmȎc־d7%&o|aXShi@3ţWfuYUQz dE_kBPC =U- $+!UCw_b߶h=s$`B+)]ZpE-жUR5LV_;x:jN&N ygGZi 3i quz z%'/a6s fIN.zsuҠNq16a"R.R2 NDKPQ]6ӊG9uZ1Σp?Ef;iN ,j1Z%6ۦp#Q3=p`i.ܳIةCc = mXuz&&݁ʛv0H ##8#鞧Ab}-Ez.rNs?^Nܬl. ̈́WW^K+Pf+)8pEq] W>T @􌋂21H5F9:^:(j5׎f@b͆f->CKF3٧9p"$o?8W /toH-3nGCCᒄ|0 %N7tt&ts4\v-g/ p{e8ËDF2 ";dwSG0D8tHyxW~QK I>ͳXOܳP(C珐ʌبӝX-UVy"2jCDqq }ù.lNֺpW: i/6 h!?LNV~52:qI'M~cŶ4\ʡB~ٌ9&᝷(ܤ\6a+ EƇNEJGµdЁHWӕ*OXνo0H6Gs1`iu[PhxhZ%s_*o ]T:y4ksg4kv[J8__8/n,V Z|8kdsBv iR>ִ[>x Hiy*x?b~t},ՀtG?IuΌ!Vt{,nIjh Aυ%!d%¶3@#[#;X1V Lc3W@")74[lGχ<F팔&:cYiA7[_"9.kPàpFurx0am?@Vs8%Vh=?o1 lt!Ydέ@cwUE3v&#yd<~y. @e l$ c!%3L2ߨ?Y+ua'3s 胊v#uA&mE%(DDS6K2O]K 8)Fc|cCnُe.1s>wb+ Jt^/(6Q%"A?GifIoy|K)M*_+@}h/ R&B0Vpo7r,Axot0Dw2ЫE.-G%,u Efn d2 s}8!ᡑhD~z:3%t`0w`Q6)Okm4l4·we~cp2wی،ObTArGҳ|њzhEo ~5,Qs<_BxkFߙpR qGLsf]mEAuQ3^/w\u3Zʔ|L AWs\%fO3"{b0!(FCڮU_ HB(|q_| ǿ#,r_ Y0Mx5D&S# ~9TuBʴlw[OSyxDtyCg-kEQwJe Ͻf OE8hKҖ|0zsy:[y+6t'If0Ozyd;WXP֩Ҷy*AD4700p2zsۻuP۶VKG͝2ޯ; 8_0zSޖtn@e/O %3S|B9D Ьy$OفZ&Q4eL*ُN￱I,9 bj.mPӚޱOAیvztš8SmR*-*mˍ#IH "']VWzIfkoCtBC@dϿh?n{ -u"A.3=BD1{bΟ*,eTOV5Fba~Ir#{lh40YM&ܞ+u&V$|.fEVG3,@o 107@p.#3wg9jMr_ uPnm,Eߟԑ5,qrf;;| (eZ_ *˱ tf7*=ţL>g=>Iz?!r?~`紷&U:ze[4Io#Ѧ-xܺ'p1թzErhe7H@FQ*)v=bKZDA§b=6WwA[#'M9 ԃ ұYdmo)wU 6hq@ ;駪OaX50TdfSGDRgVa#߳{N 9OOCIvCmrY4[})z$;2[sLka8q(hGUU x4k0ۚ␲}VťY! S$ jmA G (0]`iHʑg.}o 8t-)(RIo2.ƿ$,_)1 p/z(#&Rvju^n"Q b:b^OEiX6k%тb+5?fDIm9 bH ʩ.pyW +8Zv^#M.n*AG3qQ{m[R{qR QD:),{ĉġEo 4c\FOI^$Ltrk]d=aM)dkkv+AX޻ Ib(X8PlntG_RܩdƨLi98^=9jSH}$M>KMOVc% 6 DnĂBD Vd`*tRX'lX V2b1WtL>Hی]3-,ەizۿ@/Ŧn"z׿f!VT#Hb-Kցi{rW!}Loq&εewݍ)+zbrn-<{hyju+J@u0 m#|lb>D彂(+#>JucK nؠ>*,Dcc{)1I[liTsX˾+Aq1Z0~(%~DwJEܦAtZSb"4"7!+5/*0n=ݻJ^QԩN VVOnU'f(u?8hqec(m 3H~=! &7'g>o{ÓaD{kXX$ =k^JeRTWPuK]o͒\A"3VOئǦ3Q PE? XLU2n]d3U[JccJ$kſA2kWI"'=1lEZggk^45J1pe+dx #M~6YFiq+9]#hrCQ*H2>?g/.5dxqvㆴÎ> ",;۞>eڸtbi_`rruFy\Gc[Ig et@I: ?rـIif[s;oakäSfBӢz}LNMhYK$Zlom;c,C6-F&@+_z =i_Zj2WjONrB6u~*tyq'JAMhC:Tر,ښwYb}7fWcϏH~xϨ|tm"tG^g.Dʼe/_ (%.ާN}r!gCݡ%SCJ.:yZ> eP0=0'bN<e,N8], YN%{_JujT3Ƞj|r[Hˇ2Xv& B~*81z_ڏ'f v}=ז$NmV83T>.\fPJ&WT9ӧ>sPT Qj漟SνJAI-1A]UܖsaI5ܡ KkUb0UJëys:Մ`bz ])Sj6Vk9ap.2{fFnPt3އMf9,o%=Hج5sB3<6F&֒xXg3ZiEǵz@N68)q v0 &PLhWf0VPd?Q gcCs(#p_ PVLțs%h,FwдUI\ـjyn|r@Rq? k!^*/=55TM t#b~t0Ɍs 7bzAY=F\1C&=ri|t4B0cHe[eB#ނZTFP[]-TnEh"1QD VK l'AI`x͗oU-\gI8줲P35h  mcCX|5_'LJ % |i8- {:0Clef}v֗agxNx^RϏZDkWD/v l- BHEf mR}h-Q)*XUdr^:붦U9N*C#_$$ ?ߒ7OG{56yNSґHHބg);Qj~_9+}kb?/UQҙzȢL#:cV;>-Luj04h@4ͧAJ}0!Wv4|)<;4 b%&5P"G^+%+:7yD4@R2+ENh9ełR[ <|  &ʎFt屻*ޜ 1Eqxu PtVm[cS((C*o9[~O_ٗR ` ̛yHeD1,7,TkcV,.H\2G6u_a/MȈBRƊ ~ڸF$⃠MuZyzt @`H()UF!^Z3YM.E |"Bl{XQ+#>*Bq?~6^b+eo y7J"PX@ZdVf ;U HQIIeE>e]Z˽Gʇ>z ELejD&225s1tS~5vέ C[/6M |狵ūn&ݾXC8^ L"ɂ8 CSG:qMG-*++͵{*/ 4O`H?'ñ9 oNҍ$,kOu򕰠?7ACsZlf?jZ.&22ڊ .,\7-;f<OF G3=^ ' =ed9aZ([Kc+'+;b \NC#ugX VS#Ts/ oQdϾԇ[#?=tϺ tED.I+ XdB˹7_+=V2:Dx*ޕznU;(n\IfԞy4OԮ (rmҽckmگKWG (j̬RwzMWc v"O^A]Jy=j,d/%;RqGfYk6(\R.rgsڛz,+pvgzd]㦔GG=\(^m.@O6 fN| M v(]4$a>/y(iKhDFڸؐq9|3QOp.R9U٧ ۯ:UqやnKI^ Zxg  4Gâ9u t+/g"$FY$1xpxTk L=M4@f:)\Բe=C.C opc+cMkT/ ǂv( q B!Z ܐH%khat xrKbxQJdo#@_E"3)҅On:;9'.2VK#R@W>Ԡ%1&b0Za脚lD&e8 O 8~ݸ6xŒF!دy ! €%}@Aò,@:0YbW[@ؒec|,"I+`II[ =zFX,u&kXCɂB<6Xx ؐ3 tr0*+-a/o~t?P]䙴`vCk8aLuHD=MZ>5"Ǩtz@Qfmd# PZOQ7 |^=Xp=e 5;PeݏPSNqۿ*$&a4G}tSB 㛅fّiz -( uPcKB5=^'֝JGdqٯW1~{A}3+ N xyjNCU0y|5?#u+a(:ɔeU%2Lz-ĸCt.A߼)i){\.ШVs\")-1Tu /Ad'CM/U1xEupC`Y:oj*(+)5A ImЀT1@0c*`2"-t_Yk =%ڸ_?KyfϪ G PtZA/*6x`Gsk\Fe E>I's{V|:F1:ϕ";0MLp51\.a[1g({ݴm679h4ի 5=u3?X 2ZDGal&/G*ĕ`.zh?LRH`:kuCف%;$ e@XdLbgJ5YO/FKW|r齘7W#ܮ"4i9[*}g9ds=%؎ŅFTLjN1?>9O`sTXRJ_5qHsieLS = 9.\j, S:n#8)LH ?~VO5q˳v"}4` 5=bh1Ҿ9Fs[сwYbEt: 7;csc*Ïzt(fFü tQuVUϤ?']_HRxDk-&w,+kdAE7c% ] pQm'tH?&*ۗY|w865,Hrx;l*_v~oiIxO)Ǣ 3= 8#n9%"mCo!i,JA=Nc$~k`y){W0G\zfį%QWCA~KP<MtY2E/ ҳ8[_73ׯ&,!?(+qNʁ͜A?Wj9CEj4Ɩbx;XV*ﰉ[`=ĮR |+,$ ȩҞ-v pИ?=,1HsSY~G|wGݟ"+!\F1{1\ iG/W6&ӛ)-TEDx]`} E+s+W0^⌥2gV)pg3I @51]t$ Uv|Xp=)[  (cLKkc90֐}"ۻ4޳迫fzaY83\cÉȫ M?8iv>!"R2Zew<Yy} FY8dImˑTXս+̞/F$xױٙf/QVyTN5S d5qu+L(ߴ?xG]ja(we!})7>|uF7Q֤цwk> &) iME<ə}1; t̼~L8[ $]A^=j%˿7DWW, SIwΊ 8x[m O?B%Z .7{[pRDNA (vMź>Ia@>UJ>k&t_3SJ{a$T uCU6=Jz 抒aj۔o(nn0y1F^GJw9fUʪErlgp'ryiBf,-r:>?5CV=Y[Q-MngQ4Lxe lP/ C0 Y(eɳ:|C#{V{d**~HȆxc6?R>}*'}̏.cxɇ=P4 F?U;Y ]v-sw;%dR90D/_n|2hEDƙcK;⻚XdM&BDFGknCG"Uy'ֲ?2YtoPU\;R4)u5ld&„ 3 D^:08XJE5n]&L׊JMSu`~ 4 (دxPZEU2vPG?8'`{m.kyWF9݄ sl$m'Om)|ȸrO;N^p Ĕȟ%ccsRJ2)*H2V7X T[ݦ^+s2M߷JP.1|N7o3vTUj*rΦu[b@m}1 ff)`T Il3~:1R(3{c:IT\gAtF/~)ИmS!%(h7)R|Bu|\3nR#4":Qo\(0 )>x cQlrpdLkASZ@FSC}\1/HݦĹ* LОɠɺx觜nT*K֑.v|iEt+IHkBM z!/C%+Ai L>;I҆/KwEaoÕM+ Sk8^6!䧞MAϰ+n~R;&VbTmZڶYeսo(6ڷ"[2[[[!D”\fA4ާB|}jlii!˫M=5Ktꢉ'!AkZZv[R =e"-C)t&K_mHTKwy6(Xp e78#AVЯQ)@fe}F3˙5qh#8 !$4QC5cW ޿QNH+v]F7]H6KC GRZy'1Ni3O= a'=vhā,zs Bp0=4Ff]]Ĵ$'&s z)Gr[ݑf]fEt]-g rMqxndCrML|I  RfX6u"HaJVPRNHBmwȶ[2&++ޟ:/r.6Ssi.7/W+żuO%Z֩&.Uz>>aABJa/İ3 d(FmX P\L%z~mǤؒ*ֹ& T_Y+z痄q|b(W<,AMPQ q @T_Y'ǃ1}+>%U@Qj*(7ma, YI<1tq ^ s}0'm>YN%c[.=B (ϻ⁖}j!k5, o'9̀bʨՆ?,*Q՚vTSC,oiA R_({;۰t,&]{pa /,:+q!]Ø["ѱ  X8d:v ~H |F~JS,s섖#QPy\cT,(^j7=hCm3p+~y%6U{ny&JOiF`"lp\𵫮ChFdzό3h|:5JEr'IrOf^vqUqi5q8KV^9"hm\C: ȡӥJmw]O&VLR !=}cr{ꘑ;^ՠ1{u V0&qF^/T-@q:' #ʼnm@`YT$suz5T"S6Tpv^:<{Yil* F'nc OYn~2 5t8ȘSKίt /(.9>_ ]kx]Wz?C%a:nOp&}Tk}.@r_XD#V[ $ٻd NrV }vH .h1\d0ˢpða 2۫G.iJ&BY\J{Π:ׂ}=?~#R0H2l0ڽbHZQj U% +Pk 1;ֈyг|u/c/kde.)P2PNiUmPs 2h7OZVDf ۹Έ[{ΑF쓬"/^UInؙ[HF'&86i6I7㌔zBX+3Qߣ u&ܽܶaڛ.RF N{yo}^wJAd?wvmm$7!ئ.4 x[okzҰ Jx;o]" (ș1ODV, D;8(s:*y58z)X\|Nܑ % 4 "0 ꄜ-S܄BfSx\ (, W##m UݴUpFκ a2xcVmyc88tNrV- b0x={6 a%ҦW:;*v'E } @򁚊Ϟh GRO)݃tI֞C7# 'Q T3:lXOUSNLnZh.S:.K =cn& 3~йc/x_/[c Hnth-5:kC1~q;TJO$v},ɆO"+!3HF@/y25#Otڠn9OZN87_ p7e=/7_TNj~s~33/]Li`m 7tҭ,l\f =ľ M{AB&-;1FJ 3ljE9*VNn7?V/L(I%<򞆦nɱ]XKHDnD,!SUec~Dr`4[inR.םnEKMi5C{j뚐&fw2"&|p:uQ CXyo5RMTR+QfPLFZƚ ~f;%H"xΛ6X tJ@f.6aAB2hsp~٤zޘ c `[ 9)ś h-EjDINynΰ-аO4*HH_r.]q$ ~$(%BަLuAB< 6 ~Dz=?lzaewLs =r%%[пDҵ=?;r3m7 JP/2/IT]cD[,#֦ꂵҴ.+WCV{ Ob>ni6Jo=(kBMb<QF֢k?M8C~4z*w2q܀<^6g'e-qzZ 6NXt<΋6TjA!g?[ӟ&7Ou;Ī^|tnO^^TIA]wS|-{k.wx-8M|i 4YE˦ @c[ jVta"\" 10d_ {g^kJLvZ#!3qИ1>;n|@jg /hpQc XQ2 p RTD̏Υ&oka%b_&hhTvu점3MU~p(lz264A*:]Pm";=c wL8v1eU-}qS.لU` =vr'зĵ#vN;_!E6퀟zt]~t!?k)FplRvq{wwXJ=%`Lm)hdSi7 )gcba&Iݤtfӄ 2@bH (+Hl>w 籋v;2WB*AJͤަpC?  6ԌɅ|+,coVֈZjEFR5}އxR IOuޕ@Šd*WH*]KB1[ݼS1xU~L3 z/._Iw˼=w[W2.e`j}SbMYuUH$ڠung^&="~e"Z!2Jq0?Ϋ&/,qSȗv?Y>s5RB/VУ O!]01U6(Hxt xmHc#oMxʒXw8f_s!H}WssnX @2t# *ɸOH4T}m+#LKją#5Wgv9'?&sݣ!!p2B8>&ߟg 'uI j~ݴ!\E }; @fx*UyG`gdzؑH Z͖ '8s&但k1k÷O#V^~no`;aX]cր^r[SsK-۽N/~mʄH]@bPaք8ʛS)/%e@--dBP-$prKU@bc`]W%h=@i;{'0Aj'2|0>h':t>꣑r\TG7F0",nQsjLkk]쎚t%z??}X%DwCWZߋ{`'&rrC`uz+|ei8fOu4ezROxo"vk7z=;=xgesS"8rlxf<@׆T y)%d:%4& _lC[ú9p r8q)twC:HIdA;嘮eZW"w6I^/@z"A;_@- R1[/A΅+[fmԷRqje'Yۼ['Q|{)f'n!1K):q12mF`avK0\"`N&/{wx,j +a -Q\Juvry;P Q,ټjI¶6MQ֌K 2ğ >>ȹwr;A48{ 6u8[>b. >v|JxׇxINqN~v胿|>a QA&NRT D^'ohQEbb )r3&D/I):㨨j)-xK& bu!X{c*:e}zr_鵨hh(~鶈tmkJ-jGvPڮt#~8?z\/nkK31+DͅNZD&d3֡*XtlZ@H>r_r믱LQ6ۅ Nz: ˙:X؍;[V> M&2]JlT 6iIڸɗ۳1t4WuDAH$lu=,0{- A9nWzQ AgD}{" m)7i%% _~NLb"ݹL}t:V|,Wd"WeW_R"NzwCp`87jZjzۼT#zcܙ.Lm;'^`X:n(]e65yhCYz;\ƅE{ZaLv? 5P[ ffӔz[Q {n%FM+)É=;crrTInyoN4`PۄIH0՝0Eq-4!- {+Qxcܭ

^Iсg}Z v Yk1|- z>d3.80钞D?`{)ޱ,Xi!G=y5 (]ŎW~AͰ oH`bw=0(˰=l`hh,&~WYUfXźڰL6V1miuz@/˱=\YtS8Lk 6gQ _XIחM 1w= ;٭‚!p8C߄&tV hμ;6*61Km^>'-(&us[T8֝\~BS$I(~*0Ff T#jXvRq=;=Pt߰#HC*Tz$Sė4vn:GET=`7S䅍땖,9 %;`ی?-o5fiwEPN=iJ0KEcF[N9&X .?:o8jг?E$ϋga:9Fh6f\w?ilaw7(@#ra|qA2ЍN#[~N뾘BuTjy3=+)a}7oc KnԻEݘJYHNıU` $݄!ԈiyGWS1]$s۷rTVu8~>e2>s/9 ؄u-uv?9teK'0;ep"w!avbsa&qPX5:nei#9]38L &`R3dP"H@y{u<(VuioRlʑ.CǖbUs 0OmTgq둹Q<-V*m߯NWe=l% J`G"l#@,Fy%ţk.'eQ3}&:_sj[ F"T¢) VЦcfjbdo1Z:pfE6+ ?x=,K0uA8`% B=jE_ēD|P'Cm. T&-E6ƭiƁRe8X{,c(\c% s/w2!>B0z$uZUjRX<[7Sb"UpnӡDX@ONM#ޠd3bae LY9}y%5b #zxsW<྾Or&UC**Xt-f? Ps]9~$C&?gAm"ʂI Rs"o C8fie{-hBw|]79Ơ[sy~˵MufEW\4 6ӇQr-(#!nۮz(`w- 58\w$[_q1j$ Y瓭DPO2Bcpzo1.Y Вs>YfA>\ 9Gr" LV>HI6k}ep)ʮ`ƖZ2\o Snf¬%׸Dy0B^vn7 j:ѭtNb$b'!g&fiTފ@knTl\7nz+ऀ]%]3 w*f6G;A>y%"̨vTWI\}t;yL`P긬VV9ᇩ/n&>aiPos'y_>´ ]NuoQU\E(.o>=poj)=rB}3V넨El&QcX-i[(D&tW<7OjBThNXU7#0!l 8~OM3Idr)nzfy 1t}=9уt_,2Mbur X|ƛ$OE`2 Q]ҋ|Md#k{JHF;kK?9~[Tt-ϥR=Z/,=)kwoiFdUDiQL%%d[tŸ*(}!+-eq`Z5Faޅ9|P(|< J:OE-16Jux#=T3=n) cg" s7oeRx#,Mcr_S=!DhiM͹Jj/cx^YUӯ\>H 7~x\RPjv~$^fjf v]0,GY|<~Q/yTՄJae/+M/W2%Om%+qYQ ̻D)\2Y\`qC"dv`ۢ7J k/l8 jDT/h'F(<z X@&I;h΁ToT_aPiN@#F95&7tg-OSTK=1 ^#3VepqkB+ju=q1z q4~jL\B:>F< ?OδORR+dfĕ}S 3HV3oh ĿiHRLB0 7TMr& mKGS[073T ~J7XAJyG@yaV8G&MX,$mdo~H'囓pU8k՝e{Y= {36]a)`jE2WnG g?59fkǽv+$B6'-cchJ^=$٪u:Q"3M`c 99w TQJHSי {׭9?|=dGCA5(˝iZJ;vX7㮭X>-- ذke*[0N#VrWñF$lI*y:{5ģ+o娲MK]9y.=r&#َ, HWaݰ<[ ˪^& k.`R9 @L1;cV~*\/q]fQcʅZPfzt%m >/B$ c 互W6dqEkT'}~FB'VcVİhwdS93♨ fg%*2e:yu'm1"7TŒ x֩,wxw9R/0MThW!4~0imSY\i<6O%1 Fedgzz_MBxQ§ wa< C݁ `)Q]oHd-lCX%)OL=a{ˢ°e%TF?O݆enic+ŃU(kfX|bTJ/TM&C=OA Mp"D&SQ2>yehge%=NÉxK 'xvIJ`B`M%~DjsLpXFxx{zXy'=ğ ,YuH0ԧBzڞ*qs+܍aF\v8bhk 481rj{^ł`_rf5d16[txp,xB9Ed1cqu}B]~踦&c;%ȹP3?兩nW+Fjo,f̋LkoX\v[:ɧp qE32lmˬMǴkDT4Fcd`O3niGh޶:1QLS+cg9SoJlwit]pMd2\Q_`)*}P ϣr:5Y`%~ĉ{b)NxsD\PԟʱaYJ FGQ"%h<35qDwox3ڋV-kBVBFFV 'Ǥ/mE0u #HtI\|h..C+/u(w-XZW#{J~3k-"q"P27%6_{iP #!$xY+g&G.{dc/bFw)p#!Bh z܊a9Sd"hd8j@jAߣse{oo3d|5aQ յFWǹ)rm)x^ ,婞Ƶ $ښn\ Z[_l|VkaNS9$coc0sFvY{Y_2-l1*Z8x䠾}ʓI':F&ܖ2*ӂVa_ZfJ ]L-s; ~g ŠQ&_O(fnW _ ;HXLb@ {](NZa$t;-X@`tUlk?R h+1ǎ?G6Uإ^.HX-\dw:Z:Sf4Qy.1vn l#mT(>ԆOV8L/{D:R%xhnȴ/;mK0'ӌM'|0˪NjIvQYYʼCߤSe2.ˬkcb|y&W,<ށ.{+WaS5ANnhWo$*04 B?8!zt^|oEiH  rO}A#zrnY @RtvXej(Y?p3Ì9c#{2ڊ)lqƺcTnL1^:{ yj6%h ߩ&Td&Se8;mÙ}E4+,6k籷)HOu kc(v" Bx#^P߆q49]y*nbOÏ|PyRd/cyE3 FcbaZ #Z-+o08!I><׏f?Y9i2鞕!P򣫡@mRܰ"M 1d)sgұUUl tgs ZUFR/_H tQ51C%R XFhvVw9 Fߡ?UNP^ qiije%Ј?/#'($VwʮQ47SdQPø]8n;=y0IŶ~vp^s (&uIkM-IEKiڨ.wP_/L`Y+[r2:Q<8ԉdzZAXbu3JV0-+yɤtٴ솂Gf_Zq3պa?i`=\㊍O _3ou癏b>_|Z iXF '־c$ LqJ$z>_8%I`ؤFՏ->oҏ?nL_Zb(q}$eЉIOvvw)̕Tl>M=ᮽ$EmַMQܷѐowi9lΤe z9#L#s4ip9]r&U1/PϵEQ nf!sEgbz]o[_enқ@N1Y!ulpE\x IuuAt?3jl4 Bף=m؟\RCO{}eŹ@|hR0ó6PliPGOxɄ%.E)N2SkIc45)IP ոvut*wָ,VoM ^A QvMqLHv7&p)X~XCl8[8' N|ȕ vw _8WBbs*@ԡ 0?]X4uN/Y_|;SY2:]QI՜0TКc!!%(20"ZTD!< z'y_;ʧ w6FCo'+ ޯ8\,BPoEHY fy`v1`b{6;yGriXXjmZ˹i@k001Vp tA#%w>Y=01M4D`=7cU~7n (X0K\gG>PxF'X -*}vŘ_L{e&/ ry@6g_G,5a |RA^@yv ۍ³\D[#\=WW£LӃtGjG#Ȓ^|VUgUM{z}WI_DpW[{8h)<[=5zdkf?y$'ncTy9 ;j]1ϰs G",pnrT$1cF(x}1*oDm;YMӱ`8dkZHԾb\[GtYMߌ.R T-нZe|>4^5vlޞ@.%gV^E&׫Z$&qSNb}lQX/;̙{4eQ߼o68\ H=o-Ǻ3na> U,ÃY&o_p}aςEMmf{bȗ`J߁l7kr;){K\>g{rwuS?wT:&q58$w̮J]w/McZ)@\Dd钦T4ɸL> 9Ь*&1q6z^#j6gk^`36Y#{KW} A`S9$X+͊Y-Y5tͪ/pФ!A8˅e5P|UaV5 KVwl ,Q58(dV|MWܙfj\ wiz Ed*@"EPu{x6]%^pMaȷP=a-v;>L'Qwi2v/-z6 8=e0w|0GZ`VOe S/m`F?{.66j;,HyERºA2xNjS|c@1nZ.:F{rt2Yɞ֫?e(q8'ۍceZ7 #{ 9=_*gd_|8έx`#ܤ]YJu?#֬]Wi;[@;0Es/[9phӕ|r vx=a͈E XDA_Zm], MR}ڴ`\Z7^@=ʦzmNGW ݣtYomjhMkTR$NkaeIu|K^c͐ M6,Pxަ"μ#1@R5ޒS"Nϝ\I%ew֓sˆHBYT;ævE@AYm25 痗^~`Bº} Q5&C9G& zNQjUR'{ cւ{5pˈz.>At br;ǯSΰp /^ͳX WX 9Σa9sps$Br%26uz*{ǝ>lu0'F6 iw}0HwC%3\VZѫh"eLѻGf`4g-F6 \Fz:iZ۽M"@#-~@7DܛXCY]uyB12܅7M7;}mW ՛mTx^䎩 9?ŴmhT(8)SqMڤB>){qXs01˓lX MsFD*JF93?rs_ Sz#(Fheu`a86*g-02v&\E0YٮΙIݣU_ ibY@X"5:3az vE>486B >iOA#m2pjP+Rsq}񱽮Tn$T,KD:u3ZB`(>-i+?#QGa4fe9з/d{-7+|(є,žmxct* hKʐA*H`fWxo睙#`'F$25,R߂&v9?7 zB;XbvЯ3S8 =_o-#S;@enю8tT 5^wy"r[4Nc~(ĢY11kAgTafh9c"6p0ڲn9M9jfƽ~#LI)WU@ԺJ tG+ӰJׄ|@'j)1׆FU(j8OY(i PKjρ9#Y($ VqӾxg=E.z [|+7Q֜{$댞5^&4{$(4;CJ!FbpY>S2vpF*!S9TSP_yp8sUi]5KJH;5?H3o5e~HG5$‰XI 칶ccKTE8 ^,QryM*ãI97mNm/,3INQ~"5mpyl1,{; iSuF҇_.x]9rr0tCH Z8KҜfP\;zNǹ(.I. q;7ygJmcrǺn[c\F!YY[.] }A+A(\k .|d&!8hD0NU^ϣwW+ \͠ЌӍ?0)*' ?"NNBȎAmd.tdZiXt́Xu$_@3-z`qZ"P-]b}4sr"mtP۴D4o)wi?Տz#4/#HB ٭4eg ɭD~8?0P,)~*( O(~;C3^fI 1@zNɮ# 2דMorlaaBez&%]oA+-yӮ/Mg߬ jeTc-\^ShUUEC݄hM@<|B&<8LqFdfY JI(%vD*.Pvڥ^Ĝ [pDȠ0^X7Af;@NѰ|4Wr9Uy˄!y 1tMz>%q4w e\K#/sMyt8$=#q;^;}" g!|eo2*͘>[S=h(l>d\ߍfBǔ7m Ȝv1O=<኷[ vQ׿}^>"t)Q[f~yW#8WS-Z%ߙ&@lN6,= Rolgg\iy#XnX0mRPaB~O^' ǁ8 Z'w NgJ4\5yɸxt:C%"3$hO2e%lV,Y tDfY詖Wb+"1ThҸ1[ûYrZl尷BpI2`t5S?$HH-wăp -Z#Bχu}tqCD/Q%hR8N,!Cղyf 'g2$W|Z.lޭɝT )Dyք˿;]}e"`8cՐHRyoL(HW?vFÀNz ]06 l|*{o>oW  1:tM j c?d'Gm?|1zH)'(&O)6P?QxWLqL%SjrR%(2FzS<×fg#.4fXVNWߤb,DcR4ɥQ˅\gvܕBm7z ֻ-AL'8K?2KvSj?V?Wj3C֑B+P|,_"  ؅7C?.S"ɴU(u)f9]^ZUfsLuc^*t;WP\ڒ*8_Q|d"ZlX4ۋsN|vgO15K+{T2!M~c$xNȊ@X\ a_.s `}''y%3e `Px>Ԉ I ":~'S0>+\%$F3J+|s@dbݞ}֬l@OUDH<63A4;cRY˩qtEDk[T'ַ%aZ%[%*$?;y-*U2TP.~%8Ue76[o!65kgQ8B-3}ub ̏1&m\{/rMSAk} ;> =^%_BRHOy':"ǃ4=݁pĞeG/4G:R>9amgn 8,H0xu!.MKk)"xywIՖ@>Ф^&p_Egb<$Dmi~^_-)~&1cjՋ^؛LB&;fz[ɌA&ל|X jBՕADnP_QaQ7Dƛ퐅o*ܐ! dL`[L\gW!"mr|vҺ%뾄eݙ[l˖˵(Qo+3+6T7nϻ>c|thC0rιIB\CY'ONAWJVPoH>ߓHOR@}'Yb?WR#"O3ZhdPX  C1m>0jE,qԭ}=!$Idaz=ɑ cs_>CcQkS1u z LpHYk~[cW"\ j}L:N 5S/c[ToEMUK}/?1i~xl J_{b^ ]_SS,tITq"_<;GjO%5Zրdlo-.sJ)6X oE) cD#z/"1MWӛw T"5%& rc!1gY(7~ ,z͙G!{8rUwd~>jQ?" j*:*$L|`TAP 2. Oq&T|yQJ$˗`!UƛVY-],[гDB>+ DK "1) `\W$.{ԅNvi(MUyO^ϟuH5x@10yMfב㔰[&-j?'zTi 0,^4i[2Fˀd^׋%/XxWtq*ceBFs\1/RoZgJAIr O8}f݄2[qL l(aFK]mtbw0t^l&W=W1&KmZW{~:h;]2/[` >L$!W=Ⱥu$X|ʶ^M80:-~)IX6zgHvVv:x ~Na2[^Xϳow 4cofWۏ /6V[2yMYz|5>]u|oL wHC]_ӸUɖ\;!^uRzs#^9!HlBQ<~`iqA1ɑ9HfR94\)JR6G4~_Yimz0{KdB\)lAP`+MZAc]cZLgi&wJH2<*1EQC&;C B)W*9aq}AIi;&1eECzMbU5ˆ0ꕖogUbϵ8k ]ܤъOt5 %&5֟:$zGQ*s9 wE@i}R3BwON elYy}J7͛U TQt!J*x~TpE=\Ao?6+F貭\%=wV4ޚ~:F};p:XG=xyO@(aҬI%knf՝~YmT _BQ4yPSz 'ng ?!X\P&psd>"4(x*V=t敏[࿜s9$gf7rV%527i4!bh0;^Sش]P)Q/ʝdد7m?6߇ɼj1J*D0q՝Yn(L| f. SKlC#ъ"V>ƟlVjU7 `e aS缟[&-ɯT1o+?cKaEڞYoh5%%;ŒÚ*Nb9(gؑDyjnKdn9|}ڎ:i`2Sd33= yEDB>$S&}2W4opVZd_$M8 (nqEcO)ٍ ]K a-Erv\<>xIHX6ATHPii+'_䏯ʩ}㡘CA'VEPn0vdlK}凚CK'G:˜GhCȞ5Q$vg uL#PW{5/*@ਁLF1Ebqq1<[*ޤԁ6/R{U/_jP9yY%ݲF(a\vF+JdnOkvl!?hY@Z G9RA]:&V{L)0ҝ~+@ኗ&`1 :mz~S8tqq!|[mXꃸ9y5J.d<_?*B, [z G|ȴҭCgI"@ ,z&YYgd~.!\䶧v'7MQ16&PWO]V^T-8r O`n@橢Ssݙ˶1 @V߄}D53=2UYy.'$k!ċ WA)~M"NkΫ @eE'PbYcmOIEҬЗX 8VV3R"2[*c9rFV?KG)K݇hwh 4)ae@&ABL5t JbVW^.d8HS3Z'YAu5*YԽ>6;|Ubf[d/{u:~3CH3#/J TMW(-(@E|IFvƆQQaB2ҲN;ZɬOgX4#IM;kX/z< =S l4)quߖkJ6wfknºc-H@aI엌thes:X=- vGvb#p0ixI0kz\WVuQ+yWLA>>>wū&bVmܶ+?#Yc BݱFe" qs"h_,H>7L C>^Wϖdlש&a6 VVS8 9oІY_XT%F-XK~u"J) pT7`Dk;{ @P4e-b "y F-^ k \MvU7t"WN^3MzA.G\?P@ՇXF5RഉC `!VsK(F2WyJV$t oO #"q9@YVVȝ#1CɆ:oCVL LSѵd h(Kg@pQ(Zה57= !.E+Tr-?2 DŽNL[kU-\U"SCVg)7n@%3Vfr٥8KB\<_B^BKoQ+qZQ@=hZF.r]%${:)c$CEܗ֛;L0}/.q'5pq+t.%a_-^g&z^,UlҦ!PZ`2F0mW<㉱P a\>AOA^&":67 ֡3$Ȳ\H"V?V䊨J1cH,;zgZc\zȦ͊LoIݕ"DV@l.Fx7aI2%>#+aȩ m;?螹DR a/TSoH&$WAkmM9wBN16ʯE} SaPe?YXa$-26 !7bJ 8.K+)H?ޯ͇jؔz7:/U)kM/%y*5$,dY֩ePtU# $;fbc|e,F<.>.q ~5`rAQ?j 7DhŁ5U?H^(Uhrڰj:PQ;βYFHV-)QȻO4  0\R6iPeZ<"X{irR^t+R⋈ގB`. 2FhnVzmV̎8:5g{]SsQsSgTYEM^\X*Y-4ݣ0KԄix숈aq8\zS;=^sۖ] =1W W2O@ _GcC_qN7 3/nuVh KZzrĄ!w)"n]W˪0z\e;hYӅJ͓i`pRGza[Dv~b)b&bRk '#1b 6&9{7WR⏦\Z8wZ/7 SFWV` U~3$~zF5R:&2Bav8qʟ D~"0 4f @ 8U>1 Au&]-\յ~BKFb Pf> z 3{R]#‹ܭێX4s'1duRiȋ1w+`$4[6[0`DM5l{I7M"w JD=0ݜəI$Qu= /,fiXhZ7" JU8N_ Qt V NyiYȵ?W꿀mq֫v }sپ`}faN!n>| !r̮u[7cIJ"B'Z$6[/9_زx"j!'xn_iP_x#.:&hS(+Znzq&Jb03.2KtÍDkWb N5Û`Ai9 NVt5_ա9kN? ?/b;)Nӑ'T^Myԟ_Z)唐,эKq*o7HR:e-96z{0 ̹ޖUJ  7\rkC* {q}4 *@#ChB<#x֬52Xv8!9aի-2$ɚ\:+ס@g(n7kfFML˪&Oc>nbZ<# I< u5?M:.br]ـқdwkqw6s-6%x[:E>7k3@…SwG,?(!ը FC>0éE路_>vc7F ѥALbѣxTİwMˊ] Z 8Kx&uFx4TO }DI\iU4{idCkutq^0Nr"/rsas$ٙOId"HUMN?(o6G[t͹ZV<²OŸٷʎ$bqzI.w$ ڷZb*^bxQLo^ E V0ىl 3H=?Lomޱ=:5L%W!-Y>ͼ"3SV px 14G;2:)P]ghXǡwjTMګaʀޏ n< DUrV6$v$2(d7ݰ.r!v@)]P߬:`oQ^m $%[^2nhM͊Ni60K7ZX8m%6>ƥil[I0ňY$ AqDMκb+S?MCRSLDFG퍐1:خ}S@#ĿU5.UvpLP76''&pH_wdHZ+q :C@r\6E>Ƌh_11"#CHyA싩ЙJ;gx{bN-a 5ﶵ]Y׳Q"͉V jFU$*mSBa1+d Ȳ+z a$nawL@LQe+qA&n-K1Hr0E4=&$~N|6@Cc=Zݘ/QRޚV'_hȽcPQ0F;{o,Ԅ_Ӡ/!շS9Da SS9ՙ$/rczؕ#9ZU*I;G,q ljq\dtKP:=A-A#I؀Mleڛ풲U{u,\Ol4ѯ H_~HpF#A=TxV"'aُHެ9 Ѱ{IYJ]`d Խ@hYI6œGۄ1=dzU뵧P*BLҍ ijJiKn6Ub c\a΋ v\2ml6Sp"'K2'np:MU-HuaRmwmd.np'LnT(.pJ@)yHsf-SQRn8a@?, AV`x\3fa(7y9y, -|$lJ{i C8"^Ng"7$,M~Y\6$썵fĘr(Qw;Ŀϱ&6ٹf3}yЂvUӎ@&|$DMR#5~osv)oE'xѯc7xxnABRy\`>Y781+puzwEPxVУ};g/F Ѧ'Ws+ mǢ*t: ;j'bܧ>k"X[ߚ4oZ:k%Ukeջ!߻f{HtyP(UJ.F',N6hTȰLT؈tEVhH⌇@x{u@FJFAtS'δn&\N:'F@cELs>=&ը\G,lr{ocA>_b҅03,"#w2X64 5\fsK=OGpj|''pVƓYR*89iCDWDSN`gެ=Dò߰ cO7 c@~`.|eLIQ)gs 0/:Wz:Y<8(,1zoQc϶S!5{|/B\TBV9~/֚չF\y‚JP |0xG<L..‚hjnfiԨ#4Kc2YfNu`Fz0jagiRbɾHD^3oɀD "%O).Y4!ɡ7Eomۯ*ՙf17bL֎V |!~f6̘=)ECy!Sta7ZMisO_{GH9KakxAĵ&](R/-{S-vlp`P5b^6""!%$1#~bEAEc:1gDqP ʁWlæW %S&ɏTVH*>V^Tm&SP L R[kr|3UiRdðt c<#O.^kiw׶79YpG 7dFm+h.QAc}8o[NzT(GaSؕx!z9EfshE1=P9hU3shf࿦3Jew7s 瑔{1aaŐWT_YFML=rrٵ4 UԕlE+SZ7rHX$o:r)CSѓ3̪SqfCqYT={>FnJ@Rn8DݞZU08&C0FD%y(|;C:yUy Lʐ5K2X"Lv:s ĖZJtXC^*7'V|d~#Iq>S,| 7uߎ|5"j}htd~|ńb<鮄;hT5^LDTk[?6;E*ƨNR[4MqJeоcc?asL8 Zer[;%XdfT>1PdӟPetٖE t!F \ԅXΞZoV2Nؿ; z8y&S a 6$tGgQ//~VZPrj1ffvEfm`1ۦzJYaXR}dQ1\}P"Ol}%dʁZ_=^#F G odvH\S tn~ݾIﶎ>n"(Ǽ8&0l F0*uaQC87[H~ᜲ-Yiju縨EuKԒxLtĔ()J_JyIVSO 2ֺ/eπI aU[$JBgxMq =@=hG!Jhzrg9YpG.*_zZt|v<&IߩϤF3M4}pr* qtuy(1:#RRы$Fld+DK;Fc L0랟?`>XuBx_XuO\.*=%#?/3 f}6k}3O;viovڇ6nr/( B.yxͤ6hVS_/6ĝE8cgHMI0{Qd2ZV-O TaWt4x|BI`TII"s,Jy4" s'kW p_6KRLAy~^Z{Qq? ^dM,оjhlH>*0/m Wў߬дѸy.{ِcIH_:ayqsKFls_ #|f=O@j ()FWTK /)t:$ =kg'j:eo* }Ƣd3μw2%L|n1%KϮWv¬>\1CgrJB|!sdP+9.:ȤA`Z,j_Qml1m  {uPto:) DzF„hM"}FB0[&ӟ&,ƻlk!P?8]nf +n*V-'T9vgCJɱ|ApM6:"R oVG1I4FϽk$9qU 6mӁam*LjO:"e>FN@s삤Fs(9[h(N>eTeh{T?20vD|)"_ߎmsn0Pخ[F:дp^sQ]NҚT+L25t((:`-fK$$?1w-dW.ܢ? ~kf<{s]V~ |=_H3(Y l⺨ϩ*B7&.1 V>Kf]B`4qd;(6r1dYW`!3ps+Q;LD$55Eia+8,Dɬ "$oo%w1"^Csen آm>UɟJ|-?q)? {B"bop´yqg gA;1\?/,jv|;xXy$|@*\_,Q !VU~qpmi"^n*,:;BO5z*I;Sd{(7&F~Vdl_[\du~#>t7K,[,eiڰɳ2[Ptwd|CMb̙ץ*06!w_"D=J[:Ot٧Uk}Ľ#< E/vv4(U* :u<-d3? r/Vb},eeSSbJ #*(C.B>z+-e\UL1Qș6('TԾɧXqbGp_7{/ ;DM`.Q<7Z!?5{kE8<=蕅/}e>._8g0qZVKŰs\N@*Qx\ L5s%ՇrٷEq-ꭅ:jH2Eө(wwz{9a?r3^$魭.zF+@PBK,{L,߈>ɦSR:ZX[n \CbyS)+o F+N[/C(;_^ %Ȭe])%0de_-l^ҊmLQ[h6>*Z2VU/I4Q2)Dӂɮ6삋87@UWGک:DYЮ9fo42$qAŽe~vzF`H fs @6!HI$oO8|s؝Hs <09{{e];ܙ "eRuXD&yV:L{T1^"WN*r@6"H/JA>ׇ_\ 3t?Cg+/W݌. +LL:9g83K/a4sUxUϠ/ZpEGP2q zo3u]ɔF 0 !KbS@CDQ HGV=x71¨g\sp"vJXDT`z U`ݶآS-bR$U&0R{Č=Sw۬LmH?+un:ڽqYz]1D<4TarfH8`fs`m,W$ciO(FZ,TRw3yZvLJre1!1h'a^UԆ7cI/w;E[a++[(Uv:O7QV_'Hl2DKaUbnh0$K I%2grS"[r=Rsh,9Ҥoh@u2}vD~nRf lµsǺ6cO}A *4Bd=Y?p-GeDnRI3l苡*R|pӳa8~=wݪ̟sL޴u&= *OrҧiDՓSpaBAҊNUHMm@KVz9,C/+qf-*AlWZ\l$~:`_9m`h N&g8;f׀V3o4YB: P"6 ġAK,KtF?byw/I'?2i =De޲SaE֜}gmZ6$*scFDŽ;4fEpS>J:|23Ϋ Vzt , ΚٍIH}ַdy7a;sfצ2xmj>zKG#;awzQA1%?I6{:|d!A 2-e:DK ]%˔)w Y N"f7ʶ-3mR.Ihj䂚`T]c瀦-{^yaKi^n+DKBv_v9+ ]OyR#zN9'>4NiEu~FR`z,þͭM4i6,8^LjWHo?vPj&tF=f>sAJ, WѧV5|? :SgyscK0wp\;zmmߠKu^^9 /QrjZkvq6Sح;rT35Smhڃt Pk '.{I6wuYa7 6PLP{ǹb~v{A /yH1;~JvEEl3g)hc s0`pi̠YWk_,(ܪä)շHHk`0 t~D3w/~,ex0O@:_RLrD"A~/"#*]cjgFa"}Z+s]r4 -PJFWDmB_(V#[o{O5GpJ [l0El*oaw8K, 7VgA2SML_1$S6I&|iE%.dz%>U)OU;c& g@#2GY4;)TwW]i~S5Wo!'G^{DrȟiaKB5\i{: \O-Я$.Ba6:?ѶGPHS7qU WW>4!3YmOj*N%@{AzxX*2 Jgob|{Q5]Fr:ۂn¤~Q. HU(z8Ow<ˋŢr.j_s^C7b+:H-s#ʨOFS&9>ޟ@ѷ,?RD%0iE&7BtOP _nz!R,UDZ?c9EYO3maI\/@( grQ5N<ް di< OtGp/X^pm[7L+|:Yso O߷:(5]x>{|EHߋRΖcC?rnOayQ :Vиc3x .9cW,vP~s~Ife;/2qXRH,Z^Tzglo<}Z!F%'n7¼x /X#Nr$@_|V`>.#oi*k<'NQ@*P"v!pJ/"3[M3sCapP)gXHs@&eBA (|-%2=j9Ѝ Ƭd>Sh͞c PT@TT;BM PH'8ȷLR. j8NtDX'RT6CdMՑբ^Ipɜ$ IpccIq81gD=ES)"΋ȴ^o_)/oS^iJ-~q/ Ahqg7لʙ{eBUQ gSap~4qLZ;̿~4'7 8C=+JLe}[E$$ /OG/>Fi>god>hp|$iăY<nWA6H!M,zzHͲt͗ډ'z³X4h(] sn᰺8?aOuVi (gY&\G66zf=~g.|XqxfU3H= [`_/E.? d͊-I劏N6gi$_ mi`Zxԇ> 4+I^ +."5_4#rSŤEA?.69O9PӀPQB΍~GX!SVpc{uh{3r^*We[b߽jp"NnALQUEzznGOf?U?u? |޵J^d˒wAd'(T_ "F療X O mi|>]<|h8Z%Q"%9e6 #R zQ8+uv T\MHx%mhLFm+ ~^K e?unoTf3D@N}-Ye%YJȮ%3]ʭ͌iS]}RE?RAwdMCh 9Җ˅!xOPqWm_y"wV6EY3tWA9Lb6 {O ٙⱏ/0>qrxnVWXδ!dagYN?4G$Ķ9k3?sb\D "`@>T>obٽK)vX13TĽAv}ƌ>-o.mCUPK2 ASL3z3{|5Р2AGq &VZȥ@L "h+@;"E4%w+B%d&F?'Tz:Pņ7mGXb~Nx5''4IBP +k57Q7%jZ=gZ'\!qn|dM|9@x/LT2h|2HO6& @5K<7`~xYh܇ ߠzy}ѣKg^⶛zm:S ¬1y; )hHI 7mNmY рQu3hoLOTiUJg<+3VFEyj_=FEt{ `ږd$Ŏ%˅۠,0j0Sn$k.n/q0'#+HzxP -@C24511pM3ߡ6VaehMǯyO=(MI9.&;SE!=VP}46}ռ8߿.;QWhW`tgeD)c >(m&@ TQB͝ 2/L%pi6zs-^#mabHDex/-rչK{Ć&`Y>fUذZZ3P v!=ے+ޛO9΢׶EVWX}? $ҐJFH~áSO rV Qm`]QB.sClbֆG"K}'R 7-K[Q8? Mw@4X.+ԟ>/6# c' Ѕ2By?/uid*] qҳg= 0.[JܥJꄀD`n)ҺW/fkW)uP,/"OtkVcp.db,GsGgO :U>bAGKG@-W<8h;ĝ~sRgIa(+S 6*G!wkDv %;<۷hT6m\<18kD:~;3<8U_ǦO#.ni?&P}~hl.Nsa+ne BKt38I:jӮ+5^FaţC [E3fѥY=.fTx"QB%-Qi-utrV<)Zv Ch0$ւ|)C~n |L_ɐ\֏Fǽ}P)>6jpRa J̜}p1><FR^ `v)͊?H2D+_i ~Mo$WF:˘s<O(uATrrv@gu&@3ǟmd'F@PoƢlBnggKyBLI/oL7}։bޔ~exjWP`.(+sL a+2~־vڹ2ڈX*L',#\Cv")uE%i٣=k0,Jt%R / q/sC$h& ~ W*)  3 tbkZF '˖CtN8'v+W G&ZS䦔]-RB\"![\ԭ*ԟL)iK<rfr ԹRh{)oBsO>B{2 % BVH]p~P!]>8J(_NDeJO<6ξ゚E>2$H'p ~6`jV&u:;S5)uXRJ;j䜮c{Ǻ#짌, i?>6.Ae ȶ#`]r)RgGy>7*| }2hjK@:V`sp+X$;knjD˗e%̽xdt*O nsy3$[ûW)>K ?A.bm8+/ݳ&D{8}QJ7Y];cHIocDS5Z7:}XCMC|=z_`'1\fPp`KL)>cxrM"G3NW y x6YA[լWX 8xY%N*R充[\'Xԛ&$XSevӣgF/<}IM$_C$ Jݰ j9p uxS(SzODp0]#BD všžM=80 N(LnPv@=L<131mOyx} R(ӂ}CŽl hdvDb!aw񡿖v/83b&Y'N.4{jp.ޓi!Cq\'ΞXiz2j.BE; EF~ѯ6̈]Z0ΑFwv,ď p3US A A$b{!9dҸ 8q*z Gv|F4K0ډW+"E\GYOAfQ[7/ylˮ[h,{X&KIGݢY.dz=n$,p|R[$۲Dd!p컊d j8'54@{hU%ؘKw(2E޶>ȾDҰ.۽ *$C\õ2e1NQӖTVl-]4ujM=|X;e%?x%|X W[r8<'"3k\$?7</="uDmnLr%>_--ǎ[=8#FgmXAm}<-^p3 8܌:U_ݯhɲڊvFt9[d.u3uU#a9HhnGFY7o4bV smq ,vk1j4+2hnwoXlb%#Y 2'`+Eu]\ ,Jқc;b }Z<%B,(oޜIh(sWhq7Ma1&Me:V]1p@`㲣>~st@FfAc*җ&ҕoF7O`7u%uLj߅ln Y2@)L `ӱ}qG#,inm*BB ,1UZM8iKN__ <0Q%%H9h GFȭLu fyJ//;RePeTDiDcʑD*zX 2oT!?3X|Y.%N˒ĚK~_VP^}2B bJd(CD֕8p5hU<|Pģ~"!XpQ*G씔X:FIRѾwW6i+^zs Wf#^0Xv\3?tۣUhx,X863RYx 2y8:s>"t'+hU\o74]ӑ9u"v^0~ƍZ;քLr#KeFԅ= 5 T;OrTaeĩ%P$+䯸 + mN6CR1-CK3Yު涾|zgR)fq2i!KmMܳ柱ng(_KtFƛ < ؽ 2Z6,y6[o%;';M_j]nT,OAk *}ҹ Yܩ L ?Ew͒v>ĕ"=oT'lb[e#IkJs)KܨIB =^jO7 l0:* cSjH.>\et.|ɗ̨WS#EjuVͣ +ADiųe2Ro0O;7_hkn*moJv xP"[Ζ[ۆ,Z VYa5Ų D%T{m"Ok B=7Zt&$='W3-d_zghhښ%جY7/oT݋ GSv[ ?{qW@(o/qR&gr:s7DzRX4Q*DA]"8K/FwMώޛfj݉v)g'Ӽ)M#3&XO!V'ע刖fv"l衰qQDv;`"Q}Ǹz.l-3{Տ@87G.tèjXPz_ORgtaCaf*k5=rS*[[ùj:) iFjY8Z_vT}w ai90ʤ%@RCowGEk :$ 6s'_#vC&4(kz b7{7Ɏ#tQ¼+/ʄնz݅$ !f666٧ԅ% # b+Xf91_7mkc/$@ffbs@A 0 Z#)yMd-}>=+0w [C7޳|c].Q~GW4T v!IwvÜr?Uze)qά;)~vq9m@ 4)r[eGHoKh'H]6Bꍓ!h`Ѧๆ%#>P $h{۲"n^RTu -jj>}GJyXq^ON ~Hqbk>0<ܞ>u\#@ $LQl{._yb?S֕ϋ]0CF!+9z;qizrENw\w9Sߟ9qFUiՏS!,C#}c&v(Y~g؍jpfL3q.Q,9"NiQŢhzQ[W-I=om"w/Br<\jW8´M%5s/P֭"t<7MU~2c[>b<€VdJjb{_WS/S FBQGcB,_lq2fΑV1ê6㒅%M$$Vb ,EB*S>c2͆3%Cgk[@u5]5,./Zi@X$ Z44*y @f#nΩޞ?SX&gL^p<'kmB.@9DRt.8n{7huή\,B'9,.ZؑTLMDɌ*d9Hgb`KQ#)8*Yi6&}z~TPC+C]opS+N"!okU/@muNp{f;Rd^gR*ϸ~Aj6KPZ[ f޻Q5Aǡ|3* lOk_4tzt[?}'} a/+!@*i΢_M;R5)7L[;#5],`ٷ$ &/>y-Nh_K5,Bx b*zx8Q،^2#ͮ7[p+0H/Iд}(@ltTC|SGsuMz 1f33./J=f{d/ag&܇kѕw ,$v4t/ZQ/ _QZ^aqq;tO8P=>QTt':2,4 K!PdTCᚨnd5{+]6-i `Go*8 W/c>F[1g쌰AB+&)-_G{ͫp{!@*ex1cUN5u6ŗ-uja?;b]0STP mֵ`KK26KzS>HS'4X46pKl۾~콋(:p.SH]O3[G`4_DHӡA<4b +,28}AZ!*Fzaًρ H4GԬ_.7-1G3rYӬ,6^T2A(Bܐ)sCx"A$ai" *J/(kf~H{^4HEF J\t#$OS~eU+7/SԌ'K7p"YŸ"wXq Ml-d>f\rLb_J5x~`u)g핋9E# +gl@tgvWYZ&EqFɏY(l!20] \fF6N, <4w1DUgS;>؞irUlzސgL>򆳘OS 4|YF:QmٲRh,u-lL~_/a^P)=b9;0𨼉Mxf2`qr+B` XRL[A!d+|cҦ{L5xLA4-̠8 kUDu1yY l$&'%Q1f0TxѺ s̓SJFhLkyq61lC\:I MяYqVc춱 ?o&1..Ku/WT,Q71`L$kzs{Άiұs=߫Xt,Crf'ƅEla;"XbI*m r;[ x$6ɴؖ\չƁ.OcvFJ3Jӆlre46$Cm|oDqRiaTQ[d7| >|Ҩ:g_<<>!@ȘWϨ7U^'L?j7k,j#LѬu[3rɚmC Q-ʈ:fE!x.K#>pJ|Bdg˟:+oy}t r dp7IiՏF3O6QTB 2V$T(!E׀h>?/{ŕ5i5<?V &ǧk2a?vNaX~ǤNR 1ic~z{l腽*( ;KH~ $!/ɟ΄{ҙ}+шsczܓuzwIMf'=ne JSNIk*pW+h8GܵRf8F5-jX{RҜ 9E_@2BP9/FLcrhSEYðmǍ%o-QIyV6|O3|Be0KYtj>Ǩ>^s0m_?;u`?Ul! ܲUGi~TI43LU@3/~==?}ҝ= _pXé/}äniC޳}@;}?f_è= H<-xw۬}G //77} d{bw$4O%kI=q\H]f:޶_<q:ҙ (Bo᫝{ ȭfPGX~=^|~vZw~"懖2jfq_AZL]~9!9R Q:yx,Zwlڰ+ ">|'ɍ/ (Gb5"XOCiZr<8_Iɽnojs>ՙOG2$G1!5ka\':z*&XH^EUf5)`dJ*[1#x%V2ő_@ 4flZ|;ŪP5 zM Y; .(uLlO*2ACarN%?*V"D&it4oca;@G:KGdW2y6t<{%YT_DYnnJ):=#=>ŭh<:qrU 4р2E1N:zAmh-$ yy|fp!P& G4 )]⦡ ݿ1Br#ҟRMz[.$klMB뱎xKaQj,ᒈrdP~.Qܗ95W],qCm>;_Ld6>2.j>] zy JsS',y3y rh 3IW6ȏ- j)D02 <D)?o&z}f8QUtuNs2Vh=(>nquc~NSsý%1I+B{$?*Kc_P~4x[Krb)M1z\!?PVw1C k IC9{/̔c<:q϶`ͮH^q`'X!d^۞5OqM$UHt, GPe2DMT$ Z:yB.DF>Z¡J%<[/z"羬V5. @=t1Y> U_y+EľtR$\p}M,J[P xvw{`AWl 6"3]4qjX J횵1z8-f?Vj8id,1L^@}`)xA? Fu1f>qe8,}dFiѤn%0(s`]aGJBçW$,řQw)}e:"LCaɇӔ~JgEDI.v>ACk˔ɔ\zyz9\plH'v#+nlp&>)ا^œn' o)nvݗk|o}^-l2zn- ˻xT2.2faw4hL6יP⼯GyY}/~c sd7i8Wx_s݃FRr%7}R:!B5pb"\ ROT3xﲍ_ZP6ԆQ׍|c<}w3,}IO;OW㟢 +K9*yFFVJ?Q&Hʞ,rj!`VT̒7vi#:KlH0Ť}^ӧ"GyټsSJiwjo԰CɁLIDŽ?ruLePDxzQ'R}H?6b]Dڂg @V2k I\g6}݅X%׋ ?cQwm¬a-#g#w *nX63nW Hp7 e&P4PAک58$(|F;p߀r/L,ʨeF<4H: \m|)ΈP퐘컱v,β 0U*{)׳H=9iH?+7VQXCO/%,Kg${jƩ-X&+r/?4"I?BAre#2S_e ~?(BOf=fooN~՚UQl͎\zw7t]~e~ѤDrT24gj'ߌ.?3;;oL,'ǹOk`yPIꕧFl/ 4.+B>e^ bŽW7 w W]'~7}F;ŪC !Nt}!8ˣ:%!4XA@=0[9ES:WWd0pm/vCS(bM{Oj"f9]9-?'PF:ʤ*!7A7)@-3@/bA SVﮑDjA$|a( ֞'d{b{ఄD%f!N0dR`j(˦'s{mt!X9BЪm biٗ8qFg66nBlСkqqkZQy]U{ +Pe AS'MbZA>:Ixtf˗Hs߬~TL.VMƔbK1AP{RT[1wDYVĐh>|^]+`Or䙙,`yMYI&h&PǍ(%^ol0VKޒ>/C]xa`M=di%șf唫h3\oZ"8@$2>ὸ()Č37CȲAT̔S;&s*CW]bm%Qh8-V܎Պ5}~LCu?̆m[@NuCHȔQ%*eW=K`Lz9Š"}B%g7-mj0>kr|6$&љF4 `mÐ~ryvUDHΨo;„sҹGЏ+`R_2F:fÆtoMrɼ~'f1IR:wc6KUc@9(;GGݙeIdž5'Vl:Nl$T{/+ @dzKxG>g*9l1Z'5 ھLd!1[ŀxr<"B[V]0DkJ27r|DL8Ğ[t[UؐR,)˞gB!ޱɽy)&(s`Kiu. ?kαF%Ux]4Y3QD;B`ѵ(ovs| ]nm^) |sq\V4Öngu[нO~bU#zNGu,ィ&O!{kcUա8P mB0}Y)>\PU"^4 xVTeEb.8Wb\>_^F'EHBj/HP{S&vJ}A cMjnTd7;:l#M !_K` lH Z/j;K(GШ:!RE[E,k24eK[Ŗ:1):黯N W/L?6aŽn%5B-.Si{Dk-o_it@4Vt~)rJuA)Aݷ3rc&CTE;#Xʲ5]R"LݨN-N$X+*Wc5nڣɤ,GNWɉ8-T_^[5 igG/j6= 4Lqiǣ/mNU<GU[Lyr=seD($YŒy?d5k_wMT]'f0xP`BTiW`ЉOCOfyWGn pIJ4 ܟ;b,@%7[PZGCq{>*,-v;(Űx߉ųF(> ./Aڠi=ғU r[K!Yaxc$`a32KcB ]B9bE2V:M=x1MC#Kr4_dd@YH`G?Ayd8kk҃϶Q1u3LPTlُ Zh t>煱S$lـ-Mܣ͹>*rcw:車;L>Da_MOx›+2 vPR#HahGhUJ׼<,yK$~>g M-1Q¨"Pw=TMV o6v4At6uhk>nid@h,;aY3ccy5, vso!ڄQ#.#q6W8>2Xt$ Hٽ $T^l ^3ּPTpj(ꆼT4]g!܋*` Y&W07|TΙ>0E|7m/R]4;tO[x<$5Gpζ ^5G!,cvKRD2 *d3iՃSnx&2n*㾷X`ܓ^^/W/X.`,Dm5FOJBd{vAuILV#6°ةXֳ'}iL/x_DPG,hW^SAY C=Ym+ ,(BSGg|_4Ht89,Fvm!6#H/S0ۄupᝡHє=Klw\AJďi=vWcDGPH3I ,FfX%VE>sLzI]m:G`v $ipIs/S=[Ϲ%})a!I(!jtF<9ٜE}yi;YZpa 8pD?HcT < NRYVQ\8=!VbP(8ܩBBDye=Sq}mtw|o#SF/Pox,?1}Cz59|3ܵ6wOKUa($Viha40Jy貈JD`YO5TM^WΆRdC@R L9f³>poe,}NуyydJp;Zg(z, g_VC<}dF[Ta? hukOIYٍ˺w3-c}ХX\]EHFL> 7jF yO5Atse9\?k'ޗnvRJ q`e9Fn\O#͍P!IZԔP=s5pl ia6]ncBI}=YqF]ʁ^', 2hl=+̗=ڂ)`?Paax1= t6NO19<2ڸDqa)Og&WZR_e5|Nlco;}[Prg1cPr<G`ocpw#&ll8B10(^84;}*A$M=OA5ɾrpgR$?yНy:P6Mu,+qݷ+o:d bD?@e BnH吰Dqja(X>z]-$Tt娼G}/W'+E]˽ V,CC zXXt(޴Br}w"[¥z8)T5d4ZҀ-7,PTGIJ)w%_x ¸zb#R  :YȪ^~~Q|*ß`eV&B߂3bc_wgfk2so>6%o:7!nT?->Ҹlھ246hZ"Y M۩žVт/Ib*1;@f$6}hKvPtu')˾c=Wjɻ|/f2['Z[A& W7=93H{K"}{hrE a) GdC şDFQȮ{кJ .UFOiK`!Dؕ{)FBNAC@MtwcMF<@+I5 G 2a4jhCT#ϝm7\Pƚ3E-cJ|GuDϠ3Jh AKp|@*S<\"\RWoxzS&ML# 4Y[ި(dIj{qviuLtFnn_!2d)rnpN4+>1]+W3T?MztjRCWҲ b0-ڕCRE4Lf)ičГbί&ЩEKjɜW%E舿9ڔ:%N ;a^F¯S*!C8DOŅHm>#)! $? -2NVmjJ` U=fMUZɂ :C{[0)Zs-jsW~ ϭ"*],c*ӈ:n>~6Tq+lJSel+6ͪF$K| E-^9I6PT oάIgW:oS;8:]bA/d9_Jwv?`)>) >v;M%;(dK2])kB#ů.$v}cKJ`+v3ϗ9s K"+QW| U<ĭVҿzT#TaKŸQj RpɖtX2Q>A%>z1WIڝ|^dy, Ǐцڗ25 @'u+=s`7n.i J5Ȭvm?swnku'Nj6H!" ZS֕0=U,2qFA.()/V`t!{0t1[Xm':j{ !k$J]['vAC35Iz^0K_fֳLC *i-O1pAЫtUzzzT&sg&9GSu`dM^ ;̝AMY=KG֖kֽ,=TKؘqEhhb/yan?o*gF}q$8Pݖxm*J!e*JFbZXlWWn`,?LѬ>θ(Şe(sKȉ5F=6x'HhE`7}'oz36In0f*z;c+~&%c[g9zbRbWA|sax>,7*$صaalJOu|ӓf ^*Sz&{0c-H8kS`*"K.ݧ,YA cNpp-;|lX @qb"ɂl*y6IK. m$)ҍW!_ʫ\~nWkuhҵt[o_%jӍ=բaB'Z0hO`xQ[qD"is GgQN/GZk#%&L5}oU@2ٸ`)bلJ$mڹ|$9[! *Ed^2ƓVZOPwKdG>CX2"5dc!jP!7qи5涒@,I%уuAI@ZT&V0#Oळ!Aݞ~&fJi16KT-Yj#ǩ v墻 `#"̏בGpa2쒒M>Z)gSN[E&'5+_e;ofV9 '6[,,)vv_Aƀl.n4CVW۰̈́mђRD>OniM\Kfhx):0c0 iq;}ikI $Дbt`LŃk X$BN@D$'X&7vmlؓFl%tb)U'$,nyJEs_ӱwp_r(L9U0Ǚ=Yq:)?#*;O?r&]*bl.33vH<SR& o6EϮnެR|O<ۼ=(< }hG7l飰H[N +{Т!أ~^G?Is\EJ4h\{39ֶ_'%`|"e> fQo5`@&jW\E.xkcRl5vsJ־u>C%q_W"Ԃțp`ڦ')@e9<()kL{:< 9}$h.sL+W>APٚPmPndOFR ]v_ GH|raq/,:^Ǭ4V 5dP .$ >JM݃;0H)c\:V7,w½wzH$LXyzs0k=({CL+|z.s@XPgv#ҐO]& u1ҫ1V$DY5;ٛxhdzyB2 [{O9TL#0O0[<]=ޚ% ÌBqhkտѧ%pG m:HAmoE.*!x:tǺu"z:b35tA>W@7qPW2J̠l8"wX+u=fǛ3.ϳ9Yb0a%>(؈g,ګT~'ĞDFLq8|Sе2 mz&W=L#F]G󮘵^9H~O\y=MܼUƘljp¹ʘgde ƺ7*6,hQAqa>A?Xn1@}@o#h"`˜;Bٶ=ʞlXFDzD"=7pMb@顢ٹ['!BMi VQU0j^aTsEU 0}o:* r>dndU$*W hiu p e8xz!ƞm١o[zIAz˒ڔs =,EvrI,|(N.jTn}H 1Noe۵@??.c27,x2~1פˁB ۹_.ikDAeilZ5>Ƿ]r4xVȆHbTm3#)gTS}{r`1)j5hф۸lY$K PIXYQ|DMN-5lfDu)nT֋%< Ȅ:r^Iu[[k6_czJT8HZyO5wÂwϟ g>S6(2O낕Z9()›R~Hm>rcI):]HwpuY2D99tWr7e*ޥ0X)۸ [gE5+VMY&dgG${;֥XJ&P rn%M1WK:I?/}J8Ac|Fn\ss YY}N1e^ KO'=AqЛ/(>?v[9= OBN}[86M0|9~XҀOoN;5}7^}:1jTfSMXَuC^tFw'?új'nnEfpB3ZFv#?4N+gdO5>U{Z,sRéZ}$@sΓYX#.fl)#[{}(n*99:BUvuA `ꖵsHnw #^U 2ԏs7oؼݡ)?"Cy|EmI(yQBX~99ͮ Ig\*Vvj:+% R."f*8Z&ljևm8U}ac 9'ɿP%~Pȟx!~_pJ0YmX(:G/?!y? 7+ o}׭ljB,6Ќ|_U5A9I&&t)y;Uy69VsUQjЊB# 9: #I&1)5za//CnI-dN 9Ed_^0u2v%9elI[&lľx(>ᥢm6%O}S@W] GH397p"C׆J=supkI]]c(q$2yS_%yծe!jtw %!T. v$V禎zIDU)}~%%k8( D-ijC}hr-UGSivDk]ɪSq`śAX'3;?TC97#]BAϚWzg҂hPwXm8XVWk榜*@1u"I1{p#PԶUI;i8IRy~GUZBu`eW҉v໑B<qi7 螣 {hu~csBq2l/`aC!ë:(B҄uײ\ ?'ZqA@΀lVԺΗn0tU Mm`ę R~XYN~CEXo}L XA/si_~X+81lR6Vj?+CNn0c7zw?/xM!Ӷo1jHƤ\~juEwT^"64^{|sջ!ގPcXv) cDSQ4?%4_}DXm -xIڐ"7 k_Z dA$GH[a=q-S 8}lO[@w7M\2RZWq՗25v05d>(JAq3䓡Hq"Qf9󆠺 L俑_gn\sY2͵:]; ;cdUEBQSli+o L"J 0пA.4ҷ+X}2Ѷ M;cL3Lj˫ŧFRahn蘝p@\p,oRBx*\m5 ]w5lK6Ē3H=nGNp&\u Rd JdDpNo2?QV ^*:Kj WL.6bPp [Rw+3~Zww9C&a otOkgtdcdS|ĽbN.)(5 'ܬ;Z9S䟶6r03<٬[>pko8ZC2xYgDDDT@/)E]h85F{DpRr>qjrfmt4ar%9Kj4Y?AuAX[kkp-*Һ=CO5_2KQ2ͭ4OU/\Rh,]¤>-Zh PCőNbyT {cXnk{ý(VT6d87Vdu)> @g)Ksg |kƱۖ"'b͑Mw#! OGވIUzٹ?nKI򉪕ΐb'0B #!Ს9u%ѐᆷ9y\cv\ҟjh΄z2`_8n(t /c50:Z0 QG:3b3/;Ƅ̈́[vrz6wCIv =j:RςP@r}luP pބ= z6h~ !7] UTEe8r@|[?.wSF{մ?dn̈:1g!/%ž1ti)ϯիS^Or'.vM5Pn$;`>Xg{:LL1]_ 3.OւAK &SFƓaRDhVSZ J ې/ߘ-NROjʗCo;ܳnñ`RKN֙7QmvJsN{&&MeX2Bo?B]{执U`N!dcўm9$,6$B:֏PYfԖNl-i\=U[(̀^ƍFkGL:"“)UZư$06XZS.;tWrVv5,Fi^1P#^vKĒӟJjL bs4h$Hum/=,#@ԬpL&:y$y/"p*1m-G>{{ۿľ9H#]F΂`Ǫ&r*n Y1 xq"nrLb=HA11&*Lxf[ǜF:ȏ7x H#m2Lt{ZBM_xk)$P]Pގd хG 䤦Ϛ%&`X]4NFk -,xYdg5x2OY^ӕPoPbYH#j)Ʉ xhBU&wz5 G# τNeꇓ 6>խȖuMt*Z k3 QH<%>5 zqy)2Ru(N1d\&6R , QH>ճdJD@'ܻXMD!7 #.\w207l-{h=i'A˵3w3]hWbPSԒd@ˈ^TUiۊ͘BeZI7rbE*cq}~c:U}&Hj"0|TKtC{J{ 9dnDeHjrm'^$l6/^w}x[RH=e$]hr+D۷ `!YBTOakLc}Ry(GjY5:)}'v$MX)@@YQj8&ˮTO+M'6s.Qrњf)Ir|\b–,gCl}<6q6d4N_J2¯t^8NWr,B/ֵ{ h˦YM|3Sd}.Udk'HT/-}2^"R`L+ dń j[*^VEmAM o hʣ&Q1);,]'b!_Ѷ=.ne \ҟXP$2yzEGA|gX8>* 醌,)w8ˇE6^byi{fyeOqNMjkӡF ~7Y0}}2[YAYou2%tUdzO3#Ғla%|ӛB䦋oɯ-^hֵh4|Z&iI)\-6dTK2{iCix(n!;o/_W6xdJwy-!~jyjzPf:Ylt}rnK_H#T^Ogj&|#)W"&wFf)\e8$NrFܟH@<®0{vʣpF'Ŏ DB`/HA0(Žn|[5F>}|IH-3ξplvidX)WN6f +9D&q&0 iXCf=s򔍀|\sYC\#N4UN!m#.A1iu$E*0$YMX ehNe"բn1*|[[MfvH̛7k.,LJً!erPZ:_ :e=:t`^EàK-7,w"@%;.Αg2Q))Rq)! '+s \v±ew )$Jk`(n1e6oл8@סEw:2u|3ši)lي fSMyr$eMw}VJ hT>xU!)}>7'XD1fj!AdnrxtL Gޏ=cЭL|m 4 w8܊p>OXŮl&2&Iuҩ8m:GhНVזTv]x0Wch7޽N1/у<,;=XȞ…ZG8T>!kw)'Hgd&!L]vHξ:p;RÒ| ^4(9#L[̛+f1OuGEwwBׁ涑+I=V $H+jKA@ԜKvy854̈́.ߡc:4e33 ξ] {' ֊` .pƑi-O3ٙ b,!%H9GN4YHrWSIṚPh3ȀQȥyrۥZvT'eiը Ror+ S$Ko n mAeo1;pW ":%M~XCKr̻I0MKR8B׊J[-3<#6yY5,l\QSf>IJ.4@0;Ysaft,G1TFP2{בEKD_D z5v[z3629{!p3TTShXzd>#'/3"٧c1FtFYk sih&y-8E,P8wLeJRpeh78ܕKq 6;BІ[n `ݭW|om YxְkbiTJkMe(g,IJOFEXc=]0h$ox|jPֳ`)iúDh3eCMz:h6:G{vhzqXzWIUX%rV"tEN̺>89jA`/sRttGݭ!X4'`F.Rn1 1t*ڋ\?0 0;? E3l-27Y߂G29]:>;{[?J4;h;$V0UwrD;wS|:(Ig 'Y 3a7[|O+YO&]uhH0!8Jl#7jYcyNRuHҦnݔDidPY%jh r2tI@@_&xP-;r,s X0@d5hhYӦޔԔVOԖ4A8wS,#"wVYIǔ "'NObvA@Yo b&K#~rr).?j) άD:Q M`:˨iϲg+J9:!-!codkV…L`FqFrȠiN=9!ӋUG>"liЋSe\c 3N'~Wh&=uI75VLBr:h; L̟SJsۑDryEC|qWu IK?q{V4#dZAfhȑ4&FMaWy3q|X[Fjz]b?9? ]o>_O->9U4h59#I ;cZ OiSSг#1Rg[bI~7D}P&m?N&%[˧Y9dH>*q-3sEcV{%ͼkw j5,t=/ wqhV2YUNbvѕwnYKcʫ^;oE\t_R#P÷[]Hf/Q^y6Kd:x\n@N9pJaFwtU ~'N=䍝ˬwt]ɺM |+$9V)Î_3޾ ^_k@X̬ k\TUnH ]E?x`͑ΩtN5G8|ϭM},D6";IA5(z1.;R9>'%qcTrBUѫez\=8)?1cK3hZU@20I#J_@?^ XY]5O]T4]W%տm)=n6py,#^~F0y;Ub+*쮺NT!#+E\^N Fn;Sqe4Lx5+l YOO~V̏@R5w0ӯ Z .6|)ߺXvp䵜%_Uy/ֶe`> '[:] [R5Zɸ'MCZl"-it39zS1GeIn[GQ=]Tw!H^oy,l"!W !ٸ)w~ a`?ysx"l'O,"2#Ş*:q0.1²88\`! ^ܢ@K tKYv@cr0t$2j4asgE+FTBC`K _ʨ(Y/XT2ݿ2K.#P r'rn;63N}<šӈXe|+8?@o%tT9gӖZ~fXCQ=j $%:ZsRe o.L_ AYHXZb?Y 7 ܱ\5$^,1ڠFxPV7wBA[3gY#ʔzEhd1Y9K|:sL*m6ʙab9LV>iQU 8/ 50~c+3kxq+sn!⣊m@/oA &߀2>{/Lgő1O2{AeŸԊV,5JbRU\X"~DNl^]=mxɜF|uSbAOEN̗}\"Ss?UG33$F <B;LB?5;G(pNx;:ͧAUz0x8{]*^a n~jH7#I"sSVjl&GE "/uA硽(Mߒb'\ck?f;Wx kW9M65} Ĩ]^]gT:k }Zoiۇ+]Uk'Rr"̏2ѹ}Lڱg=#Ƒ`rZĵ[C< aB?l?'C8eyCF* 7K 3[ ya5&dH3: Sc(OiU4QD+T$WQmL|_N>Y V^˼VehƓ<#:̈1LL$8j/ DH`X-J hSӘDxOfaBDλxByI]13aU̬RsaOd ?;)5I` FלmLr<SPs_h" GC7Zۆ,qMˈ<A ڗ^m\-4 ႮhDq$ƹPh (.ځJ\| Gr ͯZn_J'7܃ۆ. J5\ )u$Oە.ԙ%# [(qq| 7y,y5;L>,Sa<3<ѐﴃ`irXn5jRģ|ҖE/ XI]f&Da@@jŴ/ uK|~d\ynv8 68#4| -fRQv5xHqBlp7++D$P>5/a nS}\=Nv|Nc(  K'{D]fg I߆6&t5Zcl] s  XR*Rgz:i͊چS˞a5*Bsm嵗,,ZQBi)|9T2j@gs|8+)~ l*DNfJ$`tӪTiH[͵0p#6V6}3T`A+2c2(R0C5zyorgH>Qs]ޤ "a'k/Q{m+im-X4`IEz]L@D?hf!뜍&YBr ocF&?vAN |$>c"y$Cevb)nv֝"0spXlv5pD5}]&26/+ =XnC):kY5Lyq{ݜ+ ztDm͋H*K3֭ȉtXUDM,L AGAy$XǮ϶- D`o] itl m˂rK˪LlC[w gxI$AxC GJ84t5+ 'a=}A{l\$-;4CzuFX(aK:>~zb֘g/+Ije*s:!3v8JIGʽtzG$C_=VmvbMQ"Ɉ^'\bG[WY%n^|~x _pdN`?'?̅6,Q)sZAF6sZN_m> ĪVsx›nWY)*.UaD!,Z$j$P8j66tŴKYx^OSD)RJhV~KF>=}+LҧډB υx ,%J };48`ɏ(&sЭ^bѰ[OG;ÂM[g1YF7#R y)h0ë-3xI_ 9yk52 ӛgmK 4]IܧyLYfzYAgH}x~2=0()%.6$U72ƴy30=wdi$4 '#v2zgI#d]nڎ]ܥ0rkx١Oh%${uD`>@B>58_UfͩU$uwTAEP|/EO^iFupxZUY46mS 9*1DHa\ 3x)(|LE?k7impx* 3"Fej [bDUX],Oo* 1=ۋImi_x'\)&(N^WsWk'?ӿ#.q@9ח Iz}ǢeP>Od4Kͯ{) DU"=`Zs^6WKLwXʵ'?`s_aaa %VAݾYko& pxڌYHZ3?S U BHda9dT_SA08&}d?#aB+ s6񢋓!_0?2EԊ++rkBg Ɵ>]/p` :a=p,㈉:TqFm Nݫ9sp7Y9qIJCEbe#Ơꛅ$`3*?t Q" jݨ'}LhL\g4g ݃0%3]e +^CqC` )0->S:l,@'$+LL3mgE믫q#XO^ﷻ1i >,\V#H(Vi\AOnW5yUbiXJ΂j9!|}}oaw?)*YݞRv[m<ޱО7$Neӊ+tΠt\JxԦ_Y5@%)n?H<ԢOn|򉙃A&rv}J-nQ'20!nTςk?1Ie(`]QQ̘K,V/Qlg7:VQs.c&BOp * u}۠ٺ7M1" g_FɃ/gj Da R!Gjϴ!o2}uMOD˓B)ۛ7%Sn_7T,&jr&$l-WyoIE'|$CxQ9x!d! S\HFd92a'.cu2~Gd@}V͑ `E>kt2*ss$}]zJ''㓖O)\TĘ4.FsO&ZJ|SSD̃~>bPYA-S%c,V8*1 &a 0iG&G<'mB]|o}}DY22)/HoFIfTCX?dXf&P U#:d,(ī{ a]^le*W\e&~ &̏_gYS:G2*T @ԄuߏE $3F!u4&Or>q8l7QN{n։}c9ȤkL$Y}ا)IpC,UY?N7bDT~;o~Jî{Z@fMT->p{'5Z@#6)-X"/pJwrđٶ" Ek)yIk }N? ohٹπFLO vs򿙃]b3kNɪ kWǎUP/g;ҾVƕ{2BGU~[IS'm (Fmr11/N ouRLou2nGxAij ׇ+>P ZaD+7O+XD{SR AD+^@mz#u뽓ij} ~t,mmCWJ9׍F:i"b<}a.]ִ[ ҫUe:}JcD:2# V 0 rqk!{ޖP2ƞC0)iЗ52\u#ߵю޽\MyLOpZxEߢ9&:SOv`&f!41ϯwxQT3*| RKnu-rHsզR'"Hҏ/-#hLix&`= <:2Mt`0IǀՌ׿]*jYfLM\|Ocm4 gcIa}ષtCo>vGz8]oIvò+hVAPa"s*LnO3FtDLXӾ= 6n"m]qt %Ԛ@,v4.]oKF1(qx;{v<[Z0/bH$#EDU֒Yʛ1p*d&i@F+fLqc{{*d;J_dVPۖ΄ ˫' N\Q"=j1@"Dn3 l`hpXɤta{b - .6*jeN;5^!ƅA"";]賉) I&t$jC. HD")ߓ B{5bj>:)hd%j/`D fFRMȊc>!b1Bּ P / ~>[n[ab"AnB e" 8<Rr0a'7Uk*ռKY66'_TսS@I4YaY !\^U0SE:-M<7*)"He"QaE^ z8SjpǨzI5A[q o'✐ .5˯Dc/?:e #s꺨qBiv.(2UO㉱xK:p[y:b"qS8tcG]oU  AQ %CzFJK_1^/L_.M k";PE9q,oϖjnv=^v ʖ%P$Oަ8$KD/0q`ൽ)8y3.3/j%,?_Bc P`5 E88յR3%R6bL۳L `y!4YF'Zc۷},[n7vطd*yst_=;L\m5Jk4pBbJ7˻¡>l9`23A|;v! e0UJIce * 1Z>ri866\ -=]V'|%k(tME miLg"< DTi:Gs`3uzʥ@S]ծLoŇqe0)4:U h]Z7 ;R:=.mVB[a'"ADG/-" fKʏXib Kp&3!Ʈ 5%^Z'>@9@k~\ZS+., /|f wXөpd 3vM8U[mWBs^ԧ+@bDIZKV$(Y7ȹd3/qMK rorϸ&vǮ̐c ai`vH L'HQ.ݑ-OF4),Q"**ݿd+r<-:$~{ ui6dAhUkkK,t+ow懭@7%jSᤔn)lӴf4z]o'mhZD4RQ}၊7(3,6*M`cez)߰cLYI]C!geDv3؟APvqCQCGJ/riڻ)oV`5K  aRhd-h^?f6Ԥ\HrFevKRWCjͥ0!\K EW[A/|"َlZAYnl/i2wu 5,JW<zVD_I&9A|V)ER|伔{"W~7R.&?7U8`app _A1 @G-m':߇erW8CLx)z:i$PSp7P6}A1T 3'CW,uεe/XA=7ETTV'Bi"ф4Z5nj%PL`oˀ̮ɂ}5,B4ɖh$1E# VMYw/ZP?%Eձ̣pYpR}4g ;'`g`G~<=P[ <?LCV%6G{dy2AD3>H3o-3 >l.A6 k ʴh &3bZIc`Wr\P'DARE o8NHRѴIuwM]v=1ICaIXWH |5c lOf4ZyG jo`ns/-^ k؊FX-0 Ö4"} 42؄rpjMI?\.Z@)W 7fh݀$I)$@2`Mmv8]c ѳ]JK};2$ J~gDoi=ĸ]ٲp!UԶuUQo=[iT!J,aޣ.FrՌe)ސ. 0G޻]Ɇkjfs+a͟{pP.e f[<əzUݦ'V²R<ˊ2wdE c ƩbG* jL8 fC\ئ_'fXS[ʺȪޓ Tw9`Tz!w$2) cpdKLWjӰvbɥ[O_~gN$&Qe)بLy2n"N FyL־{HΪ30IP{lYh=iai4H M ^wR^%nl b8"d'k;]I?6?T{*D.Hiwf MxDS}|̈pP-򄮯I(hlf~\s'?5k/((<ɻĚǢ`LK5)vBde@ZBӺyjK/fF@4:g]ڸCC8Hs o| =%A-8X e+e;¯OH;V!7*^=,[C|Ropam_E|K&yπa:3_Uo;QZ[`6t.je~Hvrٺ_,\Ch54)O_<=3(=`{2eo3TE6k2( DݐCt1oTiś^Kp,#? wa;Ef|T!f 5BzOnB֢;%>KLq2:eϘ+f%2p'gwpؓgX>5L+c~-|հ (}$Wu}1$!;TfWE:![|y}9lxb9ox"Y*#[m17qPK?t{ZEd3%4>~y$U܉MIZTHsQd"Kdx[>YCg.I#l熄PoĴ'0 sUjJ 4iP Z.h$27߇XkG;Iɥ$|f") W/ANB };-V+n=;QH]aﮭz tB-3`Xs\/SE%ƥITuhŽh@(SU(}-ciȬؒE%2ϥ)d/kaK^T&%jG/cm9CֱVт%>AaB{'rHǪPFS7#& ud[hj Us$c6 {b7* %Ils$ŏ[FQ;3.gG <)S'{ {i-+$5&"bzXNs`R*Ro_nng4]0'+B};sbd zみ V'|*z;fBWPkWA:?0ue6~s:|p%ع&,#POThҗ }(y5֣>+lΔtsp'Fw E̸rr)G~ wЯ!uf*F@=D2=X}wVa5g 1lIy(9MaSJfB:|B}v|d>)usKamU ]#IkǍlփ5%U;]3dwv9 /M`#s${~qPI= 6Yb"_R d/Svz-xw9@!GYYn=%[1>BҠ?t^I 'jK5{4urP(c# & ݅6)+)h?"*SÕojxfQF 7APolؚ\[S$UZ@|K\!Cq􁓷c_<^1nϐPbm5KUv`14AuC+ (b+t:k҂8Y;v2 |d_FOzpdkoEyKJ*&'#?po8QL:0SBsG{?G}&iʩxä]ͩԮu?)d!) IaRnw 9fWgӍku+7?*Hf ګ#yKOScZqiRufזW; 7(\w[3 ȡWq}K nr%(iI6>krQz'Ҍ+@y7`~y.*)/YK?hÉ3BPCsВ5``u8 ͜'A]J %tU[ i>q^dJױ>B9VI[¼|*NLxn٦gLja 138Kx*B ou_¨\XО5V {n\0 cŪOqM7 åeWIYlj\`ċ^jX w#q|d·V&|8D/[3xn/BY~yaB7$Gl߂u2ȏ)0 xqE[GFʡ_ 3."!`A|52$u"|z!Z _ $*-QX 8TtkA_h_c5&'v odwd@.0l ^fKe&@?qr:S&, [Bvq{a_us0]mO7ϕ|U-fZ*n܃ARيUMnp$ZJ%sT0L;N!;+f>TbLg=%; y ~kԕIy:>`(tֽԟ@ٸҞu8},wsOYMk/9HkD5ܹp <ǛH:c`J'6MVIaT Wξ6:!$$eUvPuJ,ߠ̝zխV ea& v|?Y5 &:J7$ }lWi.C&rMSL:OlbyMZd[O`s?d;Z'cGK`V\B^}LLzA2-o P9Ȼ7HmwV$V.fY)G9oDLƦ!"& N[Zk^*u&L 9(l.\~cjLz( A[mfc: it=to 5uYq'"|0T!ɊN:OH^;4zمb)KovHjj&ةVapχJzܺXPKQCuJXKFC7ιݑfv4GU&؟Bc?$3o.UDŴV|5,nUd?!U ]H ޫFIQvb<'e^uK tgNg mtą`oF?,E$ Ym/@suc qDg3Gɇe q0 'ek `ߐvk{:0#q+@ÎHkP0h _X<38b#xugE)u9/8N5LlC@HKy.?AW#Cd~]D\=_׍E=./aDNĄe̍$AqWg֙|H7j0jP^:o$j[Ԇ;+Kƹͬa\oSx\u6:MoLVckܤƐܜ'L{n}qzL7>&j8&^r"3UTzAs$lKxxTIIKx' zqWIS!*O r|=ɢ}262xn3~)10rfyQU{v]{}T'Eڻ8Nsw 9L7k]3?}9ьҸ1k85л;E-o 3 c7FnӨm`dA<i؆G6Z?de\E, )˸ ZM^5\r4Ht \T%~瑔=;9.aDqf{Bxtф_vE𻠑BN_MQ5`ЪQ2DGIqF?7|ynHkPChBevڌv ʈoO%AnN؎i+=S4OkȲ:K8xə G D<#|qX@&pm ͔̊7XSZTiT1/>դڬ1`S}$efFLv&bmHA9~w,Q!~S F7 ,ZIw)Pr-. řs|[ LT9jҨ,#TnVڇ& (¤š1K2Og:Keʓ~C":0Q>x8155#Yђ)+r2$D6r{ ہpagPMux BuwЍdLQۙMlD R')Qޭvrc$r87ϔ{/$aY#KetQ+n]5 PzO澐rO䏫ט #"rҘkE˓Sx۶SupW쭭N(^Pggu-2~ԃؾ:a`P ]" ġd_26[Uc.68#%2cqAg2IƉ]2v TS:Də5{ zq숧jdZh&r0;¬enqL?oܰ ؜+^ x a/WiJ+A_0W=4ǎ9}7X?|:q6ggwFwb2HyPw-U cYR{ʇ#ڻM&B+*-r@y4q ewW>9@nqpjL,HUCCWlǞTM÷fBz DxyRG@eWGO,@,Kr+~([%'Zl~6t>0۪q0x+r0xΧdcYIYn `CznY [؞Ԓ-;ՉC%fUBNN-k>5:Ő{]x$=,PA*xL=B؍?L9dυ7ި]cbK(*lDecG[&zZk۳+Yh׋7&ZcMq)]78bIu?8zc TDBܠZC٪Fq8z̗$8b7JašrO98 gt~ƎqHW.jsEH*|oVhbl:9Ţs%$aiKFr#~OՓyx6uRm}hlX|'PvU\ҟKv$(w&z:DET-b(Eab QI` zqҤa})ngI2ׯ!ʜkd;Iig8bVRlNEa8v[6{Uܨ('.y fsBJ1~cH&w2zN$7@P6VCեP=]@(zr5G0~ۊ->˿f%ӟ>E.b*#]?'d$) 1K#Pc#Ir)N5Σ1Y ⟹1FҖxe7z^Xqi\!Qr< Ba_;֗o>Rb D9,e%S|Tm5~Hn9J10f>ZF~V* .y+ؤ'?xD J⍄8\O*OF0YOiy Ξ}:nS//=錨fúb2rֆa(EݠSc~*a|]F!>_[0 ٠d$s@AGYMvZ55]Y|Ŭ4'Q6TQ>Y#/9-!IpKE`R'RܻsEqQÎj8Dqhzsm_mξs B+LuėV?Rq%۴V +rY 5TkVL@ku_4 f*WM")M܍HS1\6ҷx1S2 tELTUw:@+{k2j*`'|,=ThUĸԤ;țnx)dgGc?: j&nKZH&M3X̗*ҫvk*ie2CѦ -ɉ:]ť2~{=qMѠb&|i!_N}ρ%,#G5@e$ V6eܷ]+CiX}BxI2< &f{ K\ϭeƢUZuw<3B ?%`8„܋'Q۬ ڡ__DT ?1gDZ8T 类2o1-iXنoft#|e@B(qo `Ta`H?8>@ 2vqDvrcBJ[aȰzjowc*4ŅX_l2/W Q%7/?'ȨOXC %鮘%haNs1,3ii/XB7Vל\Ǿ1ָSZ5z;N|#}xʆEy.yB0y/ k8PzēErSKyh>O|Uwu2:&YCaN Ikyw{HyG RBd|gppmTM$4րUkҘw2igB`eCVE]/Ul@ o-  w$dVTBl>kJ]>g2*q4 O?, cPpLLH;%q,NbxٜssJz dqpL2״*C!=R jʷ m,%&yG-Y}.@EUuH?Љ<_C _rd~7QZPrE&GwCng`*#(u!q<.nXd1_~8s =mG'JsW?AphAݚ9VG=-x]$f2(F<,jj&(sGMˆ7.u@ͥUfr`g3\TH7v݇¹ÅK3\bxiu㯆~J_5х JY'4%tu] B6(@+nj0q?ޮxGYn:ɵܡn.v "X;܂ ot4餧h̨j V d-3(D(uNeS6“ P)~SO.BcfeuHV 4E`Y"_^K|orq<m?֝ $PDp ~j539zX 93IڥC[[ϕĵ_&xTA)L('*9pyw6VbwzZ 8QDr+r_\SIBfqZDU˅(R[Y[hn'GՑ:Jy庿`ÛO<{^$lDlݔsGV vjM߉9QMvE|"Hb'Z9&LJw6-F|Y ^YELRufψkb١Yr d߭gkgЦaφe9|m=GsO2Pi~w|NJ~7[v>;U3)\@,G$f3~z+dq_Vy(x7Sۗ )r!:†с%1SEޮ w k20J/f+YtǺtu5js,h _3S>/_Np\WCDݕn3{>hԿQjd J 1w|aDe|P^[_ @U}H(\6#Nӣo]ĻF~؋h*"|~d< N2`'VO0.a\'Ɣ~:IAd9K]7V>[ >SX$ѥTSȎT萾bJNc[{< ~e ,Ee}M`aM$8vkBNf;5"؝#) P̺&`{d&ȚaՖ8R#fCutEggSIc[zO\L354 aC:@[-8b.BՊ=j ˦9!v願t ʈ#f^]i.9j|(Ms8Ma_9í\Wl J>4ʐGVZÈa;9;P <|m`gVN>{66߷CX1^a;DpJ| OuV2=>-G/4ޏ(rC,8})8Z",ү}YK2?,5D2+dɮ}et\<ȃw Ip4|Z"ua07-^A*:4 ˻*4ˆDKdZ{=DG@5-^/;n|nW{WfhOo2*ij0:m̈́ 2 A0 2] C1;` M8˘znڙwo*;C"QhPٹns^"AY=q?\;tH^ʗ\##OqךqOi)깬Kr"e;NsX/?6gE̖c~'a.#P^wl~,Xt[k_b67r[Qa3djc@->6jTW2rzgXh2XЍMD{!NX(8 xʃs *4'Ň3{fY[Ƶ!ca_5/˷fz14n,^"=5tgGdPBƓ05>0Yh%^Ѯ}zY# .+{#u W8i>&XFKsJ)FvMƧ1$1Q"8#+^R6)XN*||' :崵V3Gɾ`K엯SQU+^ݙ)?ȎȆ#|g=jMf=gq1qd( ZH=[P;PcْeM#ʅ;խTg\'v=tgdP35E+vrk#<ՄU|nRkFsHTs|,"\:~ȯ#OWb6:ZWZHfo+X 8H!Qj >[֔l6WͼdNbƗ XYAWᘴ6%n$9 DWsp|JTj:Ox?QE/˭7o{#zťjĀ`G#9*٫XꡈwW|: ;|6m ] $.8lvU]$k{o*26 0V5ma\M~XWNw'jL$ x^fr{qx[٭l g:3)h^u# aON'`O,Y60d3} d}Y.'#g!jh8tuECf0(r9AY׀c:`8g_/ M/zv+̀`hHL%W edWjFsdtʃr4ݣa)q(N49)u9>HTÛn ~tf'?|]yooERo (1//N _:rkswM>183xb0 󊗯ɡ!'KMpιB S&kvGl1F3g*s-Pݬ֝; YB?go âghMhôFOɞ 2k,(SUW-/q,*uH$6tK=nSo?suٓ`vD\>*?p4VĤ 8h m , 6(Puwn=\ VqX/'R\vO;_+%^/"FOCD˄{"^$?|tPt˱*y\ZafQh_&Mwfv|nY (UkXK^i'AɳvWI>nG!ʔ:?ܻ@MҶOĔ2G(H=ڤ"T>B`VbgXot(ݡi;cgoѪZXI/>ڬzB" Vue1ᕂSFi<4 % y>OuGχL!.ޠsKJ \l^ڕT kxMd3Q' vf{Kwѱ-^ϹyqwWdt77Ny, \[td"ɲ 䟰_y@Ky 'VG00Rąn TŽ`rKLh?3ͱNO)O[-! zW0PE;K,& =>?SӖŭ ʙ$nn7`n{V:~IJ(5.T7 F(fLQ8Bn"+x=q#"}J[*].QN_HsPdpsϒcwBiPi9O̓/+O!upƑ;HtҀ_m:ͲMGA4lʲd9?,e5z kozH &2#~m5,u1(Ɨͽv'#z!ʫ ӛU\ Tw|~(cc-V*ZP@qY<:ڗ`,>6 o0,A:_['$*w?(>`Io)a}MHDe0Q[k9;@/ct\s|9[zg`"}%?X)Q8rKS;Ʋ݆f&tv%(ZA%yU(̀QmI%%Z;.+ʢvJ ~ȓn''ݵB?\ļ'2i^~^JۅMn2x{&/Ra!Jv3ڥȖE@6Mdu8.m0>άd[}Yx1Y"7FzˍRr|#EuW=+hej`yo6pm;T`IfX6?Z}3Ee&umN g EUJI9/ (僠Y)8ύKؕS 4L(пbngE̬̬Yck=۝:>H"?{$>e5 q7<6q$אH/PDTiI<t"#C'#~pȵn~CJ>CߦhuVypb'A|-ο |-AtkӰ?(6<bݱDqE̜.OĠ=BH Q֯m֡ތ0POurE\f|:6R|ZD,mtӺΫAO zW_MdF:8= 4XE\H܎9:%"A֛>*)=yLI2? f?Ꮟ1,t$4jbۢd,T/-c `ۤB UJ%?LZ͒P/%1wT}8BuZB 2&VCM[L7c_HӏɟZ.Nc$>O9HQuDs[<ϞDBV.{ޛv=xVot){y0xơA@̭(awTSsted/tcy/pd}INvM aRMYa|pqf߰"6N \oQ2;%hTFa;!>4JW+o"+cϫGd6o= h0KrZ ѩ˱ ~cS? x.A-A;EXfl87mO0ј: 9ת90;(4R#pVv/,_b<6'7G/u=mz,Bjojogt8ViV_$AQ},kN֙]ԃS?=i:)Q>Lh$T7q/i{*$)n( Lg;2m^ S s"cO>oІq/Dywd?O9UE:4GD7|d0;Zju;[bHТ@@ȂHN0*]1Hڈ^R־;uTHver*2=ޢn _vMZ̼wt7fNY앬Q ổ"Qk#.pᎋH:kOo{ۜ;Ӟػ5#O϶nbpDm]+S",5|]̒-K7R=ȑy+młZh,d班,:ꬴ=j {Jh%nN3̞A3(o& x7,Gif@k@ڳWs]z{;~u;wYdIa,h3!Rt*|TZ P| EqަjAipڵ[cc'=JFZ 2BF mC> GvA+#b]CFlލ2hrK.|̝D6BnP,Y@m?1i.^ψʿoӋ!B?>X~1mΥ{;"K~%Sc`M3>fj΍2OԘIe<>o{ x ~`~S֝&>},S7a?_jV.y'- ]KϝB4CWAMs.&Z}agA\h2|FdC5\^lxq&ӍS/!AcP8"iOgJ,J $[%ͮ' Q Thĕ̌Ep 1Kk[ҕ-vCDcא&#Ffu/k/tnp0Loh<ƿcIHx#m_KPYVZ'2nEU')oAET7ucŚ{6W2oa3:%"P2?V 7wFeJ.8iu#Cn;R59,P_WU/>|bw"HgD+ |cZM++Gk [J9OL]ܬ0*fYZ{(ڀ#W-6=,, d;D@RsɬkAk-P:\m=6&Z>5+syk?wOrGϩ %24fĀ3k++[U%r P_2/Xf5-X"xFLVeaj}.K.8&biӆ @@K:~p82L贚ÎWdo! Ng\͘计OG{lf$^)`6(CEh,C)&,ODg,H5jÃm=pci [«l4^p+Ѭ!`%3W8hߩ%tAVI^"Q r/ŶF &O^Uĩd:Sp7Ɂj_<ϹHMC+Ɵ0@/7e{<11pDjGMx9bj"~Ao_x{BZj^ wۂe]8Nu+˹|U hgeCUR/_yԹUQBQh>PF2gp.qYcOh&g (#b+42.쳰ٔ` *%hV'Q݈/hfg aH0}ֻװlj|THF@R)PBfbԉ +L;.2,ϖxv${`tL@[P}H?\X#HuԷwr4 {Fh"6 [!9ԫ`HJɫqcqJH9I#Ӕ D/3[BG~2m01jo ESTiy!7}u3M{1{g_H*zXF%Ac+,p }5)*'zHg[E8&)hVH,eKjQr3mC6S%rYJPS×ZB!A}_|V CFz%3Tu"qo?zKԳ> ,>y/eW^8vS2X$_ROhQFSSK8 Ɲ$oc{}2>r4u#5/7f/Ta.鲬fjb0R`F? X84CJB.*?2P6؜uQc iDq%̈Ri7胧tH4tsj@#DAOlso 84vrzN϶9iG/F(ä6kUO(5Ѥa:NȁW;ȴbTUFv B1(G КV06$ dۗNtW zyU=rdEHH=YK @A( k s᪤.JQc;9H˧m>3u?hW>+-{rfn3P 4cr+ip-Fʵ8kXp=Pm|#2Z5Azpl]#dݬM.و'ԒƓo t|W}zr?x;P;> [6 D{BQ_yqztE "l+qldeL74DCћ 46::[0S &IAU@UlΉe+zz_(=Ѡu1b;m2X68BokM!=}aZ׉(N

]mg9U^1n}AKB5 БBVd $bai].l{ze?y_Jv]9=(d>;'pKBGFg@o$!G+{v"8W 1-x,U]ߐ`3S3k=o1FݻТ &!F`8 *? 肩070۝h?wRhi9Xi[ EYba&݉ :@06V RB;BXa 8,HNpYp5OLPJ">FcrW?pMW(@{׬~ = Ż+{596RY՘oXʇA*)D@o#ը&h;Ƒ4GȸI/1E3i-RXOwT.ri_U'7iz ݀-4v< /9vAERFJRݑX{#@:'Eխ 3wm9J9Ε)RyLnx<3#ukӒXuSd#gL#N n#4a9 ^ Of!'Q,2MM_~78Cp EЈRjȶY:o&cw.?@ۢeዚlxh0",q2[2J?0M?˵iάqMP:b*AWCkZ@HP&&zϔNE:# +4.Q@m8vn`ߕQM+|ɬ]a_b1LHXnY2j,J;:j#6d9ls4ʌ8U3R>JoB%hM5xQ]ThN)vrSY3d m3--"=(d)Oy=m;ҋc3mqsz)R+)bc8z|-&ץ>) <>6%ˋi܎yX&;@ }F`Av$Gv@*:|8slj0dz|ifl˒prӘ34x*b|#dEi| Ӎui0;qzކmd_{Kk.`H$un |RmǬ,24 kK1q[!X\.5 m/h@{coڬ Yv9ɇ;UO]{^LRNWswRbPD 6<QFj@ܳ$7JƠ}K\5 ĤZTJ{.ց.{R+_k>\?H-'➙p'f֎>a&WBoX:Z^sKSmUцaHew}jfԪfW}`駦:__#]3 q¯7ƛx:!"JDZ~SI\<ΕG>t$:Xx_oF,^|uP-Rq~c;> , {B;'7ܑu2Y>m 5/sD[5飱).7: 5 /3SAD*ϗo=,bf HkHVi^ 3aSv$4VrFg=`&/=& X(27jhߊxD| 68ss!ϐx{^S46;$i{;v6DQ>6/59>8U>l<G@(c*w?Gǽes- Q o0_ zSL#ځVG`_iy3Ɩi4ІUw\c&y *N({<f"9S/[뽄aU H0qW$;6㠙?uUy.sKmg6 ev/u+5bsޥSnAizQV)K*HFl?W7tK@;eYma0?x \kzg ;)T4LPyXvSY]zǢ,ڤb5K4%j]W35(x$\z^iPR$rӂV;fKuj}=l[kxhQŌp[Tk25z"ժ{Blu"JBhZyIr"f4qNPG3KF*IП欵䠧X<_=½%QNX_b(v\_-h;)|iMRM+-Kelwix*q8[[C敹,I 35n$Ԃ%^Oj] D_cVi O\ :(kM=j`ī'LJs9Rr]tx/-=e $rK+v:CFZ+v 쯔Fb&߈|ԙpysTu}ҳKb/PO[qб@\Lֳr8vHf_CcI SquʺJVPL{"b?~Lq gR;.ĘZϝh;UYv5|A`_C2I;oTE jqb_Z) ?6@@v >_h'Z* @:ʓ/ɣ#p 1_Krq!~ݞq"1VOvs9ky' 4G[?|_[&y7a5\O/tWcIw{3WN/_$LM۫ЗM)$O :{BYJX;q\piEM =Ft'`V1%aفDk^Hy\̃it>.]&QGw/׌w}{{GQ՛>AF> 15SciE[=~gZ8BZ۠eW?u&yC옺\֓QX_.Hdm[%+vM)iAX>+%Iz@gʥC9`XX7H{| ^t `ybFM9ԍ]= DBkD2C^puf|َ,j/pٞg \)g8i AN+( ﶰtLe^ *,}{,,=9gP<_,)AN BX+"/̴T)26e&M_?g}xKLnQ%~Xu(;dsP+ݜa8|dm$N;2l5)!mٻ-H."rg"$5L0ŧ]17djKڙG]6J{3?`*ś=m#;꤄^yDlX'T`J}Qӿ|Gӊ>4)DC=[ʸ:s2h-+N=\VpUͤ\flY _',m m{oW](*Y煲 dNA/}IcU$ÚW%hہ2T5* B,4r#Q.Sw?դ2=SX"~ܠK1fLa|w;,q/Y5 j-+_aW~'rKXCw,eaN=?5} --M:}iz"qyۜ@5R!1t}htR] a<ֿ@ k8?EVE$U@݈kB{hJ {}G.1 ӦG}v'UnCiz]BC!'rzc~w#v{kG{~;|?WQ}~C?;>~W`p￟T;ڑs]Lw`V@tf}b_ P07+ f[~q37 4 sG[B7:SNZM5Yp0FwY r&ZBBJ64n)PY;24/QuUhq8긊f%G%Z_֯f^.^Ma[QJRK0W+,PMUi&D? xg{͢xk#./Lhn>֝h5p82΂5DS9#Z+W^˩W#->Íɼz%0i7A/iX~IC,~SA<S/sWc3z峕JQr< ^*&fk˂\lg֊yMb tTlΐJw̖bOߓu` h{]KӟiZzXBliqZ/v7a|4}'g74Qc[y^ZY/e~uFzhsAa?ÚpXQf`cE8G*xlt<%jO$vk*@>}W7tQK5[ܢ}jE{>dŒE6,ƠLݣjHDo(kx CzI TSVVsmo.B dHB8DKg Rg9˄m%8"9'[ j<1qМ{uR#%hrmy(SORK l]IP2kK_n!$9״ W:2),iP!ΪrO'cW@To&cVZ} p`mjpAgq 9ȅnjQ4@C33>AN9p?'m٧ RYMzbҸ]ԑ{Sn\]!*8Ӆ" zD6g[Itoh otoAt;Un }5=m:t*S R?M b=RHh^%0yFoj2y"K:?q(xw=RP{ʋlxDH}:# s|]~ڮ,nt+MR$_WbR[>E$ר[Zo*c$c28w[,8sBxS ΜWO@DŽφG=:壊T>Tv*԰aaHp.yKȠbȘ,0Qbvz7 jy-:aG˃HNVtat`= . %cxQodr"Y]~ܟ_ấZhZqj*-Jke 67R'ls;B@z&ks@#a"@ZL'}uI5e>Q@T-J&ƄQ5P"pjj3:b?)mY*#<=ؕoL^_jT{wD+2@˜ơSbvk+'6oM0}6uCM-SQ; [; ۾+_G݉'_ujrdP|;$~7:! fzpc"U3hݝ$ir%I<^H{y(i[sa%y2tbSS/db^ rBar{$N:J4Aڪ1riVJa6B-'4 w,(GT 7պ(hvWdT۶^ׂӺVZd:-haHPU޼}ӁCY,=Ytqr2OSf<1y/pρ9kx]-W<Il єnJ@,4 \TGL wKQZHrʗb, pM{h~@Hw6N% #eZ&tDX:u=b98k-@4NŎC#t#X}l9:|` h^nEQψf6)v'uq03x>+wga 2>\w\ou֦:lkJdy\`[%i O@+:Ŝo-{m*|,žx; HˢlBηG')θkӷ6HQ4vR8x\D8ny_gQK*~Q$ ڲ=b4_ 08Ø@YK{Cx[\;-@OT/|W#|I_29dfN,CQi:abGa+7Řk`6PUte '`xTiv*MhR2~ܹ %%ZFCNnwjꙉ#+yQcld$$2 6~+B[A rGgndd84\1Mqc$J4r,%{^M&"8㲅8yQm s{O2[?TQ)?'1hm$T&dXtk^%![T-R; % {`9j.i [?OZ~~z9bsA, mS Iiq_pWr=z K\4)j81PCN@O^{rBV)b;9j)b*g5ENm9"kVnQN.$S;Y\|RfD~gu-)_Ih'YoQpڿ0**n ˞/+'R[-x̲5᫠(āȎl1&l0*}9|顾V; LM(ԔҞnz["򪝝!J7"=U'e cb/\V1pb*+74@C﬐+v_É'~Pׂ9*?k-@'`6Ao3pGIC mI;@dv75Nwj'Dr[e62#*kI%{dLiAw\n㕂SkǓybBw8920~1<w..p^7@{?'ϣlgssE I`](2l?(Zf:ҡ-6/\:s) _XdTԁ kzÍR% Bf|;5N g(ERI*#[԰ضl-U,brs fXIr(arY8saؓOrj4\UۚvROH9`dE,%Z<%GUԷ0q+ [xc^im(YM2VRwCPAccX ݅G/zfL9lvjEKqXy*~e A1gm5Y9VO|.AgDՏWLN3.LhE}58mwV2Ź8 bxUXpqj7F'ql?j`8#aO /= IUgn ([{&mavp݀d& 1^gZ=NlAPs#7YDS'Ja˃YunYIp1zg0q; ?^d3,,[KtY6U`C |ofV\d7^p2~\U Z{=*פ߳2L0_52PzY7uF8N![\?):t| Ã1[UɊ?Xր"dA:1ӹ Ux|ԆgGK'=~c쒗yOms&ݬͬayY4L^CFZk%1#1ykiĊQ>6x`$"!ş<+\@cۭЌ_@Afw/W~uGJ$Tװ=~>%w6\[Z WP+UGQ :>R#n| ;fB. \S61#5YZWqUnrp9(#Ց^Cʗ=Vܽ`Qzil6hową ڡg4F WbI6fw]7&Aܱ"1ϝ< = |ZlG2R0~hzPmx,r \JPA!+U+vNRfsL9R3-whFT,x ٹԂS8FK%c;r֙# Z݄=h (oݏ x"/ExAw:QMDaiUd(H1އzG5Ǒ(+WTLL*lcD[ak,!B7/a;1NIVHIe-vP:l. ȸ^yp,?~#CCOD2Ǡ )^)ͣh+?+R' J3PzW`lOmZ,0cszPMCsĮ) Z9[Wp(<^1xSð [z,LpǿcTneF6*;IkJ ̯JEg8%</DSs, ?@}w Ȧ23?> h0V.ϔyY3)M/9ܡz͸l>6c3Mij'Z6%T ~oHѷE rg)?n`vCANH5 Umfq }kDl`])|6f |J6SYG<ps2%_ r7ISEؠ{P^\0#*h ^?* *Ԇm!b8X"-O1=m@2h G]E)/.F?6~7Y|dӀ[ج{bU qc~90t;9@e./aʭ; XVe*Wpk~"Jͤp64b5%D)GS遑yYlħĔk~"t:@J{ -(BQ9>jiu_|R;Y0R~fIt4 V^ڛDzk"ךbAW; ^&>žRErM^Ւw>0ku 9KVF8u4Hփ*0zXbt &MDҋy+C[d~PxԿZ#5,du>-B8yU^HoDRA.>JnCa v㵀<J&ѣ>+jh>.h1*WJQU/g(G菖;n!VJ7t37v)7Ƃd;6A3o- 'nL)o95lK}H:mrovT)Qp'O/;sb5?Ap^KXF{heSVy}wbͻd~h!6'#7ŚYPqf{+{ͬ E׈m!KK{tz'wD| JaζKʠb8jGQ!EbӅ_dƘI^b`pXnjrndQ@ jʭCS9V" MM_|dO6v։7A7ˌv")|ycL^Yݰp3N`~OJ,,p| LhfJl(lӀu]_3'=%t:`&/f+d&l}@k|O&Ar\pw>UſhF=9~q'NZxQS墚FKPdg!"p5M5{҈Ȧo}AƍZ|6CCB )ZjaKX5%=0MҚv ʴԂԡ>TMm"Z!E EC< <D 7wυa @q˃C JZF&!Xyql^x7j6$}ҼhtXg5oCFzvKPgyX8AWsjo= ; T1nH4NTɸӺG-4R;4!q.mL=LZ!̈p !y@$R*TI5A_65d<1dbP(4 K ӝJ ׺k%\Ax!8ɸƁT6G›tŋϐrhy]&˜."j|GV@Թj.˥ R1ŸUdcd~Zqx:tMsj<̉"eJetōcgi#ks=CF6'' lTVY*.p)4!ߚNN)eQ1;e|^j(Q)|굝~K 8'P*Er~fnai~R~ˁ7VDdpO^{e7~3ahtIǰ\W\*|,U}~ruhZΧݭH |#y+/$NtJLЫRg7մ= A' 8/o~h(RY%ؓ!TWh= Y62 }10 ?.8~ u3Xa\݂ƿwGy$GCdfjIu\%onJHȯr}AkNҔo݇(~r-6 |OÔ iUe%rLRh<H[3}EߐٹAk5~FqzC2|r:)K2QtVJ%=na@nMP e@Fݰ3P9rpN"oRvu8)2,>^r* R1mQ0iUŷ) 5P|w+AN6FƇLQF}IE*Påo'1xOC,ocQb]R|' Ps% wpmd q)61~#CylK5<{ b9MW35$( S&қ obmRr3Adi_'2[9viƥ] KhVRLL 8lmE!Qm0ԭmT_nx?\x͏}x61)Y@T7j lP@UT%<+yrUmNHb4 ҥ>z~5m~8]e lşiI'5[YXƒ癒XHk;wK!JQ?f-Ĉ/ w 4&;XDȯFQ VPa۵V2:L*kY?ep\!uڧcFR 2I3ETvuqvgݭ  aAd[d?53Q<30=CIP"o>Uw@߅]Ra˧TQLմ'?닶YZ_{ecm {,ܧVZᩔ6f K[|XWgyǞZ_h@R1aՌ/m?߸a1r;jb8= |PNɒ@OMW5]qO+[CH<bL?mMG/\ 3*DWerimz&nm\^+?tI̺4# p7(m]ى5Pmxb;¥RL.4$j; 8D<=ummUKqO/ X>kQ kH7A}N4=_8yx-9?Ա Icmn5&lqL[e\zU Dhܱ,o*=\VE0o7m*\ZT??+6/X1kkWn4}LLrx:LEgaXYTZک$zG\UM*@1Zb3j;{sRSwl"1%:ASMx伉ɤ|x63F&F;ܟl#,;"z&t_{.I(马5lÿr+Gԕ@L5X{H2si%qN=Rn}#INEN݁_a.?M@Y& xK{?E:\32@"B->AbMY*Qpd1N>&#_`g X0EIs𯅷b =d39X71KwZ,1bA9Udߵ":HHr^{2R[].Xsv9Qq:feqUߢeՇk0ql;߂*iҳ/<%Nֵɸ<]5HQ2wu8krTL/ )@$)GKϛAqeǜ6%)|y3[;z|F#Yo$@Nt` [Dţ@['ҳ9dλcl<3 0.<{X> nv|& &  eȖ$Pk~5BXhDl?^\i|u #,1Å[Mo 7<5)k~VZgg_}qyr1[|H\~_U,lҡ9i)YUbdSt!ܗP l ڻnQv]7qS;ac*~6DR![`\5c5$',x"91$l^"X- =;&\9 UQиӹݵOҊbioqT]˯\//=GzBÊF$ss,pW.Eb~v+I}4w:jڤSխx,vaX)C! Stp;&\%L 5<;=u'Ky+ȑHd,sVzh|}{K'ګ5$WYLP'{Ås!^OkqkL{ K ;OYYKꚫvLAsuz@Dz\ 0 n ~T@ /ǐ~P ).n}Wˍ1d]K{e#N 0 Y>K$A0udAE]K(\A+}=]TF*v as+ </+He[ɯ]hh{>ޤqըm'n8ܠ0S L*[?E#D :,շ=/~ޣ̮?fll;Os$Em07!\kOܕ}a)婯Ч%>~PRB #^BдYJ6 gnũLB+њC4AI2vɢzYI} b&o#t[}5?H3ȜلBn8鲕3o6= Ÿuw^1VrG.x^Y|@mx‹΀.:8X1l"U䰒-Zߏ\L'=[s$҄z%ށ0[Nv y^hV eIy*L~=6d(JE.^r-[w9SDl(u{@?3Cю/d[Zq< gZ?/!dTKwEW.Fenτu.Rn+Z[Y+#Wnl /@l(곦Qb&#UhwL|K|#L5BD^~Aon>p jX W[B }D0J~ŵ)&J#1,#VbxosP35ޘ#껦G0lJxuwJpC垸Ms͡x' iș5=+]K[3>|xqxlʘܝ}Ae='g7go/jW2fضM[*)KYR4#&JK[.-n^?_`$Dm@9ԁYf*o*CC_7U_f|/ٮ (CaB|@0dFZ["f16h|yяw>SK}1ONY̗`oU](BgZ:CG`#5.UJ[pNIƏ91OB<-¨UW_z7^s<[n)t\a;qS6 ~:k})LokS 8e&@I>w{/2/K/qoB+C/vG.ԥ`6N}b1ZXM?g93!~-6+ʘz c4qע~#u#|e>$Ql9ݭ= t = J#y<gv3j*ၰ>5 W78Z`2D-l uAO !t<ϩ9475JQ*!B˯ aĩ8NanI޴ՖÑJ"vIj~ ey}/p+lBSz>2n,s ]$NJh FXP~Uwuj#a:o,zE+91r2!I*Ej_,qI^GC`ƟE"?YA-PQ@ZZϘlsP̧7mzY_ϻP.@~ 0JL}gݯϣR]Ჶ0RӖLYL޿UjI{vĪ#kM6)C^ |~U[ahr+NakJDY 0xahBf^J32WǓR^捳8t"3']n|PSp* %gy^&YʉMw٫ (6P(4pDF.u?=iHΩהD 鐕:$>Y` ǣڲ-az!ꖷ纉}: Lreay`Z;N&`=N oym9D@n"2_ Km>^ i\Ϋc6s Dr7Vqs^U; 5}QRxԙ1 _lδ٢8iB`!ҥ/Ѷ QFB?2fm0ҨPp]<=Is\* 8S e*`FzdR!_U 04\<,1 L#+1Ѐq9Hbёoa"f yojٿa<U.t.W\5]q,>+FLH"Ф}=j(3@P~u ,XY '  T)<#Gڡ '`δePlĘjE9&Պ]J}vZ4vDN\@G[$z(1y|^a.]x:'H2}uqnyI\|R(Od1% riK+ *nh?6^~8:k6^H6(f5_֏(4l\q ҆\t[p ј ;@W­c?00I/I֞4. x@rvJ]=9x3{2R2nh; Q䢧;M N31f6"S1啋p7'0.TC/ c2R;[~¬ "PnLżYfjQGj"-+]qdT߇6kb89iN D85] && ODKsWݺ d ]y(֏92VxT`Ky HoI)jNBǃ{T*M.맍7Q0]|ZSi.(^T -~/:dۄ GopPZBeV ;b\<~K="D ]*U.n ӛ}̈́\z54jBWHt-JUKFGA' y0:K"DߌB&Lcޓ2s ;Ng4?.pO!}Vш 1]ʔp#*_&r͖uS Vݦ˵+Nlag~Wǽou ]XL)Hm5[ZZ{pN>OK)2U&OßǛLȍܫ/w>w3Ԝ1e~SkPI^.gU/mf>T8񊍸Mјu:$jf꫆b&6vO(R`+&G5t/0J°KƞTxbM=2[r2('ʌ^: { +>c2f6݁RnՇ5WifiIdoc3WX|87flxJ,FT:;_I]v<|6s no44Q{=9Ksv4"C"{j͢bq@~4a)#F+D% cbcRԔb}A3jw$#ß$>kTLe@E&Y{7lJKvYKEmp<6^i8pS#0/C'M yn~^yw\?*l!Kg-!yϼ-ZRk>6P\q+ڽsYYWY9À?Mz$6k/}<2d XBg7\B~05v? /J,Tͻ~Ĉ i(}L#|-Q8w8gm<,;/XJat-3LLK6RP0y4hG NuHr'Bjd/R7:]`GL,廢0ʡ-8On6y BІd(JcU44UwtrM7PcFځH_°7~fxe=_ enWu&3YΒ{zX@!56Ɵ/ꞍAKz`w9 5ܣJÝ^J1q~DN/5)& Xee*eo+?ܘSRᯛ ݺliFa7HG@Fh-KT WUJmfKt?b(e v+^keT5a/);'QU`-n?2# [5r. לU5z\*K—8R #wc-{TpkO^ QyBf omP:hf]23 O@ Uo@ZGQq] W\J_L!tw[1B UXp}uK6N=]c|>ɷYRZ$"0Wki̝t+΍*sxEm8T"}`m~9aRpEtfK'&N^{qM/^T݃Sa- |6;-pYk(̊x.rbƙrkXU `U1CFlg~dT^L /g_Af>4=g3@w Gr<ٍ9xI'N`]o;ןq~d ns3-jWLsIap)??_tXx[%~b-g~=|cN EfNҼ.Շ}5jDétPaÅ2P:ȿUM  { ?ł=~!Bajɠ3kF7[ z*3q2R\D S! {RžΪG@zlUp8Oͯ$Qp|Qf#@B,RZx|{ +WN6Ė)!FPlޘoГF};[,yI>Bުf|h:t#:7Pw˥ȱٍ.54ԅ#57Q徊֡9YE%/єYI9gR<9iŇ7&y~,|mtҝ[k '; ުŽA} 4*/TTp3Ά${@O _mbn V+{I7+Zkۚ$˚ kN pnSlJ(@`w`4 DY{Ag#E d-ƖRr PDѢVl-#vR<@!ъqM mvuF#o AIQf;ai{$Ip0 17gmBsZ:XnLJ# K:Z^g8Skwj]l,-M*?@nU-FM"C* ".t)qå׋_rk638.p7]8)|wW+KJ#|Y'ròO9+rW 2UzxlɦwX[c]= g+Pv~e2Sh1M]r_iTȷ_^T00В9@*CZY>WT&|Ό`y(Y?%͞$t~\`SJXAᅙpu߰` H&ʗ0,2C଒ŬhJ:mF|\5$Sa_@S}8/P x>X4b&1{ J˰)e.;O \j@XWY(oQvVߞB5%2b^S<8~;jXǓ%-&fzBz}&K#zq>~ 5$\{ -ǤpA2ZvЩ 7*0QL nO(Pym6zב> BՄx΍aGZ,i"#ŞY^6#(PoTn8kXi~//~{PE=*l'`8 '7CJwoZRWs7jk8^F --|uSTsc`c!dvY %B ׍\|"L'Bq+324틧 #~^7zSkRKC)шN#8Pp F[]f}=ʎ<K$V0a:,(sO"UF'R΂}vg1ʴь9t( B/& ur5"ABW+BhDٵM5{`^sS2Ҳwf+f'lfh+s%y&v'=C; [2Vj,a]$/`Ȑk+V(fUrX7uB7#/۾P$EeZuB- v1*Cҡ%gHlż 3; ‘tOTs`򮴜3NyESxI-][mU h(g7!iO(d-4%kaK ͵>|u;G=-|bMI>6 ED t06BnPpN%K8!˞FByt-Qd  kf`vl SBlPص@liT'oy\`\l$roMw -xK%hI%R2OKxO}[})w]gU7Pq;3zT9NL|dZ#Oڷ9Ib?LfWw&vd頡Ow~슁!ܓCE.Q3^zżYWv3m=ֲ(CҬ?Y(S zת%K}IzU< r<&$Mm[up ONk)kCr1wDrʝewVkFGJq{qV2(] ͽ]h7hMV{g %*Jsnd#^3h{*/| :`=& U4_[!-o⩝(:30?!Z‘k$}+uOC:=&s@0#JxX;g1x#6H@+aXmDWk1%9%ʬ$)u CHsaȋ?Mѡ r{LRG1BYq0W9`aH|jm  \CiBꂤalůaiwxJ;V7@O d YdHzO[,}|R7"5NgnTB |s-X;ȃ!S;B݌ċ}Z-ףVԐW9 [L. M ?F:/fw@L`ÆͼM0O^ULJA7tj}^Ї՛Gߞ9vڂw8`H÷LW:;!j!p]K@^o'r,rQ+7=Ay_CTW(m^0/d'u2k3dν,F%sl8޲ޱ0.u{!nZˬ2zx,]-D&t~ ,Bxjjh3\\Uxky殗L-[t7 :0deƇ ]B(  ;0z1;ҥ?W}.}1@DY\~[zy~,{1뺌.^K5K05f~ |>a3D_ۍGkmXAn,PtK |l Y>Uk}3xs1W1r~ #˝jА½\~ʈdžj- +m/YRJ `+8;a)5Z^e"\?*yXX5NKK6%p9-ka%蒛A`{f(>k.ܗ~#F< \}VH11R*-``kk/clvOQKyXiB~~Fq`mdyj7t1xKS|+2\'.?ldu{],@a$d3 p4-vUP<<Lݧ[&i6IlE4?4~P)߫?[6bb$ jOGxwPJ+_*>|%ʶ\ErHjYNԃaHy޶MYשb6;OPW!4&Ck%XhWN5s6X<:tաz{@lh>eyyaLg^S%%èsy:͙׭a cMDA[/Q mhV $0;@!U#qG_ =dl;NLó8 u4ʉ<>gPAlAEI%P|y* !9nUO]>_P@ZChlJ=5R6+2% /:=,a_ HO~h\X Y^.TImWp( Ƣ:KLѻE. ,Jŕ*h[fh]Ɨ)/IUzZC2sHt Z8| uΞ&M5S<(e$Tx5 8\Ix0UGQ8R-:nNP^wIF;*zY"TbڤI] )e -nvä <+{dHf^`TvVocj0dSİ'jݿ416TWf&wvDKR?.zw|]MvԳ1Ύd'ߋmFmru#X(~gB{uOFd)nWR8 CjPN2_i;gfhkZ-"ߺlm:2ntOF}ɍuݵ!Eß`6^S61qo&)3@9ɋj5uc& E4#j:kJjcU9:p h*3z!*{ 4-1Da."jg4cGTc!߆cZ*+clU0[o%[ab.94ΣoѮJ?Jӷ[&8[ D2hFae2]f oU[P-M{EkHg8R^nzǮ(۴D^w ):/B8ؠG+'38@(3E X}~|T`֮& vѾ\&ƄZ{`ɬ[c[ V}M k06J0P 3d1cQ)ceГ4^qvfۅAB9UP2_t(mDQM[Ad֏%Ѝ9DGl%҉M9ejdpMó GBL}z9E4׫+6>t6^d~Ja;?50ZYg O얧# GQM |M`c)julf*ӊDbKTT!X/y@JO|Пu<}GW&uD:cl}{.c.4o/vۍQ6o5(Tn_u' s'Tp JIOx PI .O]H4̣2fvbDB!of|e9$n AFnxŽQX~Ղ)mBX(3Gf%Ov<mk>t3溪7|ƭFͭLsXT1vB"uqO`ؽ$ى7Ԁ~+5nSFssmfоEhS0ώ K.Y0kWRDS5;BOshoz YYqrFNON&Q,>o]逿ʐpogwPϸkw1P&ᙩLI$\ԁsR).O5^Ф(naLĪZ!vE\g4,& ]Mim-P3ag+ S0뢃E C~|k|E:X Μ15ۊdjS $S^ cH~5quw\[oe/R+ a0f"Qtie0>ERIq㗥^YJyGǘ=}*7PhH⮥k$9?C YOLFm?:bf'L#ŋ䭳4sXQ7@wi5EdGN+y: "s$g q<*J0@_TCguv,R2t =r)-pnYRF7?BedK_p;{"]0<  Lifyp?ە~I'\Ps^' 9@҉@G\īb-u3:+-K3~sޚJftSbd7ɞQE[G Ͳ݌(j,#WagPĜ'#fwv;ㅍ U4igjNnjQ~R[]M/ġЪcCruz0&4DJ+kJ;c A hQ1D]ے|Tǂj=v u0ɔngOadPX(/n{`jR~>GT 3$ߘ[F7>y˥w¡:M+O}9]%EkgDkcy8 kA<5}g/CZ`̷ʋz'#[OޢEݑ6ԧUz1ĉFKYmD v;J+T<%;35%@Mpܭ8\`GV'f 1$mKNcv֋# - `<`5LUyEk5؂ATRǘ eJQU6)K--Nmn̈X# qK*fתKC;S/' Xڪm4]Útԯr͗Nɰ|7+p>ǹeO?j{:u[ܰ8U=Œ7S"ΑLتc&=|:3v0ɸNr+vj!? Ncxޅа\6zC;{ eFA1B(eZ~58-ռ~ׂa}^stfV7䋓ev IY9>^^ܜ*g+K܈D~ѱuYGK?G0=ky}KPw =zv 9W@<;D97iܘaJA=ZG/@s+1&% 5V$G(P;Kb|@3sAFqbnvI_S.5R쌜7NMҠJS4PZ5dA,);Ȇ2z 3TG¡,9?;1jCxP|p]xQ z5UYeeqkADL8XŹ I xJ@_yd:UTP@wJޭMc`~Jڒv_¶q + \'mAM j=xLxydT^!XZ58jԮj P˫]r]Pi-P ̕7g׎]iU9d/ ]k*&|QC*/ZnrOfC濍ByYci 9vt.M-| u"y/Aj{-kJ:aF Rr,ql5UebTC?hW2NIM6Q,7VfMP<.l} O0ʴ*s#-NFI\Ifá_7:#xh|$|gS.-Uz蜵(9׸cP gR!;! QCŭR8v(*#puWXhK+ʯE&y_N9J[TK~L%A&I/pv=AZ@7$Iov'"xn٬32w6z˽d)djsZBl zv*EYU Rzb?.&QiIL&#"li(Y%w"ÉeBuRJE:Sc@fF&Btf3?t; p`hE> <^[4dCy}%3HXL=WL;Dc''%_;m#⊤x{|~MdZypZȌ^~yh[0 !nb Sֹ@˪vb_90sJY%@.xC*l}R#XlTP>\9c}OYڇN(4=,?FPmPQ[+tbϠ~#j-0?!x  S b"pΟf3ypI 1uyVYN9@_oń?gXm^W'OVE] Ɔ%wOQ%i שe$˶0'ZFTjXBD:B nS'-ו<fH/ɈbZE*:A.HOSZ4R@I$ߊrP Qy3mo/|)@Om:pE5Ϧrՠ*SO<_ӭ%>SnmDĵ|A /w]X:bw?UPC-'~KJ2߶[OSm'p 81(awek@CI: *=ܚ!w\;:L/uNJڛJZ;鵎|Wx4 ¨:3[J@W6 ᑨc[(B/aQeCZƝg C%5Eё$K腛GǠ#5]- nf@~ebBa ֛DlHa 6ߵIA}ܕz{};rٯ{`A/{m6aeIXU6Cפ0|քz}A"?_q69 #H1&8{l$Rk:&r`tY!섥z-հMritXqШ< ʭ1Zѽ J,nt<֦M9T^;!03@V[дFY44 QޤM$m~UEQ Vn`m u<Κ/wMڋl!+!TA6 ur0_a8uhe1ruE/A yG%2z^mrx Gcit?Q|ZQ=j el[[mxE쪢 olRUkej E]"bc/!OV$hܤ?|hqSd8RYYv2£LQ*@g?fū| \ Ci*[":I% Rc=B4A:~FňJg^pz{%ysIQR@a+{VzYز\NLcGM֝-mE.⶛t6oa= ǏCB&4).NWR gWLa07|J*gŨewf+;6l\W%v過w~+ai f& rR|UR-BHvէJB cgU9 /4,F5[~IٿK&gXne8Ip+*[H]BYh][PN|DL%"'NRriX1xz,T(c:bqy@x4dcWZRW_4&t!>VK0ުCD*ͬ^v'?ǰV^@D"XDB@u-Oz>bvڛwG.O(ƶYfI;9di,N")]9j0w% <@1,1l+"D(<ϕ9 ieu3lLlљ(ia CJ kWH\òY_`C `87} E8eVD25%;7YQ64V KKC˯GT:ɻe[%jc%P9:5iG ~2)7IMz: ",<. t~ /Fxhu^`I櫬֎!cǬ`pj&OE: cOS>Lj%M}GGk={eE<;2eԄXbpo]ϱ`dzA<~42F~C{WS}j@ hݢa7@օ Jhl<±$A,ڪ<-tv Ft+i. N]U[QX2y=Rշy(Ҝ~Y}]Ea ɺsYD~O{p{XB @b7f̈́wNW'ޥ7>0SGLBR5[qpFc22kw6qA>~c&G_^xrT10h|iHf c(ْEޭa}1%ѡd,R_q#xzl <GV2Gi)h)S(/ b?k554QT~HW}guXq'*lrDO\usSazcM( RV*y @v&$KpPVdv)Z^Bg[3;,~ gV-VxTL#-E<9V;ך w7퐄V)L*cC ݽh-lb>)k6nxxt7"b%`G&cfv[ )c-Rs/A9ϫOKM1~`Ot ]TL#knc,VcU@*HXH~w ʪв][N:UwnriU ]l¤̌CmKa4-Y6jñ6Ҍe_ T6|o cE0%Of5,T}'#A J% d-0 RљLCVM=C\M1OZ2,.&&sE XԌ0[#w^.뗈4N!>~4 [scv)Q#4^S~  (Je0gL*Œm'>.vz'DCx 䒷TRz4tFֹ4M]X: mvZW-rT_<ه*y 0KD4Ϙ=+tpP!m(,'QM3$d=^H%AHy(Š+y۾'|T89~$N,!D[U'^ ~'" Op2Kn`mɀD#~$e?_ozȽLSnaĻ8m/f[[NpfC$1 !g`Fc"_b?}[o׃9N^(^Qkͼy=5$t S oeHg)3BeB^3 ny—Ĥ*-|Z:ue&vC E~%< @;JǢ$> ~Pm\nqi3YCz(I@q]ɔvan.8.vn;`pFXdzc⯂K˪uHU7ݯCk9GL.&怔Jsigȫ׎slOd b {D鏑oQra\-AÑJاDN-^S?~Odr~ uh*bkJ$֮'/pL2ZKimLW=T{ws0LܺNKVoNSvX~ܑeOLkT?@>ҭݯoK2P ^|{L]$eON A 6[#3 B[mc[qёr'R@޽ʃa<~9,JgM/MEoMW00xRc*g`y-YKW&f0K9n3ZXIW)W>'j8ɣ"&S8(:5h7}gj4llًKI#Bj]X@oj ̀+˶5DSrsPLux1g;~+s:[ $&䝓DK?"]6[V:R8a5lh B|_Mȸ\IcKY?R ?]ey4>𠐅nu@s4t+q&7hab (tۨ[! +yY!Hdq 7i4)?ĂM>{G-o'>g ILtu>T!U}{o34;P}pYk:7GqYsV24Au7uD+>p`]11M㵏s|U5Y |19|[5<syOH>|a긿Ȍήm`tދp!^9#mN0Qr _78!)ʖp{Ih9tA?gaXPٶvlƳCG}M9g3'dZ_#9_5uO'YH"` p{n}P]ڍ/qYݗh*0*YS?MB]>E2,m:HƗQ]Y\RzWAE:n̙wR Kn7T4 ^zW6)iHط:|}Q+>ҟ@r2wxyeީAlL+ v~š sFGȣXGrKО]ɵAGVz;/{ X<;=KGŞdlG]͙YɳGUqzNe iאN}ފ^>ˠPT Մp7hHLzM >^}@)9 }K9*"~0IsH=%H$<ًo^bJPx@_t `\ Hڰ:Z")ތrҟ-G&I2Kkki%Ê57k'F;Wϟ?}as&a,ҩꈕp.`Ko{XNa'㗚ߊo}{}0t|aU c8u’ݧH陒i7w[\/sEO!>i}MmybY!d* ]`u')H$ϴI.OE巟 A46O#rUkgX=Ԥ؃tcbA[Pn o'E*ԷajO&rW/x5-ɷe]dܰ]AX#TNN`\FoVJ/O-꽷{Ҷh7I'p>: W3>tQfi鵜fXips`С@Tr[m;L , x;z2ʻ]l4d7CgM/*S3eT lbct́/ƨ~s%$:kU\Wv هa#eɿlüx"W˂촓vZu9tq#o35bY,5r~D}nN*$YhnJ{A j5RZ7ySE3rN)Y̌r._#em|0v$0ɻ !Mӧ^=P-dElxPWin\ 5Xgcr@}@|)(bP8Z]٘A8ʭT$*}J.>\bRWm'h&penT/pY#{GkjC'լ^+em-Hpew4٧<*-ۚ+44m!.X60F_$EPOc7"ع幬lkd\[0 ]W [r)XIf0CM|VQTkh(3pMldyˡE7}J˚Lޝٰ笆HΓlTX;Ĝ`1Lꡁ_%WCXa6$ ;Ϟm'zt^ FJ\OT,8H9}[e2u 8(s gAw"b5 h[ؔ%S0sC}rbh9{s _{_->E?f !cӐ^{bDtJ:5t'utzJy;&#_@nf|1 8 BWu>v>Y-N3[=%`#5r$CP(~Q Y0{ v3P % 6ƫ&t`:5`6ݓ9fNt˸s_D)l~@+8:Fɵ&GBjzP esEN?):LLSBN)F8΢ 2'?+eoZqW*J}>; )h@QbrD`}F)8Y&Ζ's<b@zc+"6F*)^ߺ"q! $N m܌=OV\k3!:+$6f}E0n,lKmDҡKG0U~֘{ZjR' "A](/W6eⶀ`6FOl0r{=iIMbįߝPv|ֺui3Ө 6.nJ`fjqF\#ɈCFuZ)B!7>'~S,z!3e~YVxwJ5Q|.%2Qgx!#,iϔ8V~caJYSSρf̩0(g"}l]M 6#ۢ*nO#w~wCo\hi:>EM :gzҵ(߻U`sPX~;RH$1h\^5,^{3QiH'LrB2# [o1JU#4D H|g| LEToYƮ^q^հ4UȌ򺖣1Y_Б]0}OrJ&j];,-5;ǧtK e휝 #J?9} >3k3*Ίw;D(Gxg8ef1lÖPccPq^xc&)t+tT)'" n!j sC V–|n-c& (;&XC#490S8v ļt=0j_oci 'm2Ti鰢(r~+1j sQ>/f“Ŀ>^r߉LLWDSUtp+8=`˾9Jpս=4|7r+avt{FsD!ND rі"*C0.AX#כ )Ga~6>bZ8_Ɋ[o=wQ6NQo## bI=mQE69?}g  T+Kq f= !RN-z2ήȦ0KVa ^NOKH&8#); TZg4dW TJܿ*(|ͦKyS"\aXV87']ꓒ=> Z xo^z]w]Wa:Xrhu)xMhr]_'XPNkP Nަwe'E6N*>)m5 HW Ag͜tA, ~jPG8Də'ys^؃CCZ:+dE)3[=ا;"рZ] .< ,ñ7Ii"k’&__1 WDLzWE(ɡ9)Qg SՃp/,)7^ęG`"`&Z;C:r0Ԁl7B=Ei23l|Fu*:#oIMϬ!Me(&\UӬ:iod7GeX;8/a05 4"v˹ 9r4^^P)~-0ޗDvFYm|Ъj#Z[sNlx-.,{:WOgGm<? + ab8x'ҐoP۲YwR`/ { : p&˪əe.9YCF9 иQ$,^^,S+\E.s&FE UVs̫2AyQa>++WטA@ sT "B M+~&3* ŠDEd= I 5 2QQOw 7 DH.>!r"z ^C(uIi{{iؾRZh;/o{ߦv&9~̕Hq0^$F8T;ٔesaGF@MZ74e| WL'!@ڗ 0PCZWp4A%Ap(i9Dm'A@.8}9zv%S(>`|i1jH?;,t jBpAЄͻ #൑X: E0L z: bk4dnNv^ A{Dž8j|v+XMa[7PEQ5-4_t+Swo J×͵8`$1tÖU_Oe@%mɎvo[5  L)v>hW 譅փ{2Ͽ 4槖gv+h0W~@`XKG#?ꂧo;S`[9L0&]3 Yظ&ݻd3s9:8_^A`f\DGR0NYVl{֫v#j}#1pŪ6UŻ), "Y,2.H_|h\ 3#}Ȗ&u5Se12bY W`q4]`S@ 򫂙4hN^/o&Pt0[;:劽z &t.A5;'#C'J}4i:1 Hֱȟ@Er/ γ~Nlβ5"j>}!jO۠:~۞۠qj]_k?g&[/U}W7xmjAU~gOR+Y߫DɲUXyZ'i\,'9NjT|K:KFq QΩW}_ 9 /eu*A}Ԣf]CXl^:ąjz҃k]h: 5_ppum7ߺ_pc@\H HńI5ٴ]uS߶eב6}_ZŹV0?૪U{9Y NS퀒*jt]ZjGkՆjT]M(M,cI)aA΃#2睙r)}b#.ʟղ 隷ݕL>]K$Rs#Llz6 ^}_!ǼZߔx~c,u􍰆 5@Y/0"+<^ ٩]!>6$|w˩Jn ^C g J9AYL{8~笷9ju=6hq#y1Sc΃XkcaevC2By\NS'xC.R^S|V{b'QZ|9{tn{$%IL{MG||sE!hbk3hZVw3Kw7Efe{ Q%>ab3 `geI;5Q/FI5;p^I#U~+5 gG~{R41z߼O̿`g/n >)kҁsKg5g1W,~h!5:#<~pdOa{LԢEf0qo&?g _Q CҾ8+ȮGhqs!E gB>G1&B:xrvU'_?`>E}L`~-+E:6bT^7Uqq–}G AXj৅hWPD{̷x3nAг Zgc;9 nZ\CgoQ9_7a0!umHy9|;(2/їXmS fT}8eѶY9vQ[c*ejG:KԱuS!.?3*NޭW 8$Ӫx`7i-^&S@"ÿ>sn9:c~rA (Vr\-X5+4Y"8aC;mKLa[LZ9+P1B,]Յ>o1| S/2MrYFy$Q7Dcbx[ };(xWW<) dޕdGUT5(!*x e~SA(|Ff 4Sc1G|;o8ܐ$T ^Gܜgn,P>pd?&96Nl!=n<?ř}_WǬzB5#nt6EuṔ4q^8YL`xD7Ms!|c Y$U@-,u|H9yY``{mln5ET<جB"Gw+'EԢ*x!U|(g0 +(  hP_N`UgI='vJh:2  t82.5߄ _1B Pba0U܇)TQK2@I)ܑ/7E0ũ t1٧IJ:9lMfRta?-{+<dOi"vw,}ۊ[ 3+?(6*ŢZ"'=ty ;?BM'_&51)n\3oYʣ1>t&j +OujݽB:-юnuc& ~Y̱>GblH,A]O $Y{lL8ƚɌ=#Xe[h}A,`OUkPh'(WP47{5K3k/LNM2 Y MV3KV&۞{Zb܀7vm.<$ zf bFx_E p.õK0a?MIE%pOnM̒9c[CԗMl<ة&L=߻QN.YMX'=U闋_ԯjq5KX?\YYVwQ"3SHd;XE AXVZ0\(!64 L*kh G[O+$a#T2Pá[oQQr;񀒮lud(UGV(˟ܸ)'R.[Sv`s|^̚C;V,I%pgIh ]ewE5ao!.JɲcP7\fF)PZg5KaR :896 E)F eP%tLsqk^*m0gLƵq\8<8oU>.B9H(\ pN[H[EIjEFRꕴ'ERXgs{3Hig 0px_K Ec9ӌqW!Kj-}%7lzrY\ XC3TwWFI FLZOPsX3fgnn~Tð*B1ARUKϲ3_L϶%u:X}XpePI |k€s響 an秶ᔶ1? zDpNu` ߉*Rۨ7p΍LH8V]/ 3/Ge6ٵm.*݁)X%O ݄tTj,=):_"x\-fw))ʴQw #4|oGe5u8x BM䈍W15\q vd_"[ ^DGfqp ]bW+yBd%a$neN9UtNslQ*=h9)b&hq7v4aⵖG^_l/kҔ0ch͟}dAۊjӰSXOߛ j@Qtt}z*P,tD( 3/!1dI25-s:a3k]*J%Co\h2H" z1-Ti;s]Xp{DFA{9L>=`k"ӎo7a4c) -xKS/^l$do9%(pž!}Buoemj 4Dw6- qr#Xl꭯X.覸UWؒn{}ب#XV/|" ՟l2̾[xtفexCiC`i@]O!VwuGc/"Eu id>?gz8?αR頿m$yQ{](C4̈́gRh8X9$ EXcC Ew/#&Ɉ{Ef>",Fm;m@Q&wv4 i)h+I2ў+#`Ή!yT_&Px8Z($N_ +v9??A' |0&덇KxrĮV( 2/b`?qDtEL#+acr)22xE$g> `G?thB ( Mۛc/ '`+\F%ds!kX7Bi6sF#a?Xhɻ~ys1gbOӳs7!1)O؟Y1< Bi#t(d3Eҥzw^9}w+A7{ M f1HO_B˶C[JOT HV.<:=cHA0ђIUdqB-=Gq|_^!q.=`kk/l+ZV~xA[hbٛaYJ(9@ ̈gZX #lմ7_Kԏ3f{ZXC5ryC.n1Q:3ҜeJ̻T g8A@gs Vdhz,< bAV]N#*<6=hYzOͦϫvEⰆ{ koԏw0 -$(1}-`NFK<ԳXZs4^@ju) QquoRߵ9B@ n:4j_ʚ~C݊ok=B1KuG P#͐!D)zM;M$y|xE[ hmRO*ߠXB+}k{ׯw)/k&c&ЫpINN#Ҙ5 viGLI7kOSB"Fpʶ;=a|(dgz*Eї+ˁy1$ lC7jiD + A|F 8{\Qbݜxp,R!n|qp}X[)Hr'.>sX ˂Rh" >Մa\Vf |2`~G"E!m%E<:+c3M7TLҚV(w998mwBAy[d6Y~:3)7'͒Z=6Fq-,ۿI ^V,1egc)UI1,-y0_iwsh8GZh-]+?PEyulx8IB9;jWPGyHzR9%{9^RkX ΀zcOa%v$N:5O/}E5<!&s@ٶ~(2*B4{tclg1/!&zg6ἾZkLe3_e3bIfS8 ҵsxJܩ͋@ (h\#q]C9,9kuUTx/yWaX+qz!C@Fw\*AU덣39|QOp./8a~7%'Wܨ \'2UuoZMrB IzUuxg{nUn9>2L5 Ny+ۡ.x*jBoG@S hA*Bo ,40__P:>\Brt߮{l(äwԂE7F~au {C;U+ {=0vn>zn<3.ԛz*J$ITI3'ݴ*”[LѼmXQ'a˲/ 0G3rdt:3?q0ܮb %Aڍ 8}HҫjW~icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/mapedit-icon.png000066400000000000000000003321571506470510200237620ustar00rootroot00000000000000PNG  IHDRxtEXtSoftwareAdobe ImageReadyqe<IDATx չ>|aa`u6ʮ((*EFĨv0dqxU4c.0U (  3 T=k:U]5 _=Mwuuuyw{^ƬYf͚5k֬Yf͚5k֬Yf͚5k֬Yf͚5k֬Yf͚5k֬Yf͚5kZ 5k֬Y;l,5Ua͚5k֬Kh{k֬Yfȶ]IM[=E֬YfHܟmeDZ6}6wdNj` 6^֬Yf#%]YUߥAv~MDm|[b/k֬Yf @;+KGcYnlu x%o5rf͚5k=)<>O' "#zDs{Xf͚5KچUp넷3DZn%Cخ]5)-V{Xf͚5KZϷDp<[D# t1>`Yf͚%?IycKXf͚5KZ .]Gn%#3ڑ1gZv*֬Yf Y/?hz`?mټmlE`5|Y k֬Yf#-j'EE'(tk-^1A(c]Ql5k֬Y @<ɢOew!>]~`֡C{rU}("@x*qk;Yf͚% _T e> v "`j:@d`!֬YfDm:s%+Qz }V_6;XMv mߞTp֬YfD-MS~_7<}?>EP0cyk c @Db.osen͚P6?cE!E999۵kWm% b#Dg_8[,'Ba] gr?m! 7{;G4^֬57\@uUWWt֭{w}SN#۵k#tQ1۳'iC$pXl-hbV?pdAmvObh  >)UD) 6^֬VڷRXXXT^^>C۷o-*z`UUU'%CO;Y` pyAo08A@WG9GR# ϙ` 5 {a[J]›/Gn>țAۺm[C X=bJJJ*Rsa-H ;Uz2 ?#ɭ A'Kݚ+7_\VVF{$&|ΝYMDNXUee"\,Zye| vلKٸ .`%a.zu+>;fN{q.^'OO_x >oC] /uil # }{oyyyyPC޸VJd"Ծv׮a&8{ﻟ4F6p qmϛ<{νCy7ĂQ8a A0-%z^֎O>tgXcnj}"P-C \=׮3XmM-=uL̙ME8Q7tS~ `,sXY'~?F+x|슫N'ǗdtI f'ߠH lSkں'vHWҞ{P+J+?b(ފpVb&D.>߰QI.}UU{U޺)>Æ (s0WX s_v]\1sӞrU}d?/|?G}rAHR9E[eoz?ϕ|*!wۡC#ob?۶ş?7|6g+ g(@~>Ʌ*@D*ݿ|s"@K$r̛;^s0@&BH-vE%AdDFo|NJ ŀw(4f2,sn@G)#7?8-7 (K\P\Xu(Ck }SU"c(%)_e3E oQ/"~uIP:j+kb(t 2$q{K"I*7/7?*;;X8r[ocٳ;{sr9x縭ll3En?~&iuii)hߔ\I]#_~ŧsYZEK,[~ٲe_5J1NQ+**v=m-B.yyQX}ΜU~|J l^|-"b_s߉c>Gmll'QO˛F.q\c^?rC$R*HE("OY7ڰ PߚF^{1v[p+@j,7':lJ~UsHǎQi{0#]K;=]߽[[XgۏB=lGB3g>'Pe_ veU Id*u0yD 266hON{t4_v_63 M@(Wڿ9C m!YYY(;#Vm׳0֕=iHU9pSr":/GELuQ_#>sV@t@C^xA\rɿl%ƒ& M}ܧN7aA2رmwII_tL?/E?C$MsIRP$^r4_PŸS+A 0  Uso~0+sO>/_RR^^^' _\`6:5pv5rr%%J`J.DKd&a= tz&x} 3~j,-)t,@Dy]i%>ל _»,tB@ Y^h錂":?~0?(|]a=q: .cWGk^iċt2h@NXD.7o~A#){@t& * ?1`(>+Zٻw%غmkZ1;Q@h&; }SODq"|*CzBL`-qHD\ n&͏E`h M yY<}C(Fb:I%I.:vۏ¼FsZ )XَTTŇ 50M$ׯ}Vܢ6Bs"@ ]5=SL!~~i{>5Q^ӳg T#9 2$f/b&ҺșhZZNẍ́\`^@"LɅƭ1bP x8v7Oȟ6qX4o i#u&lU8  *0.T#/K ELH%7Fz_:*+H7٧(]*V3צlrJǃݥ]P{%uCnQ1e B}Ƚ=풲S٤c2gOBT"NJۛ3g ,H"rGlKؽt ^M~糆*g",4f$\ $5)ߊ6:~-y1 c׺+`{W| B޼A8(C@KSI!m2F ϋ>M8==$(p0k #$B ,J~g|+o|AQI.L^@QiMΝ;4B-<\tU`<ɧDóΔ\zxDtz& a#~fu|Cb 4vE4 @w\vOkJInDL5PxD z*?l0_B~R$Ky>M}Pqx@c#xWgڳ8rϩ~ <%׋PJbvo>'YgS| >}J{~;2B^q[i]ͫvp0ŬzxU@OWfUC "  67_'M:HN ٺtrSNL "?Chvb@И^5_[}=>;GPk(;iQZ퀝Ra#W2%ckkH1J+b_*6r|O`<8 ᠉o)JӎkԘ c`7`i]P= ÐH3WZ8{r~"$?7PY? eCv~ Np qap?<֏?D F@$rT"q`Q/H/>DzIj"T05 ٧0;,0Ct`ɖOC Zm,T<zqM"%#o`"K`Jw7Hަ:lƏ~," HDCor!;¬m/@#l?L?L$O^S_1o޼GN,n;x`W7= ;Sr7z)g]GLu6v}B:\@bttxm'm8<{oȷsM+MU 3LG 0N|NԸ[wr1@"@ˎ1 _2p _D*q\쟬feoEz6tLDbi'n+{ɓ`S(;r:|UU{Phȧ *HREnᙏ;]U#hE!Q<ޥ|fC.FZFxEP|:v~aLˤc@./ eр{<(v"bI}2OB$03<.{'@wrjqP1cF ~|Pۄ\fz2MNص7 7q?$L ~67O$ܼ\4nN.`7pC~̿mوI(cA8:ăH'9Ykjjj ><OڨKD<8;w87UUU^Us/yz̀ s%wrL̛,`~Gх( Myz7OBd(P$ђ 4i'u*@Q(3現zD@ϤcD`ʍmu඿S>hX^7f6 gҳ?wn`Pb:}&ӦMKRnw(lM&F.PSIuQoƯ~' ٛ7{IXT~BECi(2 ޵{D:(-@Æa;@BAϥ$e$!O2ɐƎî3?M@wVk@ #"H z?C-at]2J뢅TX@L'`71ٛy3'Zo>J}KIH&I.J kGx`ZPxLDcD@~^=:qJQH8H uׯJfs>2&zi=bN?{w{ϰOX8"IҦ"\" |\oX{LAz LyR7_,3'I'M.\$I.Jw_NDBs^jJu P @Q:t |M-a&}xz;&rf%pP S5qCz3lȾ2gp6$ +|J *om]/PN_Xjܖ &7Jo<~#;m)1t-A.mCT><٩G%ꒀ{8 Px/` g "tu 1pUOu $=DQ=VxCRVUwϲgB=dk {l73n# M#m *TIxB0Lw8do^&|\5oJn#6.'В#b- kSi8* C؎l~elQ;^tfk `a${*Cԃ BD^ua4ϩq2^'d@@[6! @SiSJŋjmޏTo:B(r>>su)Pא:յJE~wm~47* BFe-8XdIJDtN%=jk(x,x,2ؒP4r3 -֨oͧ~czѮXLlQaN-@1y5"@m> X5*M tTQJB)z}[rNڒ qeRمi'M%*Pu„acHްAU^m1 K AQ#>+ Op(PZ%k_fST#/>* P#"B1`ݚu(7T niz$\$)68r0w| V=j_ޔzC@\P^:#K O76$K~5GT_fg;|IQRAb 2%qO غAtN@@Gj, iS9dPʛBJ 3y_&Ǒ@nTK\{̓ coa4J~ߔ|kA.ߐY?r B;`X@!?t@:aCAx.IjO~kW_[-tr ʀSVF1)pe]0HO4vIR@N]w9 liSSody,2Uk.TԴ-r\{zt'JNf&a`:* 2?լi6HTl. (|O' 1"еۈ&  oX$5ԇl! %䞴V@qJeDH^^| N47a_|IJŭ~nB.폋\xyNfg&L {%5y̦4hy,s P{瀏:@৵O M S$_W8 !a  Q h\Ƿ}{M5/{=Ѕ}"G’?O)NMN pw>`XMy,IGo -!&yXӜÐZ"rPr/ lvI|?Ы&yv!iq?JÆpAaHgI&Dx( p׆#HI ?<^! ^IȻ=!tBkz Ht0Hv@:=%KpŞқ7-ͭߚőoy(hKKz('+M- d >b9o`ߨvcKL1@o" pS{'AP"0% B@3 i-|(#`DHg5@װ7%N`&^ۄ:ٻۚH"%"8VHR /dk!z5 Ϝ^ BD&Jq.>`9'_rDNk9IJerUZěPgڑ>(0o_Ƃ'h@+$O,ֵk sssO߷o6`AL5ulיj[#mpAKtd1PT6W'OĂϊs#Sh-O˖H/fP2 uqoҺIÐL6tek#"f }c;cr$!{ 'M`J *1!Dm󊫞z$84au`Of# d>w d^PgjA$){|pPS(<̽vK76P$@ 7O Iu:o>J4ɭs@/1?y\a͚5cۿ?lΝZDν^zM yx=r>wB͞=?>=)$u 2X,\6[=mn>h %>S^iNls۷tpInf~]]ݖ]ȝ0xzM(q/N9~=:#<rUozJOb#}Nߘ 4plk!+i^LΉ; KbqoCLy3\CZ#Hr(Яo~3osy H"K.]3jԨ(pqǥS"/W՝8XǴ;hgQIC{ D3f8g}ۋ Qq(#M?bZcB>?&@MC]E-}H9@)chcQHEEhBx\i$u[R?lͿ?b6D-jKq[OwA }! \9l#x@z8Y__J)$uuz^|LU};@X"0 O]U 1 agW\q͛zMClN7]@)EP JO[?*#Iϟ& ( T4ImTt8goܪ6;(Iiݶ\ŦURRBY6 6@;[#9i* w6n8&3f-X@Oرq)j L/*s@oF B)O*G'=-|k?ˋYnN.NN'&O.B/}2x9[ܪ QIUb@Cbb1 (Vsk m CQΛ"ܖ%%4HS ?o^7\ 37FoZI6`Pk Z| H R0dѦb ]U^]E1@vJPIEPe}+~$ ΀ZD(лW ":$qF!ڔtce} 4TwaP7@ǎ2r-t:&/^yP:uݛiC] $@; ے%KĆbʸe(hcxTD=iCZ;HRr媔GZ&-;woO)۳>tnh*((}堼H\l}CXoj1x +*3hh#zK_{/o?Y u[\~@7ŸsSl'@0%WZU׳gR>|W^c֭c .-@PPW59/MMPH%Ahu ~h$z II^y? cIѣ:H`}A#&@7_wxDgf@4\b4%o~=0VV}EmP$< I^&O.<9q z3[!{WjZʷ" o2n7@>$+o(2Bj`lʕl]6!t^&}]=H]@[63{^WI~9dn[t( ^3Fl^gᣛ`N1=@؇JЭZ5VM<yAx_q6>E$'C@ћmLyOyOR wZNkHoocMZw[gSoё/W^qY"=GPN.֥:o>h4P 2 -HD `dsueT"۸Hŋ81@[ Z))"pdz>}8g7BbwFOÆ<~@n>[ 5yr `XctB@AFMUl-!%DA"PoYq.kMy I JJZ7I:ԛyQ$R!P*--1v4fG*0Vxsb91R  rK "v :p,//l^ GG@y5;:Lф ' g^_o_cC)iܼ AON'K/۟,ve\O$a~X~ħVZ|֓pҾ%u3"Bƒ ȅ< )(7/{6^?ܪu3%uu_UDtFTq aD Kd?FxcH w!A@c0D:P7cy_( %k(ӧo 2'E/++s@ͶFAHL{hϓr ُGhDM{HD< EEl9Lŀ͡EI t7O$H | 6a¥2dH9sy[ OPm -P&6FwiÆt͔ `?~Y2I,u7pP( Rܧ94 plAcb} ˨aD6^vCuCqnK, Pm,_㕽ިy?rqjh ***3GcƦZ 10#bO/bCD{o7Ȁ16A @Q?.](Cdϟ Ah"#HzyLNx DD^_BB|!~> d(o-h;ژLs~$H 2J痱EZ2PIx;}{#rG'E\b?^!^Ȯ P` 2t/ UB6Q7O?}^A@̙x8`lG}}{U36/P~fRD5vX$,h4֕Ʌ7o2ϫ/Eӎmn(PrA@aSN|ߒ$oa]pWCc7[U@nUc '*ʃ)P ЗI/@y"~ڰz@L 6 ֙Xze6F0!~ Q60o޼X@sjK"Ni]7ʛ2h hص+Tp(srYS`" X:5*+,d١8!X߭4 AF0敹?YwĈSَ;y_WW0I&S$D_Q/ZP"\o:9z.qtLY7 DgRЖu[\{(;&7Q}m  1jԨyj<rdtP*bppB8r~ Dt}UFu:A Ojؖ-[SO(38!G[$14k>~ixl쏟x(d<asA>Hu=](kJ.LFc1fU[q"j=037 9mDZ*矫%(ZU/ GH Vj "-x&@*2D>B՞.8FOUǀ:(0f8uF<&(Eͭ0օ>)kkj}'^{M 0.̜8,o?P ^Vh~iVy?&]a!9T_BD PSw 25"g P5hmtU{L#oF W@tQ{#"}ae8%1ɛǾ#LЏ%VQ$0ֽ4tC.hT/I^RH"wժU,,(fM 2!xdif(AVE EwDݩGBB~Z8 {:E Ȓ]w]+@lcD_&2@:`Ӧl-l͚5l-l떭bHҎ;~dV9, =zg葖쇹sEOыgdu&$P C2)O-Sx3*RKb(PXrqQYoԦV D&B+! _6Ќ`hGt97ڀ?1[sF": A,2(CX}RD@7l BjY͛7<o?<}x@MD׋n$ tMyznaHAdxMSn ,L + b엮\Zkr CQ$ό(~7M7 h@rO>8w, 'ZsNl'*{%y Ƙb(Zmٲ95cʫӊ4h@dl-~#ēc޿w֭[WGFlRd0Z@`_Z`&d>-p/s~M__q4-’ dW6Ɣ:,qԉB9w-Z,4,{ RÐ aP  աU𙒋pcVO.TM{6_O`@@F3֥4ڷD›'+7C4~1>~O# >hw{sלBL!Dm}W?lر"$ߝ{4޽T"J+$@ Cհ>EAL='sПAێ,} @\!Luyh ݲCyS8/q20z}ugmn39PײS6+me1gwWS+w3Fu_'Vj߾K[K^ !` ठ1rB"HB/ $5??rH@}}=+//gYD>~8vۮ]H۸q#khؙ"AD0f)r㍬@lç޽{ uB wQ/zRI0 mbFqc"A?k}x@Uyp"h.@&i~ܼכ~ܡzS~xS瞮i ĉ׈пHqЮ| _=x]0"8FD.p˗ŭ/{7".|JGmL]a|M?) Q_a4!S 9@`έv)"o")!>|ֿl&MJ#k}oHzLp,,,r @m#qL4o>~}4pކe~]ڿ/;_W)U RFtid:^sb X[P33~cQ:.r9?c6L+*zX~5&0C?Ŝ\7Ǭ30F.(C4ZW F Ul LH(4dE 잏s߯5bpH@D?#;E>X4Ҽ^Gsƺ4o aB~]ve}@ky%M*l}/CjD:a*BH8FB">g{fDGd(YtҺQx3f8` r87Һ7D.L# .& z+WIN(\HGĵH'd׵B<F WV~wl4G :D`Dp>0YWl]SBI7~[L+S[/{A_9 ۴˗tE{abBi<llA}@<y3RX:,f=%Bob𠱸Ϛ՛ C.3 ?ߌ! u"LrMo0\$qۘ1E6pgh t*Mߐh}=P uֱ~u" /@iK/]{"w)v[ UL(}lӟxBcN{,r>A ƞQw0+]+H*~*rc0h=e{êVۃC ) C.B_[!t߄!دjߺhyQ7 ’,8 0(hcx(@_yńXE{ J.t>DGTl@*vhS>Hu=o0WQ.!/%K9# @ &x _YLy ~h}ƒ3W׽. iӆ\it9Q)<0@m*P/@tp(ݜ\`%ðt@"h"Յ8#ͥۯ!țG_>qĨ˸V.36NLk m? “7+}^cA]ۿOܖ /XPSߕo#8<x[e )O< 3p?;'/RA*ďA`}ɐV0B h0PmMhѫ3BH Ҩ'@LZH*FFNUև%a,n~ٛ}}Jo>h㰺a?51o^ ʄ܊@}ԻSP"*@T@B` :5 ូ;0Ӽ}?=?s9bz4v B^'"^q1b>i0Fe GQ_GiBU~i`*d0л+ ߳\  F-F!jEmm60Һ0* :6(7OֽÐL;ȅ\{:,:Z.[Or RJ;2`]ߝlDO;4? ;|W^|˘W@ ᵸU+o !>b@jC࿼^I^- "nxw:cΙѤBK*s==:êz,(r҅O 4 OV?L$ 8*PrTraJ lf|Qb0I 7ك{B CnBkT '4jM XK޹){j*>z: :5n @E+WrAP>$ rX^=L EAz}o'.ХK1ۼyYi"PWj<oO+`e&HAʂw"|ׇ 4z̙X t`17(CPm0UY7[?ܼ7\&9S\\EG; CnoӜNF3`Pjf'xh&)G`{~x⊀H t~u7K,a#Fࠚ˶lʎ(Ac~ŀHC5{/Z(\FRwĂ͉2߳VsQ_T;-2@hv(#Sɔ\P0q r/#i rdy֟6{_/Ct^ Lu 7r){$|Aa-\+}($ a+D;lHhsQi`/֟. pE 8_nS^;l;?`1b@V{C{b  Zj)j=uKnA:wt-۹sxo޴[2aXIU( Dמ?;MnJX"{/_d<{٢}rƏ~=Px`_]ܓP C.cn?(› mĬ?[%D%A.r~!P#Ox fa< r"'=i'ZFb c_oU u==i UkWX Wnd=1Pgp+`]~=P`7 mc]LWa6ob83fw^o^;tdݺvc6n`֭+{W'R! Tx߈~aㆍlh1@}H@H_z!66 B $`ܸ"'&Q-.{QU?a\s8f yQF(B'+Qb:P&*i]A""갵P 69Gh-& A㑪.L|쉛R J/ 2ww W {ǎ\U =Z~D} $F DU + "F zJ| (, 9.\txɅIWU?^?{B4{6na|'7~c8$]xSo9U3iXʛ:NE!) ji]v9\֠۟ R{#ׯ/gv@d~6?/ >io ~duRC$PaZ80~ʥtW^[}GL&,-)|7NDJv)OuxlQоSxdz_& BiDLMn'w.s>{l%9OA t7@0&( $Lueo 3_]k <=;|oAy rRʕEd}t"׾T(9 Y@[7<ȯXä|#:LwlvSr7س=TbՉЯo!`H'ܼ@ZnrFZx!*hگP za7rss˙ (8u4*0XA}yܼۿ$~)]ELS\hMUȂiH=*#~P"o'&8" 2u^XXXcD0p:=D&=; AM@mU˯]пwg5kXRKDi]+R3W$)(rBx㮬Ia]T~!\z3ɡ@/jn^vDT? yYKTy7*qL_և>,d FxW&q'~H›wzoDAөŀ2e ХMǂhch8{7Z A ;M>KN D <%m 4C];x8GD5(K*o\# ?.j)—8N\A&U{&" pn$1|Veoo揙*و@f`hsZ~x8S$A]ۡCb >̟XqRȃ?yTT}+ ={q5  2Ё/fvKwhv nA2(Ґ ~-A~H)/26evNJgAt(X| >9dS|CEgJ.`A.LoCҊdτ"aW*2T  ,G:L b??mu, &~]py|>5c't`,Jv{cwRHGxugl` d8|xrzdկֽyP!6jwH1pܸq"4LRr#O^T<@1l}X0f2h޼:"!; 5>0Һ)`02@CGZr(P yk/y~{bq|D23 2?>d#[0Gűdž=I!/\tI}~6l H VYq&ՕCVȉnF>E` ZT}e=q5NT/-~|ܫ@uuD6պjyy'M:P,j& 秇kk1jkܡ@Y`Sqr\/%oWaal~qKxoѐk@$D?knΝ&]w}ZA)h26E9{9j{&eP"4I|1I4z-Gin0ܯ߯?}_wwן&-ďnAO>YDLswRVR6n3@w@i,WUUi $i8(OxŦ$uK"cr\T\PtQ`/P So 2 )(\^H? s'K>@@x:Ik5CX@ k1ThFzjQ&+p|r Hjt$HGϛ&N}AC~ ~X&aMiS/#ME>@7ӿŀ* [U]@xtO{VZl= d~!~grs<-4:̶s2?߫6{ɊyI'uÙJc(Eu+Lպu(E o&0{)갺dO&8"&j*iݰy@1q~.۫Uk)09A"/ RR>"2-F"FtޯכK#` 6 =A“_l|f1l_= v2B!EMa!wiFjG%c;kž_}*\`7 pmc F4UJ9d9z&r4d·Rغܼkǭ/{*~G{5Ł5"jԨy6+/U3z@0H7)kcj ?H'h It ,  t 'E 7t >\,1tO/B@ ؼ-i;(5~ճIt9w">>{}&!v$_JJ},ݻ@Yw c9%q̄\`̸@4r!GЕ9& FEbjL K.8oUUy@A `yɅC-$t[h!H;yME.L2f2"U"|:Fn?㕃<띰Z=_m">¸uC a@X8̚dh1@ (Cyv@ԀB+۰,M_m/}snX=X 'ds BQ^^GʂHi K;qmAP&P_;P)Çϱxf:3 } xï VBӛh|Bar^͛HAn( qPϝBXgdtUdJ`վi1@!ȪANR֢]@U&?^\?q3Rk(OPEe&-b${FB݋e/}wsPXLbG>GMz+**X߾}Ũ^xv9́[}""?x`s U͕3Qpʋ,5(m2DD`ΜW6%2HiU8r&rFAÐx\ 6D?=CǺ2-uC@@H"Ś# "jn d}Tu to$z`H 2IG%׸!)9)T !erf`1 . .K}s`G{~~IZ&@3!}xv:֭[״G~ÏdO)!r7zg$ryO 5{ak׌YqZ0㘱":޺ȅUI09(6ț!'omriRJ$uCh!%- )ӂ4&x/lK[ޗUUTTB2FD "C[E}۱?mֶQD D $02TTUj~[97T:u}׿p}kz O;T#CR)4/ϲruTpW))STC<!ŀR5 !=zQ(MNU@nM6G _ǵ0M>]F2@oxo")z/?@% yuM.|9o#,+җ6h_GDzꩧd͛jn?@FƂs"6p8Ruh%&[= |p$HLbI(#k8jMͩ  0@\/39g8YhW'C#`P3 s)r^:>z3F8VF~/0 hh!#ɇM*Ud> 3o]\? 7'#}x rrWg8䓌?,z^XT"(1mM#[괛DL;ǸS>Q$]yۼFCPT~n?_ Vq.p"<pǝw0OY8Ƨۏ=s@Z7bsԉz_|/(>o |QCo@@մ2e`Ws[;_8)o5 zʑ/CA1ǎ5v:655_4558qx$#P`TЇֳܾe>8~u/nt2+VgY$*+"'gyF85hϷl"uWMhof8HCWP.E{ce Cʓ9ݫt2gEEՙPHqֻ&|haفh؏@6lؐ4@>@Fkj3 70@D?7w^tBC/ kNr@}ơxCMMiSG9C+֭_/ ^{wغudE$m۶$RAҳ{* ѝ?uktm>U?g+"0n81$:~bGHgE_}Ocʵ@#&cI9:/&hr} a.ByͧbϚ9SJ'P#[$-- 8]eKNbt?1%ldjFP낔ܡ@iW=i߳W9x0#PDe`JA$!\Rh}aÇI%?G#M2}OOӸ,V1EX;dbu$!C .yS4 ͢ߟ{` .gDT#ƣm1g(E+&}n&$K,4-]YϷ^tP*ZBkѨljєõo%@J)hp ;iA -N.Ilg47aҦnEhOܰa|aF) J3z M@LkU<"_5@Ád,=pԈAPM;yϻAYs @;TGSdF`p$5os`R #EL(Ȣ:` G_5܈7!wy7QeR?Sg{3Hi3P8'Vw&e=naԄЙ,>|D&: &8@ C{zu:09PŅj M)k„b?.iSjƍ"6pgȱUH?p`,zO&'F׏)wȗH ZE|XzaXѷ!Ԉ}A]Hmѣ{r4oI}D#?s>тki K,PT,Һe _GXhO,<-9&9gF"59|j@ꞰBSQ \TSHM` l ֑h(Ʀ ٘ }yg0}Q5OFP$; 腇rj 0$2C*+S;献7,{!i?@ 7Q D=ԣlT!S@}8}!ֵ߉kzkjQS]#/Sď>xs~'}%4 0T8YsqU*2(S$\``-yzss퇳 DH86GVG2Hޯb/b,s0 z \Û XbǞe(o? v9ͣ6pGc(Ч>!?O\}_ؿ^Y9DPpl8j-VmS7exN}0P;\ DgzF_EN >MkG9Mj LM0A =x$k׮-r#2ϏߡUO綾ϼk26K牚Z |uΚ) _JEqe&:TڴD)2D"YuSD͸0:@_W)O:Ir{x|'%N}G_ꑆӐX"3!Һ!їC{L)47_nP_@JכfP4h2aK.JxIBPǴkP n b2|beQ1 @ġ}L9T` {J'˵|uuCHtGLn"Pi惫 Gtt\.5개Pos=p*z׹z-{I}?8+>= O/3s/9ׂ!ajvyF߇ '@+@7HatP zwg޼ \LR tIE.zAF\+u}!b`U?wN4 (`:@$@` pJDg#j(֯[t!X266|pݐu_WD3vQ p[N~i+ҥK%=ŤI%64B`,CwIUH|*Ӂ%/sٜ>֬Y+N1C =BCt~f>MZ7$7F󠥿ݛ|LDk?8NAUSntС@Pţe[ T#qMv - \p)NJ#Zynn\"q01%K884jx6`06*01*0^[WH'sI_S_~E,_hx);џ")qX- M|!  5I~r>)R:xYęg)^ n: |:ŏMzS[^?Qv'>.TEaM}XE^bfѯ#<%q6`gH|H4/3%AACiZdS&@#qu5? OoK~b;7X=( ɉ ]G9C-:1bV?CŠ'Ku/#)rra) IC2wM༕U:~:jhhiDHi,J:5BRpR{՜>_#**+Z3zL.=3 pa ý`u [iSE}ͧ4 dZA#J%=w_[p[z͞ϱ .^}j#5ʽjESEhnޖV;rD龉YVd@}m}u.BC&0DjZ Ҵ*:OZq?\hP'jJ9ApиE) Pڣ ͛"0pC\iJ{8y ea_m"CU]y 7\p+~E!w!BUpH 0m:@iʉ &M|b6/"t>.10}@ XFjMOjLॎvNHVE0jd!B0 TpJ9CY@z*`% Jxa(p<Kg-@ͷEMmSi~B`lL}|"FF߾m{F0I0lXlwtdMMe!y5{d,CH)-'F@N n? [nP F( P~4/Cc(POwtwSׂ?6`Ou*0jP ,yٜ!0^4jk޺Djg'LYF:o '/?Eug;b>0!j U=~'r9L'T}10Uqz3'ͧfItI3\=jK2>95p1wUzǡmwLo(P^h/E?tUlT!+ @MNW;\ G:j B4 MRhy JҴ1*E4ReJ6Tر3r %G{$Tգ4V{@^::5>qQMNAN Ys:MDhjڋMyzpSE-jJex m>sdYg͇8eZG&k#\+ϡ@@ d"jk3Ekr00He|49 )?o]w}\lQjuA_Nt8d47SN?^?)ik28e~G`mm5 g*3)6_FUVj4V>~O z p7tQK*my43hzn?dlzGΈ3MÜ%hcDh>3lCĬE`,]C  Y48>Lhi!E϶]8w0*+ ?+0/&{Zi&9 MOõ ^@(Fa$9cE邅ҨSZ6&_G=crO.Gk!|=dYg%MZ>HTUUV &t=÷9T-4˥n~r(JMmCq:\pRDAӐ~g|T;\LL@s#6=:9iC{I\pY4*膀jK T@@HT@T׹V0PX } t?PZ Fr(pCB`Ucp'`- \B:A ?eKޣxܲekINS4#QXll,I%O 4Td\]8$sg: mF.T\?`iΤ>WU8VvKu]ѼwP)N rys NFT?' J&oE:+s@W^yo}[Sg +U^w_^HAơ+Mu 4Xh_? _O5əszu/8O _ ?s0P3gtJrwFt|7\Ǵ/9Qx0KSY PB`W!^~ykrd!ҦY3.︳  z/@[ ZOE$M>w%;6ͷD |9ӈ众Oڔ*P(Fp0n:T4K/>^CًGS]t[}qy|GaH.悛)Y3"AҺ $CBQs_֕ RS}+E 5~gmN>Ł \C*0#gꟋ@W5s /X"m:yo .P(E8?"+e@IN?ZUXJf M6SY!k4/#ĺJ,1 &G P/X{P 88|p檢?{Q&i׸77on!. N QNrLT:rJH:W!`<+j?;%S%~ Dξ*0whZvxY\c@zxiK_7:2!ƝT8)>iS,Ts;9y6I6m*&Wu #<";_ @,gUK䨏 xp4jU:% k@}wPɸSa sE_x~!y_>}oذؑrui:rc7'gOT+H-oŀ˸.hoY|/;̝klwiq: ͛X|:\!tIiE'^0QҾT`?m^W~oɏXt "%lQЧ$_A!HX*XKNJnl1Ķuthn.W/nXNl= Is9 ?fx&@`c.d,.L*aN֚۝.3pϑdtIT7E1!( ӽycku2j4OnpFi*}CԽi0gTaC.BXPi]'iE1g}@ZxqeL,@wDǮ݃\8 t5$B?d hc d!UI@R x'#Éuv'.A;|~CtoryjMmc:MOFI.[ߺ*6U%uԢ .bP; zޗO QI,h: ):s/=gw~[23gՍ,.BXPi]<.Fձd(T@v@Ɉ' dq+_/($'a=䍧t`oDXЪ/3j#b\=Ħ1b)D&ARPS5W_->ksR&>iZ+ os]#m ݸgxCͧm Nqao{ `YPxIEÜ"QMд\ 'pA{PLҔ+4qۖ60;Is@GԾg?v{7}_ +Ā&TB@\O8DX@̧zJn>B 7Q8Y#НO}^1ccof;tmy/P!GiI#m;Ss ˩.k$͇6܆2ghgJ\]9 "Q$^Hpujba!iE&sqV a2q֗鍪T%KmN'(ՖY?5Bgi| v~8}4رc|]7Y惫;߽)1NA~߾u4:{ڧ>撢U{Me8ҦGCop}p7|>‚sr \/_-|+n~i~\U?{Nu"iJ3qH_0@DM+ LQ4ѧAu sD?h *` _ 0MӁDi;~(Ɲ#rTKsM1t(A^A\RS5qMUTУbҶ6MbC+)q>S<.4cFC*GwG*(DP~j bB{ؓ.JkEGz P)5S"-jmݶYx6[8"`,;v嗲[\ ń:5ӣvvtM ^[[4~ivbz-җ@.`dp~:>BFK뺌O:kG),\6U fܼo,Pn?r4( =>W`w|Eo㴩uԤÐfg^V7& n9sL> PVJ_]YD@H-+bN;E;p@غmSψ5b=hdz'ܣ7*nCG"ٳ͝wSC '`(0D=Oۀ\:#(r2\BhRI9Rt6UqW^ 5̀4P"8Цۏ$s_*i+\ Tz}c["KZy C&>oa\[x#@Gea`BJiLpM?q¬?ж8:ڍmfx{F 8d(0BJO>lRI Q`]c P: $o0.EnUG]:oqE6pU/TTQ-+mG_a;LyGwR~xz̙Rfmw@o`o 6L \ 56 rǦ"$M5'E%崓μZ~u 4h8Cp۷,@2@U)kHؗ;*.lh I"amBO>]\J׿iy8NdC"G .\=ԛFj-͕6FFf`OW{z%V x&iS=Q4O}z4P~˵{˻*Wps@$e} G&X("LЛ>X橠ͧCm(sDMBEpT%|޹CG$-y{ny~X.?h_J kN}}ҤI2תw\t4(:zr0$1ML~%m 45K,ާHBUm#j)>[|n_W&'_9CAKoþD G~!䄸9w5P[3!"!*]FK~ˑwM O@;Wrіoőg0Rj ~s^`p#=#A#"斸8dumw E Z\cq.  }qyǡeyGj}}s'CmS@жsi2Lo6 VG{_ ljAOԊ:׏4\ѼmHXgLn¾EEԕ*B@h0Rc)D jI,>|E $kz|`t O&Ԛ0 XRuE>-`8_ɓ?çeNOlh&AmuICp].\cMn0DipA}`D @W&AT w-qJWX+@3 Kufpm,kj}_['Q1\$Gt؈o(?vnQkbz_E@r)x6PkPt5]Q9l*9s>}}b'8Q/*QT.20ڔgs,SOF{6\z\#Uy=!HX7>iSTc)7/%'sSSBF(LSNIqE*8ybE qpE:܆CEʡ~\ 'Gղ[|~T7V= R$i16$q !u&Z3(n*{O~rOSx,0(XD. rul{kN V3 @Kq/Z[[Ĕ7zJ7H7̹kg.i,S8EZ r\3&$\.B iV0#hTMER&ꌱ):{FG4-.}1^ЩGi*ClNUNc -*ՄmNXT]O"^C_}!)EBܹsE`sKVOrt'k#ۋ ew@+/"pP-]+ĀPK}qIx}i1jT#oЩc馤2nrt@F!7QH3ܕK A@# xou I6Rc7dp|ҺjA=,ڦ/[s-u\j͍9`C-?H'@ `pu9^Iv%s&"hHõ(u\dY=E_'7;}xvNmY~19I#t@}]!{sG 0"VD`[[[ourw?BYAUx\p v'T8D>DԵ\Ѽ:./ clLLKڔs}FBQP .(* BSS uvkhi88BCFySN}n>rp.5.pM0\g$5y r[Z90:LhO>xj@E`5$TyjlvR[@ur` t?$0 򦨯^%_+% hYUeq}#Zi(-|2MMgchQ55`pAƨ93v:\; xM jO2iEڅ}CșΟЙmu"s{$jC'`[8hCӞ!21(/-s D[$+^j$jT)#8bn(̧ZiF<{yOxkx-'ǝ8F{ )Zv]!jTnsp9w ISw9R, UW3D}J?9Ĺ(3qՊ&=0HFHq`F!QYZ|1cEe/I])?*z}AJ,i06%Ɠ!.paSqX1  :&Wˑ6UA WMHZCY\dۢЉ~kS*$ Ŝ.dFҦ)qyZi!}7K.yޑJ)Z$10՚tX`[򻪓ǁ 0i-5fôN=mX"%@E? Б86卣w&Q29* uzjt+)P@I& 0ؐ8|Ν֪0iG?Ce=djȚlF!F׫V*"sE; K4DT-cUUHdLEAdܹoDxun?}ޜ$RUp\p:$@oR\挴2lL1YqPg/R1it^Oh4 ŜFʭ7Opk?hL0&Э1m_mqU_}^a ШIRLN;(ytwwcS0&D.k/TwQP־h"<5ꦫ*x>pE5>O_ƲS աSoFxME87hNp%EaH2Z3Mg,RdCK-0')q 8$f"#1BsZYR014Y NB=J $7 ~2|Z9Hlܸq76#9~sumٲEcӦMbb׮]֪@? ͨ(jkkT[OWTRSn i]RCd}#}on?Wu .`th@&J^O4tQ4dF'|H=W?wb8u - 4Z"\pa D8<9WQYiX_ѝ;:2*_8yMR?~W1ȿNI?t+]"ݔ5pt`@6̫h?,F P)mR޹sW([ES"5Ah[9KTJ$d(% jt)H8Dj 鋣>t Moʚ0WhVaH> ugsz= Cmv7{ZDGz$]E:q&[c;G!֖RUrn(>lhtC׋AʨpF#}֒@@Z SG^uRUnRWD>pQMR]QO-[q.QK;+mhNu_\[/˥~}INgo̓9ӯ~FpCo|!C`.jkk'@Wq Q_8ЏJ `R_;Dq`D77xKtG~A aAn$b R<" 7 K+BUonPr1-9pN\Ed>pďiMs'>< I .Q]U- usn˸+{ұ(/NsM)ٙ3ോc }qy8Z~C,@XQv0Ebk6`+8~oف@  $= P+z55PrDQ_~߿_!CJ1 @nΒ6@:V|EN/e'M,mé"5FK61B*iju&:jn.tCH:QlziSUx>WK b/.5D7=$#ce9z &\R>p^}Kw*>ttpc@?.ܼC;?uem%>."{>zN?_$&쩈=ݼLgTXjU#`L@ku 5v:j6Ǐpp88a9t#s/Exfd0?kA4oj#hmUq\pF`+wqAG} D)tS ϚWn:wIgi"KT iJ }iּ 2䜜i"n|fEa|}3Trq_8XΎi0/" db{,Ѽ.2ª3*+k⬁ˢ_`O{ϝ{E Ё@Y@@'_,t F$@SKwkοRKՑcoGu}=  >Lf˖b1%b@ddȡUi㨏n9\Ҧ"r@^y}ciu}"|p~(>T5n#&mJ-3Gb\i[oM^~[, 5^~pϑaq ,f̐=" nQ˂ `5 CŠߓh\q;;8IH d*^p6z]|K|p;:JC5UیM}L]=6J.E 7-q paBtYbqM}CMEqwx:qN@@WUˆq;R,n?u6 } uN.\pA>}ՅƔưmo9'^bVXPQۑ =vRUu^08KX]Uqۡ#љjA܊_6}0oR@Q@߯R=*x׷ :PeT&<:vO62xNUAtMF>F2}*i\A 7'(ݘ/ }F!k/yjK},|(PFtgˑ]͡1B{QeXr2ېƮhU8W9ZBtQ.) {|YZe9>hyx0“\0l`7"> q+vt϶]qkv!tk]۵:ܵkW+& `8E}떭y_MPwqNعHGP 㷮:!&nh+DE^|M Jrsj4|3Q(\'RWK+E%k:7p̓t?P;P%Hͳ:]}h5!٤"Δ:WwnC3C_O+ TiBjT%de~{3u2nh8\Lvh"W!MlޱIt=G>"1qJl]"m9W~ݟXVPNPQ*K{j`WSS׫hP3k׬930Æ T&У=Rh6.4z.NLR0YsY 2Dpl=婏 | j%=wueXRx="C_rtsCXhÂsiSrvֱ^`9'̍˥.c$Pk䀋XvAAF#`cBuqo9k=t^!K@pA4 ?乳 .0gY .@ugQsιr%!ҕ kaByZ4#;*riE=ͫ?4ԓ9z\̈́'9ܣLvŅ\5wktL7t4Ʈ]Eg[Z"+ TXKn1pD*p*mjsOpoZZœ6QbhتjYfcIEԯV9casB2~@bkܩMEH n\X4.Ð8m6(TB}L>\\/~)"/H^985Rr ԄwsgJTc}qh ;hG/HɡYmY9-9N>2g$diZ~)AA'φU&OGGd= WGn ?0{d۝L@kZJ_c?23^KYY h)WOyw\4ydG+^П)mwl>h}+m %̜)i "#y'*D6䌱? BNf?GT)Um AYrim:'4 |39p=H?.8cCΉ{T"!^I?9 9W|NQ>;ć*=j*ruw=JVqآ~0A@7N>}-:uhim4w(8Oj&=V-OAf(K˕6\ M/{[w.N8ύ7,-N<+sf)72׿W_6p[q>p7?[knNp; ԅY Ҋ4iEs)_ummmj3TWn:_%f|^tW5EQW h zv!J{jÜ|t()v0಍H rj41@&qw AEGmAX'+svn: "|hre\ j ~d|DR%G4aB3DM#$uo^t"~OmPptGQjH g`j4S@ XbN;-w!o@Z2\A>Q[7ëNB; r{\ѴO ^\S\~8i@їC͓Ei n?gQQ#f;\P'Ez=n ȺgZ {"`rG D\E v*U_'Oǣ(,0921v}=B2N<NUܩ0m Ydɖ/-Z,yc;+L|cҀ e4ѼL2 2=~/Ҧ?2IO3 eo~p>@N nco! +SKr؏4AGd]8M`>\!!bZS@=fR3HQ^)'O-⾟~I}cyUlr؅'s6ԊgG߇u=@xt)u[nMm8ySXN~`"㔩b5)@Cif #Rџ -iӬy=(.P6:қZ@vΜ95ڻEBߓ@ĜqyG&40(1qxcԯ?E8ֽg_;n4.V9}V6?GЃo]aUb}]W+*1'L-,r-/I}~_x/z͛|gsH~UEo0:%4=(iSR~QG [,>>oiSϙ7u3M?_=RS}73NN1g$O‹if(UAԩq%eϷҴR hѳQ!Y۝_W#X#ls8b?K,\D|j<SПtDQǍ?\m66=# YYL)\g_juj1z>JidsGnS߷Ԗ:37-~qXYr˾+?PJ*2RNJ]ڟ|߮=j!(yW]NpᢎUmz@}k5riSM@ lɊΉ>";@hcS4 YӉIttzv{! aԵ.pc`P '+stI#SSۏ7"aht4gx:7oh%׍燜n--``tTzWUV#zGt$yh; c^pᅣG14aD(gLh CHtΝf|!&mz*#% 9) Hc{_B]-]Rb7e͛>ǼuU^; EH{I^n)rޞ.✉n"Ggght.b?k~8|5c"Ͼ"Zw)+ιR9m~GO4 ${*+Ż" 8PMNߩEpsK{n4SKਏs):\18Dt.:m2C*s\P,G7br23y2g_g{oc8Eh|]0j1gi?Qqg bq~)Ow' CFk/8|ާ _F>cPQ^A@K80\#m:1EIp"ܽo G}DtL͕ 6{u\pV|i4ʲ8r0.p^Sp(r!UQԒi/aG[-yRyj̈́Bg^-!Cm[cƔ8DphC)k?aee@(080ix+V*Hm@_gsLjWtW'\N{o yN4«r3.WAk(нIj4G & a.W7?я8F0 )Pli|?b[m5Xr[=O AQt.梺HTG,~93j{J]ckvfz UP`(P.f_K!O0 $p 稏H}\p]z4K,8cSe:>;8xԞ)׉GS87΅iR[\#YUtܼ^$wg{E9.~ oZ8U/35?D|4PD-GG@`Ŋ8iƌ39'y][e@ h-d8jM nC .\?Uǎ-婂㗒I{E<1냟g]7]헕/:1婧İuR1B^td `\*Pۗl/~\7_wR1FkJr iS@<5ŗ&tYYƜwP7Ε_?/d6B(Ź׬]$+JgC!(' _Sewuuu֋=6̒pYZ_/?1g %>?4%oy@Lp=Q}_#7J&DrCMMT('Oő,RkLđT Ƹ9{08\L \YsEO]{ Ѳ0ܼ\985W} ,̟>{7ߟW8D L @gQA=R*lW_}uǠqaDsAn?Eti( G4_| 1|ϐ .GnqnRsEudF*>*. /Ԥy5upHܪÐrǷ94!@)~&篫 o*|O'gt;3TT 4oٽ9-?gknkENTuҡ|&5&ձCt1֗j m| 3gi'6D~CdZ5hkZ.7=k=cFg^\}(H}'mJyzj꫽Æ8B="~W] )L.Lͣ#0$x0ޟEAm;b۶_۶ ].ӢBtOZ8~r80|x,vOxs\q-6>vGBN-Y_@bCM : '61Ei4Ct\qRθ/).(ᐸ̅,p(qh'^Qq`Ҁwn(yUq@1~RQF #Ĕ #ʪ*1&_R&{0'QO>[z1Dv#Z7Bl\۶ pP0nYxV/1!3}q4nb.@"Ot6{8B?c_΍uHd]Ƥ5{9;.|iE;䓢TRj~jY /͒u5:uM.F=xp;7%3kOGϲ'>,4۴Lz7@ϓO>\6M3\}O56^} 8c7d .43qJ^h8?"wnZvH)Rו~']WWNp{02gi=(?"y޹+W:‡~"yjq1cEuSz :Ϊ=us/zA^.ҦQkS G>v}6`yedy\h m@d\ͣ7M bqS$}O:TE5XkE.Qb`ZO;zƔrIb@{_^ ?9Z  xws77Oe0Ψh}޹ uLEM V$1o :"֕Rvnn.r?~ːjqNJ1/**k2{6Q34cr#2"VW~ZnK  S,w֪\惛"}5(q sF\\>բaĈ㇤?Y[N'._ސ6 ͫѼk1G;[S'u!Y?%IVp׾\Y%}:q欳DuQU_uG%';7oFiTi[Yo/ɠm 0?(@) `e-]s?^6Zp_!CLCDԩS2 U+U#gЂNoyDh>|2w(tpQi]#Hyr33fxn?0.1yP^'ϢIt >5wμC@WRʿg—|ӎ.|@{ߦ!E8` X|CD6wA#5kluFY\;ߥyo>1] _ 6 |Ȉ>\}"sv-w"ᐴ rpOM6!~7Ŋŏ!bŧc{m1@M=;~7k:ߢ1{Diׂ0_ e"mM7 _>>KzwY|c@\gq̑64wiM5琛[E9>pQltKP|I?X<=ᅩo*qLjIGWMhht_ܹN_gl9v|jZol{mlOzm B |<=NŋfȨis菋iS=Q? rLmYl,4lnRYM]<ߑh}ۿ  \g h #S44MF}C6QOS ?,?y^Q߼iYIߵ:Ğc29BZU-v /lzoV$NMLLy8/_,Dd:*w{۝J]dc:Y {LiSnn^alІvÐi߾ 7*ĠA ySO-w?iA-0"ĒK}6P[XiҷZ%ћ7Msw:`ctoLqڵC~$NC4_Oٻ.ynjq `f͜)KKs8]57_9;,.Gܼؗ̓_[0?Qk(P_Vr28ߊløq~~*38cm-~UTrX-+V~PϾuMkE1-o=&ߝ{y0k `ɒ%[B~~m]c$L 6$OX)ʚσ;rߕ\SZ7vh>d1~@ ĝx/opZZ[ N_uO^ 9i3UӶ^׌M[5{^i{K]g^s#TJ4V@l  u0~iS7;Z.mG`}jǾ6P [4t4ICu0~ذac_9GsvI߹)zW {wGn_{rBx/Eǐb)@MNQb z29eG}P Ҧj^W?{oWue o(k,o JA+y۶mFt|OsQ\+ \GCD$/EN._%FUN4SS yu] _6e'SMg;ewN2sf_ZwFߠ,U. E\@/*_?ڼ%YeE'콙X"2}ZkKѸIӼ?c4ڍ_}.ԶgҠ_P屽! F S*?Yw70XA#mHژW4jb.Υ)Pg^3g>( >}N.~~QKI촁B799#~@=Qpܓe`z:Tvf?7JNا!yj5;vT@6nں8`yV[haԙ ba ]]6/F:>p{B)kWYVB^cM\F@#dzy1Mt׭)% H N΢ߝ е6l{ 9+*$}W!z?F.yYL _Ps4 y5΃MGd 22FϧiD7I4RlL+E:KURdtȳiS5DZ)g:fH:+upk;̐V6-{̒~<|6~Fu_aqP3 ǪNS&JCd{Oi!癐d(jT#~tĿ-**.((Hyq(iS$m[͐pAG[+uGp+g 7nlͳ|h[+ !NÇ(7wTM%Q:#ClįdsLU(G KC k\`#e߬짪wt$(P}}}=z_z*ܳqơ#ylMn< !Ec uOQ?Gw̲?}PvwykNX,YϼZ0 3(sKg?pԩS~-3Rߝ"ji fZьsﯺj }ϽG44 _}28MX WO6 ʡ֭wouo⹪:.=;?#~V?^4C7#~v~'ψf)i`:lػ5lk3ou 55qW/j 0+ @,JN/;Ɔ[mI&:dGT7`!g_Ѻ6](%`NlޭqgbάU]P;^ZʧhQ>Fn\2FP=f#~*U?^QIBG-IQ]Uo:\99F W짴4K~l+*22-u':Y?JvٿLviS7fHV<_`Nc $sSU6N[欢Ҹ+G-Q '&RuuFuňؼ4庅4hpoGTPyZNшPʿ#*Po#KOO.Ni颿g1gkr9saP66lv1}:r_=$ 2nL;ßx6@FMuE4. g?;p[y\kŋD9{i⤉i&#?}8*[nI5kg #~iit!q͎E֔)_q4g.7g-)i`/:7pȅu!M0)\Kh3KOyyy#WUU*wz @[  24)c :N6/tOD^We5͐%OF`.n&&}2hDnA Z5?73ghW㷞VѾW_Bc'Lሟ_qy+?L9F/t/}U48 98o(*SP]xX8tPS# ⤉`VVp.Mhn7D)P4W<!_?6g~^z`}V~Ps=o"pϳƣ.oy1ed刟_^VBwP&e%g=x0G?l`r5]bԙ:?^oWz8TgtZҦnk:L.xgj:е6Im>\ |ڵsAz=4zvj>'|Ϳ'{C5kp}=d} )kI[[FT,j޽;~&P% Ti) +˗_o~s#5@n#8z$_q ; B3^s6ϙ<20s̅צ@^3P66g9s91ڸi`/7"P?%Kb]E?i"G܁[s띗+4h͛>Ӧ'!-ny4ce1sRx3MG@ _r3~@A`Ds 򩸨%pK'jyuʲeuҏ_n>0h(w޺ˍ5tjU?,֜?PPrFnP/gx,K=+f:*++[zC*ip<upy5@M,LnS6G8fH.:1gZPG=ﻏ}}/^{}~ .aÆѯ~Fi{]1;M[zRwyBҷ٩UůRI4d ~f?sWez?#L{@'$ݘy9g‘UcW5 =+ࠄMm)~i!э͝\Gm_TTL10ϼqD/A_E_rrx-$}73hEz]RadUumʿ?XBEJU?{>9A}\7P_l~# e2 @)[pQsc 1RZ7<7en4g:y;pq.L| (g?pAb~\jjj~Wsw[i\rc%SaįY/i x=9RJUU"샯&~ԩS9ˏ~:?A)^ةUw0ʉ?yt.:n*`?ˍn?=}{}J6?4H^VV`4?s*_43U_Jr27p/ $}_{,%}d~:ZC@?R 22F@05N։@?x`nY_ ~kʔ)@]A?nWeTn^~ȱ+R sWҺVB .GC'{@Gs!Z=~.bxF?tG?`&@J+/9%Y02oA+*_|Rw̉tYAC˿{A#~G,UwfU?~ ]>~ 3/=F S#`UR 5 7P{e 䕴nWWuq-1Rwuu@jdV9]#p .hkiBξ7Be]eeTS}JK߽|Ԝ N4RSjoV bo@~S+?yFP*U?9҆O}ӧF|/@^K&O.HwU`NSpҺ.b1͂3:y]kcAnIjpu_3&:%S s!~LGI247©bWCunXxqDկO$a38m& ;֏{#ߘ^>oL%d`/ f(=ޤuPeX>͖|8Ƒ0K|jWQnu}3@Cg8׎/_xAcFA(3#'=x򌿛:|g]nNvɖ4¯SJjOQ:Y`YFQ(sw,HQ裏Y |Mvkͳ̙`We9[ȑ#d32ۯi#/\p '~tC@c+ ]Li \K9У>&~+zT#}M)^M7l6 wh=y*n]ó/o,GtURSB)>Ԟ:}~G׳AC$?33S|$Æ ߱sg Σ VK t9P[mN^qPGpҺNټNmޜå~n?z, E=BΪ6AZs .0VRx۶!\xg"ȯ_WP-td2joQ/h]u]nNկXe}~f?>7xAYF?t0͙3;?FcMN [uZXl<-4D?@wbTm*"cMX5Ly%|#3PUթ[sa ch|M3IZ'A7@*p^#</.Е㖭Y"N{nOfe?۽m=FW!_4<?O7z"QÈSk/!J)iӦ3 93?|p1uaQPP@w/==KJ֞RpSD:}]-S bs߶}{pN\6o\+S f@kw.>b^d>&@+pulN P[?9}ۿ~HgtpGʟ5~p!?P^/U7SFRo/8yZ0RM SaSge99TW[p?>_iܯa'=w`;Dl  JcAl ԕ@Nټ.?@r}! ZUIu&y)ѯ;m8B^p3 (I?Z\ -QɂKq[1Ƨe?*?>rZZ}.asB$#͛G)+^z 7ܰz;uT!S0rِA^`얗ђֵ+A7Q41 fpa~!cPD*ho~p!j6k,tJ?EcCcX֜;Yy.\D%=gG]qM ~}_}.!a3JI_dp8l<#~5ЈWQJ@g+?~Fgq*+Rr(bx)xˊhni6`Vu:/(MlЗ6խM$XCSsۏl}"[/*Kq0gWēO>~K/LKoNҺq@ EeZ '~^оvu n׿>fe\;\sl>s-/3 4 p___/~L|a?_U +b"T+@SÈ-UN%Dm\猿k|r;vs!%F@ޜcǂD=Sq:mVL0l(HB~)#ewSA"ytouuQ#(# J$rY\geP^,u]I(,.Xb F:<5C&sƇ]3%''G? m)ۍ௖ z,GTPIeR̉7Rb0*<={ʪj!l\_*C=4>--U\?a$472@J.u1S ?Ԛz;ctGqplv̓n 0rj A3L u:.J \O CG0hVCC='S ~2k_jټlm翼*>0/s6K*`%|}~yA+]vӪ|JPY`_$~Ӏ󩵣/ԠAtL< 훐p֬ kذ9==2f?}/3 n?[c8?7^_|ֿ\S@L]S !|wYҦ9gU6cnp8S z.)0f5\ V a3b$+Vdqk /$+?yl38^OassC֏EE4thNP?\r^+Ao\EÆx~rN#~KW۞MjQC@`>nXrs{"}R6lW;1Cq{ͽ(W䣿Iv`vc 4eDdtTFFΥߊ W.][xMu*UvCM&S94>;KH/Bt|d +$|#~4^9 [n7 @sO /PN==:"g`F@MxN5dz)n | #<18 g @b6\TZ\͚5Kd܀geS"?~|ĂKn@Th1\PrV8~@}/hWGTO6Tߠ̐F?<؛ˁ_vꫯ?~A/[Js&΋7ꮥKN6W@wd#pѺH~S6&9h7yl@Ȫ5"u$l.AE\൭ Jnuej~]3$l: p{3,ҵGT +q_}Zq?~4yp/UDJϹ҆1?<pOi H<*?h#GdJUUU2gJ[2ζa:y'+a oѠ; r4_hAT޼w .C=Tv4.3!M6s KKGpmk#vw~6˳C֏f3KYoAWD7V#~N~'P&\NePB(8yJXYc~^FWAֽ;%9H򜮎FRR@oߋB PYY٢͛7Ӝ3/^#@Ezo8QSL dֽ6rt`jdeB>?nm^Yƫ)@4&_O3>Ƕ3t!JN@,إ}b1.d^/'U?P5]}'QE]t3 +92/ӍlzL-qZiiiz0.k .A@psZ9vUSMh[5lttQ^o]FV_ژO?" /:\'2`O/?̜a?;U?kCBo@HzG榋{M>ϵ~CY|ϒ:\`_ii>{e940c")mģTqؤQ-:cۯ8";בYGbX[i](ag,~#,\XϿ?ǩ6F\u6pauzFF:5W/wݰƎ!tb*TϠaScsti!q /233Ž)ws_\ UҟڥnYN|.x)Fzue7@I>cE\rIԵ<;)&QZFI7,~,0~aiBgYeXi#6vk d5q}TAb|,#w:TP,T2d9h?W30{)!2 MZ+V._ܓ7.p3$\l'c.6Z󿍴6f.=#Nb"Ò]+%MINwokORֵd}+܈ߧ{?֮&7$-oHΣQ*b츱ƹPB'O?7 pCJ/8?ܢ/aJ}vFx F(ýgn({` .td/؜cAn⅞E\ ۂ2gfpJgE?}-G.q]} X٩5 #+UA=a՝H|<'%%APg5}l;Iv3`حn4l(?Mt~E~h,,DWUޅ{W%}ovMuFqNԜQ=Yϡԯ$U׵]FdmOS>c?!FgǿoׁҖmCT%G&O>#e-6?.f޽5Nkiɀ;n?`h:HbAaexm~}=4S7D vō`+ \ kF@>$'ߎ,~F)jQCSiiAZwPkg'{{pI`i T*QϜx#% O ϵ#A S߉rK:=F1Rp+UMS/pT@= @' l :Q M$_@F'=׺LDBԭ gnuAK#x:Ft2}/۵s4tpf:q굽w.gkUpQ6M{@{{{VS[:N7~]j/U~I(s54(1%R}CcpFGMbҌ އ['ML'1rY)/<q`@h'q@쮻Ң2pAީ twh sfp&2gfdd))Q:Eеnrk U2ubIYcSȬUߵطM>k"rii)% N /j&ḇB [0]:mO,G@[`M4x`/KUKMl|%>j7Y?+7yT]))r t)&@o٣h`y&v3`!g'?Ր^ñ6Z_}rk۩ɖ\V`&h~Y3;xt \ ciYYȿ50l.X5C{Ӭ3i„q/}7hg~]Ffy~4A=9N~R/}Jə4/7fLe{qW"[/((e-v#~Ѷ6'"|F9e3zt]mh?`ThzmUҦ x:;h6 uy o^}ϺE?f@K8RnBvR3;{Y11pzHvV~~͗[ka̐SR]k׽GUUAx@wWg"B7V#~hCoEůMYo<ݏ\t%&gI8v4,u~=j[UH_h2~w@ P[EEEME#-]pS5c S SmޜnTut](P?}@ ..p<,^dE@#nM&e$@t*ZR W65e%[<8:K'k*Ĉ/F͛y#~%;_US"Ϡ~3՟AG^F6/M~f?*(+B +g&0{ـG-z+T+ē 5Di7dӟ}^,|/ڼ.ǘ!N-S ;pa> 4w;X @oE$SX>Y'OYw.6Be$>],_[Z>@%ɣuQS63Djn#~yyyOGC+ _ůnժ~GMI=JdN-i#)s"e ~hD ro1>rmHHyoE-{,Kה K/L}h)肀z (wuy9l/t P`E Y)6a]A8̅یNse4:ن[P;ٍ1>G̪l>pkf.T?4і'+?z# rwΜRs&y~j/RU?etC:4;NUUs(9rTQjk9w?y!ixDC<vK=cq] -_tٲeQyl7^%gn(pLl-Ao"dNܩCG\^j{5VҦX*;(y8(t<)Q:wBg9 ns,@K$sm*w;n:?33SoOÇf`9mxCݴK9}YD-ժ~}eR?9ollӧC^jjjꚓ", _+r3982k'78C𜙕*{Ac-tsG 0z̀.蛿o'i)P8ys6hi/Uܘauz .xDF}!p^0e(o˷N< 5C %J `A#d>R埑>ti1A3~81+?ԥS/^ܥFtT%hk9[ p5gT[[HFp5P 9&49g9|k7;{@&_+ {XJT3K}7`&ڞuI{S  Щـf@؀7|&'ڼyuS FT:ҺkNo|Mn["c*pa~ߝ͝N< uuErGfʗ8A^u`n={7[7l*-Z(2wkњ)-|sҋx~jOGJ+dįPu[.צSq_2%j~^diiitޤBKaa4lP~4]|j2eY9¯}&%QCSO ;uTo<l)78b@@ `33^=b`N?pko:Һz!1y7j0v"s;Zwh¤+ʙ>?A<ߏ'/h|󭷅miEuFTv7 U?GZ;Re{I0PSRrffU~퍬<]Cs[; _(srG Yc-kkC?%5}p˒$s1kw6{Ŀh+G oʍn?6?6>QdbW7\`jE?׎f0yP.=e6y4 Tnow2T46n~HB}YVRF7EfZ?ўuF_tX٩5΃MԯoRկ_1r3kx ~A~s߳=/L`}l??9 _hrg;-R%:vڂ5\yp?{/nUܸ7ĽRYa%''86T$PWoFG74d̓fbtj,?3pvy .P伢Ql||0sF#22~˚.Sz񴇹/?/O1Gl?(eLrR^x^GƏNXٔ;#>546 DP⇎Ç h/a;a|^Cs%- 6?;pܲTF#MKg@S.hdLu;ف G.Px$//uvҺs6/7t: A52렟!mWx4fY|36c5s3>e"]^m PkShG8x5M=!#~v~K[XUR#~YniÃ}zzG`G~daGuǿ;o~jnjJqL>+挧{|>›CNmn[tr߀|?2kZvrdP[מ^ zu"4{[zz:q֯ZN@agwx/*P@>ѡc\_?#NÁKi]/O?"e4u*XC.܊4'Bp[^[Ύ3qX] jlcSS+>t)%G*<#s}Ŕ6á ~;5׮]/ieO.D)遾?k~1aߋqcO՛^[J93 Ĝd25}9@S|.Q~[mʠn/3¿?hOloF1cl,T5_weIj ta-Cg  Ra83~?\_LgOw# 3 H K.ɋѕ d; .1dL@!;Une {?sl_3e\w0#Xv:@p@v_=iM8js2!?T,f@ 2SմZ͛;.hXE78w.'zv 2} ɓҧ~*bS~S?; Q{cn?"gL+.yP bqSa+#+DQ(0P>,>DuM,l\N=X,\D<':U Ѕ^֔6ŵFv̔!#m*;"$j~p\3~\[nI;Ə韞*?$;[C{?<KLJ﹤/(h֕z~8ůMG}Sh`4$w %75 㥥4utZ?lhG\@ K+)KFr9YmԱ&b]p,'zJ#p.0 4=2iA Q#B)RVdaT֐P v|.9cA`ER>So]E~/K{uN~=Jp7|0=JG ³gKeEsb566h̸VN6?׉Ztdl3)@hwTuxCYw[̞NNZ\Z{n"4ao$nkl\~rI ]i]!db6Pfpg"WVV*iSgrk`jQbyW^}䑇`}TtgJ̋YԈF[,U2_CYT`ރ=:?.(&ko&XPpSN""4L-^0ɕb`S_Xz_v/*F"XU覶dMaDKb:eYXpaB̼7킵[S V<7Wi  4.B)\Rkr=DT diS.KQNwc̟tǏ8@:\D BR>J.% q9SsRgԪ~pyuI Y?|#rSjC?b`A. v̜vڼF~Ϯ͞C š!PwENQXX6ps@JuLt)1s6B~\;uuE 0ؐ:1)Һxx .p04p R;diS\;6Max=쉐_SScdh.}=ň_Ot甿K\:2& J 3=f`q'N$Ҍ`oW;}>彤3)p_+,+--MHɛ{ @@H)N2pho"lއE -yya7Ow:t t*6 AV) fj ns+pQ,5C ( [۳>uOLuc7Щ:uboظ:'9 /3FT=@@w|̠/sIX~Z#~ǪN-b_6JjI_}EmAc~ n.:jr_>Eoٰ̜}"aά&aqh歘3㴸q:3Ḿg 0NA)MdcG#duu Aׇkp>s@LG fY+96vc{Vkh[i{ȸu^ 6 ;hg_>|8 6 F?,%} y~~P^/;U?]MBoHj(;(G/.~C׈!x`kK.)_|-YXM' n"ټ]0J^uLZc +lfn 7oP֑C ~[̅n}mO!u7BbCЪ#mLCّǀR$Y 1+mO|&=>̵Tdlm iY\g}~gF?n;v_߷k<Տ.GZ5 Jo`x}y|,s?#$~o nuY'" }#ut8^}$E9cxL:z&|Z1= @0ЮxVaq+|Y2GFf#0eǙw^ۯ9D Cg [V<~}O|oJWN}{>sZf8IFI_s63''kcژ)b:\T$Dd05oe-|y#'7eF"QJɟMi# ^󧥧 E?p?zh/ --4y$%o1AsSV ':=?r, '6Q9!0([8(a/AwYmOGn"Ai{lyU4up"@!⠾E:BNƪk Q$ώM V d=@f7g'm˯,/g~X'i`]te.57ur6ogm1?dx.=^j!g_JI_PS.N;sʿr/5VpR;XB'NV@C'((53HOK3/75jdP v/Ҳ":ΨH@pFI Jvڍ)}.`UG81 F<`/aZtyڼwZztjxtYIVN56(Ɛtj:!0/\ rW-553XNH?.6q lf$zs 1B:q3`O 8acŊ'Mdq3S`NKkNn[B=`Vo7WVF .p7)od_r wGMh[e`:v>CB^|^ykx>\ɪ~{v~@kWc_|C;D,u{#?8 ;"Un(6e=cq~Dx\0Sʾ]nMTocp~WGґpܨЉp&", 4{@Gשkl^\2$akX7*K+EYJ8nXxXUAQէK͙%C7RK|oY(/>x͙?'"XxLuHPk +Ĝ>,skpϧbӸX nzݕFYo~cnM1x.]GFw<4.Qz=0Նf:^g_;(ݚͣX6oΘJ:V@>,q/**0[BDP5β]ϝw9;0ˌ9ůMqРL>xFW =&|k2/9Ћl.?2/KtGsމ9Zߋ;N~ Ru:Fc{:ܘj>OyZtu@yZp:;LhN+[,1$Wn_;l ^L-PRRRtc ?RNVvc6l)XHgdvc{Na(@d@Qs5 n\3.~p?U-UG73@̒oc[M|Ql?7n,YUGСCf>xoGeQt՗SvGF"U#~çQ ?zDՋ}/5 D9C1>jO'[@Sj7{g@. mJgUo q9YsssW`ÆPڋ7@Pkѝi9: ̿"SD` ةN=g.VߟYMH(MU6 S=m6Ϫe\@]Sx)!0aB sW 3?cG+TMcoɞKjIɆ3JU>(kµtWkٸ"0[ityv{tA?ovFDEk>%u7=Шq ܋\c0 `8tٳΫ7k [ v| 8 s-Mt8D嗕A \`LQEvڻl<:q1 8fK:cyP;og)OF>?/70g1f6vڱc'WЦ͛i)TwY-#~91.d ~o;h؞BUM#ơW4O F(%U\t7!###gOKK3i#9%pwtE4X3E5Efe(BCg_~dÆrYPMs (M: nrnttyAh d 47PeԱk׮2F@dd耰I(b<؞nICjx,gq6-/<:Šă˚6s!9{/FfϪd/]~ mn5|e̘!iƸi \fa~} U{6#(?{s̬~TOw.䒟tYltNpL Ӏ`i _WWjieJl};%lL8gƁkVVҺ*h ijٽnS MA.n\r0Csҥwy:@o5y Y٨; =~@MY)g`d9_ԪϴPԧ)4BҒyN7"&#~N~_7IFc\"7˝b^r/Ye<=Ec`u-7"SL bM,JDʊws勵 R t&tFP=k,ݏ`otq 0gv\Fr폆npغu ;~KĂN-OGh41;kp̀N} {|c>7YInς2#FugN~5'(3J-`Sfxzr/U!S(kTg/2>|?[h5i,Uk9 Pt["9;iVjdn|`_:3nt.;pg}b3 )= ]8F<5:Y_sAn8#ׄ yQ)Iڔx=Ylه(RY+?2B @VY϶nFs(ڻ[2c+/\ҷTPZ#~PH1: J2A|9CYfds9#߾}lm`Ό2!Q[`ntutn/v~_|={`MSa :m($%`3G@U@fXÍm6XiЁܨ,uMqgayZG};ꔤ>C!i暫iݴw>zͷg[UKNp-3zFtU( \Dp?} e? [ 5mEi\ѣF +?kA-ט {k(vۏР׈ .(syN&`̍v2J m˖-ԌN똚S)Pccmȍ?8k#4s ˛ȗ1f!zC몏Zla {!J::yVc2ɸ>SR,Hҗҟsq 2l4{.3gNnUK9&&ecMU5>imi{C̟?9*,}\89[~"?eokJn*qqV'!R~@#`oIp6g#geeYHAM\ (7j)Puz2\;;it+ENY} _C`E:ZoCF?qRC\TtH??we={}f?L+Ȣ~( )itU h|n7XFTOǛ~bϡBR=jkc~{}~}顇~" ٿ9ϩ,{%@dԷނĨ0g)-q˂2MDt{kO'f0 H>\q:͏{qs70P?&7m^_R`|a1O]>ۛa3tF1ߏ/sIX9aįZկ0Iȵu߯P=z=3c?VNx_۲^GWƍnE;hkv[S 7<Oh5 6vc ΒLt 6L8۷AmS 'JL`GpMn>tR5n.]?RFiόhA+#L DhR0e7vB-jֳchp+΢9x}y^'L~ k7^IڹЛ?7oOQ߫WRկc0O%f,SyyX?*^3x=0ֽK/~Ӈ~ҺL(~P;]H*q*+)|8s|QK;3 qp`K^9C3A,~d }xi)2M+%}#~^KjIկU*U06JC 2ZӡE`YF# w/9.SVʀl;t~s y]6F%7Oѿe$?=XK80@@FHq#urP6N*5AXd8x1 X dT0t(tJBG}jInpbcp^G`и(!4U*e{Zj*7Ў^+W)ގ5A=QT0|z/s5D}ч6 qoIo$F;|N5'EYV>dL&1jV s9tH총y&~s7g}}omiWS.~Ϛ.6ˌ9=L˝2H=1fI¸J.l< {~ l}ovo]u&O$~]}*3,,;칹׭ͻeR0Cv& UwX&vB\BR"_h.JzuLyM .C]3^Ò4#e;l~;*J L}/w} 峹vz{,% utF~9PؐIJM\@ gLIt_^Qs'T x5oy&d a(U[)F8Jߗg;~zie SꪌשfuòTh #-o>l5T__ҦzM00&dZFOSS)`} *}A 0P?DxF_Oo暃eʿ%召USR{_j*9j#5i`֬Y'쵧);-i_3S0pʊn 3eT1YU/AD\o9n> w.yʛ7o5gΜ W .s#`{S 9F,gتyx #S*B \dJwVec%m踮IHU4IQj%e]K,Ė&klOֶldWRNQ,ٲeKDʢ\)R"H Է3wp}7K`0x3|~߾ 5IAA"Cg=)MR?{~ҐU׽غ RC`ˤ_͂uxLOl1]a= әVw8?wK"xT V`BsA"g~{*`2; | a9 &Wq j kl>@80z`ѿJ xyK=6ӡD(iP /n*>4r~BV{(t@Bڔ I|~GP ? rؑWW]Ɏ&UVU2HQՏ|lt~ï~-l䒾{O7<Ǝ)_UJl4~AVU?'7x#q|nb|i~bu}(?_#AҊ~E{؏?g4Г[;o{k%}W_!~/&15'qi_'9gw>яHW (_>|[~  \:Sr $" A"yS/~˴а4Ⱥ,D(\G7 $_"[ Ga\Ą.hqspr{Q35/(|pڇȚիr*y o#7mZ$l ?u!J:DR@?>CJLsYZRf3f %f"@bSy\MpCFMbH.T!B?N"8 3eކJ} a9ƒHjxƆAMM{KO=tA :\,䢵VZb1:޼W-/y|!uZsչePÆe/]y9~"|Du>` #JTlS~~_t&'53XxZI7!uXTbΕ_*ҽƶ,h ?  TP *X^">,_q'%: `UucG0!~&sy콮_|po?F5T#>J~F;ng-~?Z"OpTtsV츊>\ُ x d!o??k-FAJ~g9};4,6"~ҺM\ȢI3-IZ.0֚FO\~WƲ QyǸn͆{.`QM\'d(PPS S r?o;lƬ/*{{{iii)XYRU|ɪ?=O$ .p$?8/?wnL#^HWho>䖧?=c9CxOĵT/u䑒ܸ"ǀ\(W_ A3]#L$0n 桧R8.b!MϽ(q2[ 1%=WҐ˯/lwT4IM)UZdSP700/Ec,M_C8W7돷a-C.͝[)Y.ǯTZW,C: 3x?n8&A#P K/#y@  њ2r`N DB;r<3& f ä7@Ho>9F 2rc$A{/6^g%5x6ghkWМGNկ4N-RU?vݮqPM[b9>%KR]722J##4>>A @/zx\<- /u]*r32$Qh)ZL]ܙQmBۏ5wAd̤Є\yNJI5f ѭcJ7b:5F,Gt:T z$ 8q+A!~m6e#AP焚 aD!b_Aup[ڣau 7z̩DR~i".LQ݇z+ Lty:p\7ϭXI< ^XUk*pq8>zqfzߗo_Mu59D{~-_IE7n_?w=/~(D~I*M]B. {DqߪU+ߕ+/E b?o{W)>3x&nrRxG0Y-[pA-{޵iLtL,[7[ٳ{w \^=t>!4 [T  qVF,0$% hll޺uj3B/mʦc<E ǞxlDt\+2ogi^^RI_-y_=M5UrU?5lK:ǫ~  ܿ'ڳ{~;[=D6 }~r9q ґ ^}#@ y!3|2 Eڛ۷uTbG3w-7&?x`:M K "` F@N0 }[cqtMLZƫ (G%=tRSr=/2d?׳\tCCYU saQ _{ =ymuO@R^`GdT F#A5ȹ7Q~\H³@~{OXTȔ\E8~maC | jq "?۶Jr3=8|l*Ǐ㡗3G>-~|k%}WJ鸴?Tu -'y \W&#@|GG'S_TUH{7%tL-o2|-gǮsA[Ug~ǧvMT o'OW޼<|ر j~]ESn@T}Nf[2F1E;*ra*m lg&C.PjJM=1ًyÏq=ƿwXuttdl?c>6YFzJrBT&K(Q}-mLKP7 q^~;=t-~ gn?2I 6H aIIŀ (i9rxq7x*j~E" nނ@GP 7ߖ~˯>( ϔғnt"n"mx8Q7X4oc o뽰?'?ĞC}7xxǻiæ5ETt3%\"ld4\|Zt~ :97Oa9l^jΥxx_T(<~_ןx}q֫D:]JqL=FM'F\B o~'޼CB'|6Ih#hhۿ_@|f=BEAuFdVNڔ?? ƒko~bT/pUbc2}o~y6*>2u4KW;tSF&Qi·S\/M5MWNtocRU?mz'/^Oў^& P \8Ojqr+qsVyןzQ)v?>J{ŸKÛ7}MFqӛ/РҦ<|n2!D} T``Hc#j{u9¯> Oww@Mz7x;WeMcC۟]ξI*(gA4osえjөqo ?U?H]® h)+! OiO|͛W^Gw-m5‹0?oXU?AZZ45xt;N\HGxCt3}J{׃r^o^W|} {'ݔ }q@Ba@ Id=~_ ]w E0W Hsi ۘ Pq̤L1 V^S .B| X<Tԫw5Wr<l>E#};Kצ H tzKjD<͈.Zt~sCyKwdr)> s[8>-[LKnayY>8x"skDn58shoooq-v> ^iv'O@6u4!@B-0'AjFp1rED} ։ cbMD,@O¤D:}|ï {>5Emq|dKW]}T?婆<]RCj 2Oe\F=Rb*-~]{),͠SC_{7pTtsVU?^=՜Ȅ}pG_B=<'Oτzr^x"OAԘ۠cOmj:9DOJ{U| @͇ I;u?: 0aWK%2c`1oD"DZ3lasJU&&c[2eY?ȕ=c۷ogGS:݋V/,P/'}C,/KGZ1T,%OD*m&jLT|5uXB P[;nʬܾX~x[Z \^?ǩ>Acd[o6B? 'SK S=:RC_cSӰo~T8e}>] M~53 t3\_|&jDȯt^v 2-qoĉccc^x?@}B= '4G&DMY[P4E39bnU2!_lrÇYd+.:~|L"g 談|Ώ5Q,kc4Qio}17/R{Um `{>k9ЇBk_o(RM|:@z=62 /i!|>i Q|Wн*|j"m0b8yRkkJOt @<^*˨巿"omdZi摽NqЗ欸E Ǝ$7lO4QA4V`%|r8~uu{+]bE>D^~6}e[q`O0Ol(?)*4M6QSw1мE<SYUI[rejVL&XsʎlZڴes%i椓S:"IyZ`nUT?ڊ#UYeo RCâ,a)~^d> aj TJ˿(f: 4X_Ÿe_}]MtO~ 3~ʎd?[ejoyR|KW۸_n~Mh-. gKo~ջ;G \>+7m 8~txIvxښ B?( xCCC]vP#u[H̫y~`+3 ۛ}0w.P @i)]^h2{kO>%bJjL_+_Z6jLC!,m^/ Ȧ[\ TGG9滻]]]ax󃃃ݻwy߼ɤ|芑7Q3ϛK,[$u7r(P L_Px u=&czH] c$[HEߴZ:ͫtSƛ"'jJf_T즦مx5s{?UӞ?zSWW/"B$@d?}zKC3w5uOj_ҫi2OsSܒQ k+|{xM@>iAW47G.t=~ت\r Q|Ecn.Zda&?'KdU $}o&~Cןr6oѪ7gy!>t)/X[haw{>aOn|z )+8NОb'doY _yɆy  pf8r_a(D}Ls{OȈL? qO|{NfoiϿ,I@% @Ob @ ~^&R"2 T`'RU]B}S+~j'-y<=s  χ۷oG^#K1{1_?8~>ނ%%'&3N!@"љucԙm̽y xwugB#H`ƃ_𢿊ryY>!7[oKdu(wBB?lrH$hxɀ`ꆍRS@W!n`h,~_o6ޮ$r(ԕJ$'\|!^b-INᒺ\ߘ$C1.mf͌7ml̓Ef2( 'I2琠ytH>-YFoL>IzCߑlYiO@YU-U]DS;pLŗK=1HOx^LGW_}5Ϳ_~[n}!kB9U궘kJRg+-DқX7ah>y틷?FKLLimɅnj7ڐ$Yo& 95s(\BGv}?g^.LLw(D9󜃾$ SNJeLE:ԢVC_EyRWU\6G,[Rjn9IxC}}}\|) ר zK.Z7Pz{{C 6s:oz!-+4M!kԈ"y 7/|]GGw$@Zd1nkp?~4@${+p1߉i_ůarջ@_d{?ԩSC%gΜسg0USMmt6ٹq,[ --I^"m47<|B{(C<ȅ^7 s]h2d(,b}z2?=i<=o^|ڱc+ffȀF::ɬ?/Y;/ٜ/ʊʩݻwgÇ^כ?kյ'8,5w*R 7/OF55x40=^] ?2P5%z@o"4z tWO- F);+8AR 3qZjUcker(v;D|k/_g~~M2%/_mun칊~99222=888vˈ@RCOVvxMmAk>7Es=7Ms^ot'v~ Iᆼ 5|aƃ㌧}puf];Hk-dj9dY:xE> 'Gf4F"tH*ƩZ4EOuO!?=Q1r" `'Jz/5YP@/ 557OTUUJ=ܼ׎sH %hDBIyC?[8ɽ~K0xEܿg"4":$߾L?U 8IBA9]{RgCOH\|&,Y:OSinIkL_ؙhx\@rҞ=١-[@J@^!n ߟ}'… +}w?sYYv]w}!!{l#%5YJ 72XܡW['ܑ$F}|-s"?y]@oZg:/8N!^Y`M-/iXt;_Vhnk&C`81:!=@baCb?6!X~ Ps7/BӗE6K6mD2A^u{f:u੬UVU;}ULs24؇M_ ȐyJo`8CNRult 4ȁ) $5ktSz,U:R2P__)f/UC8 ÐSG_=Yg:i])yy?@8ϋ\=C7 )CCxRzE6Zf?;Yb?~@ΐsSqx‰15Q b_^ΎfMbeuCf<8T/e2{3o$2RGg?S`#cOӷO/M&'94vNFۈdG=7&<d {I۔8~O [D$dE|>[ Yf#$ `$ b2օ's.`L2`U&C ÆxX)A ŀHH&>"h?>IZ=*TYd{Bߡa?iv!%t쨀ƒtz)j=f|;~8(xc$ hk,xDL# (># A3@UUQoB.{[@χ\`HUwKX :KkVRۡ]%[`}O9U!X -g@_l ̀n#4CԩVoiisW@Hxg@fB<-!b=@d^gXf WYuC5@EU=ZQ@&d+a(d@b0\ U!x0*[˱9mT]3SSt5F'ONQ_qcumJ7oߑyDҡ:rU:d0g[zco~Ji-z'o͚%zk,UA&n(s׻vҬȮхW#3w,ˋ ͫ%=Qi@$@7אwCOv\l޽SS)ι:V]Wytq~9e'k*gvdD~fx@H )=#SX .Oӌ@Of=`x=?/īzk,5M7(k B栀<L@mgz:G4P t~v CLc---}ᮎG>~c/7x.Kownjy6 z&v:x:OE΁xWSws4^~r_s?Ib?Zi5k\duIZk[፣G!&MyY! v*2(t7i/ݻG(XHd?_qÛ(eZmtIScA>qXX7'!ҩNj<.<ّXGhbT=-V@ zNU WAނ5k\$+uzk׮])yߚg/1 bD@ID?_þ;::F;ݷo[ZZ͏^vmd~*1|K]RrҊ tLG ?o LOǨ6vǻxNӽ񎎁x?eMz>&~G;nޚ5Kް^PEMLLh{PUM[L*GW ===aC›w4k׮ҋݏ =ToTV +ɤKNgYɧ?do`% b/;MR~ok-[f E!!H Q߿_<8M_s$G$޼  QsWTW2+kh3௓Z6Ow\{(Jq0zq<{ޤm ֬YxIvkkkS"4:l d<>|x !7o>A@? e %޳be7NMͭ,TVU"way%-Wf]zQ E~-  YࢉR (J4A?t(P/~vСJ @ubMzsbؿ2@M͕ugaӧO3?_PA+GML%G;}Α8Cq}TBdzj&Uo͚5Kސ/QWz]Ɍ{󝝝#GJy]!iԣW6#^'zeۯsnuhΕmSǏ͐~b 3׻9kjQv=.iYnߏNҧf͚%|@RY[oodtܹU2*7NcBn>B,A>8A>苛!W 7ūW]F }#!=@*.x[ԗP|C֬YU$/ pf+(PkGO <쳬ãJ{}! I:{[j>*d-5MP[[b>x[VU)A?hDWcG  Ţ>7%B@Y8o,4o͚5K"y*Ņ(X!O<97>;vl"9>ԣWyAP?DOw5τSFvURwO^Dt٪b>Dg`;.̻)^N/8v@Yf @~`Ҁ $ 3f͏GGQi?<<}I؃zIP͖  V5T'heݴZy>=ÉWۢWI<}uȼ|1RYf͚%UܵkWΝ;r? o7_hћ I!]ϏgzYQy wCXTjڞ_^_׾WDT^~Bq| ֬Y3=WQafLmʕ+~+}с}gVIϼSgoMcUyJ1/l5s2ƍ;63IO;C&# B'+Se@7MZf͚%E"f8Zay>7MiFLط?6DדOP%?FaH969 -熹/ cg{cmq!ʐ0 M urY&5n@rÿ؇UxOjY~<ǂ5k,x .|D"ǡҊu@oHǫ|y uwLN=yR9p $} ֬Y"#e~&KYi{"n77A6o͚7Y)Pb=^~z ޷f͚%J~&2 echo 'public class tmp {}' > tmp.java for v in {5..100}; do if javac -source $v -target $v tmp.java > /dev/null 2>&1; then rm -f tmp.java tmp.class echo "$v" 1>&2 echo "-source $v -target $v" exit 0 fi done rm -f tmp.java tmp.class echo 'Unknown' 1>&2 echo '' exit 1 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/movr-dfil.icns000066400000000000000000004422421506470510200234550ustar00rootroot00000000000000icnsDis32WxN& د[1 Ok N6Ы ҁxPAφܩq٪̱Giݧ S|ʷ 2N)MͶD:8WxN& د[1 Ok N6Õ рxQP^u@NښγnBͧGTpmΨ E{츁 'NȿM̶D:8WxN& د[1 Ok N6 x~HPMt}@>x8hgo'Q7RG?\S}8u 9zh긁 "NŽM˵D:8s8mkyțm<̧{H'tlVo7"5t3XU ` SOil32mt= ЦwI"D۳V- c8+ nW *  S W ,80~~|µ#۷pȒX a}°Ԗj2T⧮ځ}Gsӑ{ɐų#Ͷn׌: >ڽZ #鷟lܰÃМ沧 tQ8i Ơ^ EŎ/*  ?ZLp*)Xmt= ЦwI"D۳V- c8+ nW *  S W ,8c0~Tc[#\FRX aQZ`<ӕpΡ2[1आܟ}GOhuZ*hj؆={g~:3 ۜSک㖀Ã}䬀 eO8i Â^E/   x?ڿZ:p*)Xmt= ЦwI"D۳V- c8+nW *  S W ,8Q0~B퀃JR#6AM}X a,ZʋG!ѕAnܾ200ߢ0TAr~|}G%eѱZ&S:BE U{Q&M8H~z^N*K9M:&u{_ {}uoz2K!7b^T *s1&ȼ Z뽆[Wx"^هcPY͒rVxG#yˆRmX|ݹvB %ܯ~?Il޺r Ծ&D"نt8˿Nfđ }w܎hB˺Qhp˝  ۰YYƶVٟe`-{诬 㙄y|L8΀Ķ诬@֭tq5Qɻƿ鰫@܃v[(q˾÷갩pA@vwqPD±Ŷ믢?BlxlŶ뮥 Հ%ٸgВ|oq{~ Ķ罛ʙځ&drpހ Ķո<Ҁqo ہ݀ހ߀ Ķʞf%ijh]zہ܁݁߁Ķֿކ5'ǸyDPљw݀܂݀ހ߁ķԣqN" h~J{܁݁ހ߂öʩނh. pu(U݁ށ߀ķާ߆ ؿ@ 2aނĸ̭\G׷PC<ĖH}o!!ۦ[)).+4/콆[Xx"^hG)"VΓrWxG#5*aj9{ݺwD %ڥG9ſKm޻\f ӽ&D"ht#ʾNf׍cn }'6$x1ɹQhplw  )ڦ8LRĶk~J{ށۀ܁݁ur܆߂O# cw(Uށ܁݁µzlz}ڋ y@ 2a܁݀·nۂބ\7<6ŗH}o!!٢0#+(0*|쾇\Xx"^^ahC(TϔsWyG#!8h8|ݻyG| %آľKn߽8y Ӻ&D"^IyȼMg!| }'"tM+ȸRiqEK+"w dz *آ#OĴ=m=KSP.#u ͸qV?+b2wPmzBKOSWT1 $sѻvqzz?l$]`ͿRbI ERRTVYT1 #oŷ|sttr2?ץ{6̿D'JWVVWXS2 !ovjzs{|]j6e8̿F" (LYVVUVR2 !Glpvn\rAS(Dl_G !)MXUTTUQ3 @natyb թgG2ͿF !(KWSSRSP3 9~zvrqUnz}|϶4lx" ˷gO*"(IURRQQP3 |~yvttw|a;#>a^jahm{llLOhWM0"'EPMMLML5!>{{vutuvxulE`ѽ1M DVgiu~pnmbYP3"'COLLKLL5!7qwwxwuqldiv ˸D0Xol|xVY|zz||th\Q3"&CNK5"7qtmefiuU 8 I2_kwa^xy~xw{~zsj^S2"&BMJ6"3_q(Fumix?=WdwQN~|z|{oaTJ1"&ALJI6" C5[uqerp&*6 K[jux|}~|yvsoh_VN3"&@KIIHII6""B *Qkpli}\+Q^n{|xvuuvwyyvm_PC7 "%?KH 6"#H| #Lhnpeylo&$3Yix}yvuvvxy|}}yrg^\fv[!"%?JG H7""JJ#6h{` I_o}|yv$wxz|~~{uka`ht^!"%>IGGFFG7""J k]O{zyzr Vbpxzxvxz}}woc`cp`""%=IFG7""GB}|{|db{z}l-S]jrvwxz}zrf_al{¼b!"$}prdWGԂ@J:x"cYt8mk@qZ0 ϩ}O( Gص\2 i? ʣwJ$ 7԰W.  uݻd9 ƞqF $Ы~Q(  Yٶ^4 ˜l@ ˤyL% DձX/ ޽e; ǠsF .ѫR$ hc;  O! X96 w* " %x ]P1(  E! nH// k'  g Q?-& <;yqM'1  ^gK GFr.1h% l7 R# 1 SA u+9  3n* o7 U$"1 UC z+; ?]&~4 I!*/ cD x.F  Lo0N! 95{) Q 1t9$_+ N {^39+ " rz6Q1( k! /p{UKIq=5mMXt/U{A:/5ELSig  "(-3:@FNXwBK #)/56d\e>yu ̨x0*uԠ^ϝɈGsGHPp>P4OW1aP4{vhSW)Ub[#>EWmRi-/m~׳ɏ,9HoP@i4R^nN|p9vksAĎ=ShLЗ (bTPݷ3y< iV5 k@JWvhxԦ3P ,DT:\`zYLwZAy u;zD\Oλ_$.uF8lB-,|:{ rbɊ蔿+yl&~/#QN#0㊦I u R<(+N~'r?Y^{vR![9˗/YtFD^1:N5D΀G;A*Fܑ:>BB*&Nm"}.1^|l DP\Ql=aE,%8"h~V9ךmSWS)#DT_ř=v\.@BR'^q쬴Ƅ$ϩ2VqkcyHz_ ov[̓[[8Xn9"SՐ+lFH!,q>&A75]7mlӌ]>iyz?M`^ Mgݯ]z +KR5`dӅ‘ՠz/s?½j$g UF\L4`SdNs^B#@cN6u`#YXWZy’wXR4> MR-fBJC5!~\,JHpkvz8hJsBtWߧ\'wYb V{jbJB+XзJ@97!wʑEq] !yH_9k}~/%:1@ Qm;,hծ҂8Y!LGZ9 񾄞PuYe;~Ҙ h(z VLq)҆Q`Zڷڸviuem$ChR3Ie}Q]b.d <u¨#Dh|[J`ex,M8| ]zBBʛ*/ &nM ,S3C\9HzHI$ٻ߹SY[[L\֜3}aHضp /ʂ@a:bS| * 4^ds1x_<:igZIk3K؆~py 븭 jB#keZ.[|DΒE$.i gad*nD'ȐC3g}f R4RVs JC3q>1g2Rdғ$ J.[7Ci%ChJ;Zp>;M#c]R{K&ՠ<*2.Č>&Bqvht>~[9n4aCÖ]T%Jq5*s"_ q!%ңKӑO-<;*hPO7{n'~9T_lSiOў>#I\!HQ!oWjnfeP][#"aᕸæGtV.I42y*)h~z\ zZa?vnXfGD;52-6 Yt $Gf4MPj;@i4MPXq5 do[Ч*ndIlos2tjZ8z].W+=q҃Rb=pE8CAc2w: xڎ[]r*`/9ғ6ٓU};5]37EDcz0l%;$'칃t(̅9X=o >M_W <ڟNjM/AYPBY$qBnz=)ecT@RN 7BI\;c+a Rz&'hR&<)&|3^ b%qFZYLE!Mdw [ +2z>,1@9xG6N-28fXNTLε>`fl$qyLި*吿r%S!~b?i@zNCū@% PھimTD=*Ku*ump[IђE/孭]}Wmφ%2dud8R50[)ؕVЯg ?,e'VcސqpOM Z턝^"nCw}̽L̓W+Yö1Oıª}+cptM x$r.PVszCN@jm"PU=6[>R)3vO`φ)jYȧT@ 5EvשFkD2ȇ|)^.WVWC\hM "=zxYQ[taU< N0m;lGsX~o 3v`aaξ(aTB4f: 6-mx[&#秦m7X kZk\\% ?Ո3Ўe$) " gt@'E{-a6c8֒0LFC¯ ԖC͉QdvF(] B$8ȈT(zWwC`nT*WGWtX+]uC q\3O &o & IoRߑa2W'PJ?7q҄r!uH2-{ݘh}諬 y ."UIIj{HԄ`han.FriO/Ѭn[K!J'}&o< Oj~x;zwhyPqrË3lER]{; .Ɛyr?<9F O|>3~)G̴Q蓅z;ꆣgȌ:;?|Ec1$aYŀ~*nQ,X}@9w4[`1F/Xj{pcI[B|Vkw7a5fY[ $?ShS|/bn4Fѕ̀;d-ˢW#kM*$7i$hYWIQd/u1T'$ '~i",yeFq2]shȱF)X܊%R[bZxi ?34Rzi(Z9>n'Ȱ7*q>ql2Ț># q5?`Z'O'NN:5W9sM"C ,E1`DUT%oYh ̝mt#VO֐풩̜B?͡pJC{6ZԀ9]Gf! ]d)7j+>C]86& (3zh[XvpJ0X~[gxî`NAY`'6vd) B$ڎn K`'T608 9ٓ wcY~7n3jwAxl?Y`lQBwKlXd0MN|. 4#s$|8~XP36xRC4Ac=u/j^<~Ɗ _Qٴ$< Wnh%?ű 5|[SEӁ/Z~x."tT{!g~?,|7HzQw1gzO2"ܿrn.H5IGP"$Ş[C5q,#O߈q@v-%6H.QfEIPbOxFK WSYqUJ AFoZJS98JuHߝ9,b:rHA@Td$@OѺ ǩPtjy 2baH fgvm%NA5rHLpL543vdϣV%;>n8?]玐8rI\ +B* ={_dՅd/:nTOW"ļ*In%NV,{K.ȼ^r~->hT?뿿ǣk gƥ❅i /%1P?z)-,4Mxu6 -v?l?!Կ] {s c| p8eg41H(tvl< @>otkP2*DDz4Rķ^yjP3Ѓ蕺(&̀/=Zw 5RAg9DV D /'uI̹ xctIM%b?,{L{}!js4C c++qu 5WRyo}kH&7(B E@McS %v5dL0z^Ǵ=b}}+xvq;pc/@RB ]$la?p\3Næ~^6Y_|*Jbk3ͰnxsGxQ;4JpCJGii͆I|nA9:dOxe/BIxb}KkC„j+e6&$LI T + -eCBjöPЇ{P Tܹؓe#tOuyg0(#7-Z_/Fg\@b^0n΢rj |G@~ jąTЛvJ%Ibrp9FMg$Y7Dib p|S̽ 7=b'eBa)wΊ; 2';9-@ D##!:C%uV)P%91t< bHqkXT2dJc)U3,^ꣲqA%/6ͽZ{Za6kM0,|Oj(\d]WҞrj?G.>リaFù} QR$XŸ*+AL$j&3v9Fgo%uOzLVS]mہnڙjHh!\4`xCtYmaz\!f{uj93(1tf~` =X q쩯x og C9c17C T3Ayv$^}^ZChe[K`+1ե׻c}Stx.4Aə,42m_:gӌe`x!m%J uoOrNjM"Ll7s?,7uruJ&im⏦(]]j}mѻP)B_β_<疂",Xc"oS棄A{caZN/ۭ+ꅽR+:]oY=-Ʃ; y#Z yZ%u:"mFtΆhq@zdǜK#r.P􍈫]guhI,=N|boDBy˻ܘf+ڸU[9f(3h?9cM{:i7*>&k*ëbNN ;ukeE>[^It? ֎ỖLɪg砥wH*f3Sxo݋R-tF׬βv%]qJXBVud,z8yKz _p %T_ q}mBt=3I ?QB驙O4}lNiʼ!X sR>(Tx(X l̑¯|BNGP6nK>X^Q|/?AWG⛽(!':Ŵms(""G1w7#Nf9tj#$y=\b iό_Y;6eQi2|lI>r.nKY-No;1{c& '|:snPt*&}boB_w^ctsӲN{l\yO5&m"("e#[8`8F[Ni()8O܄:+ˡ8f7S@JUgav|NiUc :JplCXMiB"cԮvKL{BIB8e,YrG*b32D3Gp0ݍgQ~!<)P|3ONȎt #nB\,\S6 SUP0rc6Dy@̾S%$R߹*`, N]"gl{}KP{%PD@}ۇI0X߭zm6HlKwp!j=,JWC&1rK]sc1!3hBp*}1 ʅAV,Nx,_iu 4BB39UJ<1%QĢiAkQ]T/|5p_9A84[!f5[ӂO#;IOg0lHŪ7mj)S^Yqh5Q֖uTt֚V^%^7$m3A0\0Xk mloYA؅%],YΙCn)DuPW@綞64*БJ{- se= 6;k͹ftDn0Ņ0<>uX܅m|wŠDBu C&(5kW x[ט|#67WoUA+q HV·HZ&{`"q&1pm 5_{)mb"ٜdUa ~щcB exoP5}8z4( J͠c8&2i6vb/"<=E*EM[q)_]뿡''6cܓhG0ۛܵOvXs- w̅Qqg1ϐCQwp.9 \^&3Eiu;vWn3m]fb栁y+C-ȣy59<8`beiIۡwR,' ȱQKX@G6>Crg ,{`cU1@me6LIG}`Xx[ZqȄcK<2 RyN#f C>-8y_(XE.fJf}dz~#Gf$ 7w >P-YBp<{r61H:rR(>'gƸq+#] u%ӞWgŊپFd ܽ v_qa8Q=+= ;id-:&_ΰ Լ>ްzGB $ bx'ܰRteț$T\Ӵh-Obs-.x犺臔J u7FǝOwHBRƩn& ZD V)P|EbFc?^eĪיr^HU[D2@stf_68Ym=AC ":Vʙ1Y ]  UWl'`I``1$ `n^ƖH U^`XD ƚ TNI@F8E eSye \]Xio]QZ8EB8ETuZR醕$aӁ6kqXa#^XBūֺM񿷓5)QDk_7/ݤƬ 63۰! ÞlQ=@"QȆDoƻ֓`u1~iB{y]^c7X7׏0nkVxRjn,o3M{BzQ AZ"wsOT}͎_}2Q0 QѤds)&$OSԑ9b{7$q` !5`QB^7j&j FG6O3}_iD(@r$Ϲid5_{Bhn#H6&%K٧w ]Vy'T57B^7&>6}4apRK>$Vo9"aur7K0UGA`vU/a:.,pѼ,뿻#luڣkmMi(6rY+cvUZ\^\) 4w(d g70(`C[J.^&B>=9L[ 4lJJODЃ`{4٧J s2 ZɱzUv Qdn 2 P2`!4x1bmƴN"'+?RQ{TBωg6Z2d,Q^8P/Ujgҝv4't " h:**ZD+,3. ?gr3#rmܫ>@#k ~$ q`eE%d CNR< Q?fRAVȦ_Xhe:zZ-Ӥ~:|lQB\xl6CbWclAp_1}ajGڸ'eYQvqfm|@|EWO2RGHɶChG X 685qyzC$nV4#>EMҞuu?{BZݶ/ŜðPG>\.1{bp+{֞r6L|/7 QNŌ"F?(uHt. `1q;b3[:3sm-pzOJ'*W)MDxYelù޻ x噗8I4Q #JK̾wCVjyo?W~@$l M㖄^$pX^!_5[(LP3<R@Tau/ME_||>PRl qPBd"CAԬ%usP#ds&=am䱥g]sc^T$`~5a6=낒JTǷ0?oo0LkVfJc̓ 88&쮣X*pY&7 Ŗ.Kds hb<2:l+LVs3(cE>*4fIX0:M|Oif٦OOxqc)Zѝ 0ףDfU`ze,% VCj~T_c[͌XDGؾ}OԂn~ nyf+%\g \cionJKc}g$XZ"bJlS`i`?u% p}3Gq6Q po\bbj&$B(0fZO6pBygg<ߵfgHk.D2DRs[? ePOM] mE cNp=fԱݾ=h+]m-)7f=0dX&Qnc;\c,OʭHD "q$@-.m$upE+L9O8xDaf6ljB1TGW/& vAĠxIE.X(㉧riZ;\ZLLz|׹ ku1hmn়rЅqTfJ\qdDHFsnUMlg1U$4 ?C9RXo%(%me7)Û 2,%|L]m08)xhpj9(UHd奼j#1^~V184È/D6,ИRu 7 66?,T%eCSC }n#ALs hY?>Xe=Ǟim4uۛ{Tqg8yI :}@\?Y@{J\TK&4]';"4 C/‚8>[KM]dRHFEKE|B^_ Sc빍ODԜ[0N$,?H]1HڦzRH~` +x6pez/6s-VFے%yWܹ a;CXE" X)sܫAT,+ ~73>WAC9WJc*O$VnP6{_[>ua hKySx{u:+_û,C;':?û %@תF2\K_u!EXUk MSN<6{(Kq\)t$gAIz9H+{I d4n7?S<s C;-o#zٗyx"65:J{eh_]Oq@0:AnJ|Uae V2 =5Z{.VCUYM%ޛ .FL@lKGmI'@-w=GcDA\ H˭(y)Cl3 q%Zuz,c%6L1>~"F02QXYE-kV7 z,IZW|Q0 =rKp2N#т1܆yNS,Hb˅(T%5Y@ Q4Is ƅwWQ}ծ ³fER-A-ړ'ѷf/hB=vG7\s >]xd"6b^)MXeeįsP5~ u f[I4{Aw~MPS F g@I^}R$`iPtrIb NAqlkpRhM#q` | i&fOɯ|k+P+X<,:k'P圜jnle-=-P{Ok(EP@&bmR'er`B0LQbW<;jm>.0'<?IsԝERK&¯v5\&QXȌiąVUS{&m)Kުc*o߈ hwV0q+ #u_`"^ aLv2!NךckP}Si%鎣D7^@6I-’=Q@݀^gH*HKR݌0Ud緆aU07ʯdMu4_B<"_\: i(Kw䬱ʭqG չ> kA\mM3VdQؾ[`a(E#J'[nP*!yPXp[['G&.:V~^7=;O8fu NCRbO}Z.@-;=~}6*tcc^QH%:n'Δ׊i e^tNb>c;ӹ^}[ɵ8+k1u4l+ ^9JɠA^o@e^ -_xHqq HpD,j.xD㢻%F`\p'T"b> "S'vLFZmK# e)N3HdڵY6VV˯!;7M!qꌰ&-3o9u &&*4 =dkA5v5rkbW6",:1F Nux14?\ 7e(BU{=t(p>94Ҳ_WVhB8W)-0 FkCTs'_-j+e;!qAb2ý٠qk L-PjѲi.Zf4qt?@z򟲪4'Ld־J5 P]gZf+$m0kwUBh&;ME3ބ=}9&"zSjq-9VcΧ&ָ/ C+x mr5{5ĒGc蠠xe.*6 DXGQèe~7V+bnR&fkI̋oj ;\js~Zt=>@es R@qάD_aH΀&(r.yNMLzuҰ]}5cA5ւٲO'I+S_nPB2l';? j.\KI\Ȩ^r>A8lĈ|%K&`y9348"`Ǻpߗo{70-~#cW >µ NT8Uzx!yfcj[?G(_7M*"S-76))QbcWbw2odǥɭW~9@xuwO-^;ZسDBn*( {/Yg;Be ,Ἒ2$gn EaEI =Ft;i$_/ڞ mL1 dn=hV)iYYC@΋ϧ8{ÈZr~f3KO J}19[V=G i%enyJ,7oʽ'³8t<-cLLoi_#Y:^QC >]=*S #3e S%l~ImMPIg'otdݫё),6W)˞5<ʌ\Peb8&)D˖;)Y4JKD8-g. SJe/ҳ/"eԼpbdtlDc8O%dg@uTVk0b(#dPKCq2's6H$Š3,lo$hɊ[d3Gs\W5JȰz4@j7:q ++7Yޫ>$*emU^UH{w"BR^.ƺ`Ȁt)SKu(3=6#ЯP%&ğ {YcOzP ԭ\n 4A{LTCeri +NPؿ{q^/ayyDT*iyJ/ ;H]=P=#.Ix晗)o:K+tw@? @IH" ,Pjg)3 !y&wS]T&)}qό0{L`g1NS4Xll*~(n2S ˀ|bE~Ŭ﷛aĐ9[qEvXEFd T5kA4s2gsf qeڣ]"#&bnj /,epy(F-ד{r x?NF*,$WcàJ鯼(t=j?s޺8@4øjG ?HK#0-Oh9I&۞C[A 2_`\vPOA7QT/8F?iJ!76*g%=[Ӯw׳& {5TyQzj'r z5N*'Yu {}rwD`%"MʈO`qӋ; *Wic`S4y4=Aqz- H0C8 ">h j{߱ N45wkA h90WCsܕ`6lѲvk嗌`4Gv 8=Q|J,%tqΧe š> '1Md딟BwB[KQ{;p/ZASM~[9K?XxN>7s.U/x¾[v?jO"/)q Oefl |7#nsW@ya~KP) !͜v5W3};~"*\]+CҘL= 7ol-LHd}W&3Zk{NVD]3ͼll ~vͭ/f m7土װ+NaE߀Vv5]35q7{~zzroJug+Þx$ZȈh%y@YSKk>.P}4Vӹnv}L@Pc6vvkUPQK;` ܧu+-Ȼ{sk;bkǢ7V7=X_{Zӄ5%o9Կf}&"2*kF;ђ1> h %0SPDjH/ָz#$=S*j„-$n_ﺑٺBInvoc,|5p%A#݁7 %[)+.K|xQ BUu @MFaLX V[ЇxW"}* [&4q-KAA-{"HSffɩGuxR|vRڽ?D%XbW0]tfCکl/|f\L6nx-Ip-N+d354wB\wB3L2IhАN1!6McʺvS.#-OO p*^|"oȘVzpfn3skةysFZR^&^wT``|j(|qқ#:K :&qJH+td=l,/4~ze>XSavQ% K8 m^sBhzi]}JCj\D<u =ȑ)7%Kᓒӭm{"!9E;V!BLDs%ƅ:?aFI0ĊW.Ơ [K08o3ogۂ.9 oXفAYjhޞD;B0`v_8D +K=ŐJ>/b/.3?xV<h)U^t%MLI~߁Р3s|A /S4s%mȠLPgجG[?[6p!I\V0Qϑ& QCy26/E5Dx ʓXnw7Jd^$g#Gn3. ]!g !QPϘ/|^[9– ӎ(.+ۑL= Y6ZG~/_\]~83M M?s&16=EgNm I^d]#^<(1P# ip5(@@ ANґ*cWJɋ^qbH8x3`5OWqšKyۚi[7*6OY MaSiKfЇqir m{b54D1YP3R,Џ@2U vS8T`9 YknzFε6@I^ ԩЪX|[3#V 78[{9?&ƻ<by؛Le)hkh[QU!nLcrmU&M:*ݤ 9`@  U)[?Iդ7ߑi1K<%%d^czVś܏? ՉaH5CǥE//!R&o3}2RtcLذjJ< ^lӟb 0ӯv 9r݇@m$<@mį|#F^O(GF=D^)[o[6rnp)%gt΢#ٴUl2>}9b͜Ոwpm'XwOha0JrUÈ40x)i]R:4e! b$8 %ۥ-OzB=Q9 n[!1aD3*f^ꈳ/]g*ą떈 R0^Uyr;ĔPLkZB҂ TX׼J8-ϫS^ */ؤ\sqa<2Bn/D4Cҝ}2YveRu~_YĎO}YG1Sc%`4ʡǧXo}ȣ!OyKe.i8ap;ޕ:zo jĀ36uB**m3 jDS' Y݁ut6ew4)b8_3[vx42"@W`l.Z)`XzG J_ga1!X86ygo/HK5)::JۻvNxV_p5ӶsK)X; }jp`$4ru)gIJx4Sns2ô!gQɜ˒~m60S#C{߭ψ4K`4Q*ECŌ,!P4|avx atow&m2thc^jڨf\s 0·}ST14E#;V\,w# ./z LJ]fHgEv@orjd@@(C8@{tCk:!17b(YO>+lpk߳vy*1gmsIb.x7ډ8rfhMfBVrM,A -Wmo+pQ&s/2e* S9N T\\0Ƞv+;|MSg7H.HƙQj|eeYkRGge徘LVF?'<%,g k*F^&ך6$'ηBGzXl2rH& 7֢^ƀE!Ǒ 9u1,|`2۳p7pBZY%ERtéLwlNHz}hڥnTu-`QE$ 9 f(\Ns#/U4ܕb7Fm*@l&jdCT 1%~H}Ljehsvi-j l-!E]fx8=I`JZPJq,m_c``ܨa1I+O=dq2 8̌w[DǶ?ȵ g= EKaFNº= Lr4MАl's{Za^V!ү+G=.x/Ikb^20};čH~r?P&7-_EB@FcF9,:9toӠG+|]RU Z"mkꄫTϧC Fݖ^Ϋܤn4Ӑrd%3%z]ie%LnAX+^Vdgگ \l%|3u՘ntVbPD5% HZ^R;_PZ@=!?7|zrJFc~)Ƃ2x),̠ᣨ  =TFx1.V+"iT4*l|k:ETKVoUFq?qyWRvexJoG ~tQ6 ?S>AfKOK]mS$JR ɻZq/n}@{v|i{y^cmR Csy\*6lRZH5I]y5G<ha˧:w6b&{rHMNճih xHnnsi-äFwoMcO8עZIBʻNfl}awś|_ԟ{DAQZgt?iQ#βA^NhmZv:&#Aޭ^߾} gIׅABFeE^7& | ʦo.>nDp?08xLVщԢ[p+Avvsǀ%BQ6wXAQɅQAy< DFp.NDr ='v cFA.%B]m?𑩥t&?xRf> PeT>DL1s%v7zƂWLuYM݉6zx?6.Y*0 *P;/Ŏ#6囃:* NyC`%^w0Ա9ޫuKgX>M-BD>H|ӊD"pFҌ"*~!}QȜ$Km8ɧ+p\`VP9)anhU?KE45:L;0f1U=PiP K ?. dغ ߇lXO`((%ފ8m/oCDm cluVikIVbz'՟+ӭtQ*- A,}Xc@dۋHoR"3z _#Q 4y7s։|'(Ԥ)nſ'kk+]ŊTnGxJM&q-`J9|=UAH/?"tf0`~$|"9:[@ "X[ \rWtý N$XaQq5z0 YX:lm*KMpcǞ uԙ"= 2#lgv] i:?b+“8H2EИwY[$`E*x+h6(J8>莚5Š8n*E4|Tb7ڧ閊Pw"ް4MSKVZ#~}^zCXqM9 _l+XI\W&Qu5bɅF ǛCϬDQtlmWa^sʜA0|J:Qb#biי }ﴺb$pŐdZLhCz= 8-.0:WvMwr3A0!]&XyPҾGG,rgO[K_4t!̭9P>IRSOhbxTdbЖEe/1j(:xJUƹ}[Dtk︌MډI2V~6Gҵ߿CY1E!Þ-s:кeGoPN`c:Cn P)CRyYЮ"%Z9!Ӑ0ga6L0X $x4N8=| Ë|=g0:е؏#@Dщ :HMGӹa=|ߵGK/oa8-$Vmo{H:@oD@yltQoa%mzS<E6gFάU(9 ї8תM7ǏI?CPBH,)=-[_0=lgu p[ڗ`sqT^"AْWmO:mM%cxE:Qi,pU7,aO Y/̌TգZAZYj R%3=ayC7<4zZj݆^bs _jF Q6 )KQ~`̅@CL+F=/JKzg.^,\~ATl\^+0 8P\ 8yp<d@rAPr='L} +m;\EGC(<Rڈ4s=%1pFݐDXvE#lϏ%]uڻBQc:ȸ9bxh2M(bNi͜0= jx];c`$UK,[I\PM>KVjt3dSU襎fb<Ȓ jס~z!Q bR)CqI*'Y_ e[2l;l;~4|I 4nG???.[hKe ;Yʔ퉖 :1JsKNǂ(-?3+AV/UFi#;fr+#˼N%*i=*f/Qz.U w hQ>-@urw ˲ 0,St=@X4,r2US*զzLy+ !KѥG+Lm qfݲ5Dg>ωX|Ytrݜ9W bkGZi*?ɥQms2Fp/=_"̻R^de?:2Ds] h?yG[K,J6<4kC =joϽrbKѓ-yj(w_7|WF6K6ΑCATE*9yx8ɢvdSJ a!6tBrۡ'XwJ_ %Ź׭-t춑6zLuYǾ#Cή1 b!3EHgCˑ W-Je;˷ԍu(#"^=:h<JӸo=LNϢT~N­NyxœԘ2TAx幁fx/1=bn40=TJoJ%7bֻ:XhD]IsY9jd|PxH ͱ䭲ِd{W!t$f0]F~]]xAP7ò}m'U)7vr5]IoζY*+࠽VC|ϔ̰+!" W$؈uH=K-.\Ī}elO EAn' l8NJ燽 >-4tnSm~\Z1ɸZGAP~DvjE&˶_gvGSoJ*aDOOK뼽&)9ɩh; 72 ({QI'h$U/] C.[~P 0K,eB5v`*oRVMW<~GDۻ(oiηքz  齌HhEϕ5奵f?⍃W2)%lP4KQΊ<  cϋt>*;SF+O$bj&Z@U ~g.N'E[CW~_zS`߈ aƘ޴,aȁ lwT~Mm#TGcirUh sQ$cMXc1R,XZS{G8EwUs@[!>` A%iprI+ {%!$S#{X{ q* &*#~L2@#Yj$t0:m\ޟS"./h)s6͎THVDCk/kz6 :u//$u)\I1%_S yqnPRM4)j%O֙%QB*zaOiƉ{NyrFwNn-*<<6n[D(W"44|ε?sSl"ՅjŽL[gc'D&Kn1hDzz UD+ҫ%{U}5AUY 4Ed{fa-Nk0P+*~%XX)O`x;aNM/3YI%^eR mdE`12f6@NvŀqTT,[:FT4b9L& Xr}; Yh4~@9j/Ѹݏ1,UFj5+oaGh3vڭ+SǝHgР}ǑBByW=} wo:h ~3dY[0`;Dk K †WR1uVLk$nF$1 +FE0_Q=_6#?9f>M1jrg9 7cQxbp\'bB*f3m+imfMHn/è!w꺍\eGmI 9 .7Pfob,Z6èx,PK*U6נ~+jZXA&2׀ +4ߒYhYl鈴Rk}/D)."fWQo6/aޣʓ6N(TZnĿ,mhehxqTpH>]|=k4)_P_WE yw_JkG|+ִ_ѣygjG%^ڸ %nuB4`ԓF%_9D%lUСT§2w'-~Y,eضsr$&[-*ΰfʊ4:^kgap^|wQ?r :'7>' |-fI< g>j)aX 7)y$iNWL/ C);bЌ҆X9MkW$n,6-*5˅lѩ V<,*TS ]a~V8>Rϗ1Ee)nl"P.UdiKR䋏tux5xcq \rXɬ_k SZԔXvdoв-- fa(mE-JE3=-[%+ٰݍĄNˡҡaJUyaۢ 7~J" &#A}Sʹh>Lf2Z-:Ġ68\~:KLBYK`3+4-@rjUS<}-$&?4ٮ@pxT]\F:ȃ (HאDbf\PQ|xR >\ȥ U_59Qt3{z{guxXבs+pqQFacS!5{Nȵ (h'-L]OB@^|}O`q^؞kjLt]EXSW 4+K>üDwfb"Qv:\ DàBSjQ_Z*`+X:Vn>JEy= K=icu=ε l` -KF'+΍H͡ikX$}&rEfhBuh'l0gI]B]dih{ " xI4@þJȆdae. 1ͱ1bp%ܩ }!2n*6L˼ p9t)k0ҶXkV @gCw҃X0.o׸729,Ӄ Q)?a&kfQ#G>D_ē5J~Man\=D-].?pr` 3>/ƋnF&[qr \u}L4$wydE-\FwaRߖ,dݏN#Lj'.5*5yM`#U-O*֏dJo.0!$mGdG@fb )jy"ĝ@_Cm/ 0P`mvPK7LѤ?CZn]m/!WHL#BeZ*+*P.JC aꡝwVʡr,.}Mep%%J_2@h%a xjYF9* |Ow₻312$c M]WF}<޿! +)FGmUmN4oߎqoV+:ex&-(ܷ3E܏'&Z|rm|_xAzy/$6qq(V|46&"0"dy8MF[="Yg%JZ)*l.jL` ¾OiMtc᱑R%f1t.(SAdMJ%$W2ne y^a߳0[pTY@vd DX&>-uxk Z(3J ,XhzTms{@JKp L 0Z: BMX– 0hk&+ݜ.Zoǭz"kr-mcz6%[ I0/KDaiyT2a1VЦ ~*+šĀSzR87ž@,Y[yu /4&JH򶩨ȋ6:GwtjAPhŌ '>N5,̿4N;aG]jGH9XT% kY#- pne*'nAG?0N0h&a;-ɖY$[.7Ov :*z! a*&n|ͻ΄tSn*c Ãp #=>0t٠nM耍n;6&[*QM,| reTDP,J:.X^Lzu]՝| eAHvE:fݫ!vpZCR -,RصU#AX\!{]qgx_x#@M^WΎs>%2Fs(t~Ĝ \&؟YۧWYfs;^"s#HQpcH:@ quDsDk….ep'D$T)aG@),+MKZPG: /9j 'y}dC I1a2|p/פV+87׃TT@NhF9Q#n2 "Ɯ3߃g/[v?DQ?gUZ.=: D? Gd㹦$Ue"!@h8,рt+GTA3-o4oP vl("w,DR/tq3ѹhB͕DR^ z"߭W ;ܕL'ܲY xRem<|)TJ͒s@Gc^_ ^6Q_]M5vmČv`3@RopKS(.S0Ț\J=īu>-,ȉadδ VE&i)>1#0%UV^Rwgӗ\FOO)n_^Cى̇YLWƮ0Bby"HՒBGCh7ّx' \`G7,0BB@,f\g!%qI/ \!:'@6eNm<'d% .e\eW/:#0[#x0:ȀdYNAc+B j\XOs ~.Z N8S*vI]#:iAjXe[@q-El*ggwH:DUݞ (s˳%עI4NATS#Fday#v;ti!,zbdzsp 2{ՍODNHlt0*)ލrl7\%cUde+*Mv :Rw\l:\B;. ms@Pz7^_Mm-7gD>?lH-]M;ghȳE7rSbFr( 뱌oC$@N0V ˉ2C `m=91'0AanyeS=O 4~x4#;9$D;(tI&ͬs\Xk_$0sV PZwPļ7^{c{ʱ"ƟhxIhSkn35âTxjݓig0/$IeX P_7d5r*yq<7Z"Sz }p_UY:T%1v@ )>$Nn=j94)߰<΃%~"Uq^2_,͎w)^Q-Ϝ9&z} (tOEئ7,.V;z>Ko-o7uusSX(a[ Ӣgd" pdWS^Cs%rp$br* ޭt+v""k'Sv Znu]2m0zT"XTl 7B=,;@hq3YMcT^j]d(L{Io}UJ䖫^=\2bɘ$kMqsmgt0қ[B弌@")  `9mDx%%wq 8/%ʀ]0f*-N}VGٵ3 B M>(qD 8dχim8{*]Q,)}[Vb ՍZT0d>@7~)DE^|2DV9<oO?`q}$y#Hˋϩ)I+&{woX0VM-;T>Rxx#$XMXB5%RhF3+f&\̏8RRp݉b(^ཱི~y5!-V nN[У%T>\g;SW Gv6`ɵaQ=jN<Tw\sRI@lHkiBg Ǩ+nzed' /p+$ M/zNc$}y'0") YIM^k@P;!Y 8zrp.L_A&(,;9!@?Oa@ӹheG pZ6B}[*/ێdCZ] 󻀙=sRaֲsy1 Ɨ! ss((ޡwN;tPyY1,.SZh(ن|1 6ϊ閡D&Sn+DVEG pQYu޸t RklawZTc( x#ܚl]X'H[T[.f CȺ&s Y;RRud5|^UI:Z^5&55.)jmÉ7m١kP}3fpe~{G EϢTx%sn8-(XOt KjP:ƪgJEw(>fe&ިCl8b)Lcch8{KQ=~V_EKZ.]Ɔ~p7<>k_nYSdl ~j~jbs`/"(~"\[  %C<϶;7lI99 OsaaOHOR5FrlyyxӮ?31ygX9V'UnRNJ7y"dVUsҫsM@+[09J|`ҰFG#9}DJV7h[y `C_njH8 qDm:Tf>9"'E5B >]0O[zh-?kL iKҌ_m}E6tQj, KT.{ M?~6EaTa!Q D# Eвf̃Ǖ:)-d5R׸^hfBY NP }ڴШS$P:IF5qQdcKΰ_,τKZjE$ avtΆbtclגS@샶z)M]mݘfe2Lw #jY)R$EOD:S;.Juug AcPU"7NcCnw зEl pnz}OmcM={Vb_ "11η$͓ӖWyw}M]j r.7\A똨qёPsU/)cDX!ru~R3L%Y$Tӌ97}bVp!;MjۋQI8lGG Hُ5TQX$qAvKaa&z aj_P>`\ĩ)9pCAuG]" 6eJ;)[w04ӈ-ț};HhL ;l6~Kֺjq @Lڨg\B ]Q@K.j IHj~FB(ھ޴])o2Lghe zx{QTwۈh \i/$wt%A}6n P: C:Na0:d,##@8K)Yvj'(0ʅJʅxe 6lHCL M09 i\<+z$+ᣓE\Co8zZ}BL|2PfLBBwBsH\eQğYoO푰88 FrdLH5Ͻ=oYjF߭{ƳE)n]Ǵw4v&'Ap`:f1umMmt7u]cgֆCG3!nWXGQ 1L#lgh>I/naՒ]MȮ@(BASI!k:xѡ`#/sQ˚Q6`ӑ.'?I}!}2"r-)r77!"my?I Azd Zqg]FP"1y[:Tf*]̥ trIcDl4ɕ+{TZ mR+ch]EH҈=s҈d'sq"1 2d+SHQJJGBȭZ!,O;rI7bK$QgSe_^xScoĉY86>7Os5 #HYJR J`Lh=űc(-Um8f$[.S*h^7$;5H EVFD?y.KN\Xx&.ƐK:햪U 龱F|:@k;; K8rCl"DkC'[ L"ڪ!Z~@FfڞKP%~q7ne^1„)=ʸjuRbVdi[uTc:rg!+>(}C#E7rbWԦ-)cmՋ0-N ~mtڋ]f(_S&"(sʕV VɫL}Xscqf#a7slpOėNDyQ :#~R8Ճ1`e~Q5W3߼UbIqW q@/|+C/4jءO,ZS-*~pH=sSU®~ӟ79(uiѢVo͘\!p%ܫ;U T_q~"&Y~p!YHl#w$N_m/S|[ Aǭ*N+5r;mgXDDTv4 LʗIA5NH `v^iI/,;8֞qLpYHL>o5H5ͿF3j=4I@' R!qK&`kZqWn8mX1mjekpxtEћI [w!EL=JL @W:3j^^yKeX]̳3}2JuVH[z>Mnۺ[ cA_C>~ocwDq7tv>N~ށ`O{>~ުn?kO VqtR|.k W}o_{,a}]@FSPxq SIYQjq%7E!?XR ziNR9?_I:B&0c||(br-`_QȞH!s875]Ԛ8\B7ҲLB̬;z\ u݅嚉 ^s z] R7(Д`dd@4-, u)Jy`?vN-0$E/cNIa>2uy0nkt?i.K)2G,QVg@QD]^0eX_"e_2,bJ+r E-/7`:㉧tM*< UPBY7c ͹+O(.<%+9w:r8u-L< )#](/$Y2@Us7S&p7Ɓ%qB܋sXٿʶr.|%,vWwŦn ϐkLm@]>ZO:4W;KÂ@|?gLkEvDSSd:<5.Ϗ5u\{Bm(SN {3,;%(9F!3K4*(A!JY5DJ>HvҸpmOԅW G?)WxօU8Z7!U۳M#:I,iWwpD( A3^$H()xAG{> ox;J׉*s25 +il/qb3"12L0ґyXu=/,^6Qˇfpic*I;n0}0h+yfjy@nڊ&j I]/4niB?k4Q&=J@IXQWXjkT%)_4.eOkcQT- ]( Pҥeꏤm 8U4ӎ]}(2o7q鬔cG\kZ6;TynPa f ' _zFʛ>΄rx@ŧ^ߝTW'2no~GD36 1SνY; kwTkn%6)ߦU7SbR* tky~O>!<(uS=sʄZ@ps7x+sQ#O BlZa6z/RPjP f8O#֝G˝ y(Z&2kpS_\LdB8nl[f+ 5c:6dAs8|beݢPn} 'q&hzjIy9fÚfB?@k\Ŀ%dHIԎͪr= 'zטLgFv얊A)4T_#/'`v_DD@A+ncǔYc[rG~hVUtARv&ͤv,m3-wdv7԰يZLkE*hnHX7]4yI9 =Q(ZdxB/"2"%p[ {)aoQ/Z# (`B/NuPGUmC)tւLZOkj2=kK%ӣV'M랳6N2$u_g!%/gn= ^Xߌń>;Uduv W`N|viB%ߚ*0Юss!E?E(,2eurUlַvU MYt=y᠝k. 7軷3ן$8C#Dډ[xTJ7i%Q{'2k9 cbuhN3]e. \:jcYYs@]`*.F\1Lm_:phhc."Ts‹K&!YQk`` mz0Bz:K;d JM+Q"-j/<&22縮5 !%ᡘlL[kj h< T"to6'`}.g}H4"h:e#Zjϵ ʹWfNLwM~T˃K⟉Eey:w; _s XL;󉓅*]}Qz+GGUx=oL/|7Fu~z ae %S?{$Ρ:4%n5Tz+.4nD3j'ddeL( !5W6Z$1/vA!g=X>.nHB9MT72@b~blwSc =@mt4Y$x9#c~^å4;#O*]qV{vy/x-uhī߿$z "Ǔv R!Ň(&5<׍EG>KrzoدAVsbgVGIQCU#]I,ҧU]?dݵ;~;@tO%m:<\@qIA*mģ1؈ܴ:TdȭZj Ċ{yd7m\A 7?x:FGS BDj{M=4\n]A&fn';1x9BQヅ$ߘy*Uov /߱n97 M{&P]֪OƺMN4p_:"Fc|·7 l9- ;.`hܿ8>,;o/L_Mb&'DG.z!F'EnQ[v>Aewd.ԟM3VҔu103c֮^s̅כ@9xꋹ4LF߫9`5 艣e~E e~&N0q-T#[C\^H<Ɂ4e?~pُiރH̠LS=;[U#k QK ջRgsM܋xr1+V.C[NU[y^w os)0;2S6|Õi |1়x2n6%Q=0)hm1ak>;$DVLwT;[ x?\*f,K :ӘA!;{EyU;k1 5 30zHBj'(vX }U5"+H&#<Σzd$oY@ rK`8 @G[զbiC&q2 HWj Q~0߷+,ʼnT4Bh7sGJsySuwmn,~/, {04hFۜ%:%b@:V#}Ulg,*CX+Y@&P)ߓ=zWcuU`yD},kZ?Lr皹Ta79~C㯔."B{3,IY! F/kDwfFUSsyey95z^W9Gɽ?Lxq/yM`\,J/FMX`G8v/$oCO#PM :_aӭd9~_H6&!e돩mG$]L=ov<'.0NUrdĈQߘeM_*L1X;p}<栮F;Z!#@j-Ulrl5O߬~Ḑmb~~O::>^KO8 :2Bx6S$Zze&KJ-de=Қ~ |&j '_%f!aD]dm-[O0l`^=kEVvDmSܢ3B : e JT.;}l϶sۡFz${ reXX" 妊(V^~γTT!ڵap"A#7TAw|1/ysЌ!A7}"B>#^Y߷\f2ƏB\qKVFopMBq4{ >U&zr#Ћa'y\ƺU\PNoo̠r( if/a2TEdL?r>:] _Eǽr\|2kh~7# s K:g+f]/TWSP=3S/)?+)+ٱ/7I_?9+g+t 8 ?2a&)mE:<Q:_'0#y_ f_*-@`E@wp! ql'gXܰ^K8 }c~%ѻ nӦ=ɚgL~.Vr^]Unyo/WG6tOLһ nLyM[]m\<7h8j 䀔+5#=9lB&9[őp9y;@& i{rJ/YD,d_42%o?x^H1Xt]/;blZҘ]OQ>tS{_5&|ZY<ƓP./sywl&?Qr?}^6՗7lLI#adZnAYV*a*<oJzH: ̳)XnRE}̚9ZYyv/'::dyRuux9Rk 2S 3]jpTٔrbL> Hv+~h¬!#'HmX)0[s'%B*v@cX,zSp 5.F?"udxfӬK6mO77}pPMP>H p~'Z$aMink@XKts8!G Ί'W WDcqMlb:? ױ:&;ܡ}YKC5+4.a^Ҹfҥ~~OP;}gBܝ2tOG J8', Z4Z1K,,Pu"NJ`I9WV XnC5`fֽfu*@ƻ#Gyd DSF?S$|K%25Ol]Q Tț(2 qq,s&`^4ͣ匵' &5O]:3VCbhsZMb -}X>GIvS^>3|Uӥ<N~;(ua9Lm\)Vɇn<#@p +95uń/n#{iVhYP8N$}roըvJ4> tkKso*ɏ#Ҙ-/4$T_]60 ~}':G%٪_/'Te_&,4S&aN"gFlՈ6Z犀Dds"BOY69<7!od~~c~7ah)<^_D"U>=_ѬU0Btc u5^)"%pJIlxi3!E^=u nN =}H]tyݽ ,4o]e]'Ft*]WϠǃ(1w#._%W`Օ!MMA_mPV~E PmSsLVscңO6^xP\CWi MhUS>mk*i=\5Z5(1,uD4m=;ItrWٟ~+}thRGZȪ{i#]o/KU?l xߐ."첪?Z>Y%i={Y/:jVLm;#mR fON'; X␋:M4!~f9n}:.!$]G\9Y,X >C[è] TC4` 3! v3(6a ) !Z+ MWE6;)T8iv]c  qHN +WFțzS.Rl:5n$K<ѡ3ym%lfѮu}=FgcQޮr.Du%ey|[l;)o2+ry4)텨ђk_/R ?kA%() 6ʄtP) VFzeNI", V闵NŋD,XT)ڑzDWݷu3eWm>,,n QKg9 B8tBAR1aʨe =l58}QS[4X*))B_x4G}.Qaa_ ssZ"{B s%T:o6j aQ;;,}#}ǺGRV/FEFtczHٶk˝)UJ$2!z 3H(O%y;(%4y-jQJt>WBPi}Gjx%oqD};,`I8}/ \zܭ;Z+ٟ$? " ]T93Xd GGal7}jҖ惋-ZXhaw|3FkQY) L'_Ls7;mU$.oI/$hG+{TN5UTT2xV f:AwN0Zi0l_ չmhgJM~|Y-*hr硫yV,TڵGVA: rT~b""aŦMfci6TF%e˥Z8'e|=*A@n0'Z}qY9RtKٿnU/5^kl 3x tb|Jd>Kiq~7`DϦ; >FU(r/GyZ Wr3Ib?&<گqPaN'납X[t]5kρ"s"D M01mfu%;C$Xx?>t~F h -@VKwf0fS]؃p;R5F 8OI%H aAk[Q>phjzF4ml9 U 9lHV"BH!3[!8=K \3G^3 i%U|6Ҟ)cP\žURj۬~0N;l6[a|De_ 5tElOjj|M(zeWN%nԱW6^ޏp*'mT:Gli,Z藽(juPU$Sg];^H/ rPyc7b^u(mYNik^WP8 V4@,pgz]jmqf4HtdA:9W}IEfmC{sҀ^[n>БV,̓#|{O}t 3T$Ug>Ѝ1@;S݇Ks(\G}y*Уۜ-I=RHq5&PN"hfF]ɱC]OڼD/OL9:!E| OJ&G[l{CjgGN̲8kyoZ.CEC~/BrV(@dmT>y@dz)vO~y{Xs]7ܥ 0V8[ ׿y'P\GPؐ:{pZrqӬkfPq[,؁ Ki+N!BtK9 vv#=6JDiFvLc!#W4?4mKʨvsDgXRQn!]%R(%06ڢoʰ`gYPZ]y Mēg7D8p9 ف|$u,e)#Wv')gikτ&w^ӿ#zRN~?M]~lF-ܹ6JU&|"_:Uѕ%K^`,-G2qY9/🴅.# rKw|\6xzy"/RlBx&ƹL;ڡHV@Y.!R]|2DԪr.RP}!B*G IAuJUZԙs{^jjwGKDH),  D< R-zF}σuwV^- qt!갨g#8ɳr$My@]ͅ1Ԟ 䕲$aY1d8M -ly ęOx ~ #LЋUCNp8 R~ T"6pK®l?N;8,(a 8h\irʐ9#ԇ,EItb&uznqBAP &)!"2 bH(EbNxq#IKbśxkd}IxkNJnA` .ͽjP!to__omAZɟb_n#E''L5iQ'fnƮvq8 _)9)oX@]#”}>$ǭXP姂Ko%]k0|/p$IE,\aʑ-w^剥W3F8Cps_Vr"S{]Yy`*㎅{HnDuo8jrTҁeKܾ~o>&3./m՗J W?dg%]" |Erl['(cCKp̡ x_~(35.2Pn@0q q  "uamv^UtMjI. T7+W2Os)+Ӈ7kʃ@ʩ Tp|٢@g}]gT$-Nd%b-:ڈvyI &}|vMyld{#GgvBuGhT< -ꉘy ܬUc 70p.}9SA`o]ZҖAl'@mMԳʩ.j/F#ACNyG6Vc`\ } iXJs0fU~V`ԙ+miαaP*Sn 0-þ[SS $l8Ug-\&XaA`Pz=dƵa}ps\S\a_24s){NAry!DB6V@cQu? $ l*Nd[YTUޤTτ B4%ֳ5~iGP89q`7Eyfk{KI;Vp:SJѾAKDO$AV*V''P>S=wݎk(3412M"1-.aji+ >OrGYL vPG]2ZjkUjJi+rF0@ۈpiF}^ZΔ-=Vx~(q [VKqFmJc X #~1kLP׾IXLgZ^|D}BR̩'ڰ2\:duy9CF&K85B+.c!!2#} a76%2GD* vy;9hԂ4&Vm0f,`/&f-BUev^<(-i\ˆ]r ƚήR_=(4~|mmr3ͬ*e\5_ pN'&`:}W?>ƅwpZFc ]ZIZz<-|o˸}e/AB@ރNk;<5W: \Ҏ1qF!GQ*$[JBשkg[- j,\jwPz=\ӻUhDfш˾΃E"ӡLXg`ĕއ!|Yx `[!o ȈY7aw6~OXPh Ng1,51$=ݦ-Ψn:~"7Gn—T۬*] 𰖲Y90JjH<9\)ֲ޹' m*V[]=·4 ʦJ֝ ѪqAӮmJGEngM%ls:v6zK;ǹj%CO ד{\1NM3;>Wa^@5Cj%2rUөTXkJ;l.JG0r_¹cPۺyPJ=#Z;.gZ3ka+\!g0{mjQHC"V\V\O$iT-"l(ug?rp7hti=˩.|Þ'b WdR;^-o 1QNiZD|s-;|,m?ag:ɩ8$ʿeR//F2G{Ě]PT9$spi]rY+`>ER͢83<U>tʓ)FGMʐp9Uƞyy"Q.rFjL.IсktQ~1+%em{8r|aMHJkYiF"b3,=iHL0H9(w)@$ J:f.7:"IU|k5&,dAtn |H;k~Eͫb9erY٪z CmM<BlKJV96AŴ=E/N|mdM+1tVJ(?f.+N K8WFMa;%9=W[fj~`g̅@LEܼ=A.ZTos*p)T8Ht5Y)sN\U㞟,H-t$TPSIQQN_l))-epG dH۬T{aP+|LjOD^AJ)4t}j7 =-',{4 ǜӚv.|f{r{HsH :jk#C,@8A U7B:!٨!Ǿkrb0O# ԈrN;hNvSv><>a?"tykW?fWY"=mӍ%M]Lٙ$P(VgV|v[>6*p54w ) 65dM\m4Bt?@{I=>NIfY%ÀFY Bʄ#;D\͖F5idKZ>_ft;˃,1K[aK[.g[zy2m-xR^ҝh-ypZr'6y@a-/''pn5QCee=17r`U:Up`f6ԙ;-%8T@Zn<a,`|Md [u7DmQz|mvNIP*rP覩UrdYE3SΗ* K[~t{OVy$ Z#?WJ|7J,KҰ{whM )XNJxRշ&  >}y~p剛w| ''Z;;IE1J eo :&_ ޝ6b}`EɆU"RtBv^/:ZY4Qro y=ۋIiĽ,qܮB, jy͸S%rrSihSP6&fKB񀁚zF45=/Ŧ ]a,X0a!k!N 1+{Sp],N U=D&Vώc=s0І+)ZYYyc#(uy28=[|Y3H@;˿}Jb/[me$]%ޡb^qڃ3ԈJ3 zTrĿq7T -Ì igaPd..wYXnh|dیduE^Aƌu4%+Mj,&ڿ~0\N>,?k13G<"`ͽu(`.B:WE87?5%d(l <f"? %t+8$8LM+?D8w֬ Q<1lG>Zn4u0Auy3&.b’_&^V $CުR \ۤwx]z'ggyN:%ŕ\$ʞz,+} Bm8_=lj qm@M{m͡E!eQ('ٷ'm(-C>,"}d$ .Y[VWޙk ]B$ -tY1^IX`B`IHt&/®@홄ix,=ŋ *jb~ gzh>=;ð?ZcɇF:K?u;8F;,.]NMc9?@\cmGAtbCZ TKmXi jl)QzصuLEAc7"ѵP`4?% ;PDZ8z .{Ǿ !avH Tk5hP^ ]il t l@tfV+Tؗg<@cxtG"6bxg OkwxPߖU+(Ue!SiM`MfCk23uN50;/Z7 oLӻ>UT仮"a?J F"ڄ2zזeXF\No~M<[Zw~N?B!uĈ?^'#\.\)%Ɠepk~24Мxq(F9]zT<ٳ‘l4?`#K~FcגeNF"GmR+HFޙ$I˨vlYs  ?ͥKB$;BIV4 tAq&x2Vk2z\XaW_,,Uޢ. _7кn `Px~x:T@kptk>/.w#mN#z<}X,Re3mDž ;},' Yk3 ؆Xj@@:l3ؽAw o$h [pp Zؠ5/Uv7~q qyTHz(_૊2F*)!Y+\W%xe`9Z'4 ,y9E"Vew1hGf=?9ws_o~p `v,}~Qq24VJrG(uӉxQEԏmrȚ-NNf?э /ԙNG;4cSZn==ǽINF΄Mw >) G'n͍lc_Y PV@h#` TDZ*6t+{mXE/e"$݁#\T[$!g+H 0Ì~}F:v1hD-[ɭ){ 9}Gˋ=-\RRk" =Z *J +!s;ƄWT~,b vGb_%_~ccz&{VV6_X("ڹ5;ӒN s ؋I jj}S_Mr'M;2G9_+`pUb-@ycktqG\f^"u[Yo>"/ M>Hm;#O`m&gh#\L׿~fS?g oo𰁤i?qjD X泺幽 )MlԂߜS(Ȩ@vph "بsi|¶pfLȆ6B-w^idIkf 8ߝ muK蝜2 >+r hPy9Nち7*1;1pnt艠_7p3 )&yWr-!Ӓ^၍X- aOpGy}DKH+kV6䒦f%cLRDž`AJxv"ߑ8B}6PV֫aXHn85ש\D9D9< Ebάb Sn m.s0kV&N*zק a6Ka&Ln-݊FY8cAԛF1rlf 6AMm5V!CS2Dƺq/@('^^TXew eJK{U8oN]Ɵ﷥nv;.D%IxeTӛhT]u&:·Oה灝IO󛀎Aa, Q|9I`CS`Kc&p$IˌY)g͉%EP9)?~9pA !5 i1c}Amrُ)Il1hVb#hGz [}m% LZxo0Thǘ'&c~WGBzꬁ)`"ʜ\ >Ս^DSk38^ݖeS+)H:l?2q rDYhw4Y8tzflfX)ʍzߐ.E+q چVͧcs!+~H sHG=0 EvLg`õ5Nr|4\1!csc2#ZmyH0oJtLWvInw;exaWhk3L[;z~a]pu|YcR:XԞS+J3) }y*tdХ$CR 9|nNv hү{5CDq4àR*(N1m1CR KRӉhghjJ#.Dc*1+$kAScJ מ]6?1K!C4I{O}Ŋiyb+,J1L"$i~J΅"Z%dNm,'&fZި)@q&3 (*/뾺;L*@J֝"dhvόXS"?39SS&)CJ`t4[ ܷIZl 9ǃY8(E5e)j54NedwJ5LMLJ'ѷO9yúVx@=i&]b&3 m<wGiW8if1{к#鵭YU)qX[84[Fo}x^jm9:^?lL^ Jz}u.~NH> :CIkB7BNU1;HzgW]LbsR>@#oØGA"r̲kR9WGMSKP-Uj:HTXLܔ8"X[mGt& }!;tilnja,n jS!7J_r!#_O i&Nw6]dÍCʱ"]LZ5lLnn76OÈDJG&tcH] BH #"LC[QݚEuR.|eO:Gg >.wK~hij[w/ⷨ9 CdATw k~G{ƱrM۾y lä?m̰Y' 7@&gQntcߗ ޘ59Uks5Ol"s,u4v>j2Rݤ+cSjBp)\V+ROtv* zmfkzjXajO=vjgEv'Hdj9Ŭ?Uq6SᣲQ̆YE9Z6lM/l5G9v*xW멐U4!; iy8'UQc+n<5JX [%wn QNqV?^&[w31煢G8c6}14!븙1iKZ#Ȟv3="8#I zQC$,6}&Lu}( 9Y4-#jP,lZZ~~4&K4WԤI@:Dyf7׬FއT+=>J gBpz3<#q_Q&E +p}A| pJrp\DJeSaG eqm?w<<'q/kЪ87;mZV)׭ʓ˖*ɀH&-TvMh DB[l \˾f!-iR.{cC)QfkhH(r¯Vۣ'pl9e/vggUkK@%"hޞ{~@6(G(!'c4~L㌵4WRq H0-G-1fp/ Jꅻ"PB05=*q̴֚RčJRy&J&3`;N N "F+4 fߠ'Qrh@`%)פYN:fȩN£uQą>8jueUF(O!\xiĪ ZiJ67a[-TVy啼ROz\qzGxij=E*f2i |y&?k<eA7f\gηs{oD$#y˹DTcjaP„󊼓H.WZ}TfVP_c74[UI,\IB8lH ̥& !"c 6(D#hǜoH~x+ؑ26-rUl^SJ{2ͨ:Gggbc#ӞHnWDE}>K1<ϲC[7Թ(-}ӄPYg׆ 7+m~rΕsMhRv`Pe}r[0DhP6Tlp3"p,y:{{T*8ėa^/if$!p]|ꍊRLi%"<2 nkWF&y CdWڵ%ZA[:SSx? Tҭu0Bo 86x H-ekYuhdc~Iw}{7Ž?`do92|2nŬRIFʐʖ*>a\ (@Ʀg渎Y0x˒k!h 9 YXH$ynhOfZSqx,aBYu9A5O~kuyX&' ,Pcͩھ1\J ߜ i26%۳ ~i δ@wG#W;xU/j"l]*)7S"D3w?sPo8p|!H(FmaS n0`Cҏk\M1^B<FfCmU7CcM\n2h6pj2c ;lL͊/(AѦb3+vNw En>cV4U)ȌV5]:0|}rbϷhᆋOo 䵉%x6Y꒎#)"nR*BC/Mo1!?[ҏ{!zr@kS5vVI=AdXLJܱ;kF>#¤ #"Ҿ,@G\7J/5{_]H*Qx1RXMh~#js{ uOs ".B(z"ŕP@\&j:_sQJf x@D*,筼 0iv_r+?1C.r#/>3dŬbA=Rb1n">_HѤI_JJ:_}|Ҩ~;sYTacHrMi2򥂎,,UzD}+>Gg7hL&k$%:'uz0Cp |CGGw`onD{cZj I7$95eJx$K5*ʈq<&S 7yR%T2|€@Od(Z: αV{PqS 0 >xJ 0msm'j௘ǫM}lL5'1c 2} j `1+T"F5,a8,ڗ: mN,:JXu0Mm.t' ;5czLG~ 9Y @v1 =r @ ؝%ˌ_u5z~MrX S?HkYűr%l$YjE5o%b+kV J& M&3ͺw pG?KeD}=!8"msEfS> k}hP Fc ű*)(؝BdH80Ph"&\,# r|+)}hy eMcG]58KFJǯq:k kJ#sOɌmWB"ӟǻBh*8]}[w` qyƵ٢$ڢU; v;-5ާdIr"B[%GT#"^4'Zǩ̭/L&̇m[p^ʩg29Ӳd+unW,*KOUmWA %. CkO)J,p3m1)K&C,rST#2QsSu'n㭀Ç0Nd'ȣɬzX{#`U"*XMrݶgݠh:2]!Rn>;"mb_6_O1DKf|OeBQ" ?-A@zQl'O^k-.M|tʡĤoekD+9ZLm*Lx G#;[>v.6oF5<ǑAoaL~eafDotL`u]GۤhqcWD' 9pcja'~Zq+J+p;Xr ?dLe0-aN(V9@U~|E kS5K3 @hy4߅ +^<5Nqr*M$aѬ$@acU 9Zu]}"h>PK.}JY^H;WϧVWGB~__!Hw,=u'\}q+O!r|RwjH-}zƽ_'`}u+XwWՈwz[wR6 'jHwǠR C~AٕK\)1uza: e?kvcc;ޜԛ*V ɜ>4XOó-8X'pg oPpy(_!j0L)ؖWAR]4(LtU`{cwƪdS[*(8[2y:ѤM7&n`N_ En=4%!Գ\tyz? Ʋ@1)6/N2tʁJl;dN}qϞ5FG`iyejk.U5`8&,VYc| h?Nto-87Ðle9#T)E'D>@w %m ִuMN=(Ef#!u{2pŃKpg.刘'$_ʄ}7h j5*rs`_HK0DV@J"%DQm3ŮP'ow /ŵ1(s8~ ''W+ 7xƥGO؛ֺ(3>шps>F6zB,^ hCuO `ƴwTrDwIH>,O %K7yccd38IA$z;,3_m> &趢E~?\LKeqTّ76BbL>z^TIPngG cmJ037.39Q?ăھ{6x!uC;I kúl83R9z ݙupF(Ut|\mo`[F5}ٌ/*lr+ϿnG}C7k8,l/t&a- |b3KaB< 9',0dvkzȁyJb]nGVMoPy7FlR:bv*еNݻe>ZøtD t+1^E{NS5O{JHU,H o0P;TLF/F .VKMv֧>(=.R*!iNk/7^O~ڐfknlU-h<ڋ{RQjH֟7 $6/S}oN0ǙGg>閒! [b v.b_۹|tnb%#WPC7Ļ;sdy#/f`FeЊȸ:N^3?t# Z2W( &lwz^ ֋d~8o*- 6;zq=Y]+nNѺm3pq of߀dRW4m#c_*^54*~!o^X݅3^?'sG ZԂ;kK?t8s\UҙIظVފ5CPJt$fiKW,נ,wD/9MqLVP-" N246jGنks0U^CKD< ]f5qNVqiqYwc˔%b!WzV%GY!  14Z;zw~396V9` I*ǵ:l1t_dU_ͬK &q#$긬*\& Hp:i H u] zd.2=_*;INh}>d:K8&ikaCxnH 7SG`6Sy/d0B򲲀5HqNvHxE]Vq6tU`["6]^'!@74h&!?T*'D,UF >KqOOEhh`_tB/Fv3[K4^q28K5hM\7VYζIMAL2=Ԩܻr9`DMO rgK~EV-):z<  :ӘA!:Fĸ:S uNӍųd x| !pmY"\ÿq-6orEbI'1NO?:.;`Қ*B4thkF@_&'8Ժfr;Bdmn^;TPycdVlI.7 mSZ/EV>(y}dmQo Ak6ŗ ̿CY{NEĭvaSC{x (^!kL>PcIݺx(V kQM֚O Of?'J$(SІ-1G1'즾qQ%58яiG'6Yc; o]t8 .'Ҳ=X$J>e5vP[ L$<$4DnA)H-by+KH{z& n0EV>~<Tmz tz-* 'SD 0o #0#cTٲ@@2)3G+;Zm+9No3+VnFA*329<]_Lhۉ9Irʲ&x]&MhD*d6DJ2ZJj]DtUh sLF;ӗAPdL;!,zlGl(knȳ3܀ N%y"IE],! )Y,p].q1;"TGNuBX٦e]m.+Pw(y, ܧ{i sñ/6tǰ I&}Ghn{lfoF_Nl9pU]Z,Gև*BoM퓡T*ܯӛ=P g39ɸuR h@#DO6?S,{s#mmm0KIRhWj:Im&Ɏ8{Zzo׻BP i+,^wV59]7 ښ|) =UՓ e{=i$X1Jj Վp@ը9W&]+/0]Biv`\m+xjWK/)Tp5Io s=zr?z3,ق/7i|܆2)&e#"L_NXWU*<>>9FX"k^5OUuu*Vomj C*&5&hM)^a,f[93WQ^ޅ>5Ksbbg2SMIN}x޶2D (pBQ5Qx3{f| f;ޱހ)g7W"D|o%glV g:adDp 4]R:?vxw-^c8NCh 5\"-lHSӸCH iQ8kC)9OɚyN8!0[ B" nu5ӈWw<%ѕ̵M2z_2HH[cHYK{wQGZ 6r͘dvv& )'vGUbL/DaqZYQl\:p|cdJaڂ<:A[G8r*,."NNn!z.YE;h XXm>5knFv]K݉<K؄,,4ϙR,4J7vw$dgi="&>9MݙzG~Lq 3Vj5?"ӯ-IӃJd)`z ]]`mYSB hoh]YdVwv374xyUSAKr21x7a(MKdku FzQI?b'8b -! /dŰ"F jks^Q G%_ 0!~

._⍻$尉f%oafjyqiY~.up$ɗ #ޥ(c˻}s7Vȅ;̊gY.s=X4+﹘vg|H@} MwwJg c-f7"P,nBǞCgr@&_}j-eȼaBUUC4JGT*|u 9NdssfrON1χfY .9Ǒo^3py& H(0f2$7>+̏mztW6 W%w;|YrVhi.KJ=_.gC/9nRBL 5@Mco >mf:To2n7C%j#h[c8cӤ_-"[k r*#h`^l$dP9FbhvڒUK)[#:J;eKwNtE H T8aI/Xѳ 揩>>Y~xuCGFMDJvv( F+haX:|S̬݄*뾎~(5@r>x1Rdov % A#G'dL F#\`fLU@SUG> ]čQlswk~2{>nJL}yg`ӧaWlQfL[*ʲYzQGl nhrX`s=Twa K">IRux=D R|k1ˠ]|,|ޣ9ŅRfRwjc[ /Ŕp_=̢;Օ;k٤Jc؜. A*%kvĂAgK !pxJ-A{9VrXAX@x)סLK5NM$lG|2c6+`u;!T&9lkԳ*2Rr7CFM" 69f_a%RR\RE3xd9:&K'NjϩAydثm*xi[vɈ*`w$`4YQ~=Puc;x\Af &y.OlH=VH()JBo6>i'o29:}xHIu J>x-4/4Wk$/TVtpbȋK{wF*_u8w [M)>soz8d^ҳ티 NZٖ eXC >BNr"iHp(Yn̘,]^N?ګ3əuۅRz3X38xR.;Ы)XBuYC)ߌ)^^ #JH$jjڡJS)P, ED1 Et$9qނ}ؐu@l)W({Z7Toz0{0DSv6O}tR|*e |$F}uToơwC2dL*ZFnfAi4퇟 ?g.!0eTe(^w_q 3+=bه`AW3!A Npuq_*{9H0A'tf)(Yc*ƟCID]dg56d#W{%zzK h wvv"|.יq@DetZkCM"¥kHy{&`[69@.?|YV+K ?T{+=zH±mZ=Z z,py9p|*ٟåfP1Un:aұS "i<G (Eh7 TKxmFa2Y-!>:4ZItJ?;A>qgўjhh*%V *rԬ+raZ'6JnW10bPCH", oDFYtz5cM(&Sf.^?#uuu!nelXǕ%lS$A:%hlYA4}.PG4-9E,"k3M.M^ud'\TYDY)uU<xΆ Qشf ZvGVQ+Qx='Sb2?-B}76ue K#+U0ylߺ N<'2#TGHrcJ $}(F\p̪8pS ~ _㮢\jDٔ%XGlivK;Ky0-sWPmgOG!5~b;3i ]LOӹD}Д3Qk3wo/V@lH@6纕u#W^PkܭG){#fN\gRF7<A]V@ATRn~a[VB٢z}8MKo4Vi3۲\s/UUTg(Fo35s倯  dRbX6^rPg,bXތҶ,&jZ6^-#U @ vZsAhڧ~*1z||] ۿq֋NתC !<=)?w&)"+dYXnnRZǒNF^Q#Y 8SDsg}NA%M$9\M(kӻLNu vd+U?zbTT'8 թCE^fѯm?`N`BM"xY(ȿB1wE|[ ;rq Y֌$u²)y9y}#*ύ ?q}^AJJ֧lpjT,z/7l:GN,eiBq6Y(6:T=%:M%i}DD˺|]T|f^`۔u"4dl3<@yn;1,4(9:d9IyxfS>7=-ޯWA7Jg4eS|2}9Ac1HB17)E$z3[q G}W&̒{Jf}/U#:98E73q~.Zs"ذ~^wa*=+S d(M;ˬ9bo1&kF‚W~6P7(2oʷÐ|?3yA/hWQ_ĹwȈELf#n:1/v8ၣ4򷻣yl(qO~%L 04 x`Lkhw -YE:]Rlx _L EGUrѱ|#S3Dsg"M. o?Pꢂ.N-Ct! 3p05q%5n+x(0kDmVy崺hSOd>I6™79m䫮 F$EJ\ ␻tf]dPq{S& *3A,AB'#/4kV?;?-VL&RKWC]SK+\8X)l9nٽV5x?,rjZv]_qíF n"[j*`5P_"m IC6/^Oʉ$B)G# <vwe/cr}*E95^ByK%oy'o QH&BN7Xw?h`Dc˻ݥAQi@J}؏ b{i 0C]k-\ fGv~*{GAH;*+q@f^R?tAKv91;m99LC/.{됄aj2VT.>ig ? z0X;.8_B/5rP Lrw-fp\Cɘ͒La1-P4Y~SؘgȿLiN~nW^(^L%86*gP*MqIЀyI9+1.]}byEpGŋSZ޵Ujo<5z6YEbC6PVw8MJI~Q|R)U?"fJ ,rؙR[9"N:,atN}UVnHSJWmcɽ|sBjy˅ppߑ9]:v=TS7+࿜ѼU/D6;+3w%oN*37BN,Vser^/V`+(0kFn?x]eɝP(^@2tbALqD 4{7LsY5D_?CxcluuXXx:ĽTKJ'F%f,a2 a.ꓺiϡ3%ET0m;^|$js䎓{26mLIŏeC%6$2yPK[=PYQKA6u!n F1D,o)sv[{eZT<]v#\hU!}t-}hB6oO:kW `D@7;yWMl Ge~ģ `iҟ˿ D`*N|p_|/R4Ւ?nxЮ{666SI) a4?2Hn#fj16w5I(r_)z"⦗ͰeZ V'oc0ҲǮ[A`b U5kWΧh&t4RBJfT YFu/Ѧ,.ab$Tc`ב4@iFH!0(v6_---b 骢tj$E2gbg*d,dN=Ѵ<GE)/9z(#ctW+w(>:T%O"Cɢ3+Os`Yjӯ2@,'κٗ1D`i[)ڵ3iJ.Fd_1gYIT\qn[[Vtq1sąY7`ӃHwyhJFf-o e̪a/(Zj`J||HJ\ '2(eE]ȏ>o5t_t9K0:(dDžA t8U(ʉ%> ;#J -G wXcSѵWhٷE80?Hs2u ƚ['%-ku}/Wt&2h:PV"XMeCν&ezTX*"xփ\RHC_F߫ĭᖸ$0I%@tۍDaT3Q%{hᏤ?2vD軧(E#R<=pB W'*SоJ$rJ\qgky 7 B[܉?ֿo(Jh$#+y# VA *AI0#pZlIY gA~濖) (̯!Gَ/{KJ{Eҋ" [Aw%bWC6{S8؋osY=w2WI<ɇyuHhO5]g"C& d}`=LY:Z5/NۜqyfA&\m;bNXtT  Eb$tr) Zj) "Ռ#Wt Nq@#Vk`N+0عd<("::=$@*,|PQTp^gWk =8)Gc1XG 8!>,V/$c&ϝ)(Xj{}q=[aٗ<ܟ'K'h_ݶVy;3%e(<8Qt-.r</XWVQ%Ohduڍ _ƦBgy&hn#&)?ѥԧAJ#ڞiڐoiُ!t/L]/}^.ط W+L2eOZh(`[f$6;`B<]Q^| LFcny&mǾI'СRkQꃼ|@C֤Q1{2?r,cezPUzg!+Y`g$he]Ǵ6g{\4)L;aTT|1dO?O,{m5fcqX5}/bNs_l6%CTrp,wv/oMBd&&t::,G3-,94 /Hw֊Y'/GcF{ԆQ吙l\xگ/=Ĝ2 +9Z}Ej{*ݳ4ڕ!,H7|[&'4$E*EJ̅,/ >sJ%}ho.񚋪E/e쭓9 ʪb*hM=J $W[&?rƕ6!$vWrܭv^;t[ޘ/Z~ChaV0?V{aW t;_?k80Ga}?]5ojܻ5 g׈wseFIA.`\08v k5/Pf^h}CMz06 mܕzEN#غqUPjj ~ժ'&5qr&狼\J}PrtNNJل+i &dFRe?F0!R-|Nٻ~q]FoDLtt $X^cddT-ǨgLLCLDor7+?K󎤊dujR:f1"~VB-&GzISs1f1D?B6@̡P8ܝ54TZ2QsZ3vK#:ǻm`3}.׺NczvmS#\rt7tv>AT7ĺ"22 Duj͠-P{TH[g^O7-2c~W I Qlܳ2YrP^Y|\JÍ ; =L% s Yq4E4?/vTee12YįEux?waeaPKOz v^tן&ѯy ^ʀ3B(;K;!`뫪;Vix+&A%&}%KЏ_/#,;RkRB9PU`O۰_%^J#^&K Tf* o-@Hަ!)snJHUnpQ KhrcT%fcԂ׬Xc=(vigq9@0wC ; i>@)9wUsχmRL*0jgt00JKL\9EKV#|.YZɌ~Sl6j樖6(+)~wHj٬(hBl``n:˙vֵ:JCt%6o$K )vlBvbK0" HzEQ2(S٪T(L Pin힤1]^d#PMܱ6+ 5]ny24bb8$5W3Z7pN.+X*$ș/Z#qbUvNWD6}~Rra[zYINUQBk3|Xga@S>@fRfD"rو7鎺|J*Y"*G) ʦq* ve3̈́gnUGF=,Bn7so ]fB{ 0XúH9#n\&i!"a#XGD6"E;a I=a:z)$-|z_Q"^3xҀ sNB1*̀A? 9lږϻZn!h u WD8WsQ\"8ȾΩ<''ޕ) T>c8rgbᢛ׈5( ;CLR,\?U,W_R-@eZ%Q'3Oꂟ9pC=;FgƔe23eq#f !NUlf1pMvT| FJ Bgq^i hr%i>8~|D?_u})][| kǑ&#XV;~F !PDw](Ƀ-(߿`2Blibͫf~q|/L \cя+`e-l;4uOz'OՎC/}q_ 9g#H f}8:8a;۝4Kr({}CC`b dퟄO_2 I- L{JUer6A`䪾0y3sc^V!SG0ho 7˃M_`%)G@a6DfŠڵǛc c4|?}[?x&7ML4NirƋn[}mF6S`y Z$ZeڠQ6w&Z?–0+e|8G-:Lf!*Ji-]h a(mT٢׼n!RVX:SpS/WӾ_ = bt즳v=s.6%Er(oBzO[aLzPP-SobQۀ+|7@ _fO>Quhp „343>EŬG2_0ppB9oQxުA*,v/ Z|B~9c*}v&p?U)Z'_}߀ 2,>ۛP]Kʖ6AMogL]~z\֒濣G3tii !My;4|5%թܹ}czwyCŸ+;ڽ|` kOqv L F‡$=-U#mr[e>A[?X\'9[BՙT&6D=k߆9$ ZɽƨOȑnNp؊OLTGsL+'n& V qDoAF6 ?}2i|~i9XuޗO$43Rnlj͔EFPA~OuT# |;SS<6&G2GiՊAv,w&H(%$yRIJrAk@Jr\q)9EZ@i༴!`/[u1d|Dzջj\L|o4~8<5N}9|a6 JxYW`{.zKݥ6{YK+3:{0i[eyuVNƧ<+ٱź`R9׾F+* x#J+3)Ġ J"pR E\RR`aya?%{2z z穓!tb3XtWr]hLMvo0+;{3Ss5=\zN w$TLyGr4vp崓g+Ƚڵ,sjA IxfHq=Ĝ'@Ɲ瘴X^p֝[ٟ>4pBof Ğt/>r'TPVޑԉFG0%S -e={ץ,S% Qw^AX}eݳAz[G 붛-\9ԉkD1[H߂$1ΐ@cZuɅlGG~=w@4$Lj10CĶ^7i7$wt#+|>Sg>΃Ǧ8 &`#xNIOK(PdnH%=TO+H'!T]ٵzMԌIq~珕xF#8e#?<8 E;ALZ !D&FBp6q#3CpXژ\!=ˏЉ9AU ˊeδωMͰ@ˠJ"ڣ-N엽O8\O맇OXǭl:D~`82-u(g`cvuZ.;=5`_^I0N]`;ݟZ ﷦ F{= s"4G=BX1[ṹQ?or7S}AJQ?:ّNmU#]jeEP y+5H͓ *o'ӜBMhG)LE+DRBX ,pQG(?:wFq"|UVvیήٖ^Fx8>kepY85 =ңd>]iT$!;^y^'M +t* nyՓ+`z<3e֞G\x*{a&,Csa mV Hhc _)<bi%X_|~q䝳pkmn+v@RdR1dJKEx{;AgH9ڕV?;ZNP6mCQ\ b켚NH9EZEڨ=q3;k=G*٭΀PRC2VEqZtJa5F=y 6:4k` I1aQqȓzNX*Nnng͡`E \Ŗή\|~u) :{z~N\9%U2V@:+̓k53qe]' 0[\ p81&̘ ˍz: 'wF3ˉ[ϟ SEFP {[k-].HvfsV>wIZKWr U>4S8늚ھHWqUL;sZ9`HgQC4"d] "C .LR-pJ+ 5Q.M6kT(V25mx+<J&JKwN`a؃;] η30U$c,G8F4Rt M3+\85Qb*1P#Mm=c-7UFM]v}rw3R8Vf>7Vp u F{Ņ^VGdA>56hxރ֕Z1v߁?|xjeRTY&l ¿Yl4r*Eًa/Yߑ=wl])v'Lg EliڰO\r5B,xiy,{XsEIe ϐ4[za0SC+ҳ U3MT[M:U+6zň%thT>78W۲-ګtT.}SGtpbC>&l HWDKb填H`%KF ÈJS|.zP \إ t(Xx׵Eӕ_ ,MhF@S͖ЋP18[ Q&F3p@=eaä`uL}r雔9u*^"\ː YwyB$- HZv;&MM@fb|ތ v7W*MF^2=RsbT;0j"RYovWp$|(99t0؀&m` j{b~in ξ WlXzVCɭm믈(kc @XS4uHjnɭtn<{Z~*VQr~FpO4kʣZr+BOqen.`"ǒieν$/ )VL2$ܭA-dHzSOJ)R= NJcn'TnرkP@G&@Y2~QCV7#QR1(3Ȯ񖪡@^\OkwǹB,SVc9鋋eiU5@٦`*E&3*R4eѻIW ]I+שBepI,5baMnC lz e60Ut$2^_K/dYL%BꟇ2xMiZ#=W#5 J 8~jeg`4Ja:rW:!Qz$ןs׫{-mLd% b4;Mf Q"-*yc tˎcu48v`QԓYO~Ve~>TմGK`4$CX, ~'gfs11_25} Ux8q lͦ5eOpW0A,Y9؊-0sN[3:IqYA-%GWnOvݞ{nDs~XBD;ɪ4y.,}oUQoa!gi_˸{yսHhr>RAo;BğNTZޫ ӀAm X4o(*<)J_[fM 2n*)lZQzDZQ|D oh2 ?O/JPs"2˼U8`3bn/bTqG*yߛ_ @o'*Jg,_όj[7^~p~IqJzby7SB t{J0Dlv4']F:ͬ YhÄ ҕT Ƚ&ݡ5f+v!/ {t3X9S/$ܢd!LVYVl%m1JĈmD *%idLD~S iCz-rC@'ZG1Ӝ6هH9}͆)hs)h%҃"QfO+%9eRjkVzO3w4ʧ.@K՚TdZпEkoBR׀.>^听/ %r䎍 NԳTct ~c٠yzyP+EFCv7fGB3)n}/U,[ IpW!wqb1ô ?0y&\ @[_q5aQ$i)HWk1mft%W 4# $edqH4S" |>t8݊W# X:pAuVϨ`vM$\}+PvZ3K]*g;+[ApNO;@g-a{ߞE:Ih5|pX t<ݫ 'pO崱ݬ+[\ל J0Z?Zσ e_"!lt{~aJ]sb}}oK= >L&!HT4>e֊]O9B[eBMKAAS6KW_fI<*F?RuOMR<B7K.dx-ۺvu( yxwK\KL~ׂ#y@qi=TP (r9`^xmܮJ7Ϋ&D]80+پ^ۊaLW1~=_ ~_TCn`Ĵ:(:u{h,Ԩ2{~2@:†5QɰW1 cΤ&a;)L)" ;Gټ©, ԡ5̈0D܍i h ` `vFۦJЅ$V"EN-kRc|)g]n4w <vUaxؓl@)CoW3DY|%!:h4ޒȱwtO7 <Ki~AJ;_wuܱ],7GH%?L@Bzp5 ok,Sk*tR .Eq7q*IԇX:O,R!I=|=nfe>Js}a!-LP[/ ,OHD)4Qkk0&֐JPҔ伬,y_\dZx. r-!@c/z)6nh,ٹR4!US#(6X?L'gG;jfLkeDs]-N͙#41h F { (n;K$[q*)!1И';6T%:)WU)I~6 ^TDz)^O|l>,5&Kl qL0*#ӗQ7˛wXG?gVlk 3n(&`GdrWF0|ro}^OenZ.~Ĵ>4|T+W"eTs` ~#vY.A݋:zވyF1`sV,ҹ:;FfgPWu,K4xWֻrUi4@߁z8F 8PBbqjU>YƮО\#d 7v#\BhCyՉ2db1d!Vd\%F H̀x ⢨* Zc+b[k~VV{o-1/y2MxEwU8 wa X<ڑj* 7!C)oޣ%P#D>dlOs E9Ǔt>4µtyCz}#4K[ST3Ϩ$ 7 B٢qC?LJƠ :+~T `%*jvl]xAxeC+ugUzsZ>̓PH_D Lᵭ0B\YMn0:ĺ vܐjߦYVڊ36;w0e.q32>y=1JY_xKTn{KU bA­hmEkּ+mo8/uwl\U x;g!Kn X鰮x3kh5a60Bp܆r-,&FB[6t' + :~8 s\<6kuřuǎs"fR|iGCH+#%KUKot`^6#FQ ي/˰\1+Z'~<5<,F/1Yy1(u (gȧ(©tMO|@H+D*ٝsXDmpZ9l9 wtfԥ)N,Mi|{$ӷ !ok<^|Gq:AcG[8p,=pq8m]X=XL9? tvF \EߢҤ rȰ9$3:Xnn_[k^h4+vyX\L6ԣ?GL6~BTJZ|thyWy`pyuTf,K+A -lɮ'5ms~@&s,43\vgO@<'4xU]ǿ@gc zHen>&cx3cYoscd^$O`*hXg3Ra*Q^0gC?P06ue"y0~t>T3 _& }C0zrEDi}sjFIUNu!>çSmE8F v)-.VoXiK%g#+~uAA+Gv $TK:FBmȂ1K*ϛۊV,t;8cD |ΩPMxT0^=,5"*t~JEbX cD@_]ba1~/1/IҜ_gx8V3Cߜ4V#3  K.~P8Z[9T=SyS6q)%г8Ӝ7^ΈE0/4&Q\b*S{+LZTKv;ːi#wT@ʉ#nIRF0tz3n oͨ@7 BL֎̱c@sP&YfKEKIXSMB-.E)ژ0k]s>}dR$5P7>+n7$*i=*H*M~~enm5eaBt;Ĺ@3Ah<ôް6fE.yٌO`[_mȴ4sHsMG{ր;߇͒28Gm aXr{0bO]J,s:>Gm Z{ͨT7fJ (9"HRx(]YԼfZZB U̮A-;<*ԧt7w.6UQg_H6r͑4gצlXW.K=m"~a!+2z̙XM1r"ie8_62cq& -!ւ,7MtlyƴzΪ]3]1z T {dN4R!ntx#͓N02\̠ٚe\6m#ҩKQ^t< ܼucNb6 t8B6{თ {j#ӻ!etu7Ocɓ>sY+Tfv9_#=d-9 _u%5 oQhgN;Q|ƣ-@-zm/22K:7qMŞ曾sMzYP H@N)wis ϯπ#NP+fܹ(-]l/pQ}'xQk*`Z1bt{𸵣P3]x ؞Wnܚ{.=&mf_6Rx$M$1z.-+C=IETԻqSMlt>y0 5 gN4YK4SvIVb# ݪyp0A-vtge8QӼn@JX?ZSN=&\lM8"@J o E26uZH}7wG)p.W5MLv.-,l҉tibAgRC X9bЌ7B@tmjL".>JQx\TRI=h_^?!2@$EaXF߻@'ECmcY 68Ot"#b^-^ jlXnj6?,8 rY*v é%}Brgia +k#45N5].{+XT(W}Y+N%?{g}QXn=k,hA}#$-6ԟZ)"GF8yz L8"|wL9LAZſ \ǎG( ʌ`tT.nqG);jna,}9Z#3Vo*De']Ş/ xA "tUO6HLTv=N90רF88BkeF T9oXiZ!T˘'E ;?ZHEdR O4UYh6y~,L,a-rG0#FF}y.}ILFmoa,%sl$zٶYFqOA=x1DtB!"ْ~Inu`m˹CsH/5iJյ5QGKxp>,lWx,"1Py`qs+6ͷ Ӆ%^_]Zhs5XoK$.9WNV9h{13XDl}'6\u=~\uSD1pA-_\;Z'g]6tc/>9h4Z MWGuLsGfLBZ'E |pa|A)VӬ32Ck$Aը/ta4CHygtyR9p:6f0UL _OGzcy2%OZθc }Q+].l FLRzͣEN,bjBk#1Ж1̗(J'uL; \Śuз+ 3;iJ"vzft38[8e iL4q <9W#N`57[3ۓo+S>һ9-ϓ Ůt}MxA>j*S3Vftb94~.eV^  .Bլϧ O21á f X$LUȕM6(1md|9Rށ9~k@1ɳٲ_w"x+#ۼleJ_:Lxn3P`3KxNmV '494ymUm5jJJ OVxhDƴV }U ageKq;KKكyd\ t>:th7EZZm\bN/ߣ#p]C-c`Tŋ: Ê<65Mvn"4ں5-E?#X0euVZ7l+ْ=#.=Ԭۀ gVf"ڏ)FBH+v!˗mjmE*#ґtsp:J+NzīqX"aFS ^An ;uH|t:wA2,tv;7 {/nO=_yahVd+P-ǘw ,AUCn%0CZY n4$^q:k=‚RZ|mb;8ٗ%R~+E7Zj1xjԹ>+ˇ+uЧ@|@UlP|T*,GӖjd:&VA\w ',W bt0[9i5ρ>oLq^ ̡f~Fd8^,uWR,:-5 `LшiV'TШw[;$@RYTc mi|4Hsp'~C{WFa>pLf<쟶Ats*>Ѿ)6|x Uٿ_/@Lk 뿟ei]O}l~ ϳ۬ՠKoBxq৽w "b}}_EvFsS,&j52 &RAh2\A紡P_z,z8;2ǧʊ%8(Xч/VI6H!s_AqƢN/؀A[)*#ѕ{k><0)Ku $]&| F3W*|,^eT/glD m ):z` k9>()~Э$vNUCi5N2pˉp;\xiM쌜r{ kLj?FU>,Bj8߳e 4F$cWW!?piW6 RoH_,@E͒?|aO $}45^ɽP-_O&WL@9qhK|Vvtix~G* 3(An+>yߞZf^xWP*J(N@ /U ]A[$ƵH"(P*\Cu6,[l;Bm&*c fϧ*눈[wBg48ʊ2CDqMxfS^E 8m{Ykʯ|p4kgRbjdR։pXHGp%7(: A =q"7#buڿch?Yw5ef_J0Յ$/L :T%(ۃ:ֶPT󪭧ˠPXʵj@yB"=+V ;&Tٜb 7%م"@#Yjr迤U/^܄7qJ8IO_rRl(g(ccbxt?03pB"%@P{rcmv5k>ƯY#EӑW]<{ HC>Ы +x~e&sP/\) 663ǥ?.m[2g lpu Ek|UZv~0 %13s5|ҩN\NrNݶ7t(2usYKT>>`Jzo3f5k;`mJnG0`R(Tuz^v ~šl_)JͽV ӥ~J#JjO+N:VfnIxh|fn*i<9;ڱ_BCA0וMh-9 x\nJ? }bt q_fx܅=iX2JZi(*d-٭T m 5ׇ݆GU#v.RTMΧ/4( $TrU]wVWI ٣0OhZhY66-nz/:p/?@kp9ł 6K2[9s# 0l(c"`~IXv@yWAػo. ] _:Kk6fLZ6PKS]XpIOBjsӜ}b,4_nQ2'E5FD__+2ô?'^'ˎf-p I>el8: "tw;O#c]eA?UHÜV8$<8{猱fG٘V6uM:)?ymGogKm9iЋ1z)^c^TY+&~GFi-S 7rw,Vd kp(A}h7(xFx;S*Ԋս\6IzX2jέNF;.PMζ <$gL*%:5BժB5U:,@ fcUz*7K 8ϑl?}0"p=ք$u%8Rm)e/LEM#2'0ksrEi{~%Nč+WB+}N:ҋ̣?rpE{\U^}Ud԰! K({܌d% qJe@ʛbyޚdk2P~#dAւ ['VWW,VPpM^߆n/*i߿h_KeYԍέٹ7kŝ-bf-P@>gur`Uc'z b<]oȿ0j"ߊ$ٓt$F_;X 0\^Tܱ,]NkHVJDJ"D$^Wm_mQP^Pd3^J6Q1I HF熥Y`pS(v]HPPq220<4|ljܐ}*z4xfL1-j3=D[^&$|o;bEcDYH2_S(XwXHR\LKĈddhej~%ȼL-^;v*4|B(e.ч/S`Úc(4fFEe6 U7Tf9ˆHI㧖MiVYG;k%2Rsf;Lpd]+S&"$LM&y`h"y,d_8j(A[ ,/L6n/ȕ~Xxo4ԝ2*LUOn vKI4>nz!XZ Gie^t 9^O#`^Vuc/Xኣ:ݚ`]yyFR U(c̶J=OLUg3%k%4ᗔ!kP`nj>( gwGKs}0LNJ2бƌt=gL4.#G a38׃ r>z)Q -aGTΞ1;]Ŏ؀XX\!۲]\:O=E~v& C3'DItֺRAaP ˓M;S4j ?{OeMuUpbS!i ӵ^=VJ[t\i`X8 ۛ[/x3yAM˖ 축rrE0/1v2\{Hb;[@F\L^]cpY'J6HDpd o[18~7Xs%oPFu|10k%ΎH l}c|}W_$MqtVCUJ{% e{}cODNh;וpTvsHqmp,rպ9fPīG,Z>BO0.F]:qPmTg'e *%/n|{8%Xk]뗔>{@bYJe4b$zȄ;JϮ#͕T*%Wv.cOdU _f~c ͆)Or\/ƗRQN. À#S Vjw{]b'_3HIvhޔ|0H|}OSbn=C[9,TS1&TbC 6f E5jҊ2g0m_JFi0Sؕ庪?97#w͋%VIFEBgqL"as9S C3@9T6z@[D15z<QR)knY;Hݩ)fYi]grcz٦FΡ;S.xt6`MEIX7@#ߥ͞h \ܫ0}#Yicp0p cxױxQp YC4AeK5iurf@=@8 )hCD;"+wR\ J %74v2ڨ-@*NcNf/HpXxSu)3a~9v(Zg8|u|޴EzaÌM _3u,+Rs痐։5)xc,v$:1|T}Bd8%Wh:cTR C:(7Y1Q(Ƞl eS=Div39 +'/;GjfW-v۠ωhT5ݵ/CݕvEM|278E&zK*5SխQ.:7$p9|* g(@ɐxX/?vP8], -_a? yj0`Ѱ}*~5i J{EY2`C~$WQU"Or:@AOrt}t&jdžNt(ܨIZ Nr\zÕ!TKo,2b6V ů>%v7KiX?ꦌ\22KK۱8= RrvRœwrf3xNLF⤆+Ab; Irԓ< c{BKd)t>ƐJ㯂?ׄQ́ +\ Qf>}=-y_2)Cj]7NQH.{PaiuW43ѫ7kmq[=KΩ*LFM0Ks}tqRÔQh\ێUK5hk9Q÷"{s\U$aRābCYN[c.E'9b;{R/G1ƟF.;OX f(htѩN0L`9Ga5S{MeDJ8Fnc;0 HWt1l$ΐhEoWo`wE ]% cvK jPE#G2[w|'ttxQG59dde#6d怜O | _HASGHm (z/LN+m=N@XLHG]*u4H/* $P7$Gxq0دE(2]w7Ĉv6/ځ_GXn4bڠ.ujrSA0MQ!x7%(Gѻ/>xe<?v ]kt6P/ȫ8қx!AUD%߅D!ǔnePÄ'Y1k4{qZ9< Hem !c>z~Vu] :S6nbk*q wTUsr603NX$ռ+0g!9x06b+=L/c{W6#j\xeѦ0KJB߉RD_f7{t4ϋE.n}wE"gkS A COaghaZ6> ct 0`RH=he(r<?r舯'rüو A݈ D܉ A߉ Axu m..... / / 0 000 000 111 111 1 2!222!222!333!333!33!33!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m         !!!!!!!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m聋 ꁌ 샎       !!!!!!!!!!"l8mk`occccccccccc_(IoXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtjo4yy3it32(OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/D"/$/@// ˀ/Ԃ 0 ݁܀ 0 0 0 00000000000011111111111111111111111111122222222222222222222222222222222222222333333333333333333333333OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^^_ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/D"$@ ˀԂ  ݁܀    ÁÁāāāāāŁŁƁƁƁƁƁƁƁƁǁǁǁȁȁȁɁɁɁɁɁɁɁʁʁʁʁʁʁʁʁʁʁˁˁˁˁˁˁˁ˅˅ˁˁˁˁˁˁ˅˅́́́́́́́OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^^_ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/D"셎$셎@셎텎 ˀ텎Ԃ  ݁܀    񍑄񍑄񕑄򕑄򕑄򕑄򕑄󕒄󕒄󕒄􅒅􍒄􅒅􍒄t8mk@ '046777777777777777777777777777777777777777777777777650# >! =/_9 qBaJ#`M&_O(`O(^O(_O(`O(_O(`O(`O(`O(_N(`N(_N(aM(`M(_M(^M(^L(^L(\L(\L([L(ZL(ZK(AK(+K( !J(CJ(#J(1I( < ~;S4]>H}PZLlۛ%,,NXAZ+ .:TAt%0 `pErk#x\ɳ@ZoQi%<0`~n_x_Q"* [{-Y\.y>:4{Ot~lQ3?o\Q 6`4?'Fi ӕiv [F֚mS_e" /$3 rjĔJF \c2[ x+;bF"$2w HsV }lu!kW'?l9Cs,^6{7} Jj}Ej{E!.tކ-,fR)mjy"WkY]V tb^cCWаaY}Ƶ)lH)KZZM&wI0p-8.2)F踋ZnvN`1w`@Z o3}ϫoW,p$_E_i =jbkvyk0?QZKEM7dw]##rn_\Ye/vX 97=]}d*=uq> JHV+rrIOٕYAb^ `*p FzE3q5\pZ댠#Ħ/YC@y2׸EclgjZlD!--f C1$ls8ݮj`b86α%R~;,"ʼn@X":ClywbkYNdӮNS-ջ>ա:<*b$}J(3uH0nu ߓ Čqjo0NŸ1@ޅ_`DDd@tV)I 2 _ln$*lr7n6s$A\&cafwe4{q6g$,! dWhCE h@viWWP`)XƋbjctWYGا3<''-oa.̭}ƨgӈT;6^E}UAû?mTkl!uXF0#'j@tW2K ?+ڤ=׺GA>džJrmx^6xc, ii1ydD+<[ āMNOCETLpў$n\O6ڄhճlp=ξLA\d\$f"M2T~%\~W@0'b][}e5'cZ Y.T g굫ejiK.$T2 YL1vˊJnY?R]; :lTӸ 2G Z[X{g.;z>Xwe(L񮏻T ЭYe8Z9?T{ks82PYu3LΓUbҕ`OX+AvS/>_vld@#)gnpy5d veC0yɺ|^xI-6El{N[8H/{18ճ+I)\e$n욝`[Jsk,/Dvʧ9PN6>ٽbr?XjyqzjLmOim2xF03$/zq3h7#g;J$11TAvLE[tlРC [D VU9|j4F&(q\8#Xb;}~O.a0զDq x (&úOGJ##%5%l2f -k.E#clFZ8C$4Bӊf= Ef(Tk %olI#P@m< 1]G_X j \54s(' 2/4=2pd3|BnI!yP̠wWՆVA@-ZMv gp)#\%#ɗ}4(6=hSzᤒI$2iWtt %Nh6{b-^c)^oK6X=K̤ QSTV"G`&=hIt/=XeN?v4}Q_jl8:<\F/x͍iM_z!9հc1 KuQM9'E#a[T)M6H%_T!Iŏ͍`WwDRo]I^ #>#c ]/Ĭ>U`vtorD{#]{~bDf7@͢*f }O,0L=^1Ủ}fu nK:"9|JۜJI=HDl(,wwN ^'By긤q!)5ݜ o0:'pK՟ݡn7lo̸737n2BIe}\.iuU~m uݘAzV%ʢ>_ǚPq!rdz hx%ަ#bSDg- x8sgZA ȿ J51Gn~ O]=]o'$~~JoB6Ŷhf8"=`QxND^7R όce$c{hNElM}}-22vwIWM=s]8 ص!]YAzy.IBW43Yo-0e'X)1 "6¾…#Cm&͏e oGbC𤀧jQa& q:{{kUdw EN5?(; !|Cg$,o8nK[CRH 5g8'X9^9Lw#6 jaZƏ(5\)eXO$!ټ$ u{gZ x+֖#Z09do }u99Q2_,ZYփ-kHH+ SG&k,GY4u7.<ٷ c?*:e2, Z.[D,!TaJ-+SLm>`ʌr籲A/0{ Ρz4s}R'I7L Qnp_%JJwIj;t1HNpAQz}8؊ Womp*쭭qɷ5x-X_wE.mŖ+$(y bbJ^HU?GN ^QzN,dK"׶N%~s୺ -dsr=h@keUCG뎜cWf_КZ'wStA5ni+܂Os1z 4MzTRQL$fEUHTB6yC^r4Tj0Nzbˋm{P@-g[Q'U]nҕTpf\sm$I+[eǓBFLwZ2]m$7CcaU 2Eֵ!bW'3y1=;i mzSWj9G<ϓw};ˊ_ V?5 #Y7#⨆2XDMϻQt١[3Mz_[gR}HL@f7[!',Oʎ# bˎ"ig?T%vwK0K/SY2= K9.9ϖJlsw{Rup #1šhS+*xȬt@5Ei+ t QԹg_ic @ P0d1Gf7 C~rYw!~fv(|Hn>XQ#m*Oɻ pAeҺ װC4߆"B*|'kyv$HOMۮ dq-g{`1=.͋(Qw]@ď^7zL*xYjʠ3? IҸv"lXc*riq(P> ]3ƈHZJ B0,OoYh Ib桖0_>P(!6I/-|_ϛ$k]N5Ob.4Î,Dwh!h:}!Ht-f˗n:K H=r: t6аrr4>qsscNӢPp/9T,yb,#SkIH}{zbr}دj4]ZZQI_s?AO27J[HȨ謓)Kī.ڤf Xfڂ٥|܍69f0üD!׿,1M/dxMm[i!L:V<WX_Pt"I-FI +^:ov>2Thjcm&iӇl PE_v[vo]#S\h:I=JqD|2Tv$-X:whPEx՛alb\:N%VXiUi||$S%TیHwX8ˊ/Me~ !<:N>Y?#P3!N ꚖoD:TfVXAHS>Mi6 ^G$vfK[>0C\t8"!NΗՒf(/b\78@帽O0+@}UX,h95ۯ7LDxfX!\ XᗥRV]ѭ&5~oS_z7DT,pr>w,pJ vzxx,se \{5#9;-q` ZZX54B+yXԶj˩f\<1TV \l%IE(á;F$dܐrAk=RtSތ-A!wm6Б8[`K,9- '<=qM>devCJL)#2n^g\.W$Ur2͆wɖT?52zdQg[xsœ?l3ti7>V8j'`Fos` SVȨiec}R,>$ ~==1ꢰXvXlڴ߸f4/뀷"ݏzuq^o@pTb?ڽ[~P_ IBdak%rh)H?(S|͙e&&~\NZ8qlf>s Ơדc ƴQk˾6QHuKe!Uv@"TXtCuGU=>,PD{Rڟ%V֤16cJ;Rc%վ=#sТ/bT Si ]˿P]o8FW a,p,Go5J T)@9MH kŭ`I7Rʼn9>vH㱺%l@rn*z,P+_jWWhcfݜԔ\w/q"BY_ԼzӕK0v1\tYl G-̫>pb$p e5#`sqP|`vX\1OaE['1ؽK! >4_sMqΚ}d֮Z׉ 1 :pUT]z@9h֦! a3:C)qĺsr?jQV}:1S3ʗio.lqԌ3UӔz,tOTx"\)k/S#G a85.!øTNzL\E\оK$(VCQoDZ/?ri*7f?&Q?߮K^Qh>\pysCsA1~ߧ)}53oo q0^e6^4> -N`; 5pr,P3P咹>#J%h# F~I`9Y\|nҜ'6Z̓C-IXA6u猚Ve{z3H!&D)n-VmKX.ֻֻ{Cs#$NgG\b0/LZh mD5Uσ(cdPG=Ѩ:z⼿ɉęk=&i&h):zf*gf4`$)^.-] ^!•)/tbGiky$MtݝqGnR! n-U;65 ʓB0HYXHbNzb=}#@0nt]g(&rgwT\SL2 k5`*K2\X\7 Wc˕u-zU.'o;XV8OܹQ"&lS\l%>%-Qq& &暌SvYrTq- *  a e _LVѓt#I!T dհx^QoAha:6Ą|$ĐhVAwӋ { ]kZIJ|<T0J/_bCᰫF.x) \)mfH,RƔ9\5V']cQTy2" Hu0,h$5֎P2xw02o=a>,L#ǿn&۰/wXU!&zU ?~BO01 ^NpЃx=d-D؜.WgtΣ"X;i#6mzAʞ+f \3kj*.}Y:\EsOR?˥_U- ~9dtJl$Kܡa{Yc#^9!Hv&U;kw9ǶIځ,هP=ѐFa|Od'{(~O|\yB)-#-O:0`hpv$9)9ȳJ1ϻq348Õ.[GC8;"7mmm+E墲 &E40#ثb6BqƤCӾ!uXWWU6}{6FDXM=pLeF*Eg ӡ#Zvf VDFصE4͇a"ԗđu.ouj â`H#_ 5b@f\x*b8V(*%2/IXTqqXž!xPuBI3ljuK=3~a b~ gxk*eQ R TsءRez~pCSLUDāUG.˻^T}|Ri1C} uI(It Nۆɤf?\$! Y29T #0aC3f.hY_$E]8>e\vftY}&lrWUC(gP(eCb,JOZ$FүU"5 }y268J3,W5`J;}J߈)GBHH=Y5ۻco 9֖.fNcѼEo!F#bRG0mH"&(selԶ~A&󡸇d Z }K1l@1cᕓ2Q#=[6Zv z]ڸ]Y&z]D!=uSvy.p] 9b?waVC-ګ Qp\ Rz͇͆$Vg8NU<,uF'뮶X>$w)E7$!@>ݩtQlGtlCŎ}1ϊp XHFgD:;{2 B,B6mt~…1PdMD͚Jo]clE`-XDb]Ǩ,N<~.78C=06wuh#{lX6JͪX],wJ r.,uzoZ5ZoeG% =l }NNB#+͐2zep0NxºVpPD)%,戀:7 ukn0u1hB7sVT(9 ';UQ'{rWBCv$d7Geף0#ǡW I@9]*դuJ.~N7wFjz7A2""@k=N);V4*qX:^=m@#t.p٨)^PCk{#Psk2f^^ƍO%u0HjG!^ύ`+NȻOX _EY ?P,Ƴ~KfҳF~4՛7S],qXL{Fw0 ;8sa{@C"EbV4FY^Ӑ/`f Y\Dc5LZ|:We_Ma-d ^6>B"2{ؼW m7z`vkdq?^i+".N9+hfL^=9S{k^ÍXձ'5`9XM7v`Y(0>qEӢsldu ZTyǃg9:r/j@x G0~t v˧ B J:QJWv%AEN H&Nk d{}XLeQ#R^g5q+NXE6A@"E>P 7Pg%f?[:N؅L۩қʘ^V%'ť{̸"3;Z2Qf,Yۀz[buyH6Gqd(HFq.2 }ޯKMNŰÏ}lܑl0rv.;^[qm7JXF:pnK B"KsU<[:n))tm@N椱Dua=;917wn/%}Bti,JkJyJ__+]|s={{x\l~xJ1C^@)q6b*wTkGpHk|ӟPhDra , c8W.H٩i-FL%ڦ??#ܤxCJ0^6%R 2T!`ոyF`ˁo>*Eyb ppP,G)x+ !zO[Q}@z&p0}{=fSa J87oD $ H..bC~a!s]F=YjIkR0aT`&1 P%`&nbu,VN iQIu-aܶ2vᄂلo Ӟ}gd}w,~P@:R@|JJ 9EH TFGҤͨCsG,]< $ +QB|?T%F 6pƛ .;Y|YυhIw׏㏦.o9Q 6MG/-*r&0`C]p5R g [;|Y9! M%z(TB;QN?s.08{(NV&D9]lXhaKJtTʙFcqj"B;VΊ{(G@(g |dɒZ_-S}Q:2sISd x(^Sal*p[T^4@әN*ޢvk.jCH2 vkāl;ƿ~p u-%(>#05 6X#8^ftvh-{`M| qCpD07qJ&z-l´6}߼uI"C~![w[E;YB(~BVLH3"D7q{5#j?a5ҳ?U{% _Q.'1bf^>=B3s*1x3QhccbvKٲ<U-.˚&y!;G,;- ('W'4 \ !'9j"М̟vǃ84Mؘ!ciZ_m%BՏD% NPj+~tk@zg/;^ e9Lio^cfvm'[eu[`P0,*L#!,=K $"Db1Iܞ(u,մCΗ 0FD1nS.)[QDc4jЭCzʗ93X}`+=8nEy . L( ӔF=HY-E+$wȪdSR.瀓~Er$eGz5u%BCDymr%UBͨL7tZ>W Zq}0z;(@mEkBtt*ǂto[+sI$pTy8zotp͞2?E}Q?9e)w&.TZ_6*`0FL^MȷFw硪Gl^g^vy? =b_g_+000(8 H уs1C H-  c/I+T=; T80NWEa Yo,XfPߢ1pIdSS gJd0|gwe')|-׺wWHYOzIљⅲ[\#^xIڒ\&}FJVǞ+Q}X,s-ܜ~#+gHlQjq En J}Hϗ[_j>-M'΂ʇ)zaXۡ2NE%Uu& ux?La rU\(86fъ҇bu/I.. vp?]PeC䶛a8u|ehHC=\ʊ՘9:+"`PZ#$H9ii:)A~AQ_9Q Yz2쓷?{2i [V;W}))>SDS%sŴVgIli=јL5hs%DF|͉$,s&LR1굂&!S2|a\ Q RZsFrY9}RQ5 B@qle份 P`+ ly/DA@I09ZBշ1δr?#F [Aĩ$jQ/^m/0Nt4t2?0՞`~D9kSn򾥐-fQ.FC̙t[$=#Z ? ib=cB*ѐ\41ˮ;Ԥd{]L I̓YPj1zDE+TQlUҁstuԱ! ȉ3Vd?8&#Q4,6t^ⅲ\')9!1G:r !d!We@#LS-7El*E <_<~[_R)al':|=8ތNN.^"U*+""t.T9XW5_ً[u|lLx w.8cm/g5?o\B=]o3*$=ܕL4B߳˯*yo?-3ɚT1q#w(C5-8`e㏨e(e0-xҬ6zUJ8\d5uwa6&j\Z64jg:ww|m|;fǚNX%U1ku|7|7|kv;;^^^^^^^^IEǙ҆ P;pG֦ 7Kޞw>ðds 2q-4^^^^^^^^^^WN9"uce`HKZR#<4a[04#Xo $a\'>|ٞ O+/Z6[4CحooFkh}&rR?C `"R M 4E0AL8`aB/0߄vʲW0ZuDJR#c o=4354OK(-‘dAbo]ؑ֋@ y6&^_4W( zE X *`j#3%=Fv{׮*ʧw]VA'hA:ϧEJle}ˍE{irňPDH/ xfN0Tق.EfnP;# +3Jy'pKF~{v9r띻!޲P#vp؅˜b'YG]FvX(ɾD1I ʒH_ġQ:_(+yvNʣE]8< ,t$9=k2Lڄ=AF8i&^g8b$M?=Ibϣg>}qs0E Yp Կ%{+|v!@S:scj>X"Ȅv,! ^ic09 jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 AՒ@rpF$|g_-[,8wOC6O&XK[U5ڷTז ^p]<}E \lp.~1ЙT&/@bحB FJ i7J|U,0HjؙXBaK\!K&Y+'^/;IF#neay1AHѠnf)⁑7eWIl3n6LjhvRY>*A רY:jxI^%)a/UD!H9]<:jrs{dlw\HTed2D-22tZ廆@{@޲_{+)3IbG'\.8xBG`|wns#^xƷs&:;r U5`pQ2N^.Obe.( ) ^&[ gӏƇQ##Ls[F8-q41Ŋ`|ie yq6#KTZ(r1-YwӽƍԾ/Tph0KJ‘nޟFq):'\_)rz!'G7/!;wByQX3YEAX]3f Tm@45һQ}-fDHsib")T'OT{|>-CI|r{n?8\ 7z3h84 ES~S96wRЃW`ymN- i׷Tξ6pDQ4E[J)0nl 6_ZhL xرgM"G+v\>XD)#w턞 ,.JEO$Ccم=3~U;zlD A"-K9Pn5V\zXp7 %"^@p4A:n! <AM!*. '#`S^HT'$.k D/d߃!)8^cxze>bĠ\(CKQ]|6Euh<;j 4|Яuo?O)i)&|7'khOc686Qvhsbu+R:f0앍NⷢM LI-yIk[(HJoSl'2o+Q7{}廓MGuU)^Q3@^*gjT&`ZV-\~Iήx>}Am_!-HMU/c<wHJĠ'5,Juwg7XpWq&"NzpzSPfX j7v@%.+g0yDܤofPPuea<& 68we2.sյ,'xUV\{1`WY͘S7m\isVjyB: +*$}^4yP?mTjƢ9膔D0%ƒ+,^j6 ,Չ>@)knY:Y'6x{1kO3qÖ*OWmNlaw'!s MY;E 5vQq(??$nQWn <9$_ L<¨~Cl~RqE_BEW TOD`nP0=OC-Z>:)\W+Dkwu#Lt.GLi$˱\^9hgGW2U쒋ck5]d̝sޘ[=ieָ8J xऻr,ߨV)b *dYUD*]2}\jA8a\5Y[ءhRa&U9j;"b GϖOCv픻MJ.4t*5"L?Bgԇtf0Dȷ9] Oց}HX)J3 Mm$065ㄈakc+*I"ivGkUI9GY&^a[>OdDb^N)WDzq['@a! 8#g< N/[aBIXlԐ3wd3.X<d6 2~Hܖ 5{JaT>S~}a'0J(Uչ~nv*~M&D$Y\;#99zΤ)>Dr(P`6H̥JcYlfzlRZm!{=MIk1 !Nb)36|w# /܈m($Qu tə=ڄ竀èkޤ\sPg1 _ġNҦHDraQLH9 qgˏU9uO< 00$HަV>?UQ"[ѡtXl/Γ{Z]Pzw1@\a>PPm$iJv; z_`%w7T\GNF捫Zڞ/K]$]5&"@>1o~>S7sR  \^p<CgEx+0I$#AR8䳫R N'zAꝴKqjщħXZR{:A2sD᠑_}Xf207wZuL.9=SK~I="f?ټ3C@14qXٽpg B+l#}Y ]=lӽtj7Γ2G㰂jJ12o6@1!6TߦF*N4AMؔIffHTB6yC˄h;9U4MֽY6 "{" V;O q&+I$I$&ԭT7eC;KEMCcaUɓR2 3Zk$8 wfxy ?)֘K7}E^g+s1t%Lc$ijaHnA7p_,.w ɍf:vX)Ի.VBOjpBD_m<P-0!Li CIK@yV?_9'x\*1 JY!&bK@͸hO!*݆Bct6P%VkRPC>nTm?v6t$*3YuG2= q+S+7$(Q$9-Lr3CKt3ѫgL c5]7+Z5F@#E9-W<0N}wd%Pc FMLf2sp!77K/SMr.`q9EAf8|ڔW抱Uo$ٍݷOGcw/?xt5asv՛xOc,/OG Q.vX}W%d7+3/7r- ( Oθ)ykwy ސZ;ۼjl9׬_%` G)NԑkƒQ{w*e"rE cg& ))RxY6g,Aoc` Lb~W$C`yW,mG:߮1'#ilR %OpAؔAG%1S&Hp=$M<~0[..aݰ-AqQ̚Ra8 υ=u v_nPO ?XmWPr^3e&7@ 0>v+K@k88 YDDK"x{?bSܬ_Ѩ8ЛYi,*9GL~a;2Ux ;uyTsd&3|1+ n&inc `ԉQ v;Q^Av}(9D"3bZw)؞ć %f| J]@DrߺjW<7"I:o:ug,W>BmFrD.A vqrs}YDR FY֚cQ8Bh$;:*#0XA9Vj5^a4;߼sIĜMMnr;;DwwvXqDiz(h/ C`r*X:)w{ņeM,'cP<w=fFmXv-;|=sgjK|HH9qL;{<@d\7/FH´eP:BBU"bńy )E!?uze]#&wݵ<`"#%O:a7lj;،]Kh7AsCnLf0|q!O`h;ph3vTֳ-A9m$PU=)аVp|lXy+[g+C⺦X_WFuJyɤdOW"UUUT@s Cػ5I@,E5EwU\[0iDt9}_vLI`v`եQ),_'\,/Z6ΛqۄG8H?XX$>E^jDd9$cf+{eѕn/:>zuCfN ئ+v7B# ss`ľԢ`f(yP։l9qCP_qu:>jM"_BtILtݎ\ź%yU=jgJ5w߇ u#~ jQT q фC(xI+; J kc=`faJo"SJ $ṣBΞ0 50?^y,b6m뇎JM)2Qi(xeȵ9_Շ3?bpw4`&CM1q T# n %<`ܸmTB9S8cOt?G|;bMf;FǴT޳LSΤUHmy/?O%[`x9,V],*^k%WkDG_G"/Tc psuLm7 RښYc!'x̣"@uDȹh({>XTsI.Нp #& /P1{= !UZKeNMtϗQ;_^9_o59cN[*n8\#k洊#soxE >3}V|ٓÕGͼ<`3f[B; twk*:ݍjnYAةw3ejMJtpa}\=5찷Y lg{]"NF}'W op`BĎ˸5 a e_pE*_t, kIO >k2WHIH. ?7G=c}{;6t|]uώr> ^,[ ),Ox|_MX<֖^SBdioUǓ+v׊NH65s 8x|LTiX#Jyag"Аi_5htWu\X,;< $~ef[IyG;s7d\`Kz—BdvLCh}*!d2@%TJ )e (n6Ik9XF-;A3Zϕ=Ľ}>%&zity&ܧ\,ݙ5+Ԧz3K6Gj# s4Sf@DcjyD<150 mSR)jOߏM2vmG POcE;S5f6Z"ŝ5F,g9ܰ,yuATu`$bjnCjDmrWp?/cx~G{h,Dʶ&z`TVˇ1lzKsMEjMnˤ_.5Q7wVNxznVO\6m0 =}<*eFZ ` 6{J>1q]&+ҩo&Hv/7SlڬCJt(_Ak8Tz<`p|嚥9_[h#19&']Kd({ r +^Mp?ͺ ; 2H͉tTNUh >#֝ A@.!KH"~WeW8zct%~eu]ZHc ooK>?0 cj!0ݷ" X7zق Z"?>>4/z؋^Rif0:>hQFiR ~`K:V ./w$rd{s>º$]-Bl,S8x !մ 7TEM "sa >fs4 ~¼G*$)9,`.4/SW @k@W K 4l6B?VsXsoBN:s|:˻kl7ze$PUfiR4ZMvTkC"X*lit%u{e'Ev_i+HCWɷB[ZМ>µ!d2~ۙCI }~ eV[t j2cGT+ٗJZ=UK~]l)m1(us(?Z;@޹{qd85DNm- <߫z%h}/L-lSrM84WGJ#Z}S YE!-?V)W}SX:NpB:!J""XŊf=30\xulKP\9MufcȆt#k-͇{: '^ce;RN Y̘&zϦtoN䠇FnGlR<5}չ,ynXufĬuܲBN l<5dc SXYg3 P?5<]?&<-80ӨO,`eۂ\EE^g+(Ni8=Afz):\6C x3g>y7J07z,?+v0 MG9TV3BN: 2sU+su_ ^ބG6Vzt\],@ꏢ|2u{`2E@@utm&uPZX7PCxSɴ9MeHĻ>c\`8{"]7a}Լt`rU(o=R;%F1J2S F& ywu(4VCvhuc$զo=;1J(k IȤ3`@C):#ĄT5Ma-FVИk[VskmauFDPo{t& ,}uχ.I m /Cm^HNp]8U&Oh>C-TB$p6rn1{7?qXnCg΋A1R,YY9MGi*, PbҎdn3\?D DLFԟ{@`I$Y.<7̨ 6I={^Cϡ.:3S!ooJ7?|If|jPLWl}OP o]c+ϥ.:bPz9 oQ 8#FnMv_dE!/K?4=)AG"=H /`ݎ"K|0p26HF/m\$25.҅}8H?@u Vi/B o0n^wKa&Fʲj;8(Xc)jﺡ(tta9E覘FCb gkئ.'Y*nFն`Crg)CBo4VPaR:iѺ"[P1-W!oxVXVRaYe؉{ZE|Svh*oTKGe^ΞTx_6˂akoƮAPaHXnGI1T~3Ҽ[&I"nZcD޼ӛ!t'6% rŋYuשI^0<ġRzF<ͦOzU F7O :]o0zዽ cD}G4?r&SudSs*0@JU{HvȌKuhfқLV4{O+ox:)'e8gU^K_w`ZQdO\dO4ecrO|.qC!egMmk꧔mSk\&"m@ {W'FForZ|iV%&]d^ie9)B>4M^?8Ukr-mݽ~fxm'gQ"_"qO bv(ͤ[OOL_3oV /#& 1sZi%g}NSV/4=?PFaLyyaU$Ud?ɪ̯ YY{uɊ>m޹'\ ȽЭue6<2Ԁ^3 9 i&l5_:Z Aa6VhOgo`#U@[8`LZpޥć2h dTW5YA| !`'ӅBkqYʁ ?<ˌîo~8OJJ?~|l`Ƨ0fHTH߆'tn`{QpyT/MRyݩ!Ž$9s $ N0av6_QW\ +25CNz9-aĩ'_"1*!b08\-˕ '_newkC7עhgEh"/Sd~-p2~Ce@ 9AG l*}yBc_Ozbأ8E^! I%-Y$|dT &L* uYaՍĨK]."W踯dGrJhԱ!E1ShyݡBa=hɗ;ˬ=nN@`?$%Leօ!p8]}>?q =ϨM5-7xR)kFv0 p HIKgsi }nj9H ƃR 2>ؔ\<M#z ;D+!~80C@A\i^v0y#0-2b1!RdXH#taǛ\'8{s.Ki䷞ѡ4ҡ{i5\ _d{87?7 RʣݙsB\`)G8'Qk=Yd|sj3Pچ-o0$HeI]u鬑^(VF,u0ʹ]gwȋϷvZyXL;-$j0ң썋|0 P6;Rnx`fi.eLȻ{!Ga$R!=7N@e`N~ޓ2 \>FT]Juy"d;}dy[::I'Ņ(`4ʺgW籁uKzֻa&ςj'IDi:23i '_eCĿie'v]q9gl5-?OZ ͮR @Ro,w3ؐ%X㒱y g׃~36T=p} &??}<\ LG ց$W]z7t(daGsl>&YFPCK WwG=U1[{GR*MڃUspϱk^X\&7/ueW6fυ=I6luݻ'N GN͒*-Pzo^|fԮQ]%H P߯Cc^C*E!.!.w.Z-Z]q H+@}V* oh{q{UE}bl l6(ZQʅ6ߩ|]ȝ0F982إY>Y›[9hox1{f8䶕r=|N.Թ2 (Ƒz5U^B_`%UM3Yj3unVC:c/j-׭p{ Q-\Qo#z\$pQ&N5r">$X"um.մV0q"J>[pZ F.+lZ~Qs3'90]w3KBLI)# OuW".U Qnwp+n=^Dmb*y͠菧pa7O 0*2u Q+㈌^wH@p%*6 " ˷p*?aVgz8t@F|W('!5F#fٛX oEN]s 5:֤>q䧄xjo.TXbZ 'Xuȹ'%P2ߒI*OZsJKy-h݅;@)=E@/EᄄSz]urH鿮s+a;cB W-'`.¨ǎH@Y *EybY6Ȥ*0\!6B01Q&p"e;t $@$\V pݪB$.%w $i 'fe3peDK[1w8U-<a꒗㻔>HI'2vΊdF(yBCݕ#t9ְ%M4{!l[S6Ƞ6Wj+0aФ `la$-yT(`е 寒p=xA58}=>Y0\Q`com`R00|gAud3Pmy>Kxr 8Xr: yO<,c[' ֳڼ>TjXKX~ⅲ\')9!1G:r1X¡08T'.d#.hc?gohCiVQ=MUCMK 2( TR-\݄=_ػ뾘I ΪMUO؉.VRz딧K AT3mI>qʇʗW4=苜њ!Ng+M6uy5L~u+1vQڬM ʁi<<% [bc0;Bᢁocg=mwc]h]%SdʅK/Vk$=테9xn~xmmXg$aUD7Njd NM)ZWc||̛ kelCJ``nASÿDe EǎWUX.GPR'P]oք:_Ġ5a Isj2^eQ8>Sj:-2v <My䤐6=.:鯥ٓ?{ $)f3$F9M.Oe"l7CPoEk$IҺy# fK(_KZ%eԓ3$5(?_D^}FIu!$aT(ă#񂵫:RtZ S.Ka)4[v狊Ʒ_A&z.!j+JX>wPsS,QtoeH: LKHmP~ =VDmFHþ| #_I&B*209(_5vZoԋ/{c6\>qZMmM5uW \D{J#YnWԷn}_j?>IΐC-2ď" 8GM}f (kdVQ[00NƦ31d1sIg_mq%a6FV騖&F*'t@;o"IcF{l)tRVxH\7|QVwy(͔jfLHXa@325#uN2[): )>[ڷJқ9;f+ґL)աnИ+ Aw?hnU ,v_(^|7|7|7k#YȀ>t*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/Uڣ.e^4B:j\ÏY6(͡qsY/6Y %aDS U6^kΝ6] FBZ;g HuަRVgj͛->PF R`<$1l-!lT<`X{Ӱ%X?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 Nמ@"Ϫrȳ~S*(4rna0V^sK7j0Z}iS4NYjs/6v@/G,$yo.)Vei{UwAxYy9DJˍ;-_yp;2Y!PKY] n9)>ܞE$^G/pCnIы~>0Y1zUr"MUBJ=!+רx!ETрR]/ȋhw+/~m[ڑj _º[oBgۦ+S'yj6kJ@ ? _>,;o^_P 3}B/tFaX z}D UdFh/#z6(&FDMH38h?ʄҬ2b!7ޔ}AayR"Fp]bJF c` 'jQ8,>})r/` ڏTVR"lCYeG űAVq y>kXT-,&VERB64ӷ;nh,7Z[c"=D0mj>Lʔ\yqsQ"X2/nV/i1])j1M(,Bg8BK&KkC•Ӭ&5ח `\ۃf9`v3 N.?xF8M|3kMsbO,/epX伈K3OUp[\p!G{<0Co1OUPR'FYG]) o!dzrD3)əF#e(/u8!bnIRu9Z,h v-j{\7h!L''rt[-yH:#aΏh=+o[LRΨ89ߔ]k<4Y&kRxI(T-Wi@!c[Vf"9OzvYhTqA#V'Nn$Ju3!o>9/ zu~x*UwC& |/b1ڀ#8lA(j;},Q 2t& ?Fn+>8N xHg̕;WL'YpxYɒSF6_$âHƑJ\BD|/1LO jě5p~构,oyCq=IsdɊls&] W3EBʎz?" /LrH6(/L8CWT)[y:[Kium.մW8}o 7=LkK^R򗔼-N˥iwHB8/kQ FQ_s:[Kium.մ!.zV얁*fj֤mFp] C? YA(>7Ŭ=)5 Ln]e@J2`v _PG CY/w+JWr *Ã+yU$(MbW-.0o5׿3ֺ$\ T' %q%_̵  $֐ѐ78e'bUQbuV][Kium.մ-#'/¬= p D&uf'[ium.մIӸP߿X걻0 i]6$0]wgt$a򗔼/)yHq u&T·?̇7ܩ)yIe1ڬS>.nR;Y~@yi9*s47%nwK,䂫EiKwVS8 g3.=KSh3xv#zY\N]Ww5XrCt_#b%  68@h'fe0#XQaUmoaV׵ld*B߱w,}3F ,NW+!/TG4."<0k;fV<*)ޣuHk¶9.$hjFt!Zʲq͵G7) mOeh\uui|)@pCwp; ÜOs->kE[:u-"SYM\E aAPYqcQfY:ͭB 1xEz})[,%*pPZ9kV m󽰭_u|7݇00o'ku|t( WEZ# Z5>jTK8X jĹ5(,bn\)}|kڧp4u8@FiKpi.C6?4H,5IAnexMr`RjREwf{(E>*@\b;:))l֏|Rl\3'$)0[%MU_S7Viw4p s`fO 2`oXfy>!!A 㚒n#'kX1YVTgǁ4p s`fO 2`OX@UzC,&4DFaXHS^}ѱŭoaSvS?qQ)03EW)wU dƒ'S(}ڳkV5ГU5k<'=˚i/K؊"|Է7fѲ L(N>iz᪎MeOX߲B*,H?@'aVeITŁw e@)ofVǃhM>g%d!}%~t^<&Y4"zl=!Đ+sWQZFBi @F؆JƿpΛ/M?J$k?X='Y'D$w"; l(@)s&mR#5{|ٳ8tc1`rpTCe~M"i{Q.遯 D/+֚Yq$NӚN@+dtR+DS/ẛ5^E#5$ؘ:[f8q!oazvs@ zUt߷~<a/,%KRE~^EŸ3>-JwwCA1Ue;X]#I]i1$[#[ܻg,~5KO|Ʒ"5=z1tIУ dP)=`ޡlǑ3$XAw("^` sbeپqkF>int71L^MzC=>8ަ5[\ӏk)Lv.+I;Ě8 24<]71VYaf|-0HKy:¢Z<9ͼ! wcsqRW-JcUN3-8.v]?PۿT `ʰ} /? .=q~TFvF-)!"yH0Z d:2TX4H'##БZSy;܌[@0Kth]A !oaILMc3&vZf86~ߪN\q[mK~ɫ7 E9I(9NMEzt=.#QT{cmX 2[^0;ʏxxւIKOdWavD-3s{%EΔ!pͺQe.n"x<>N]NjQ}.6ZwMylFއG?p sDlq[C<,`({CWH -+Y˘{!+(8 wb6J?O8 4 ݲхWl'#Ҁi%e64Ѕi)FDVo~u@{(mtLN\'c JhD';W$` bfإ^LWkyR-E<,.lfeS,L'&@YR>cٗ\ťcJ0̪oGG^p!~ɳ1AT.Cn0[P^L^Q5/ЗxlQh쾂Sh=JH8א oFfV܅+Bw<]BJ0 k9 Mt ¤VEkP@'Ѻj+C %SW[$zhpW C*-./-MfI2R0 md7h}du]_I čxK8G^GҿL71bP.[b%8u!g:׊I;C{0 LL">>'ńBTpbkT؄N!a0a!%:1{J!"YHKUp0a!@a!/ #S B^j $%Ӳ4 $#0a!/ B^Z/urأyH{d$%zHG`B^: D #^Kl 0З0P4t  0~`yS% x$0  HKG@0.Q9riW0!# b7[x8KC-J jIO Yb:X;1W.^հH$iP0Otx1h&BA ŸcCdp;O! Zɛ hxS00/*QC\/PUvRذuNG@qG!-~mѿRk@PWi_}*c%肽H+݉h'nZ}J8zk&1ؙ ؀ Y,";qwI)r2 i~9GS'_amo/HOe0 Zia -Ȍ=Pg rL [ |/tMw o)= P &l$1ch \d򺫓3@ '_^#d"|\\dB'i61EPgQZFNYG3@l3+ . ư愻a{spZJX>AtΚo%M/݅ _t]fH[tb#TOB01$ߐ jkg Cr Q(`M/PtoUV* R qI`:v;1[:ZXWZR>"`<0x"4!LRD:f766Ւ3G$L?Uɕ|COٰF!2P~^$xwa'ilr-ߋ /dLYv?W-AeiūEb;cW`4``U1 w tj=PcNW8) Gq" V"#euN ?."{,MmYzeyq0KmܬD^q4Zۂl%#pi3-*|877vk '+ oiH\ۧkRܲx%%tivh095Vys>П5w/9B2),AswdND w,ܯX.=] VSHHi;Ya:@7 `E#r14>%HwmJw*^*9(1w|"AKXk٩4|KVJ}V([ԢMZ*8$o}uqqo@;8'n a)NpuS03YJoި]m&)/~pBT }4QeՀtZ !>#[YGB^@%8 + >Н+QGLc|BfP` ԮCi$Y[hhϠ!I(UvZSMfY= Mt7ծO~rv">/3Ă5gRa$O~oCj`AI` q3Q{2rQl:ΫsClj@Bbf 𝂝z+xp/Ք\le}ɔJ:;a;g 4#`t9Ux "],îvg.(gG~Kvjg*]-K"l\8HAFylh=*IQoړhڅ}`5}-3/#D*;~PW/ _PkB4b~'_P-Ѱgkgۏp&x͜tFp2t9 נ`/&VusR/,N{Bơw:?[zR5cD9-մIo 4-u04ƀ=h;T!1Tf)Ŀ֩t? Z<_~ WVxK0io&*q11U-aP81KR{A1YVusR/,K ĜL3=]E9pǙdvA1OsUf4Ŏ@ 6DLt}Z }RIL9*kSj M5yZǃI_Elid3;ZQӼUrZ<_~,@jB0a!/Sbe!$^.#>&j& .p4J.Ñh{ 2+Y;a11!F-\M^4!$Pm^Zɺ{+Kϗ>#V&6 ŏ2@mӱ!Lv:T|Gq(m))NҨI҂Ŵa|Tz.ҥP >hm=\իաᜪy|5%:8$0^.x~gTϡp`4p=~ⶠz@ӳz@Sҧ~R=D" 6ũ1(%D&ӔFK[ew?p1NGne-l8kᵣfͯꄂH9t\spb 0r,x_ An 1{P8'l/VP*߇.H n+T]04xrR>@ !iHŸ90 l#oa|9X?3+ $%7vs$%CHJ|Y0? a!$080 3-dB_Y $%O@a!.f|HHa!# a!c #y$% P54WmK QJ><0jo }/Tz#9 \Ą.n]sg{]+ôxA9s4S/j`AIn sik%N!%ζk,z+xp/хi={ŔJ:mtB y'gVH``G|iTtYYV0P 6JƂʲYђU` ~E 󎏝F|/_9(/ڇiEO||*1z&; 9 /Um|9|"_ IA 8WNKyuMiz8TgO| 0$$4z8^V7I (扯 Tρ,@.@H26A[ נ`uVQaUmoa=ܢuui|)r}Gn>rcjmB ʴ|AXB- *Z<_~ WVxK0io&*q11U-aP81KR{A1YVQaUͷIĦ/;e_`Cmv}h?%ʈų_ڍ 7=#ᨸ4(*5yZȟD>\`^g$#G6;=sZ<_~ՑP a!+<9 $I7U0^؝N0c` dZ a10w q?2{b^hڦF[4eDV[viN}GP=֭RA*c$\JJGQ\HF{‡θktpfIXn*UۯX:^RN8@HK t xF,|%5N2;&$\YO cG2wĠ#I`eT#&7yZNMEfӇ` 6J?O8 4 Ջql(hdz@Sҧ};W$` 6Um̉BfʄMɴI^7),oBnCq-(_np]mꄂH8א oFfV܅+Bw#'yzP*j+CTp{~qhq #Ӄkpck@a {XÔq)4>B/ 3e rk S*'sygP]+ÕU%<`,@m"m6_/>5 /~^/Cj`AI` q !%Ϋ+,z+xp/:O_{ŔJ:;`4/O`_fFVjkt>^3 x~< 3o48}O4Ϟ$S*QW|ᾪzcRX~zq~-;xG_  Mx(,$b{o#̾;% 5}rι64恪ˍnZ2n?B]h0&,)QÉl*x΃Ryi%j#z?x^Ü :Vߺd9ֆ D.T|_ <?g>!9򳟦''AaWŢOy95Qe>dڬV=v @~'ZPC]hi^xOIj5Q % h+ lVRMc#~{*rJH Ǘ$5&t&di_'{رM]|7|7/eaj[Dd5Ii7~N .2|Vc/QAPّAyUC$D&~9,Ϗ]Yf$uPa0OPQg 6vJ\˴9hTR6F:RQe u. 4-D~\H'4+KM?  dRDoMo_N/@j)`"Ȧc |DAbooXZ)OgBJN Ja/@j)`"Ȧc |DAbooXZ)O3ˀ7 $!Q%λSbjhxk  m*؃B6PHB됞/B:FG_S TIBuuXx|-G20<XbouVME@BTͫ%R^bܻlO)չ4sT+uqĒlA< 7q WYEթ 66ďA6vo4u TB S [YFk.~ev+S1JcD侃=H(|I&m7M]mi(#.C"}cvARN[.;%u3QoxH(;yan`v}4Ȫ;eM-K ~ $%hltC_P[g Jz|SLavNH45j^ئp $ٴO*$(c~ ΄:cx)8p"$f[dk:*-SipZasŚxBOzM$A[{a$b?sDd@^0Q6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%Mn`ǏB%M`T|D@A#H٫8i.*mMUf'ƠE荤`EcΒNH34 `[qs-rȳ ~Lbj=C1M3H"Oe 9CYR'#EYP胪)Ca?@NӪ"Bp=GCM<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@üوA݈D܉ A߉ Axu m —{ba{ƃnrʗom  Ww؈oV  a0`=&]ˀ  }u#  w?ʦq~84'x  M-=IZfTE5O  Q)DW]bgYL7T  @Yjw|~bK  Pi}t]  }r~ـ!{Β!ڭ͋!ͪ!!!!!!!"3?)D;ڇ>üوA݈D܉ A߉ Axu m Ǥuu˃ுٯ q浛p utƠowЀ  Ugᬁ~xnY  gxɬ}l  rwɣ~u  xơ|  稐    ۵!ȣʦ!ܿ߿!±!!!!!!!"3?)D;ڇ>üوA݈D܉ A߉ Axu m ƶك˰ϲ΂  Ψͩρ ޭѼހ  ˨ĩˀ  ̻  ˱  δ  ƀ ؀ ! !!!!!!!!!"l8mk`occccccccccc_(IoXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtjo4yy3it32:OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]2/۰W=1+%%+4?Wۢ5מNQ{ξg2"Oڟ9u Vհs+s˝@%u`ؿ-wכ1ؖ.>ĭg* ˀ.ddͿ+jݘԂ(پ@oµ7C͗ ݁܀*ݶ.eƾq40+,Nt˳Ƽy_# +• +/>`u᳜´^@1-Д -A0Uh|ʕǺO(03+Cޓ-i"I`sЖʇ,92/-jSoѰ_qW383.*#10?mཱུtRA8851.*$0ݑ{%BڏkQD;751-*% {"%$1ƴgSUK?9851-*$ !Ӑ3|"'!Dކvbb\NF?:841-*&|5.#(#Eӕejbb[QMIC:741.,'#,ߏ5"$*)+{Uje`ZTQOJC=762/+*$ 5] $)+/Y޶Pgc`^[VSQMJB;632.,($ ^7+!'*-03$u{_ifeca^ZVQMJB943/-+'!07$*,147<lcasqonlifc_[TPKC;631,)$ 7#(,026N[goy̢xpf[N7ByW,P7f#+/4AQ^it}۽|rh_PA(JzT)h#*04BS`mwܴul`RB5"QP%7#+/6CUcoyǏyocUC40!,#1!*/6BVfq{ÛxopdUB40)0b"*.4AVdr|γjdU@4/) b'.4@Ucr~սgaS>3/(56$.2=Qbq|cbP:2,$6"*1:L`o}ĸem_L81+ -(15G[kyĀǶllZE50(-ِ1"-3?TfvǶۈngT?3-#<(29LarɁͲpp_L92&;/#-5DYkyͺpjWC5-#-u'/:Oas̺֐yzsaN4=Parƿᖄr`O=1</@8CRctĴ¦rcQB7@L:DSetۍ}reRC9L/ݼ^7ETcp}߳~pbTD6^/̻v?BO\kwТ{wwk]N@?u/;U:67;>>:;:<@Kd|)Ƚsg]VTTW]gs#žOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]2/߽ubWQNORXavޢ5ۮnFDkƮWNpޟ9̏M?nUMҝ@%΍I:աXFۛ1ئY;l̎HV ˀ̀CH̬a=Ԃ(fFVǿpCiԗ ݁܀*ݿYK[sL\˖+VN]Ĺ]9T̕ +ZP`п̸kE;W֔ eHa{߻ҏrpnd@=f?Hb徼z}tliT@?/@AINϙ~|umg_GC@ZAHL\yɶժ|vngaSFAZAFLWd]~칣ŔwpidXKF@ODLQ\ehtã~yrkd]RKDMِCIQU_hhﵬ{tng`WNGB5YFNS[dkk|vpjdZSMEW5EIRXahntu尛{tmgbYRIC5~ENV_flszrؘ~xrkf^UMEWISYbipx}|賢}xpibYPN`7FMW^gnu|}ᤣ|vmf^ULJÎHPYbks{!ųѤzqjcYKI7JS]fnxßѺ~wmgY^crMW`jr{R{thQtlt7fMYcmv춹~vfmi7]P\goyϭÿŽmrc7WR_iq|w^7XT`kt~x_7`Tclwݿzyd7hUcnyż¾ñxm7uVdnzʸuw7Wdozҽ|p7Wbo{عÿmkTaoz࿻zeoaƎa_mzՀǽym[_]kxٸxk^Ziwڀ᧣whYfduۀǣsde_o~׀ ֥}p`3ajy򿪨yjaߐ1bsrcjl|⬫|lk`uݽt_j{辱{iwqԵpu+lu迺tlܔkxހ߁xkkx̶݀xkqvځ켳vq/{l´l{/‰i{ʱzi/Ĺmi¿ذ~im-οegxʫxge-yd^evtf^cy+˼~jYTW[^dghb`[YVZj~)¶tg_YVVY_gs#ûOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]2/̶5–÷(ծٶ۝@%ӫzʖ1غ‹Ś ˀң ߣԂ(͓굆ܗ ݁܀*ˍ꾑֖͌qו +؎űsޔ ᑆú{v xɾzxz||zǒ|¹{{Ż{~~~Ļ} 猃ƿȁ Ļɏ ¸荆ȿ҂#ŻҎǻôùDZ溞ؾ7ǚț ȞƢ ¦ ⽯՗ ̱Վ훦˻ ɷ͞ Dz͏   н瞷ʵ $ θΥĤΒ β ռ £١áԡ¡ӠԺП̫ˡӼտȹ˶+ɺ{{)Ŷvmp{}qmv)ʾznfa^^afny#ýt8mk@ '046777777777777777777777777777777777777777777777777650# >! =/_9 qBaJ#`M&_O(`O(^O(_O(`O(_O(`O(`O(`O(_N(`N(_N(aM(`M(_M(^M(^L(^L(\L(\L([L(ZL(ZK(AK(+K( !J(CJ(#J(1I( M~c qk<G͗׬ ͷˇL^mZ"RJ{зTF2Қ7<-m;K DM-{0 tiiǿ8p:sxDG} x- zڳqD=86PVs`ѵ֧3S:$5ndz*S/%5sɃLWJeW`·n~3S_hा0]>}=%ydmI}LXb S!d,2!*Հ{vA9W#wl@F=yg5,V9Rӗxp"{YE/`'fBJۤ3=J_Vںt1@/Xotnon> {I($*8o>hylO#kaAz\(ϫsd7Gt M߫Eo?^ވl]O߈̶D>Gp3 ״2"`%ٟѫLЙ Z;ߛ{[}gEyis/5epW8qP% j3OM9\u؇z4\NE>AAzϣ:}q[Wr.%0\]x=L+fю *5Bp΃5AK+f%*|5P[5ybV^ٮhQG~ Df#iL آYeO(b<84ПurG$0N_hlf+9:K츞å s&eC?X?mTkl!uXF0#'j@tW2K ?+ڤ=׺GA>džJm%16xc, ii1ydq Ml' A6GnJ+Zz 7$n\O6ڄhճlp=ξLA\d\$f"M2}zT<nql? B0TKs~/Cs|*dLUsi!Z9Я>*<z=I{࿸|34j37nIKF#\C*E-)@;oOZfbr[fK-U#NJL>`#=O,E@h3,Ô➧=jy[ZD+%jZvKXwc>MZ9LԘK݆|s=̉_H71*no+\oU*h[ 12rśMX0zzL X3-׳s|jܰ0ף;O }EM39}:|G9]q:ȬKRw?SyoPMGi-C9{VեásL 8zDO`W%X)xVҾU}T'u+`zbRZ&2*6:=ÿ*r:bNa7ӺhI%Np.@fuzD]XPo#8wz}s-(X=S}T]ق1#)$IL4` y[vB]2|ȃ\p.UYP S,P >={ 鉅h}`*EwyaaxDpU=p.Ҕ JfSi%e)|"i->*Qk5a-z.Tu{vɖY#q\QϠ=1RihBe#vN^p%^i04^})tv9=4#4Gh9'q6Y_NIU5kɼ`H}HǃL3AX p%zQ|&10F-'e;8o6}A$A0:H 65/`He\vt2/q<"JU辐T_6<# qn!sՐ]$JtԤ 8 T}Ti3#'5H17(QvfrX?oNJJB!ug7i6~gi^̝UW[{'$/~\9^hWAq$ϳlH;'+ xDM59yU7"?D-nyeÃiH1U9xuϕiK dCڍ$ԋ:CYN7oEұy=klȓx쐆!b^䃦v ܼMv_fѺROq3g{tQό sy ރ1Jy4_?a{"_vЪ:6eF\ҥ%e_jnwJ! )n> 8xc+UK4\DXr~#KXFsQҝhUC/Ad]}v{cBQFnbV ''Bd8 .n;H•LY)3 _g9_v7}nkʛ^7BxB۞/Jn?#J LEP|Nb V?精 } _?ji!o_Tc[A'gO%;GZj!XlV7ҟlnL: [NMȾ8]/%.EL(C2.F.HqÕckEGd)ܔ1NknBF,?aܷSrf&.#(W8wBf@W*[* X!AVz꺠VH/lm~j.sH $' dzjR/ϩCߙL2WAt,nPh@r= Gt\[J#K Gt )IlO߀"*"Fyu̅ף]!ō4K ԨnqUP`fZFb ┗S+DxSbNuぞi>{%lͧrG*= v s[WɣX,\6Lrwe5́Z:SC2 [OG7{4k?dlBW+1vPhtI<ŸE1iwuq >I0” x9&6z 4>c K?]tC#K{Bjz9YAQ~h[Gj.GEP6e^}%Jk'vAi84hqRhj7YS 9W@7D k;" /DPab7bGIPt_uy-0Fq &|m[)XLb3E!5QhO&G|K/)EQ'p ҭ EM/li^$yldÈL.Kv0^ \ Prs"“pg;f?]h)9Hc f5(f긪UHinA޺df)OT'mbo %;`QH8Sa\~\FP~>rEWojF~тsS¨ Qy+W@t9fē+DLՎT5~h|pvl=Y $6KGKb: _\eGM'Z gDB|w|8MLS r갎,q# יQ()ҥiU'fW= cCsc7[MB7|) վy J螓A2H W*Tjͫ+v&g8.P+QaTK[ )i:o ?כ8Mj$UF|wgƄ;*4$6>p0 a60Iy^=wPA#^rӃ6vw+Xz$QCXdޡG,CZ3S%',MJZd"ݗې HBu!$3{Ӊ: L !u&R'%Ra#!ջB4@*cXeq9Af5ɟP_nx!>K3s"6` /:02eV%m;lar.-㏴$WFe'9qv&kNK]*V͜UIQc/A1Jx'C^)@틆Yw]+s}/Ț #&pIΟ &ki!k73_WIT+Rks&6w?DHT(hV[~@.lɢtP/?gϴl㏋n,?(!Oz3X5Ezs  pkw"x抗zucZpƪ bI݄q":o٪!"<,?H}Y8"Qǡ?ڰ+st&k siѮnug."=I* 'Т#w ,3?j7!~|Rʺ*դ V3R Dqb]}OժK(پѝ :U*[\k Э)F}1fc_|WʻCrDWpKgNX$t4KRI(g,Wag)je\{` i.d2&[ӐyIN`MEZ3J.)wXd֨(ϔx!A62*> hKAu}n"j_Aj26k\n5>C_]x}X~fHķ3\R DTE}{M_hޟ(QU 쑢.E!xF _^-d@$Ks$~O-|rutYY{nbCxm=%oPV`QwijV9 nBDăd> W8glC6/$矚h/!g(yY`#¤*reg hir+SaqHV6pT%wJHsVn+2+A(-y6vZ:زEk42 &Х@_ vq%=DqYB&q%u)ە:De*b@{bQs(S&Q)F7Dh9_%Щk zj6xߚh5pq#}~"CzX?g#ʇTe3(&m(0N63eWȓ1ԝ*5?;Lbslz3pwcaH=[銐(ٰ?GKaAL[BKIEՎR|k8t΍ۘBx?3!ߦǡip>>cgBJc4#ɶ-Fѹ=xsnc[sCRGkmk#/@mK:=#,9 f`hXK侞h9GUԭb*ZML? q 2 1Zġ~ZX}}{("tܺ[1@[Ĉhj=m=ȉ%tA h<#;EZgҿOŇkGNQ[?r\&s=JtL\ȶ '@Hō[GF)(4:54%Gw^(&`x:v5~zIVm:J[;[Ey:4la 4ѰY[n]8xWK]8-)@\)mfH,RƔ9\5V']cQTy2" Hu0,h$5֎P2xw02o=a>,L#ǿn&۰/wXU!&zU ?~BOˑ ^NpЃ#-ad%IE _6D w*2B?_1nblJj ϔ:o!6fִ 3яKV-$@h}?˥_U- ~9dtJl$Kܡa{Yc#^9!Hv&U;kw9ǶIځ,هP=ѐFa|Od'{(~O|\yB)-#-Op8P`eL%D )chC7K)kv$7& ((Y8r\<3S7mmm>U0#ثb6BqƤCӾ!uXWWU6}{6FDXM=pLeF*Eg ӡ#Zvf VpmQFصE4͇l+ z>\>0ޟCk/I۩a~ڿnVE(5nIqvleeq&(m#K찳Tk5XA}jf,0aOWpJyꂶ<, \bML0E+9_xI-x(1ɡӵXk-{4B=hC[3dg"gC$wZؚ^#_)ypɗ<+BzQuqZO[>[UW @ޑ2e vaV۔6Y;IVX:Ԝ|ո,~,1 =dcRYAEp76y_' -VRDw XٸX5)L2lZ7qh"0;W, 05ZZ+k{F1ZȟJ >Fʫ+H,p` Gl|!Xm4Tg{TsY#HԿz_] +31Z=%Ypc?RK7 88i'(s2liTj 5EĒ"=ekR&b- .)aud\k  ZRiAbsVj ͳc#)\ WZ 9#tb(zi*cڵ74̵P>خEh1+cGhPS>?ӜT:a۽l FF/nx眳ݝ\*>[ϏYg&3#񦥱E# `Yb#?_Dt^z-Zg%Ȓ02;˵|nW/CZzPe/#Zh2uNkZf }>3NWS]o;l>t}PCWOőF+/uq3:'a"g:f-VZ.Q-)c?&]'m_lK<'FE0///Wq3*p5*8C#`^//Y ܙ\4jʛyS+#v&ʿwJ˫- nuK,і~"LQ F\/ =׸pO쪖]˄ o_L(,o*@l-OԳCY>8i% 5e~ְ^KjU?{4^>C*!dMlAr0U1YN{nx܄+-/C.Ȁm]ݐ| Gd$vH"CYfdٲt$zbYJOco5K J}&5˅Z[jLDH!*We.ci7O_4^좙 | ⸮B꣞)W~,:Ll-N,o'ClOZXr]I# !$+Q +ϛB&fp0\.u\$P\4~:x@%͐+ٓͪ?`'@=] DfxU.I8<[ϿȧuAdv̄^}SZWxG~ЪSEmKGι91ImMJ, @CIPsbc 9km= fZ9[&aj_pS*o] >akjL6됅^VU9BCDRz)@o&KP7/@wUm".Pkk3XkCuhmJb2,ǫ'9a__3bJJ"}S]MY 4A@r.cpA\wtGfjܱiC3:jȣf`jb3"_ B7Z<R:Xļʈu1;]l×^GxNR1rI$I$I$I$pzD7l34r(L4wǚoG_0M$0\R>CrWx}:'}2sOmY/`퀼9uE5} aS& ^%>V A.8|ݣAמQذj|P1j?zbri~H^+ᓪ{%tNO'-F$|2BhHG h m,_>#yzka<}O(a4ΐ,|Fit+$m `,-m I4Nޑ,W琉aP d=mtz~ _K/EGñc3fhq.'*T0ܓptWdxhЅa&/號툅P_nb}a7C@MGq'w臁- Q7o%S.k>;)O5xG r° r-H:!>v)*ReP!YlM ^aOT/]QYHty]XP =PWf(8b})(P\Dd2Ml&={AߢK5j+. @Uh9k*0]p|bɗyӗDfgff`N;yj{Q_mhz7J&Cac[J z@xM0E_gJQ"qoPڎ^hwib}L~D0r_c_wR1a.>5P$(r !ض `GY͎3f @Q\e4b\s)1RBXrn ]2loUjE HUЮQEd7 o~inkOJۣ~EVrZm bs&>hz 8~)ơZ SA jK2 "%W ;L$}u[AH'x1<ȁ.,u\ WעDO}7T7s3:aSzoxu'r#o =6I?Yq9oI:VL< uF̋(#F^a`w)eg2,NQ%LJs Wg9oeʐd2`10_9LMs2,z$rBD1FOWE_N;³0>(>/ǥ~}שqidM>`42[ZB?]2CEu}R]ON<.I t˞@a;`gS&J6eDq/EKCʄ9pH#*dlO*=iD^v<ԉ=<ۊmC5?&+5fACc&y4Yvጪ׾{FYeC we}|~83wIk8􎄩JЊbsΡ85i{P2 kg3IJ?v()K5CRP`KDm|^r^4EX)Q7;Vte0)k97kPJ؝|2 %Rh| pXZlÞ8"0k+N"kiIdq=|'HN2S0%": 3)gvhYzoaUDq-?Zc&Ŕ0 ޭ?  Kh?]l4>  I̵\ bֹ2jg;ϴ稠:M1yӃ,6!C;;; bTQM5j2Rrthk٭efLeq8(gs܃p&Kģ߬ 91{/m'S67.lSBHlqS0^ 0gKH.Jng{$f<#\r袿'x{ۚ2ԄB24Hip{yoYrԟԌoע\n u+앋EzBBP0')l-4jFMqIW:eY:|~ E|qK RZLN.e:"+Dڟ4)#3kp*~Lh(ҍ_`5wypkމBH5#<DMRƺ_}o'ƴLn.w:-faX,ŵG$F&&>O.*w-y-"ydUw%LD$|,NP7I. 4RkzA(3)\+ri#s&q^^Wd ZHx-g?ӄ6Hô^cٸx]yi &[-$JYMC2{I* Y}b9I3oLtp:uӲ,vi @і0@aĢHT+ݨIېod8rcd5qUT`OA7%x2gVs)֜AmWee3 >&쯛}ɴ]/8cy/2G&z "m@ڷN>̀5 :m,5q`bדD BiGד*B!ֆ<"' 2$ĴQӫ6+,nڜ@a:R?CPwp"6e廖J'U'; ̍8cot^yܓ)B&Z0Mi߹ݗ=7hnafyQZsƭʓ60B;]vx)>l #{JXB'tx4tI<3KHFv{\TH|b壥GANRS+# @ f*RZ" y8$VXI.BVV Hdl|h? YI7T"3;Z`\(e&Ẅ ˛(o{"bb LjkZ(WLC<%DpAk>t4Qdzb{U& ~ ε+кl*Y+IA3d,N[ۃstVm nb /C٥lƨ[t;aWD.Ƹ@qŌ!2Rl95|B<]MqKaֽo?ȭ䙌@Ø;@]^aYOHF{~ɿw )ƌcBAS(d =k>Io`gJ~7_ 4󷋵6lLaEz!c?ihqʤٗ>8Ue:ɑj?k5'}@PbZ0s4ZkБTmNfMNq`ag2|Z 5nGZ`A| [NGq^~2,etta$i;zAOkۺbHoHDےeޕ @l. @Xx.[7d [Зf|6L 5U;ȽQpM}w\B&J#?F#j1yںys6D< +ߝgf:ߣ1:\)[tVڧB"/hf(CVS8LdO(WZ]b6L%Cw (zY-#4Z]5YZam:dfI{ 7ȷcX6-JZZCubiz uQ=pu9f),dv!j[STq(_]V)8vѐGoDH GBr.\nI3%h0NedFBp2 Ѵw93ԩZK.paI7*GܝO gpy|:V~۵}8&JD^k1외\f@{oNąXSm r20rَ+24=>[w!=A MG pi $ i%&e{o ͭ[*u A+qf/AwvZAiVfhj~,>bi" 5WzK]Ӊ}U~aڮ'ɩ鴳h "Gd3|q\9#̈_\' WT?w0hEO gnƨ4@ϒu/HTBla/|_^ !}  0 bY l>9 =OELEf|!Eq,M VT^ "uIhiy1?Wxn)I~&Q0@~Yo怎Fm3;5r'a8bw ,vG3|]ʚS(C»^p@d|[ͨY&F^sRP\5'ky#ܩ9[cI$iM)0 /)K] \4wb`"}cq"a7HQnNĬ5NĦZaǰq_x6yywJQItv )L?v^LX&+G:l-kSkRt vHrnyBWTf렯(j%ld%jyZ<бo\oW@oܟ  2(lWU=@]CΛQ8kߜTԤA&xkH[!w{ۗGHn wJPrߗ;xٜHo+5,ݕJ>1UhKw@1Cj¾(^+菛6e1F #u_p.'N :hrޛ}4Zq2\2WJ i*܌U\,}2's 3/c&1q?'Ă`:kQJ(xM5tňl;3;G\_G.wJӀSx iKܥȼV $ P^saXoqb"9tDrf0tn 塑LsþMpJT~jcT^MzO=6 cs@]bεL4MbӭjK.i$5_KNS|}l,FELs૳ #E[OM@,nH=cNZ2PKBϖƍf4ѩfg[d,fiH0Pz2zL19Fo1yk7PDB,Bl~%KuD`*\au Q誋u/f _9GU>\eͣB# `=X ёg I4K EG!njo{ :-&ɠV A8p|(} xMSuMzeO4M6\+Vj[KqM[W4 *K* (.#UZ8CRq_2ۼ!:k{Z2AՍzS0Ku Kۆfmw?p B:X ٝ)X=GȖm%1=^⚦łZc] nQap,Dufg_ 1=&"@EMjl)0CDПHRf-ZL!羹,{a¼A1ᑲf+M'iĬV/C`$pt&%1 'gV*5Lr,*n>~#m 3zE{\n5Vsn`v"-E*d,:yl?Z=8{ޢɔD!x YAxYffHxེHg頯ddkyҺ vJ尅&5Oʎo|J;CLapi5͢GؗN`!u=Ov[0@ !eq%!_/dUP(]>=Km9c=JkFhQ/ʱ要*){oɰ_ӳ*@j1!&{̍6e]xbz6O7,"T. g!oZ C[rA5rL#jX\_?ùv>et0k߫A߁c$.]e>ù5[be~؃qcQkrG +Z)eKSҾ->g2_H0 Nn8: ve}1,o)E h i8cY~ꨚI%SPh0XXfob TV%mCޛ>Afl1 tЋ*C#1 "glَʩ]и6<)O]\ I΄VN99ӥ ňґ |v O<09k? N$H Z@.P5i Ծ: ^1Y BMй U^xՅ(ʅ|*Zɲ_5E v,=F"s7;[eo,ࡐ圮'6ROQᑟ`qtm}1$vXpaRh#s ?*y^|@a|nUmӏ""'r+Sp%UMV2%G(ʻHkzMs|Csۨi};jDh,r4!.Pq0`ۧbVe |D>U!ey]]e=\ K8o4?:2[l&tp`Bq~FVHttN<#)@șW\CbO|" /qǑ`vڴ4:Thjܥv"nUҽ›gZʬ0ǿL׮kO4Dl%ihwz6I3xTia)-!IX[ܡI`ji01#'ɣfW+BW k Lx.ĦyyT5wg gV"qR-}P #Gѕes*0R-V Q eIʃO!>ޭqS8Q_\8:k^dQT'jlP2m57Ҽֱe"#6]OĬc R+VLZik}?D21Fm(E~ {z1R ^0(ڥ-<[é$U }բsYUk _d}֘bNޖ 2&\y_oh/\IN.F &t['RB<ܨzG*2hPkgF@OWv$ٗF)I%M\8i2v8`;So1REk,x{^"SO`WS*T(LƓ} PQv(tjֈg Ag鷝do%9,h17mjq;͕`NVZھ\hlMk+CڬUCuo˛_~~[R}&al#:I|=8ތNN.^"U*+""t.T9XW5_ً[u|lLx w.8cm/g5?o\B=]o3*$=ܕL4B߳˯*yo?-3ɚT1q#w(C5-8`e㏨e(e0-xҬ6zUJ8\d5uwa6&j\Z64jg:ww|m|;fǚNX%U1ku|7|7|ku|7|7|TZ.y)Un qSiOɭmDJ]>ðds 2q-4^^^^^^^^^^WN9"uce`HKZR#b'YG]FvX(ɾD1I ʒH_ġQ:_(+yvNʣE]8< ,t$9=k2Lڄ=AF8i&^g8b$>"`ϛ>}qs0E Yp <.8d4jx8v!@S:sc|kL-ʌF罒+2\ic09 jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1  Ւ@rp %ptyݱd>w;QbOsFq3RC]Q°&&.XPUD Bз;1:nV-4dKSe00Rh7xGdMWb/4߻`*MͲ%xJ¹PWإ+>2D-22tZ廆@{@޲_{+)3IbG'\.8xBG`|wns#^xƷs&:;r U5`pQ2N^.Obe.( ) ^&[ gYGLC#NgB0V?:Mfo_VA}s{ޛBXzloG!MH-aDŽv~X2KL_3 ٩A޼~dl6^-T #e823et+|g`c-d>80w!-Z. Atg }wUkŀSW#wʛ /z݄*^R/wƷcn#u"F.keʽKAuQ@pָvv'{Y= ir7LOZf*{l{zLj5gy!]+#uW3E׉C;Ez!8M*XdvqVcô\MqB-H]ګ2')ΠdvD\~h.+I?>:* Yڄ[!d7LR \K@ᓖdT9oIŖۋ; y- 1Iva'N?U#e9B5cA Ѵ7(9Ezt$Tnel`FU)-֞uq]m&Z'7K´QTOW 4e@LmJȮ$((*h\CTݯ#Z==-ޑN$'Y}_jd t`LB^2E"T1cD?"+-F1R!F?mTjƢ9膔D0%ƒ+,^j6 ,Չ>@)knY:Y'6x{1kO3qÖ*OWmNlaw'!s MY;E 5vQq(??$nQWn <9$_ L<¨~C᷑k? 9:I@}OR#;=%n愈kBq$4c3#%=[dO]zȄ0dX K ;$2}V.<^mwT]-Q ձSC :B'16zs 7qt@#4>m'Oo\%G/kP6rx'ۨ塋\Mǵ*(:$$'YZ cƶn/s^K:P+k.:PQ+@xwy1v W[PIQU|>VXa ?4K=x$0d'|>AhlDNTUp(e 2鹒 "^;Y;'&$YN F[cӥ$$OajA6+=A"Qest\ۋ|˃[ +1I̖ΓNTv/xw<,'uAw?Sq1U㗠=$ / O3*%[`-j 2Ay 6Qmcsx.R,$-Klk{;TT|K D,!8.ԣOl.2j r|d#1>Pv$^-.u7= ܏AQ iƾC~+3ӕ ׼ХIWTi>ڌQsj4JZH[&^&Ƌ˾<Ӧ^h'Ybz~B3CJziO5-=MJ N2],*tD T ||'JKL[xFCO4\ \OcC8hFzHI̸`A`[VYxZ=ߏf^j<9>nsMcn ΟG옒ɛgҗ U/- r,3ޛulë"!fX4rK'o {E-W+ .HpFZ3"ra)@'X= Zy(pe!*U@2o#N9at"m^s3㓩MNbMX׹+/0a8Az[-ZQB+l#}Y ]=lӽtj7Γ2G㰂jJ12o6@1!6TߦF*N4AMؔIffHTB6yC˄h;9U4MֽY6 "{" V;O q&+I$I$&ԭT7eC;KEMCcaUɓR2 3Zk$8 wfxy ?)֘K7}E^g+n1<%Lc""~^捱M(fmF~i~%d";s;^CqfQw!OR HK$t \BP eX{QHOf܌Qn5]T&4ef0uw4;bǃdb"Sƨm'¹d)HZx;wƗ- 9xЃ`6PĬNK'A66׵.;+U9v#z mI49sjt6i]P"c8whted{ȥ?I؏2>8Fk;/xmu'HqGS11 ؚE?B3&|R q ^,T:kg~"uی >+?PȆ0lկe=pİٕj*K]ƭF%ir(m]9JWoEC0% ȀG {J.[#윇0q"B uu铘n+Z r6|PR.RnҳMçt,*+ZpZʅ,\_eL  r$*&OH$߭ZzUk'|fi2`SP/)}Y"L`F`6W'U@+{|nSz9S,*GYNP#~`Wx;W'#S S;%\_as~/{HfcӸ#;<#eIƒOK(?8}fkҬ6Q8 v.g֥"[Ļ 1lPh&?u/!  1rO o[؁Ҫh!MDЊ ]\Ŵը3`FQErARh`LڸRuU/`}S~oz}UtHd*T5q"Af42vzRl) qL^qZ믰&d6 NN-}TuG&VsU";GxL;+_3Qz4rM a-Fk'i={,")gDqڨ3w˽ÉJ(Or[-AoDC;aAzNfR3lM?fIx><̑B14u?dm&ͫW@5RSrU]^ csc壬lԙhnb) 0iDt9}_ jyZIC%WJ%=Jdm ۤv$VߵS34"/"=G|ۑޑEʲs5&蚖]R!E005 CBN:}/vJ!}]`î+}zw}[7g pm]t8jzV3nKW4'R %ݼ?JķO- Ij B5ȱ %ՏIjvs `X$u s 2{..4ut[\7X?@S+z]{CG6׽{z&boK)_R{mvxDbSq'TO^J$Pg|EA5@ARO1wV{ &i]n2\w q1E @ GY۱p(H 8ݑ/qp~f>SwOхޤ5b?$uכLg0W-IĶi0\+bK@Vp!kFz{4S-N6N\G>ݏVT+/ UYq~=-t `хA8Qh b_@/F:./m\V@UoS-o!v-btZD$rCk[nO^Ped"5՚Dˆ`.|kN:[5ys6I_ו;0TC8x^IX1Ž)8AN K䇦]zࡵ._a,Jv{ voM\mt;EMLYcwawv wirBxP9-[o7`pdez`VYRwk5]>]ae>"I1p>~nc _6n=07Eq^;/3K+`SJ<ԁ%]H[^@cgj8&m#ʶُ60@rY8V:80fBjbB-_jݯ#qki (Ԭ JI]1 F@n#E<뒈dRj\4 ]s*V.<̏\GɖV/ߗ.0/`a4M UBh88䇐 q0񲀫2LM2W%9]=tyo@G`#^F(e_pm<V(cmIۘU·D~vW|KɐF[N ~л.z @(tJ-W|y| q ;u\~Հ@5ȕ:eD䂙9 ]Nn~$j03mԧh ؍f 4s\ZȃA=4(Ϣ|,P5~w\ ;dNc$Mjo截cASy:`jx=7`xY&' {(kE7V_K #M]:)"u 9cc%̣0,IkNƼ Pq-45و 垄 Jh#ɇVӻ q L: 대uĶjy:=;dD|}P6܄PKSByTh-;D]!fx}>js&}C Q cpm~6 kSyz2*~J&'oRX1^("6U.m_L Ǒݵah)N~ jz?5(w]y(y"} TdH]֔BOXF{@irenKQ/ΖYH>~ȭ)z5p?wC5EI;hE\yҵ!'#4V!R:0 ,&+,{]02vgz_]2c)8r}; *wjL81MI'U@9H@bINSh)d02@hU(&!^]<$(R:1p NT: *.fAVAϼivA8̽AUekDay*c؝khJfqevd*ewaFU#ugqGh%)Yzi׵f!^}P<:/_)C<;lDFN{FtiZ t)NnX|9<<_줴":%TsyAu^i6m9["ZOe(R'zF ٓEޱOrmNJAVy:iW+tx97F{3^e/>A3X9"m=jSᤑ^).\yafx\,hSD/ku|7|.SoeȒL/ĊۯoG^WI,}ZuLs]TrR7[u|7|"ʤd+!6`|,Dʶ&z`TVˇ1lzKsMEjMnˤ_.5Q7wVNxznVO\6m0 =}<*eFZ ` 6{J>1q]&+ҩo&Hz1;$ Ci%Tz<`p+$ AH39L`b?j.m=íyb1BϞbo6_!i=d\}w͋kD!N{ y@uTY$*U3 DE#~_mpbuUqyotdsA|m Z~Bu|^ZuZU`IYs=4)pn9lۮHm _aD+,xlrCנw&B|G޷ mB{ŤZ>)vл4gr*-I!h^b,?u&<_ `K:0p: n"r\x") nv`C{k{?A?%M"&Kdx\%J '!]9^ퟠL[0KG:lh(/񬟫fFG"cb֪<9歧q57># |1%!Ͷ@+>ׅS@#rTńNΟij-&0Wm\]LyMFug[k.y>% .M\8' D8KR^=%CCX aۿ۲*GHFE}vlpцpď<ʜq0}:69*>yV| ) :/)0a2VwБ ] @W`1 :Ś3|^kSӁ3ӍTפ3=LZRksUG+} eޝAvL+ifzvP}!6춣*d<6 =7S1Cs$*+576Mm?ɟNrXUTgYx-lÅmO"S2qsu@yH ,M.a.f~0aqÿzV(\.6CQ@NP_vH }ğPC E תX ;V 4/ 4Q7RK 9P @+oO nm+9e9'"z+HH Ov$T3\`'4&/WG[E.PU!U@J&c1AGz}xL5RN2N][GK& F爪o^(-Ɉ^ Aм<%~ PbsTOՖ7hR'CT2ho'*C5q H8gB{gnştwg !6/7[$zk,䥱S!9NRys}+yO걗6>,5෷oOzZ(bY!y_j2n ZBu<h? }3U|1?~_>|za :!Op)D֋0 JJ;oo8e%Lg(O3= ӌNvf L5EY4m vgVx =" H$Y_J:0KHcHE@&m.׋Rfb$7F]䶻My'bVi,+7Å PFR=aR\CE$a򗔼{] o wB"FhÄJuѢ$4YYgZxQ1814TǶu,M^Dl+h/Ŕm{)'tu!s!;x UÃF']]™=mDRF)yK| oll]H@?n gN h*ok,\6V$#ϼԝD' g_3TS^> l, A|$mA@!gyG? +JwK<~ٶA) h={(ATHaGA`@WGu+';b~, `wȍt8*~$mcRDpf5qy`=c$AT=*d19s$ws\w@ { 0?0!z,,iuTG~r$ߟ-PzLH5x `v`D϶/_J-= t=*WN$v`_2N. 1%Hp{o˜U#{ԣ(ei^$ mM(YFsz3><W"J=l[#.ݒ,Ejan(#Hט,CX<2sֵ HLN2zQr_'"m|$ieE+r K=CI= ߑ:gMPF"i2EU<2`)6 A9c}5_ŸaGق^0bpRag<=_t[O}Sw~h䒇Y V+83%.s9!24 0h^l}8܋XQUm\cI:qP œȚBPW0ycbGV)A`'C@j(wvN $Er eiC5. +)G,MpCD\oNοo &q~  Osa4z ڮ\yr;t (D"\M6@$?Xn6pYe?>wS!|)DW;SLOl@,N5fh]#'XI E $U0$PDj sb](_0V [~gL8vZU+ġZڟ e%őq5;}QJ0BOG ^QC97{Ҷ{&_zŦx8 SQw=G5aZj`t :5`]8yY&N/ ޞѡ4ҡ{i5\ _%WK Y;+~G EC봎9 gp_3W(RHOX,s{KMPYOpO@ P}+x^ RUuOPmL D3(()LwA0IV+/UP+ZijxV]FF'b.VFcyEt~;8ŰֈiQcڼp۳ &pe7Dq"P@!9_ٝGoLYL:!3 In}VqZ l:̦\)boRx=?Kl>Kv*Q]sYK(\ Nnj1 'D=>}ԵB?ߥR}1nKic;5AژF(p|E˔pw[3GٖWD]@H0mwn*.:<4]z**Cip>SQJb]xVV#5(d`AseU& 5P`EMOc4aoC̑0eaUDT%o\JNbUyQ".ZY'cf?]Vv? yg8 ,=H;`_jA"=R ~ Si \-X]>tO-|.7n,ż|P}R57g֭pN~b”z0< 4UJ!l'jJhPxXI> pڸ%Rg3]W?U/9 z.WId4z'7I&vv;`2ux(ӹNFs|<ڻڔmbs5'Zs,慦'gv:PSuK /eذD?,>- ts7ٻ)ȉ\KZ+@Ԩpa:ŕ6EЕW#3K+G[5} sى 4km2v%/Sggwj:LTAρ /7zo$UD$xxaOD=$kqb"};h|$n>(x 20WE@V*P lT[dAcf7TF1NɌla,0\q؎ZQN+AzlN͡ԭj%tK5čFEAX,Q-81!3]ԟ>%.Z ZLcV(w@iLlRm̺]T 01ꘞKޏ(mAn璫]Y~ͭ$b7eH˧n$wR)̸C`)naZdKx/*㊔ xaş$M>>S TTvb.LԺdTrm!q\!9**ýPk \/6eZ"*1R Ȇ"XPu莭{S7"lӰXbȲ㴋h8Sԟnowl0vY4`Z\U+aq_?Dp}[;}WBL~i3$Mf`i $t#B _i#~hPo%R41IFg$ PBY6 At~b*eϐ@ViS_Vz0`K@e1r?qwXrn7y}jA$/Rz=i.fCW i C׽u|@y;mҶ"}sق(@*Zѧ ^[Ɍn4Ja0[vJ|QP#"Ht|zP"IrpCړ0EGu&TuZRjȩ#T :c +r.If9d}N`AE} ~|P%8 DYԑfppZe:̀NV#59֎@8I,^pI#SFzEjs8vJ ݵnI7I젽V0jK~nh < =#J?ݾt=F .ڐw-"QJkn۞xK5[PflE`7a 1R;O+l8*u0mku=ﰦ{ _#Ix"͚y5|V * H[(5!i[Z_c9YJ3jP\9(8 -LT ߾G˭~r mG 32 Re䏕ҡ1@ qOQ0e"=IhnL/rܲm/wu &h?ƅOh5LajX/&S[=O*m_R](I?! Ia+:Pٯ[$ &Ӥճv| ;QG`XYZĎ3x Qctiڱ4ރ^fk/ݰx1S\nYJl,Sz!FYa`02ur\Μ4D_QG" ˍb' FzzYr}^Nf2a~X|3TIf5u"l(JZ؋| dyYC> چߙ#2jr X䳓v^D{چ9#2]Ŀ-k`M;|}ߥYJ &ږ[@=VmϺ=jKDd̮ %!VshDSoya eK!$4uQ9zGF I| O M Xt_zUc~a { k-{ch: 发͞C^Q^Yװ{c1}' R[.]皓*;UH&'ri'018|'M3m۹ҼN,_E" 8ˆ~ \Ƣ(~_Dєǐ>gTΌ}#RpT}'2+~y}8u^ aRՓØHsXXdQ1 㨖cmB"T/;WLQoDf;PKgR{ QZqfk5 Fw)G.o#=K<&r?ڀKJW>S颜Eu֪ZUncbt(%6O.V852I/)gE<"<5UK4惲 Hu-j)h еJ=5j_̓NṼӱ.5K {G/o#/gLgl:X ~K[Sߍ~}'{h]hEvߗV$ X]Lde, ےDEVuH^(Fawdmk|e,t/f`]@9%O~ nx1&U,Tlj\m̑8uAQ̯:ΕODF@Q fFYؿ1s_b;N+EINdӮ "J|!;`$~DkڏWbwH}@j+E<5jn>`\ifGr/2lDH_2P)tBf[*LT1F*]=5žW?t.v8k+q/zS AvؕrƜNk mwIbu=+ ^N.ltL9oǰFҦHNEםv,@X?%_?pC [iIJpsOoM\u)rYyË`/Kɸh2Hl{ÔsKeZb'ܽIdohsUGlvpL9Ol?dP2Ґ'o~kY7iʿSoc7eJ;m/}Aa }KN'^UYT|ƪqhJEX1xMJ?I8B2wB76JB =ԥw{5-E'{bY;jۓINzqEZVט=WU}yK`'W |Aש6!*4 dvMem#or'Pch< "  pj)Ve"KBgxSA5e%S_Y2>^u9: biUX(:15ECSjBXTU! "sY@]PڛZ_XoP B-OT!@ԥƙɮKMv/cv:AE~#nWB S\xT,<C2_:_|I," #:Ca PM[GX1ՙ7vONzV,l9ӣխLFʹQΪHE&'[G{Ew$IaQU$A] ~F=A됡"3쀵vM!h;0b~e]n?^)ĖGu9 v髚R"?n=٤P$,ǭ g0;3:6~Zd0؍!J/x_b],'4Z|k}|;l;`/b/AҀ۱o6gd&VN`2^o gtaDyO v906!_'-Lrq-ͧ69p|Gk@l iv>u⯼XNQ)5܃̀La2A&\G3SP" W;>6B6H&VĚ!3F?M𪽜ݗ''7>ka٢TtJ ZLV2+ s.JpP-냬( ;\Oy?S;#UQ؜N c+W*K6u-I)# m`oqw?SFz?W= $eֆbĊ4˴L]GЖ_!;xf9OIB1ly,0 B]:}ZjʉL)̩09 qz<=~"ڎ+ڥGEI7Usin(?5Mچi95n7wD"EHzmHBߊ!n`vTjV> E wYT%̬|\5ERm &x-/Dv:ևdB$R jqN)4ag&X?mzJ`W1 fQu-˅>@&5߹.g=jBM;rIF֮'L)ILQ~Džɚ'CHf5?a{<ر$K'ou͑Q:$ E_~ýõjewbF|E\=mR ;X>Jx[FaY$a}s,Bya͡R捪WAq_ KIu{` D|HE5ˎ)B%D_)Y5S$mPzdګLP^7KUt"ȅrgG1lzm  ;nXx(W߂څL(}ڷ>B]:]XJ#zV/( -%vDvG`?C EsFH28 Z}w&>; :r||Q9(Xpyx >eDu»&hť`k/Ѳ.Ńw?r>6<(t~*(tFp?U:~̳J}i)x#8W$?w;/z^JnԽ?uu7~+C`: $êm|Y!f jetr88M;v,5xẢ]63 >pS|!}IZQ4(7ͨ DSTJw}?ea45nv֡L]f,Hm|G`PaNRq_P$P= \գ^/X7!,+㟈KNtϗM4Bs2RAM#.x*SK BW qJX ՃM=aˑcECMj.LZmp$谸솪ey-W !(~8BSoT(=eP5Pf\uQ%Zi79Jc> ^4xi(ɳbvHB"bo6d1jUl{˜D$#buxTͤ[>Zpg=!UH'D#l͟Ce~_,,4?SdzO<5}?_(c]MuП';W0o<' $.(!z~Vd/lGtV ;$XTͱ8z7#$NIsSNʻg^)@ Z8}KQ HHY Bz{u!~g,U !j)fE'z-&3h*#-,O"j/wzك S\lTDq  ?m2r!tf.&gE3& $dd'{pbc2sa:2aS jqx,TAٿsvB @rV1t!tRp8u3%1j,Jo^j _ܔn{ul'S6qs_O7&tl`ՂQnSZ6‰9+ 5O,?I-j2%_cU kDqrEqrE5`6|묭H cn?X7.o:\x_aYffuF}:7f,,!^t31&Ҋ2IiA!ȇ0.hf`Că)K+zj,@k# ;lȸthW)t[WgcTMqWgI,b&jq̒SJ@da<"`49'(Qv@K0֒/b{]ZՈPL:@p8دV pP{Osh{ˬF\Vrhڥ E8Aii&1~e. Bu; Xa+?m{oEQSq6*1(Yc>i+OD? cӱѝ].`=jw7eC. M$ ߩ*8ET :5u]Gزj7qHRXyQ~3ҁ&&.]2BOS H< : x0a}8!BPZPJ [8oJPW ʼ~CPb Yuֽ&Cjn(Ш若pzP-AC!-q+qp' ٧bq+9{y0 l, pfk#?R9b SQjaCnWԷn}_j?>IΐC-2ď" 8GM}f (kdVQ[00NƦ31d1sIg_mq%a6FV騖&F*'t@;o"IcF{l)tRVxH\7|QVwy(͔jfLHXa@325#uN2[): )>[ڷJқ9;f+ґL)աnИ+ Aw?hnU ,v_(^|7|7|7k#YȀ>t*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/Uڣ.e^4B:j\ÏY6(͡qsY/6Y %aDS U6^kΝ6] FBZ;g HuަRVgj͛->PF R`<$1l-!lT<`X{Ӱ%X?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 Nמ@"Ϫrȳ~S*(4rna0V^sK7j0Z}iS4NYjs/6v@/G,$yo.)Vei{UwAxYy9DJˍ;-_yp;2Y!PKY] n9)>ܞE$^G/pCnIы~>0Y1zUr"MUBJ=!+רx!ETрR]/뛁_M JKv-oX}< =} >5|n)Vo~@/m>-/KJ/{:n>K on~ાctFaX z}D UdH{X +Y20q Ԝc) w5> 6%F5Ѿ2Rze&LUJ $<>og"t h͂N@zxcEJbk1tDmgYkR.z7U).`e $iߔeL V&}]2S0~ׇXpD.|L{T+voM~-̚3?hYAUT}}w$98)1A9W(3AҞRӸK1:m Ԩ+a+ yc'i78b+ OXIwkpl'b˴ͤOř,(PSlGɓ匃+<삙cqq1نXɅM=#b1>K:ٚ;{dy .7߷@ʅH`9w\z G!ygT%D-qwA \nZi&:B{?.ld+dRJIVxfc90w8>Vͣ-n_[g|3`uCi*E(Q׬yᛶEoH,:9 Ɠa`%"-AX{ [$x+@7ALZu~(% bѓgZG~C%qe !.J*UCM"@$*J\<1_.?vS Z֍`CZ27W}#Kp-Ӟzwz?" /LrH-|5U{.ak_7|7|8l*# }a' `u9TV^撷N?Gb vhŀ#[Ts;E7>< ܮI./a~Fs&<Ǧ)F(w-WOݲ  t n o}΍\+ UL"i)QM 3jNhrKIyV|7} ,} <8I\0s}*[RH^΀Eu"ظM5CuQHiqz !8[vXg,'9B/a7i )bp#D<;!2}J\B,uMqe݆1ζI=,l6<2ڈ;‹iY3K>$ۏWJZnZ7l7:bo$t*̚1LRk9_.u .#dVV9]cfGp|_5: VĶ"o黖fnY:g\%@#/f+T*oZtI=wF 2 S{7b@izC#ኚ^?I,kN;GNГMt9*̀~4s( ż ̯n?'-$6fIL=y9aS$gW0 ta$UDՍ<u>>>lCmZHw ho!q:"bq#@p0Cy"=OF:tO.\b}Exs\h 񴿊 7K9Q󘌕MBPK Μ;)?5שDkG)MR*4.6Nr :B.S>H9OW{L_fgMݶmxঘ%34NW;I4 X7 ŕ}&Z]1N0tRfW'6u5<8WtJg9osSO'OӔWL6MVޑ >50:^"#p\:{=ބ ~(2XqE#,8:yG83ADQ .nPGt]чNH=8.ܙh:t!%/fU/avst=4퉹@Jߒa0OmGBLmÙҜ#hhmQvr+ <M/YͩVV$5GԨd6qK+.k໩wC[J/2vX71z{EO MC;!{ a~C`{tn)a%z%y9.ǖ3i9H+odYf?я-/GRB>w! 6oe(.LL 0 F-? `ݙ¡GCP&|v.ׁ}tEx>?F@Ls6ee)s5{ ӗWSN t9L6p5F綑w,[_jy7 4uI)$Yv|VHQaMUmM~ B t?p qnZ%${6kH{Y+S{Ђ &_'E(nD(G ЋI!*Fg2K_R"Ul.!+fÁB}>_*/ῤȔ, U@e_ 3'GojX1>aһX!z7|Ad޴T q{r9C}w f [HGx֦|sZFƓؤɡnӴ:l#{?AU]/a^> Oۍ^ Qt0/1Zupd.e0ĝ|]9Z`1OߤQ%:%aeMqV\9EB/-%jhL)=]8²Z(T,tq%fUݕbqH[~|TW*[q!8m 27}o ɝR߈MxGc0떥ot+^.@y6HVl6Ůh Z (=lay"&$qT%:\zHܽpleXTDOgKrɉFs k{@|l=`Qi?- e$:=LnI7g`W>KÒmQvrm r쒤.4.{ D]0`fO̔ G sh>̺ _Zq}}|ǖdf0 s v^^^^^^Э&q`hO +no?pjЀ /# = JlxU/&p'h/Ì8?t}sI=Tknt1)ձpۗxDbon~"0^qی8Dd_7|_%~0]k0""KpE[sz/ J9j:"3IE0@^;tg )4\20D4hS1Q EaŐHWi4lZ"`/OׁT 2 "Fr~Svs KKhFXJ$Ux|snsޣ'6@˷}Ni1o\J *f\g] ʜz$1frϱLws.+pc# FJ?"Ү:Q,U+Rqc}?̔허-]~YvSPdџ?|^n8 1PFGD0%*pLD\B,%V)j!`NΏV[Vb*_J! 4aՋh;'x6حc*|kh- -zpt\DhdGC$8Wrݐ6CG n[[Ooŝ'rsN QÈ@.JRs0&b$9ώ)#ڔ7LOM& bcuHUF M[., /RU˃` Z\Bynt!.δٽo]Sԁ@D-4v̟H*#~ ݇s*䗝"sNJ[V|.8pLSh&6??Vu{!Cdy*хl_GC7@ _/cK磪8o6* e<=g@H<ĊJi`5imse `gbIOqJRN+z#@پ 4QM\9Iߎ.MUÎ5f[JC6[SHׇ%Yy5W[ tOBU.eNOѶG*StkL"BlVO ,+ZӼKj͓muU \K:໌dy[7z Y,[u|7|7~8@\f ;]l q3@_*G\^³+ڡScx``1)|>' ?w@bz_7|7BV|7|7ϣ+V^sg V|7|>1 GrNr?-FooTᙓUN</0P 1V*%!#@ d rG\"Zl.^#lO!} ɊOa!/-'3wvc'8)YvP[( @PxA ݋8B])| mw_`>w3V?W;䏄|h "[;x):;ܟkX-'Z.zkDpEx8%׷],gRz=ri-=TulhI,q^U3ezKIsnL5ٞ4p s`fO 2`Ϊh@[5@6-/N$nOQ:#i+ 9gXkdU݆(8FCp /ARRV "0Zq2J9$̳fO=v(K`k(QU=ưpIZ*\Tvn2%`ǔKq.[|/>myt {fxiw5=f7ZO\Oק&DVJ#п#"_}i"_zYi`/Y'SmU_u-$ObGy D4Α|sB)\е2mzdyCZ}ɭ%͛(h.&{lY&Ǟms2wі3'Y{ N`J5f0#32)Oوt2pS{[ k, Oh>U%pYH U6k[9t {|e@&6m? \yj,GAq1pدyԁUlfNw{Cى!f@%ߜ"sYPTC# G5Bi9%mh:$^LvldC&Ov/&}]Rb_ٻ3cFCR4D e . I:7IFMkw!Wh{Rtv8X#4f0in yh0{ifH&XSߠL48cH=ޖRx`Rl/ `+曆p&W>N3-8.v]?PۿT `ʰ} /? .0y/9W,4!z d"fQ^$"y]V"NAרT->xw$=?+ =' +RݮhLn?|k[[ъZNDZٽ>۫St3iS5EQT!Շs&%뼛bfc$ Y,,ܯ ĺ lD(D AiWN[ %.Ҫ3*i=-w _SC(? o#f\6D{ΥTmQ[1PY},cdgǘZ;HIU܉ٽП8 [}(pmMH.뺏5*&.:Le= ^o^"/ۉ }=._ L1Kn7 ((rB^i/1g&:6kbmhx]y{r#zj{蓛zZg#2{`nN6KPp8TF2}A)N u((-wڽI znٻKݬβ5HCjz=k8Q`'I*S7Srwr5WʪzמN?G5OQXz՜WOy^q|͙\U j&$ Y=F@xHLCk1:Nh:H }YSD3Fa1x!+Myez|mvaqO R0~M:7bh+4TxZwN^8BtUv%C%KсDy3X^8'#˪)/sƓd8R›k[_m ;¢m'R8i4(J{[nI!\ יb"Ͻ7V~4\XyI r~eU[Xފ2(a-m'I—\ ) 3=إ iq#${ !urnՒUC9}]sTd'ګ2pș30| 2h:w65+ 4C?9nӑؔD3@س;^ŋfxhߏk%9!{^>^ $t:FI$ .t omWԠ $FxĔS.*lCbxUʙ?x17xd.dB< u N5d$x/}ZBv\q c&,fBhM-  k>XAp8໲mCq:r?SQ|*b&#R{eBacwtEnV0̪4afaI>t͍I$*)Y'"&G˓wRKX\381Ik}6 K15e)75y% T澃 }X䍚^2C_#q Ǽ~ XđÇ\&KaoAq_>E X;IrZ~Xi铕״嫹%kEJueR;H^0?ئN$}=h6]!S;ÇQ66ѩ5::'sh#iKb1:1^^"o l="(p2Q`LK`4 9Pך({sdXDmZCc K ng[N K笰Ն/dVI\U9sAv魞UNi@ \Ҙ{zFD&"'4o7@i6pզer$oP~= +dPYnK1"fcSCeh xzvs9s;#e*ÎsDl" *NMY Ѥ_?똥[ ͟p"5?0'Jɠ ~qKp"JYhM1s" é=z7DEbU4z $'S"R K#0x)m2!ErJ8e.ېB犱N 8K(PM۸zAܕdZ#X'}jzҒL4iZ@>co%ԗ1$oa[r,5*Dog Gxr=ޕ˗pvIn>}S̏M]e,Njv%C8eHsL˫RBs_E>Ԫ]8רCӨ{-JB=ؓ;˿~5ysjvI 3EUei9iPfӀ| ǩʧ/PqI/|*8:s1^2a`Xm>2놌]%Yr5Q8䴑1C}@00Cca:/R;HJ^0 *$%:/R;HJ^0 *$% ̈BR5a 9G8vb05"Xɛ hxS00/*QC\/PUvRذuNG@qG!-M.^v%Ҧk_P.kR RO@ vD˵cs{.N-_2+-:i_}=Ud՟8`POUE@9E 1·lLo.f5P@վ7{t yc߸1>ײn,_ S2u=K>x``wI6_3|t~J8(!tvTm0 RlRcJIΦ> 5&NExD@j+SyFڅz)d}Q>[>П5w/9B2),As}` n# ,ڿ(dEkG;HHi;Ya:@7 `E#r14>%HwmJw*cz 4 e@{'nv K_M a[֬ ;Ci@>ܯ&Jct !iFB1)Mt"htry ~@5dO~ >Dyrcӹ>ʘ e4ecWSeϔS5V7t,YƯJMlI):÷, _$^Tݖ&pbm]LL)}x`Th ABymZCXZ@5z(4>؆U95{,d0*l0/ QiP&2 \S5rD&g7ԀMw}AlX[=dr{SPqq `|W>Q7=D]4FMU@9$S7F-Y$\o[ŀϡ’Z47ؠd%E|:R7D4`wY@3XR{ZH0ͳVhqrYV_C lV}C@lBp<Z͎~^EGZB<1]!g>Ǎ.6`.CSHOCh%AuA.%"1%7Cb#qu*\]/x%sIG>Jke0s`X #9*M%Kg[g˜h4f /C(*n޿Cٳ!A Yt:Z<έa_MRi ݏeh{c3݂mbZ'0A}QS n?nd^>SG.K #9-`4%\66 t ζhЧ >BL2KOAvLDvacqZT)NWh!(ɼH-M* ^νZ[6ڷkEJ){Dˇ WO,C׻t=*j[ul)lM R 82j)ŘϨ+w{2* nQFgHo`MA7$iH&q>gx]([ >H.zLu&z\椳kIr.wh# ?zQK&VYQDj[ X{F0/tGXSq|&<ԚXQ*ـj4^Jh'ۛzp ͥQl(ZM ~glJv@zZ, )h\o2g]QQ @EHT"ۼU5Г^:g*ƊT? ZU5"/qVݱc% [cd eeF9U&$wAM*'s2W9O/NG{IMne}L'O^۞ K Lqߵ=.P&,R$[P=< =ȴFp0:ǨqG#UfD$<͞@,\ 6Q>C OP3Z:#nP6v3cڭXmIlÂ+rwA5Mo W\q툴½SQfB2m%zfm10u#Mnә{pY ! Ӝ)tGL)WɁ %؀iqEϷVBpͺ,|~ua ]g.ԧ3".l/ uH޿_!,DZ>`4TĵKAR+*D^ O-P*9*"$~M%i}8Ni_BK2.- VUX5^Gf,Z k/B*-_sqlF"& j>Qp|2RuЎJ޺ E' mx]TKo6n "ϲf ٢L2}~TIĸt;S9<(Gap}f)Q9ygqp$!]޽f$\_Z*V/ʊ"@I]w9Jɏ[دY8J">*tu?Prb.WWxd.3Mbk eg} $>뵾^Qy ?uTɌΖ'F$p+"f,q$RpVU& vqw>I{W?\NK9$団'F;PCM/lרJ=,k봈g2lPf;8('q=2K_Xxxei fօwLܚ32^}]ЈgEvINꎍSlS{>MGuD,Q(=k#I<:p09be! a;j(> ~E!||-Ț\&ӻρ U|lGZ2;jCh6=)#r_W3}~Kql̮wS1,x%u1>C.L[BoΤВf:vtrt5R.OQG6m.ds2BsoO0B6\:-c}=G20BxTCr'L0 \g Iؤq&`W) ux[3VkLj)U$\iP.S ŐlBq8㹍U $f8$c9w}Gƾywi{-2٫gYym5hR]] y6 |(Mԛcy+ 07s,f6w F@Gۮ $_߅=PwY7p=BhIPRP=") HCiR>T&Qm7/A#4wO'YZE)=z1W';EO 'Ѹ)3Z3syےu.y'n qRyJV0GSx\PzY贔dSD-d6$ea;~jY6hXfQ&fb/wB/W둯t}Z wbrn-j kj>C#jl"1{ U1Fi65{ww@prƐ/Uc6hyhX~T`TdVO:4&OsS&1KZ&0uLJ3q)}]<'(}7iXQrP ߸Gne}wE\eGsdq8 džE,JqRk_[G pN#wōh38"$g8=_՟%HbPeb{qQ 0m*5?/~ʨ2IͦE#Xt,|^P9nb[q99>(qQf7CQ"ch`!W@f {_lBEyQ"Qb#?<e# bL *P@PP 3M1,<؜o2#{O ^ cX.ڒѾUne\DrOd:yŢhnّՑ̹K!56085vq77 8!> hN-6&)}9bplZv!;R' VHc qZs5 b18R:RH5Ʊ ؎q X9֫P\=+ OeӪIm|)8>y3^07)e(g2>tWANQ^8XUj6𵿤X?B=wsgD9OpmOwH%BZ߼q* uFU:VlԓHB.xʳKr0Fjf]ctq2HS~J>Il'+@8#84k-sE ((C@;%WɽqFs@?~]Hk8I4d8ܞ$Zc1R",yvrWC'ao\jƂ/;@p<$T4H:aVh>j+y ڇourSauwNo@b]yٮ LEHiz:M6s'/| sNa@~H6JN 7n8)Hwe?8zNYY4 3uf\cs 4啤bO䆐Z@ sP]5tГsI͢;}ԍh1ꊍ BMpVY{;fE2ijiHu~ lN/#5I1yߧe<3 [O3q|kX߻OƸfSiF>}k z%- .ޑFqU~˰h`0&'0fjZWLQ21j^yg^aʉ bhm'SߕqbcJ)(Rۡ GlP+O4E H=lu< z&2hSF'QƇr:](x-I/8"6O'[:@Y=l<ղ"hˮor&QM8.ܲzK4@ez!'L{9O&ppīb1j*0sP ҺzurKM<=f`a'osoGDYߙON;yjB=ȃ.jq bԻb vi33R$ꛘ=򴧌.x[tHJ$nG2.7EQկ|t-Îu~`#&^# wx|o=1u޸'skj&yA쩻ĵPe NBs\lrKR~R|:>E\Q obξl{kcflRm1I&vRZnJzt#C(3f'CAՒ>T|N]0w 2U+xdGMy9U#jR00-;G듖~wǛo!lw(NqE%^ aQ=RȨD=-[om}6pīw( AP@h)gc~+3?U"x\@,z8oE%;ɎkmblȑKr*]W"HPN#FB~gcm?!taAIb>wPNrLyoE* ^yf+ .3W=vX.F/!%Y 8[gnl %4jSeB)ׂhNb4tokB8h=@w㜔73-_Gk8x#\fuZr)qCEk%$ Y N_/axҗR<39'L,ôdLј;Wp: SSt`^+{?;0Nb$[AG7W(:L O{~nz,4}<"[xw_kL8&x8]zH fi: 0wPe5qm敿1ܷ5@PΚ|:LP=+Y%ұOeKa3t KOP7\]L4*Y| ew"e }K&F ?Sc@+i.];:uЗP` 2qʑ/ ӀP$b-g@ 0rncrvܮHc͍zC._M#g¨N==}W3̠nE|['}Sqm8{\21|0sn"?[; 5.92eYnqvކX[syœ#r2VccaS;pd }mL)Wo"Y؂ONQ*o(8EX~ť: J)2nT8 'X&.laܰ*+d2ɸ=P㻶!QKQgꉞJ(zW ޭFj)h.cvh"HV̖MXҨ=ƶѐ˫D/KKԦr6 ln@tXY :Ԭ! A(!'v3L~?W%Y6묶fnʁboe)C0.y(LȳB1xm WujaCVouhܕ1+&r6oV{Gt?Q0@/;5 ժxlb_Ԇp}" QmȥqcKİz%߂m5! <͒ܲtzX}W^rEJJ7ZTIVwh!u0dq-:B{XMq΅F|cě/ر;uYb^n~GGZaӰb@|yvf'3 C5lugUu=";j{ެ>U>\13صcιNb?]ljJmw/pM9Pܹafzj  0~L#޺o\b6%HD2!W:MЌ܈nųEʀd@wDڴmƑ渻2c}vT*C4աµQNxl:VQ%exIijǜR֔/AgM֨ѯp6-XQ`eيό q4ICNENIcj9q/Z/pvKd-A2􌊵.ެ[ג<#"F?34r̚l͉( {F"bj>DBC'$=\$-PJڷ"8m D*ֵw8͵As%t&쮝?g ԔXѦRn01 )nэss6{P+T>v B35h y sWf92uFeʽ@CzΞ ]NZp %2 *z}zK{IO;uȄO@C^V5n0g^΀f'oTI_ZX }f/Q%Ձ4s͟V$˜WEѳKGĠL$߱p*YQXeݛ]{\q vh< 5-+!hSs֧\t{R,hXP19^o)'UgO !e;[}ɝSZff'[#Ui.>9~ ǠlAz%JCmIAުyn[HAvvMƛ2ކuq~YZŁ%Fs132nΓ6N>yo?{ZTLʯ]:w~73\s4D\[Bdp |+q۱Uk;a=D=ޒ0fkVp:EلNvb@zKi5]ùRO2*εKq!Tۺ8O 0~]c(ϪnGP/_NPhO- pQ9 zp%$26-1v>EFxRCxvVv/mdjHÑcӭsTQjn_j2;5s m_bes*uy5wJ2 ofн`)' L}=FHvI}y%nw8s.w:S8bmvz60k 뙹6M.SfS.`zC;*0:07i{.B!u N? ư>FR"_&Hk: RAcG;֥9nf^bQ=dɾk >Q̀4JLhH/]#wӌ`$Qi[V[<nT0!H\D=ZiZqxMĘP5D|tD7#C!EBnwahk5R\>S2q"ܹE^z-!vFzݯT ҫȧ8xl@l@OJs O@`tnEϻ*8>:T69ӕj;O]92\ T[yu'wQuK̀n+Ԝn+Y=owlD;٧ŸK(%fJgW0hKaB%$\&Dˣ= r}r5uNG(d?́iпlNkIO==ڃ%0]D*AR C)|Q$`ws>rV":ꍉxQl8DCJ+afMy.վ6rgw3vQ;EdqyG>(fػ"L2%=>'xiKB%0⹏Q˲cR\9).^Ս@5u5{υ@#J)P   ERHYaRPu[(]+$&\Oh ca Z|&9VM\BbTg7LB8M=˼ܲ4_ ˞|Rر֫:΍,&;l6:lp1;Fkob3̫89͍bҭH;cy!hjXLE"5BTg|uwq⺵ѵ2zτu ѪotКL #E_;{ޣt: u>%F(C u!ҝSbˎS=(XZ',7{LhQ1b[=@48/<ښt'ѝ'HͳU@3wh \=K".ChV/ ^\tNꃛQ+">-]P: cmxCȤ`%K8Vf7z^=\ȟN=l J0b#JU{xp*+[ħ.@W/8AkSq-~)ЎٵZQ$mP6]~_XZ7i: ĢRiZYcmeY6o_j??g3"4 ni\Wb]%29x>$!%K}Mr ]퓃"is}щ$($8id>J7=C5OEZdPxۇqw܆m8EsH^JE$8Y4:+z ˶+,Dw0 ʬ0K (K"lvh$L5<ַʏB`}P?BWBaFbAʿ[}¿:,mӃTFGw /Ρ郞nV 70w(Ϡ;lc?ܺŇoxp8杈ޚsFS DxcLNC_{?v*faȘ$0E-!+:Խ?Y2Ep=6&M[ I| 7@$QHB̌cV3< Uh .FA&-ǎHB6O 1*(lS1֬ sظdbD y!W 8A9-FtK q DVH<%^:Vtw{6RiA6eBuH*.d .ȶǍy3Г=`kq  7EaSM";0i+ zk"}ah'f֗X Ty2׹G˥nkw&FBQa np} k}͛T]"W fzDʀ;fWa/qHt1z:ֿ$F3?1,Me^|;:a# 9@mS+R_[d+y XUk&ދ,O h1IELًq&at*X ~T 7GJ?WO>+ߟڈ\8:Qh1 EGM$?R8tׁztqLJmv)ZQj <;_"'XbU9.v,#ѩTx\ :]21-Ĵ.*~`U3qc>jnvMR`z֦}ӦS_7u*Ee.{i*@ yz% ɁVz_ V>C?*=dHtR|"lcM#+Y$:'Ji%9fv5F#.7.KvӮ7bV7ѡM:%}ؗSh~ltLR~@j6)[ojVhZ.Bm* PUW^D̞BX$(&dZ!/+̣ RhnTuǂrf]b!PXӻ)y?~N/:ҔP0YVַvbۻ8O۠ .p+~ rޓ"X/ XlJ#N)ڤ@8f R{]~}LHTv^%QICu6{g p(D>Y"sB4g:c*瀓ob&f[H4}&kg.ZpH*n̻Щ:*&ˋ-ڟMێ6 [Eӎ^zj@?1xS! f9(h 1}k% ͍$\n^T3)1ͺ/-F|[ I=Hׄ$af⍞'$% rC=Cχ.cQ^0rD%Q\|Z-mU)OOsC;A̮/om$,*J[ha@H<;0K| Ћ.Ǫ_+g*;ك Ә S "0dC{Bv}!=4 obb/凖L6#'Ztw|(L/u{w뺅ml;vd\IzSB Ђッ[E]xfc¯SCev֬K u*`8u&vrX(=G`:>NP^Iq2ښ[%%?i4DWZ$Ö_ޣ*~ sjZR7w)rڎ\p'62v ]AMĬU>|@aF +`31 Tir1O{däW=zj#A! !?-ͳ5z KZP5pIJ e>NqWz d}*Z;3g8 3k+XhWXMJAu;ұSF4٦Tc, K 7k%87%3ek7([y2Qu lVV"ڠ mV-eN\t 68Ӿ&13llۏZ~4 '(Xkx'+K7{ c+0L?X'A6NׂiׅtJHod7ɪ"SPܳEV.zi9 Eœ_(_t1lwjKEX&2pn,T!2p~4F?5xS 9Od|n4٥>&yƖ\PHPrqѳv@ĄoU#+titeV.߮wЩ7T@B"e&^VLs }%$cY$~ Kg}2x}OH\+`RK Ɖh2>ӯ't!Z~D!!9oxx(fߑO ],n$}d69]>*j7YS\PH-Gl]tQwڠlc;6 fGv~֫RkB-SMQ7w=3%4hT-95BީQS1~@ǒd0 d`]P VQq^a5ocwezb*] \b=/E'b:zuX0Ҁo3_ `=%pl,ѵcM8){;4bzN>]v3z!Sc℆ C:˨OpapCc 2̹nWO7-2~VO!1:NJ\eaiTiˆ6&MrWv{ UKfj&k.wS DD6NreUϙ}:th~ eўu,xO*eSUx dMʒc_T!pG tcr-`Si~|iEׇqr/Zbg?\u^+g#}9Jr4{0QS@'W1 0H$S4֥)yP*(`o(F۔ zF3n) i?:=w;W*AEEtC+Ud=[t}#3,)k@E}r pzWӯ6~WȠMBsߤ-٘DĂog7^ d=O$9GQ&t`Ӛ bSqScUFCkŧ(oFM?'ZRM =]sH]ypnhj])bO/yInfn^b)hLߧ.pּAh7⼲v 5G僊'NB1/lAf4(Q1EV+a$)+V̹,;a$[="j9 b-GCM| h@:~S:WDXyN!x~ DUK!u\j$, -ERfmud3Y?}RWGpaLv!tJAU ܠaP[")g*+ŷ|?N]6a Pn< 7z8~*͠@N2+z(ňՙ$<1p ܍^rp(Wo%Mf@7z_,ԡhR&x/{H%w}@FN= ;?bDEXgB\Sw_<]74CR9w[`g8ΝqA&dTf3CP 6aVf?%u w:m 5\A 0K|%tU8̼'_*jljtCu&ZYӜXG1tG@%o{↹N9[=TF<[ yfھR&EرM1!i6I cbDtqPۥ[Nc9:m嘺/NN;LC>./׍\ԹKq~u0#Hkǭ mml4wZ#nfT3+]lP_vgtK.{~Ͽoh)+Њ;gz rK~᜹H5Qa%wW^KvA=rIJ`Hg5 '7Ȟ,߬H%7RĔ+q7c˜XgbԌ8bh-FK#](oZc-5RnQzlRFcvb_5ܺčLJt"H[ˠQyQ*#Q U_-Ͽ9okW}jٙ&/};ڰ_Z` "8Z ׃#="+,wRȣn&n.I8yS~ -hh0qqY |J}h @h7圫}eFNgtik{s@V9fz~3"Aee6( LeŰ:smT|}1>4O֕%P'tyPd2TvT{DŽ@la}I /[=} 0QZPAX9m IGó12 X$9ضQ 36랕5ĤX8|hR`ߧDdx2VxsPnnO1Q뤄2|D0:l-U.N$dFԔ7pkuA(7f4Ϥ-$,i@vWH zzW4cCEe,P d- E4*1q@Oփҏn?@Ա;It8MZ/#*A%}.ȗ7L֋1ý_:~9(.3f `9>q7ޤAf7"zwhNplY>#-_^`Y*o) 9R ¯<|vڈy {*K˖/E<2747syUbg$ V<(R W~^i-uqyd= gW 1#St^Y=-ӡ+6j хUr(~8._V!@a'|t=?#8JMВ"O:j?(23M%m|xJO~XۭRC/ȹ1é2p#5[Y:bm@蚞M*g@v4u0 ) L fAe!]]+ 6^XZhw,]Y#L9򐺁IKhAC)e9$h7^t^7}D{ _, vYsҨиȎ \3XqSQ=X PYU3 %s~ ZuGpDŽFHPSvKטl&l۔wL,D5,.l4wA݄t ?ZMWUBOG2np/<ҳ.@.+SY+1&6zQC Gp >6./ /PI23V*XPꋺo?w>v OZ2MIu 1 M@e}!3Đ[-~i3G9y,$.еO6^Vs[:U|2bLhG\]Y/ʰ*:;-BM' _Hw:,AYτv/p;.C1'ҬjZܬDcʗt*{(6Uqqۭ"ފ3+_vEdyMԔUϳVl̀{*<)$uHܺXEY?B:I]oSD7,M w'p@g#/&jbDu]D5Ⱥƌ@ϬC#I bH# s]Ӣ#!gF[\,0ЧkLV)xM'"N&푠ao1\uxɰ|B޶Z٩~J{;Պ̹!XSԤA=cZo7>Mڈ 3R&IJEt E MSlu7=˷PRS-zDKmJ)Q"@ Y"0Ss刋v`.6ƽ+@^4a`cCSe bGuNXȥ2XιyK5G֧XІ!%a F AUdoy+>yVzm% C1C'se*/!CQ 9*usdl,c3&M&\k⊧U)J6:>\(0f/*mgC|4i;]VCl0Op,!E["oV[.!}'55vǡD[(ܱ%td0Oi;$ËuJ&oΑ0\H?rYB- }Q׵o?676;T~9pڳXJ,EtK"$Dp}W50;tkYoA9q/P/vw  2m 5mV=KTtk4Cۂ+qN[5 cwt$6几Q3B(-\H3h "qeÔK߾ߔv+W(^ ~NA^KK[63t![E@]4OK9G'A7n408d\[s }DV],TbGq 1 B!,Hx4J&@U998k5gB7oԀ?G$Ջ#\b~U*FCU (څ> Ҝk2~#mB0o?~bc\:vt!ٚ N/Y7: Uc@k[A|FZN9p8(_7_RI`Oٞ$J7! JbbsQčԛc.'44T H[srl؋tt6.Qz{/B]]+*`UtPoElO^#\SglLQK]˝BXR6WA,^8 M[ V.RkO-ck6r9iF3?k;I}|7v9@Ef.y[7)y؋z֪/dK!/(ڋ*w6Ȯ0 Aц{2khٳw'Wr_4G 5E{) ?`SRWZ|O}p)cE|}>}I4^m}KB$^gx$ 4].%IBEFjfB|_&bI| s^?p n$ЛaQ :XB l~֙BdқlTe}K)PC 綦B9q$"Q &> 1sAˋ1 X@ǎ;t^j}xZw(n;Th=}!GO"We{/qcfȩhDAdF$ڡ aRZ Sl92)lG0.2MottxHWlޛ;ˊq 8}0hPo㙚w9fKԙGAQ*xiorrCA9Bz ݉٘MSa_F/3O(0!rK,F U&h3xXnu~^'7oKc(dɐX- {/k'EQlk2e\Ksͬ^AoX[ O1" ϊYWbN }'0 AȤ}4Tx ?⧌?\ϩڨ{`az(/tRHwUQr!$Ka~FɌj>hxՂ:Ž|nQ2wӛЏ&>O3uIa+^Dj!P|%{u7nT" @S>w l͚c' 1?IcO붒73=siS\ax8J1hЧg ذiB-ݔ#ԡ q1Q(ܞjX3'jDXuxE9I1EBޟ|{/kK&1 [4(H.+'*)w3 ڡηDBςq!H%Qʮ =bcpLo5Ob]=#p E^3CՊ$u˴(.ow'>'̖ F4{{kt*Ɓd͟ x"fk=9=w dvlu&s7V)v;fcBljp'&@pO &'shE|n2g=44ģ5(ث%o8-mnu$;0{OAn0\pZQ+7n(#wc]#M(ΛRk!ɘBEI,^AR ɓRt9>lQmmHq\,p3=1l>0W%)9x\;RGO4iA;fiʘ Gqsނܺ>2w~ 2wUK_)ߦϲLÔtgӦWqo5 2f[ҊQ?,8 񫦽eTX^,_(63Q:Q%6% n%Q#A!WӄTݺבk'G3䰣}b7!*lgD&/B~$KOY7$W%yJxHS6iDЀr<,3: shZBNDQ\iWf:ʞ\V2CCDaajZ/0X9XXjSyF[6YŚ!.w?$!L%OhoL iq% ϟqCI^}I 1>}Ec:WTpTMXϕ(sJԥ{?2hGۜ u71]kWgڕ7~uS~< 3o48}O4Ϟ$S*QW|ᾪzcRX~zq~-;xG_  Mx(,$b{o#̾;% 5}rι64恪ˍnZ2n?B]h0&,)QÉl*x΃Ryi%j#z?x^Ü :Vߺd9ֆ D.T|_ <?g>!9򳟦''AaWŢOy95Qe>dڬV=v @~'ZPC]hi^xOIj5Q % h+ lVRMc#~{*rJH Ǘ$5&t&di_'{رM]|7|7/eaj[Dd5Ii7~N .2|Vc/QAPّAyUC$D&~9,Ϗ]Yf$uPa0OPQg 6vJ\˴9hTR6F:RQe u. 4-D~\H'4+KM?  dRDoMo_N/@j)`"Ȧc |DAbooXZ)OgBJN Ja/@j)`"Ȧc |DAbooXZ)O3ˀ7 $!Q%λSbjhxk  m*؃B6PHB됞/B:FG_S TIBuuXx|-G20<XbouVME@BTͫ%R^bܻlO)չ4sT+uqĒlA< 7q WYEթ 66ďA6vo4u TB S [YFk.~ev+S1JcD侃=H(|I&m7M]mi(#.C"}cvARN[.;%u3QoxH(;yan`v}4Ȫ;eM-K ~ $%hltC_P[g Jz|SLavNH45j^ئp $ٴO*$(c~ ΄:cx)8p"$f[dk:*-SipZasŚxBOzM$A[{a$b?sDd@^0Q6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%Mn`ǏB%M`T|D@A#H٫8i.*mMUf'ƠE荤`EcΒNH34 `[qs-rȳ ~Lbj=C1M3H"Oe 9CYR'#EYP胪)Ca?@NӪ"Bp=GCM<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@üوA݈D܉ A߉ Axu m ݹ рӀӽ ӷ ݶ ص ص Բ ϵ ո !ӧ!!!!!!!!!"3?)D;ڇ>üوA݈D܉ A߉ Axu m ݹ ӀҀҼ Ӷ ݵ ص ״ Ӳ ϵ ո !ӧ!!!!!!!!!"3?)D;ڇ>üوA݈D܉ A߉ Axu m ݹ ҀҀҼ Ӷ ݵ ص ״ Ӳ ϵ ո !ӧ!!!!!!!!!"l8mk`occccccccccc_(IoXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtjo4yy3it323OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؊يԌыїȊ̀ɃɉɂɂɆɁŠ̏̆̀ʀʀ̂Š?Ê?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؊يԌыїȊ̀ɃɉɂɂɆɁŠ̏̆̀ʀʀ̂Š?Ê?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؊يԌыїȊ̀ɃɉɂɂɆɁŠ̏̆̀ʀʀ̂Š?Ê?зѷззѷѷѷڀπЀЀЀЀЀں½ĿĿĴʿɴĮɹĺĿĴſýŠ?ҽָҶͶ˶˵˷˽ӽŠـ ЀЀππЂٽ?ڽڀЀЀЀЀπЀЀππЀЀڽĿ:ŶŶŶŶŶŶŶŶŶŶſŊĀ:ԸոԸշոոշԸԸոոĊڀ5Ѐپ??:ƸŸŸŸŸŸŸŸŸŸŸNJŀ:ββββͲββͲͲͲNJ1Š?Ê?Ê8ƀɊ7׽׽׽׾׽׽׽׽׽΀Ɋ?Ŋ-Ŋ,Ŋż Àˊ;ҀϊΊЊЊ̀ȊсՊĹ پيӫt8mk@ '046777777777777777777777777777777777777777777777777650# >! =/_9 qBaJ#`M&_O(`O(^O(_O(`O(_O(`O(`O(`O(_N(`N(_N(aM(`M(_M(^M(^L(^L(\L(\L([L(ZL(ZK(AK(+K( !J(CJ(#J(1I( jHS\;5~MrZpX$ Ƞ-/p-1}#W(I3/LYxQЀb{c(z&j𦀀M~c qk<G͗׬ 'P/5l n]3ՏT?_Uc$}EF 0"~ŤSy>6PW Fyrrȴ})a3bξKkx /Bo5LuƘ$yt0QI?ޒ䑌9`؏oSS0+Rm>`l`D-U4$ML˨`[@:s xB%lxIo?mTkl!uXF0#'j@tW2K ?+ڤ=׺GA>džJm%16xc, ii1ydq Ml' A6GnJ+Zz 7$n\O6ڄhճlp=ξLA\d\$f"M2}zT<nQk? 0T?Cl~)!4 $Hc'0P +p؝5p)k{iKqoTqMiM_lΝhTr됿XϺ8D Md8~vu8BirWT ,Sk5t?Q\;=i-3XI4+[eXk6C[ի & >0YoҞ4MtXz/WG5YuUY<߾*]>2R/w VIvaG_b*fnT t7W&@RnV,lņӿߛl9EIRD@{Y e!zn5蔺OW@i\e= U}Z&,+>%eP./b!LHpteΈJݩ Bcݎ< ͨuW??&vG s|I/̖/tg^@`0qA&t)H9mx8䳨wAP1YxqX gH֑v'A3LIG_I u>^/5 s^笌|~}%/oMJC2d-6z|ϥ Ecu2սGdzph|UL߶:^aZ ĮwpǂC 1ItQRrӹ'ϭ+/IOnd,>O,ŏ֢Miƒ [˂m>15 {SZmCc!S 9@c9!ƹ~u0]QCyN,dK"׶N%~s୺ -dsr=h@keUCG뎜cWf_КZ'wStA5ni+܂Os1z 4MQL$fFHTB6yC^r4Tj0Nzbˋm{P@-g[Q'U]nҕTk5$?]qͷ$I$( XĘe!!&Wau"΂{ $MCcaU 2Eֵ!bW'3y0K137cy*9pVHI"yqvEMgCBxqNCU ]ߒ}\Dͤ.周e;{dqq|v?4KG5zBU % wWuqK0N70yJk*4,-_(| ]KOEs8m1ۼ^_#|Kӡ+dN1ITa2!" ]ؿg[[=Ep]yWF۱pM&§RwLXȠvE=2Q/C~ɗ3 A~k:o9Ԩ?e4왲b$wB]5Q3ZdqC~,l殐SU}\&9qҎI>%>~t ~݈KDҐhPF|ĠdT{댾dz/A`~"L)?U:6*h&ҟI-?. hjvA/ϳ_P$|3+ IhؑA3MFGZk$;-Rfymq=zm;[͛dE[AA,Kg^spDh$ G z!,NH}=dt4F D;Ln-4mOLJVb69)Sf] maR੔=zggͤapxGa KmM'g{el Ϲ n;rH<(ܮw bg[*=3/mX ;!P^FDS 8UqVcq=) KXoy(^IqTo-M/$Bȹ*8_F4vtٗL?R[g"07"l=*aY{Mgb*M6VfY4Tpeh4"`^|c0  !Ahz U|,׹`_}^L`錺 6 lę+V*Qadaz_]& ]k>t͍ )ShYiP`fZ) IE)">[0"0xSbNuB1?c0HsQձqQpN]]@ S|_>~>n'ƈdؕKVKVe-L^n STBjG k21/yf( $ BB!4/14% \bٹȪqZFmꈂsxn47nxhrj[n!݀a v mt3Qr.eI;Z kADgqAC>DKn1nGG ڭwt/,}3$C9r,b8]2BSj8:[c 3=*w(y= >\8b@^凓Jފ=t?zNe#kb `}H1:r&0έ\*Ą4tʄ(-7㸔 g_w tekΜP=(f(ׅٮKL+ᑫG\B8Ʉ9g6V8NYDk˜-f`̚/'Ѐ}3{kOC7Н瀥CNpT H_TC.5&E-vQVӞ*ϯz<#5X(2,)7XvqlX}o핧] q#4-"w,EQjr=c@ͲԣZC2*nNס,=O1FApXbhY)<%5G" Vu4[ajgcTY H] N STmgc$s6$&Ģ&MC8dӯ*ֈ (|2٪l0e(]}[wܪd#2jȝ,,.G93a_x'tVFY<0\y J螓;& )&Gn +Iv{&KtսWiI1l{kIgKoF7'-4\BOkւhH4JeWlכM- hi;RBL1/dm0Zaե@&mzH&؝S+`] y^` Z[! +H'U+bad4}pIʇ2>|C ]Wu5Pu캬`QZWOٖL}~?od_)l+c"뫴NFæ胻?i$ U`#gKM<~8..: Qs/sYJ% ZA;gcA=~aۡ /`! 9$:t堵rANC&-̦֒MX ()PyYkkv2Xrv*ik2P>DU,lS[taT/jԕ_<[#+>uu9t+ awx^;f bj}&.pƨ{Z烊 :h J _ 6]VI%8-)@\)mfH,RƔ9\5V']cQTy2" Hu0,h$5֎P2xw02o=a>,L#ǿn&۰/wXU!&zU ?~BOˑ ^NpЃ#-ad%IE _6D w*2B?_1nblJj ϔ:o!6fִ 3яKV-$@h}?˥_U- ~9dtJl$Kܡa{Yc#^9!Hv&U;kw9ǶIځ,هP=ѐFa|Od'{(~O|\yB)-#-Op8P`eL%D )chC7K)kv$7& ((Y8r\<3S7mmm>U0#ثb6BqƤCӾ!uXWWU6}{6FDXM=pLeF*Eg ӡ#Zvf VpmQFصE4͇l+ z>\>;ޖn|:Vݿi(5nI9im%wsxqVfVRS1sJ Mv-^JQüwjqvE9'|jUc˥+ĦIJx]]6ߢ? 6+W^,2 ҟh>^e+BmK]sj4TLY}R},Hf.[t`x>~o+=,FTL`+Hx-V"WI#kyڻ=s}1Oờe +8\e?0q&h6^Q [=%sNyBNݍb'cMBB^8f70ߌÔ/,:au{ϰN3yl\G=,\jཻ̳εǂ)Q;3FJxϴnli)d3b;eM1݁OBIRX\i}ұ~ .4?ĵ_K0%jz|8\ *թQ#? Ƶzku ,޽KCT7o&}'ZN-ߜfZ_m4(2& {TYu67\l OS_U7Ryb!jW ~0+!\ixvJFxmE鈞/u; ܥyFF t꾆Q a1H[Ɩo-qe|LCcб7&q?HISV;(`j}s:[fsqR >,BG41д`uq/#JFF9TWܷC lhjc_~Ol Ps L `_Z2/Q@hحm`Q6,YXښ#J0Jd{.+)M{q<{* L\$u>:4F4[y10/ēލ/}Veϟԕ{!]BBB =t 9lP7c*ONi~qw4i%hGˣNP, Joa zh՞9e}YDah;|Nqq\./p=\ц6?KuKROQwˍi/?x)a 3!KAVH!Pr$ǩ bJD؞; [)h-lt9ބ7_cۉM#.cXxd`6o_^AY~3Uq{ N@ ~*Q@KjEĐ*u$*=5D_DeL/`^AR$F¤8+HٳMJ _`:Zqac<7ZϚk$OŅ+> bWN_=4E?p{ŢLX0\C*'I}?{LSdDɕyP4PYbmju!|4xt{@oIȂZ x薩X[KDxAX*4ڵ=K @x9#~w\ jAC|-yÇVja7nW ͹V X'u?ZP?uӹ§B`K 8&ֺ:m c~ZkJ!o0|mdжs i | 6]LhsF%?!| $C^YΦn PPAg #0:TW'.al* 5\$%D LcQ=Jdzbj&>;"vFi)0؈,M -EwDקOTmuMk}*u^u`?S gԕAcfAL\pÆT{rFok63Oc@XS\)}Y@GF?_ D( v`,3@OtykgPf/")\`"ZP2u HdG  hSI&l֧F'8l ijEm f"aa8e_{4Rq ^ ,y&oȮE{ϒ; d:@}zޢQFbwOeIv@*iVb?7qmaML{ӠVy;XQI@_ICb{0znmGiv+d+# h\pMSve0h -*.ntc!̼#  {h9܁=0#:y؆Hpe{Tv V<"~RxvQ;I  wfClƝxf_^t+'lpړ+JUm'D2;ͮc.J蛓"]i߆@~qK,|lEJHb1(*wuU`2΅Y[ݴ[}**i 9qQcHDs#|1a&hA͆먯H9/TW*[$cKc,jǀn~ ƍsBr}]IRL'I;R$_jjNؓDI9-Yx2w='DUF5a2dL^˩}?{9\o#,;kNO Dv͢ƫE5mQdoSmf"R2$? zâD-n5mSq~$swٸ\S`CL70+/_k#F ⢬AnL+?6]||cl{,63v&+.+Ql*g;=eG3ÓVkJhW3vȇ<2[`̗(] 8Fv;gwhTӻ%ق%yp2ո%^E9o@bm ^3ahsiA³6Ud!U(㿸ktӇVЈH\R82}Qָ˚JHCjvy("k풤慑B OQ|+@PLcxoD;ƞqf2w@*0׉>KjCUAihx@܂|_ZWj0۔il'I!F}_"I@\jCv}e)EݰOERUq(̃aGo|U|eg.:8:"D >3`!!Q))pE߁햯 t0uU*'A3>Gs!1Z@.8-`#ޗ<ܶ$A.*W0Q(y^fy[}Dha*7Y&jimJ!7Nyج{)\Pe^ (Oخ \Y昌sHz/uG4-V̻S> ֡o[ftV<&/M>ꟴ$Ts嬝I uubRPvoNa´ _ǫg-nBueIfL-ϩl@a;`vu(Ui-*(ȑ8^۶?oxɹ)hbW±QKŽMد(m$sˠu~*-{Aw`afvۜKEwL|t o\q'z?MTi2 񤆥QcHL5tv:+Oҏ%SE*:1!ٞ R2{0Kg_z,WmVCJo\RWk4uv#ah$k: L.%WwZ%U!a@@]IX/8`0+j@?őbA~ _x<~QEϯgRs$|vp`Sgaճ@?TNB^/8) -Wѻx⍤ҕ4OʘM;ڷa42ؓ#^0s\GiW#P2LzK8ˑx suet-74Z]KJ?|׉,@Y=Wxх~c+I}Ҏ#KIx-[*o)]wyN&PIPQQΠ-@kb<۾iڤf|} SjrÕ_P?hWS (͞ЙQl[1,uTL__oy [Qb; 4{ɴOO9KP# qy~I1dor=f=姕X4Rn Ӟ?$e\+6*Re!nES+GeѮaERT:fˑ*W\ rhtpG@7v):709|~hA42n}kEr{B۴ %7gQXM`:[7|uŝ2q|sOQ瘙.h($:9v9_~~[R}&al#:I|=8ތNN.^"U*+""t.T9XW5_ً[u|lLx w.8cm/g5?o\B=]o3*$=ܕL4B߳˯*yo?-3ɚT1q#w(C5-8`e㏨e(e0-xҬ6zUJ8\d5uwa6&j\Z64jg:ww|m|;fǚNX%U1ku|7|7|ku|7|7|TZ.y)Un qSiOɭmDJ]>ðds 2q-4^^^^^^^^^^WN9"uce`HKZR#b'YG]FvX(ɾD1I ʒH_ġQ:_(+yvNʣE]8< ,t$9=k2Lڄ=AF8i&^g8b$>"`ϛ>}qs0E Yp <.8d4jx8v!@S:sc|kL-ʌF罒+2\icnV Bffbitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/movr-sfil.icns000066400000000000000000002421631506470510200234740ustar00rootroot00000000000000icnsDsis32crځ߁, ֛ ߥ ҽ̣z ǵn Σͨ} ӛ廂rځ߁, ֛ ߥ ҽ̣z ǵn Σͨ} ӛ廂rځ߁, ֛ ߥ ҽ̣z ǵn Σͨ} ӛ廂s8mkil32>3?)D;ڇ>üو A݈ D܉ A߉ Axu m ͪȸ [ۢ Yj췙ނ ˣ}wjϩǂ ɓoȝ zֶ ʹricȯծͽ ™Yn 򪀙ðʁ ̦!ޯ!!!!!!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m ͪȸ [ۢ Yj췙ނ ˣ}wjϩǂ ɓoȝ zֶ ʹricȯծͽ ™Yn 򪀙ðʁ ̦!ޯ!!!!!!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m ͪȸ [ۢ ęYj췙ނ ̫}wjϩǂ ɓoȝ zֶ ͸sicȯծͽ šYn 򪀙ðʁ ̦!ޯ!!!!!!!!!"l8mk`occccccccccc_(IoXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtjo4yy3it321iOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؚߦ֦ڂԠϦٮǦڬҝ 繮P_ﰑ ˳^ #4ъϞƩ ݺ|9<<9C쯑ƨ▸Ӈ°BIQNIEAb͞ȾϣуLa_\VRKF ꮐœۅTdhomhaZTJg ʜПՄ뮧ҙظQ`Ҭc~}{tld[TP 髏ڢ̈́ܥˢY ܒsvmdZH Ȝ᧞DŽʡ봫IV.߁tk`No 誑䬜򺚡ɘ3Iz}sgX] Ú赛識՘}V[ךzo]S 娐껜ئŘW}p eؐ~scN ÜŞ?UoБxgL㨑˞򷙯ĸ檡ɐҀ:3vɧӷzhGџ嫘ǜڀѨҏр 9xz˼ࢭygƨؠځңѢێ%8{飼ݤҁۯ歛㯗$ʽ:Ŷآxmᩢ̀⽚У補趱>Ġȳ}jI毡Āછʛ䛡#鹝Ez͗xfI赠΢ӡ鮘ߚ#ĕWdв~shYBܮϦ!ϱہCrǕsg\N?%Ģ벜ໞÀ.f4[}wk_QN&ɢܪɝ T\a8Ó|qeThңʣңŀɀدЪA}GjtymbN ؤۮ̨Os{od[L ާ걝Ṛ ÿ³k~zoe\R] ⪧٨ǑҶ\lpjbZSE 氦Ǣйػ|I^ZTNFP 붧ֽŧO3DC>6ȧE,ħ⾣v˦ ܴҥ طب ʼߤ笎ʹμOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؚߦ֦ۂԠϦٰǦڭҝ 纯P`ﰑ ̴^ #5ъϞƩ ݻ}9<<9B쯑ƨ▸ӈñBIQNIEAc͞ȾϣуLa_\VRKF ꮐœۅTdhomhaZTJh ʜПՄ뮧ҙظQaҬc~}{tld[TP 髏ڢ̈́ܥ̣Y ݒsvmdZH Ȝ᧞DŽʡ뵫IV/߁tk`No 誑䬜򺚡ɘ3Jz}sgX] Ú赛識՘}W[כzo]S 娐껜ئŘW}p fؐ~scN ÜŞ?UpБxgL㨑˞򷙯ĸ檡ɐҀ:3wɧӷzhGџ嫘ǜڀѨҏр 9x{˼ࢭygƨؠځңѢێ$:}𩬟ݥӁŸڰ歚㮗$ʾ:ƶآxmᩢ̀⽚У補趲>Ġȳ}jI毡Āછʛ䛡#鹝E{͗xfI赠΢ӡ鮘ߚ#ĕWdѲ~shYBܮϦ!ϱ܁Crȕsg\N?%Ģ벜ໞ!.e4\~wk_QN&ɢܪɝ T\`8Ĕ|qeThңʣңŀɀخЪA}GjtymbN ؤۮ̧Ot{od[L ާ걝Ṛ ÿ³k~zoe\R] ⪧٨ǑҶ\lpjbZSE 氦Ǣйػ}I^ZTNFP 붧ֽŨO3DC>6ȧF,ħ⾤w˦ ܴҥ طب ʼߤ笎ʹμOeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/"$@ ˀԂ ݁܀   ؚߦ֦ۂԠϦٲǦ۰ҝ 绱Raﰑ Ͷ_ !5ъϞƩ ݼ~9<<9B쯑ƨ▸ӉñBIQNIEAc͞Ⱦϣ҄La_\VRKF ꮐœۅTdhomhaZTIh ʜПՄ뮧ҙٸQbӭc~}{tld[TP 髏ڢ̈́ܥԨZ!ݓsvmdZH Ȝ᧞DŽʡ껸IV0߁tk`No 誑䬜򺚡˦2Kz}sgX] Ú赛識՘V\؝zo]S 娐껜ئŘV}p gؒ~scN ÜŞ?UqВxgL㨑˞򷙯ĸ檡ɐҀ:3yɧӷzhGџ嫘ǜڀѨҏр 9y}˼ࢭygƨؠځңѢێ$8~𩬟ݥӁŸڰ歚㮗$9ƶآxmᩢ̀⽚У補=Šȳ}jI毡Āછʛ䛡#麫D{͘xfI赠΢ӡ鮘ߚ#ŢWeҳ~shYBܮϦ!ϷCrɗsg\N?%Ģ벜ໞÀ.f4\~wk_QN&ɢܪɝ T\a8Ǖ|qeTiңʣңŀɀذԮC~GktymbN ؤۮ̨Os{od[L ާ걝Ṛ ¾³k~zoe\R^ ⪧٨ǑҶ\lpjbZSE 氦Ǣйػ~I^ZTNFP 붧ֽŨP3DC>6ȩF,ħ⾧x˦ ܴҥ طب ʼߤ笎ʹμt8mk@ '046777777777777777777777777777777777777777777777777650# >! =/_9 qBaJ#`M&_O(`O(^O(_O(`O(_O(`O(`O(`O(_N(`N(_N(aM(`M(_M(^M(^L(^L(\L(\L([L(ZL(ZK(AK(+K( !J(CJ(#J(1I( ]˩%gv쁶#ƪH\ƮeHڎHxUEWJךx&CawD9|_ t g'zm;#j "ѥixJ)\O^S8+LY ok!0pE P@uKFM~c qk<G͗׬ Wk&FL6~^iQ`*zPL(S^g;8å=,<(KpRS[TbFoHI?F\4 Mtõ$u5!Bَmbp*c t[@ؾY]'3Z|`v:}f.+qvO\v`sD  嵐n{MG?mTkl!uXF0#'j@tW2K ?+ڤ=׺GA>džJm%16xc, ii1ydq Ml' A6GnJ+Zz 7$n\O6ڄhճlp=ξLA\d\$f"M2}zT<nᶱkt5-}5 DJ'8;:?Ǧ/^rL^dU\F=> zVZgzKZ><:*!S$-6Clz5|V F\ҩ^:=tq=h^y6;} AˎSfy*hk/.O$GQp_T% 0ّCgZw] Kz1^v; P5m!IQvl!T .@|wrt6];/6$7"Bwy_{g]*oIs}kO 6TJ<-Y#*~*_|eXsKu|Y,?*kTS]szk٢Ԡh">h-.d?n0$J^f>?qJBh(i9Z"+sHۈlucL*5| XdT^Dn8ÏHF (UM1LETPdzVv *9r>D  ]g XU]NbW@?L+_=׫eBlFqO_]FLd IK1B]jg`ow| vj{ΥƯG1 ot| /ۻ %ziB %)sxnA>.q-0<8:<';YP=Uf*B!ԋ.|Zyaiд߲4=`Xjd~>-a)(}QUeJT>n=7Oka/o?OVP_'6ʦnlۙ guϨ@wh`6jGx"kM!<;5ˁP]vHwa%ku>lȵvsM$~;STN:r> >CE}Ԝe7(b%o;&[u]xժ6Y8ޤQUKգ㸐-ʖ82s2ΐUqO2tioG_,W’r^Y9 QCyN,dK"׶N%~s୺ -dsr=h@keUCG뎜cWf_КZ'wStA5ni+܂Os1z 4MQL$fFHTB6yC^r4Tj0Nzbˋm{P@-g[Q'U]nҕTk5$?]qͷ$I$( XĘe!!&Wau"΂{ $MCcaU 2Eֵ!bW'3y0K137cy*9pVHI"cuE-A-2|UqpȄx?<8a =_yn[^#1> ^~ܦh#Q\~B( VCPa  *Pi]_b0%ǖm׶uDrܛ•Ny'5u8 ʭ7MgI0.OT'O50ui\|"8@ eHOe w Ki5{pMH!1 q"'ī3IuE%}N X}4 p;{&|KLτ_\lAMAR>2ݞ* *RVFuZ1rzt~醄\TQى6ZGOx\\Ӭ<|(o#U>L`$'Q<|(Vz;HʐQuXQl%,kq߆t;H a)uoo gք{h$ :\h&8B-Fo,)]vgOUWߏhp_fO߷L&5YhvP:m9#'nr6]>+R0=n<j̄@ wԭ l8ʽV 8)ċ3o>Kjaidz4nk6("; J_@N@M^X<`^iSl1Cp}S1Ͳp邭2ހt^^G)]1'seJ}HrG5 錨ٓph[rJxq^cr/G[$΢»E>w sG@xA#'YrSh@DwU!jXl/~rK6sty \X TUi2=/yRmOѲO4=7‡qo~W=m,l^cM^i"Ϊo}/3+9u-ZkРd5s~c YbLګDHN*TN"}bZ1yJ;@6+,c<$YJ„`ɀLFM0X{xL6JR45;-"r&vl@FȐI {UV`n:O[u V[*ùm: v`{\9c,vQU%к.]CyĐ\ROqg/Kw?Q8>ԮV5ߊfپtVa:k+!4Χ%}\a#- (-sW $}cnsv\0O'wq" XƀAzo7u,G{V8=p _{O7Y{,4y0!G~-BzvȩF~N5y~Pqs[ǝ^HHI{"~fMyFS,F\=bQ& QynDnu/M*\H ׬R֤.MMQTHɣdd!yUWg m><\.7Vu->'j| ,W8c'oδ[J!Q kX6*\*·?+t|`EEbx $7}`k41mOȔ%Ocjb4Z<ڎ DbMTqSB+*ʹ9\MaQ~k }E4$±k;2R<:kXdٳdg-fW˥Q_DϏ,l>Yj'E+ rt* u 3IOf=_3 ME,7K=e)x>Ogoz',גS& S7xz d^Gݜjq۵wbQwC\:)Q9Tm.bT즏4^-ZZ-Wc4~Jc e BafZ9bD .F-a[݊xV@v}UO@5f"+g(joShƄ{C躃exhKyfme*b &| -OM+ɻ0qGPJƴ󂖔5\If`$3f'x.LXr>x akI ȄqC y:249fk񂬋fr: I[j=;n ʌ}+i6NCaI^%|i:u_ݾ5.Eq[j/ c:4Jr zt^D޷|º"Z/ nnIwQYB.g&("]MAB廢8~8_X?\omdh=]&< {{ V VS,L#ǿn&۰/wXU!&zU ?~BOˑ ^NpЃ#-ad%IE _6D w*2B?_1nblJj ϔ:o!6fִ 3яKV-$@h}?˥_U- ~9dtJl$Kܡa{Yc#^9!Hv&U;kw9ǶIځ,هP=ѐFa|Od'{(~O|\yB)-#-Op8P`eL%D )chC7K)kv$7& ((Y8r\<3S7mmm>U0#ثb6BqƤCӾ!uXWWU6}{6FDXM=pLeF*Eg ӡ#Zvf VpmQFصE4͇l+ z>\>}üwۨI1;t m` K*o(KavzR[i5c c7vH(Quqޔm 2H6#4?e<\z@>D0A3.=-BkZs;+߶)`7VFf*$~L\;`lи_BA/5dMd(ŷDr/>S~ƛ+hu/p7SX'C_eedb|գDZJ݁Iqt& w{NTEOʰ3`[XR暒@]=Eڬw@yJPV(qn\~m}hhkQ{cLi@5A#A0<1jϐ1 ?\r7$lo06U4H5ʔZi!yVt ĀXV*aNV!JU.*BEM$p _fttD=82rOQ V&F\ɔX~@ڐ形2*"ԊwtWY*PG%?tꒂĵHZO?27M29Njau;\<|jV~n]y>懻 w@;׳W^7nt0kJcxhh&s[褺N]Z-۩4?kw/i<>O̾x53N:`47ِ`UZL*=r5ub6:I<ݗۚ&U+Z-ρws]?A@bSSE}[LԀ >WDPuPvfp @yYZ%4Hje ?"/fRmeWrObiE"!Yz碀;mx€(-+I92pJT^/iC5Ut+ĨljfQpTsJO? !ڱCؾFGNQINrm`<|QAbT~^-otluFF56BNt XYQ8$׺O7VoD~S:i#CR?G$(Ct%/ ̚*Iȵ*-oM$s˞ 7C>jUID9y|(;}7VJX5d)~PIxCp>8b=B୳U* ${\1Ax|ꐔ5*NUv\pC<Zr&x4<2/-N_H?+lP0ƤP ei+rdԍ? a+06KEt1-?q8J b1Ѧ#TnMXR3)J_ Gcuo5PCWOg!e2QM %5 {\۸||@i3'yh>y.W 4dmPoc{eRzwO/{_0YebpvLoON"`___ȴĠd21:RqEd,(>P BEs =(M#9f//%y(S߃OrГ$eeL&6OS8.!:P&yZPP63zuVNۤ5S]>1Y\ݥa_Z2/GIub5V&/kI6Bxde%wO3n<"t닞վ?L.w7iz^Ȫxd:؄i8Lud2(\Ծ?$ .!t! \v( O-,쫥>9bL-Z0u @ y<[>*`$FRܷ-~=XS%mE$P;јmSEvcZW5b/r` m{mIA~U#◣V4?iL {\A^~BWZehg(u~3Uq{ OaEIy|i yK{?z^x6-r4ˣ).k`Fn ÛĠ MWN2!R* 8 Q u=T*==$&b(X2OY 3.<9^JNh"nH6{J޼c\TdmG<53 52byT/8Tb{FJ;fw%`}<4ʁ6rtF} \K#x3՟+B(.,Wxo{fݥg?չJG)EX F:vng}(&4O>rq#rO ilaj |a5"'8DL[U# IۣH E 7L{2| 9y^uP> ՌkYczzs|1<(mGIˆsU&O#NF}ABҩǡmp[=.GdL' 9H "T ɥ:(Y8j0nSuК«3+_ K]/{yw]B5x᪜?9 1 p],8_ .%wpAo֜%$mGrmzV $tQiQi͇+_7&5^x|,䝘N?[M!XU, 5vKB\ѷ{,S;CQV^ xcQJ,->IjF&O*܍*m\_{6@o1̆c:.}RN&M'.ۅژ 휧 nаl8:7ꇞ:1Dd.2.!*Țl@~3SYwa㟕鳑I-C<s*{"aO=1}/'jQ-ʖK (>OԊw /͠rFKWH-VY7 ĺ֕r(zю 4,|t^qadƠoX|$Pݐ+pc5IPTM{UHDV >_YWT85e_+Zw?ggiAխքu?NpN#5deL2(ԁRw$"k!#ONp[%5Ҝ SG,.^/|X`, 7K7T{AzD. UUUUUUTKRhJ / [!%rI$I$I$I$>뇺55m}>2 !aմt^GpE9z%!y1YZ+O`xaH)J*/% K7A:T@fmN G/8U|"~;G2MR}naVRz4w@-">YD8Sᨛ@8M/sQIHڠo&233*Jm.{ l,"Tu WC.>~ۼ rY8h6Wh*?V־/F胠' 9Y@gF3dOȂTS5P5Y{'P3EkK320ab 2j !.>_NxZ^ RrO˅/YEؔrvB ik#Vflm Kg!ee$}?1B/_!W0KZ %'͹Qړ}5dTnotp|0V~XOneA#hꃴql{&PkenZ XRBʹՕZ!  fV`(ib_Dff`N;jE72xmNC'F@H.@%ӮX?PR1^/a\~DAC2^.acB3΄۴&W%(?QFԅ"%rOs N_sLer?5{>tN] I3P 48yЧSFL%\:'#- }Lt"x9-\eީ&n˨]$\ ($d䙿s }6ep[bݍ&܎!_`8⊋ý#a ^ {`mv]8 THܦ >u'8a *`#G6\2T>Y>%ɺ@чDGW*CKEީRS3؆apH>t ju|+2[nd- `Q sy5_1*QO|X-X s(e֒Г>N5x6O Y῍xU[H D!'Pʸ`BWByُ *+JT/x*Uœ|f9.->=n?G,2zcό4(U)Ux sηd|>OFf6bntChcj6XմIR0ג$6|P moR"D;I*Bjg B,//|k>KN(=7ѻt&[)[S(v黈(~ U;4s+m<KvSpcyNQFx XUe*PƱrEp  ~( f^4e$6);? G{OKS / ,c# C&DM$B-mki7-V(ͫľAw=7w֬]M{UE~E~Zs@a;`y;E.sN+wY!6!${ۇ/yr89Z,gaYD["dŤ&r*E`Q(uYb9i(!;:정1}`ѩ**:lYkj٠"?GuK$MiZsN-Ϡp$f:{qQZԌt^BBd,i0)rI½eOi٢[4We4 WhIhR^ :3v$O!)&!g_ 4+"z\ptnT!MZԢ[HTc7Sg, s`"J}]VQ3_viԃf@6Tos[`#QI!+)|fF1GY^@yLAhvr0'T@gQ2[WZQr!t6=h-Ha~9+|ELեHцx- Am@AH$o.تW&&W\gd .kj6΃Mmd#_ A }1A@W U*6%}R\v5Aq%eΚ.pr6`?ߦ<$*H} y^)Vh?#:uuЀ^9ϐ1o./5b ^/7A{UEYwэ3\FOoȱоi?zXճq\.xklT`r1z a =ũ8O>|F9E`]qlzݫ$`)hjPn F#'$[rJ%dCy9~^*p3Nns^֐Ġ:z<织_hbw#EvP iF3 GB-Bxx@ 8M_sNR\ c֖w6W .I#R~~oD7,٠l%YH^d{FD Rܙ̶8V{ܜHKDWY7Lmj"U5%\\Tg&dӝj#פ𔶑K sۉ.ʯ^=}S6UnMZKet4vw2QlԿ^cd!65cE1\kazL} ! Ed =Ÿ[06u,BA +KdTWM2Αg k JSrT\Խ l AP*HqĢ!XOCT'PdC< Jtik& O< p;{d*@жpX#K0K=?ҺGVF]V Yм9+ Č2%8]e'4$DɅ} ot-x8!&HA8T,+^ :q3]q>)_~~[R}&al#:I|=8ތNN.^"U*+""t.T9XW5_ً[u|lLx w.8cm/g5?o\B=]o3*$=ܕL4B߳˯*yo?-3ɚT1q#w(C5-8`e㏨e(e0-xҬ6zUJ8\d5uwa6&j\Z64jg:ww|m|;fǚNX%U1ku|7|7|ku|7|7|TZ.y)Un qSiOɭmDJ]>ðds 2q-4^^^^^^^^^^WN9"uce`HKZR#b'YG]FvX(ɾD1I ʒH_ġQ:_(+yvNʣE]8< ,t$9=k2Lڄ=AF8i&^g8b$>"`ϛ>}qs0E Yp <.8d4jx8v!@S:sc|kL-ʌF罒+2\ic099 jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 Lա6}'V/!\^#1 ʘ|T^FKi'&ba̐CJeyZB"zװU <Ob4^vž7o86¯B{NlӨ1v hPٙ1.]Ɛ.(]k&KV$ڪ333a '|FAE~A% ( |&{P+EE2r+:0"Nl¹PWإ+>2D-22tZ廆@{@޲_{+)3IbG'\.8xBG`|wns#^xƷs&:;r U5`pQ2N^.Obe.( ) ^&[ gSGHwZ՚%R2Hm)XG"s7DFIǒ*Oy1 tdH1F: ? xfƯM=~f<`M~!G)]XxbQR<JȢ!^F@Va(lvdM_1sGk*s6FL/=<xo:tT1 5ژ?@)knY:Y'6x{1kO3qÖ*OWmNlaw'!s MY;E 5vQq(??$nQWn <9$_ L<¨~Cjt? Fen)K9|,#m ojd9 #<~Q. ]K|Sf 2)WKOCP6%WLXdLaGۏmO mSm-_Ą).un!hO2vJ-!=Ms`zx9bό5vY~;wW( %ξ8g)u-r̕||RTJ2yWTu|) o2({~K* r0)|Jw{ɱEĥ)7𿐑$zFx?xjj(̴q\'N{ZZvmAxx1WCgH( q[teYO؆6rpaQct5`3U*3.;kʝ@ZBW8=W9F pR B%fh$դW9 FםZGkq.Ī񸣦\`攼"e#%e(]o@<71OxK>Zg6GլھSET\cv %_uSMf'ݢ&V0 فV~XCU Q$ר~)Ş"_"[w`z&X,ܝ5ɭ]y5KE :^!q΀Qs7bI+ lOFݑ|`>B·+T) > qAFa6,rtY\Mq~Gz=q|JxU|`mK#) B{2,0՛L)kɋ Bw^|cHIU;/0ɔF"+9Sk$>B+l#}Y ]=lӽtj7Γ2G㰂jJ12o6@1!6TߦF*N4AMؔIffHTB6yC˄h;9U4MֽY6 "{" V;O q&+I$I$&ԭT7eC;KEMCcaUɓR2 3Zk$8 wfxy ?)֘K7}E^g+?#<GpR&jewA#v/-W] 1A3LҡA Do&4$vRg G%<IpN|K ;"nzwS 8]OD<J#NI"QW%]?Δ !6-'T*B,e;08{T`8/5ӵ@B1צUhy۞'L"u0ؔ58DMl!A%s'̶R߇92L ) fΫBd/1 ?v~Oy)K(R煝);L"K:%P4IlԌ(5}M۲%M#%;z=}jQZjEL!ӏ .hg XFZ,VbHBMvmb³ l5$w>E`GqI-GOzK7,_paL:Nܬء2Ku$w)?gf!/ SFN4,Q(Bf!z&;oǖIaU7Pdh<@ы"`Z_gzZq͟UCfsG62P"P ͛J0gtoqY5|/aN0mϓU|HDzH!~t":+X&Q=c l(#zf}ek;XEf#&t@' F'GFP׸vIe+HmL &_'h0+-S~i|5:-iQοqC yB2\PI$SѨ0o ys,⑒\f+`SIJ8^齂jh8@QP'G ~P_+"T?g\#!|^&!GR;I;V|,Dʶ&z`TVˇ1lzKsMEjMnˤ_.5Q7wVNxznVO\6m0 =}<*eFZ ` 6{J>1q]&+ҩo&HzW@_mw5_j?  U5V.௟Q*R )BGz|M|9 #k&AvzW!Fb6Gǀ3՚Uu:QF\6\X@ARtÜT J YloІV;MHCe:l'ҹAcs)z뀘Ye.&IZi:̺Ev$3dɃ_UJMmٍ G`֏Ed3\wsNR@^"aHHzL+ A Q[Cst)WQOi@Ayiް_CL7S>}9Kc2W'&LRjL¾ʩ9w@ E?eCL{8شMa{Ry7NGܮ`IZ ?&h)X|%/B+ȫ;u.DEף.9W06Mө\D<^C2t Iixom2 Z͆ [(/'RP3֕ck.ڽd(??7*Wnqx/岵L@`VϪ޻97Xyb4x QJ^ =QKtH 'R[EDN]QC&9o JL!2 53r=I"iu[!%5ڏ3 NkQ Xᨵu?9obr"un5WVQo)|xut> [kf,(thk7e̢  $'%TKXӇ:N_ iVS˸ !\_TeDt@^ fL `NeS«*أ"F#vF.9D-?R˒:X^[QVg8͗1/A)ǀx?(Ǫ,v/:~5'ZE xHQ3[a?9/ f1dҹ;[:#x\I5_jfC2X  !G{,X?x ]+**yp(LlP EddRil6djr#&c9{{S HGVm%!-?|gy!v6HI-14xI\ 42 gb/oZ?܎A%l 4O[j6Wl#aAlG̀XOR ʀ~_7|mk*^T!E|6o`|7] 1.J^OJ|CB;"1c%ɶ:5tfXO,ȔF皖_=M}fSIpX6dwy\6%<2qX`>":%jw=3J_%c0`tz¨CqG%PO`Ɨ^3*;!H]_Ф3;h딼Ն}Gk&,?'t01@9b[&pOyqPhF'6X#ݸ537N2M=˘-zVNmO"A(h\d^&nێգpK}sCB0'Kٜ(2%92NIop][%?5tPCkf<zJsߝ7sҒoȁ8!WL5?~d8ch [&9dr:oKJ4 T{seH-) ]eT1tƫWh"C"& HD (NR-W BIGCE R!TN8S.uiU;#wXM@r -tk_W ψp@`#A䜖F,c9' p&]_g\htqB)faUB?c&4H ,iź`sBfl}Xm`>c*oOz_uhH[ ^׶pff텈UkrD3{OQ-4<[jaT»yb~+n} Ҙː?q (>`5o2 LGY nd w.tn*kuŒTЮi} j2xuslWIplkh ,^y:i.\;8bIS9;T#H)LKDvcjW!F{@'\f559*8>}溃jĖE$a򗔼/ Y^6$gS<+*Ul{MzN}1MTDEQjmrhC-zFf[H=IHS~ϧhFϴU(zlql67mrH+zh*QhyOj@dzIF} Ocq7H݊PS,UOv:Pܪ|Ve̕XEH~$; d\@1D"}t}04I̾?GafX:oX5i X5 NLJ09 xJiwŭlJ ^"cYm Mm}ʆs?\L_ğ>Ɂ$|tג reN&FB6R\u-;/df$gvdgЀ~m 3|-˂uO+?V!@K^;Q@'%sn8ZM؜kbT:7rTcL0)%irp Egc[ E? 6u#P18ލT^g SRjjr1Z㜢}bZ|4ZUB}!37Wy:+#BP|\We_Q y %yB@ «>˭(4l:k2!KNLu^ >W%?| 3I 4(wr_HsKy;xCڭS> Y7ykܿ7dz!d7 <лN$H^2TA|[w|;?ja 86 ։p^ꨙ?s;|+و\[G"f'K(G_jBkq] }ƽ+MoI,Og:%PD &bGFQ|jh_,"G}O_'Ύ 1Ai"?vޘӌn ݜ50ԉ "xH`D rxAv%?'"\hI<&w%KĞtTM%sHGupPRh/2-6f.֯pHzœ&/.m@&ÕO cwR^`G+cw(hg+mG=Z Fk&|bAir 9wC@RJ\:N~k3>0#F̜(0HG7hq{ $yk( B6_Nbޕ7w-e`1CZmұb\2q^w:XYʵFK+|H72"w=sHDpEd I(W%': oji9kUI_ſ`rR}GSShRd欀l&]d6wY s"SFA{g΍@D+?ŏ3:=fazyUNNpRz7ZeEfDCt5Ia֕նbnI$Z-sQ(ײ. Hp" (bg^q?Sފ3F_ 3keo0ApE,0.~?'b_a}o.Z"2=.^"rȎWL]c88hB_g ܪC1 !:^6]P5OYK{dWy,ϷѴzUPn؉BxFy:8L[#{~_ =e[E6+t?4_cyPA>:sFv([Ni+[fZjd/f 烨4i,IFr<ך= %1ș>*Ȏ;qRl{dTK&Cjz&æQ&3+J?@a-A/xSTARGϵ=d1<>Hpdg q, U'sD 3p9~4f|=wv7O·H1^ bt~>9͕])?Jn,`9 GK%SI12O&u|+I q6v K p5$ڔVR!o؀/{V_ݷPb{'`7"T`t6zL@3s2HF{FFG FOls0ޅ7JZ-.'lyH_.ȉomX#}J0d;Eme'(4onD/Y~Gh?t^9ϐ1oS.J;v';Ԕdx4)~ :h` j]x$ 3oh9hݬk(>LcR„b8#~׮u @fUt6<N,[o-r%&hWtvjB, =EC P&8xC󷷺JB%xW8E&b*]kz(UkQwAݢFn:D7Yo2՞Ȳ|xx $i/Id~YQ7j @BJKS?t޵|^2c=; %]a+o%AAۗ:iI>ZUf 58XnWԷn}_j?>IΐC-2ď" 8GM}f (kdVQ[00NƦ31d1sIg_mq%a6FV騖&F*'t@;o"IcF{l)tRVxH\7|QVwy(͔jfLHXa@325#uN2[): )>[ڷJқ9;f+ґL)աnИ+ Aw?hnU ,v_(^|7|7|7k#YȀ>t*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/Uڣ.e^4B:j\ÏY6(͡qsY/6Y %aDS U6^kΝ6] FBZ;g HuަRVgj͛->PF R`<$1l-!lT<`X{Ӱ%X?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 Nמ@"Ϫrȳ~S*(4rna0V^sK7j0Z}iS4NYjs/6v@/G,$yo.)Vei{UwAxYy9DJˍ;-_yp;2Y!PKY] n9)>ܞE$^G/pCnIы~>0Y1zUr"MUBJ=!+רx!ETрR]5zuM IYu5}_4Zz=֟< =}cU?|u>Bio2ҮuJ??aX/Z>~GΣ_U#zT+ ~ 3etF+eNtAY d{B!&_U7%"+h3u>ay瀸WI1#J_8,<Zi⟙R[3x-RM54Rosdhi·gX)CB܋! -5r?VCG.l_I`>64ӷ~QsR{gMP' i!n!DEՅLxIWL DQt\^T.IJwg>6vtQB/8)q*6ń;zuQ8o"Ѳ-K&!w ™b"y׸fO_Z!o)abj;Tr/rBa~g8y/"8Rx|L}V+Ub沖+sL  ƹ}+i!/7R/A) o!dDRp[}8#C+?25BHEd.?VH*Oj9,4OPpd56/;>c{Nfi6hq-U wUp0EVm-Ɩ@Pk{g&5v=UrȥFx(`kA鿉Z3'4=nb9@=G,㩋va(%iF=c@Reh=3h5`h"P6hch%A#<:Pf;YFzc%g.ޤpRb!u'eAS8 ,.љGe?~KSVυKw[M[$"4r0pc U0ݟmz _% 6p]/s9Ϩ LS [(f7~&vE[ @6̎z?" /LrH-|5U{.ak_7|7|8l*# }a' `u9TV^撷N?Gb vhŀ#[Ts;E7>< ܮI./a~Fs&;iM&q=@;*%F(w-RjB,75x د[eNk\}nMU +p2ZQDz䢈nQxkyp2%pɔf"`A-5,>w qDĵO@:7?[wiyV9=vRxٚmб]8{FZ6X" VyA L6bP B*B&m4Fd`3+%71b[:^SJzUE sU dN6˛LO(`ڪƦh H(lK@˧ê-[抧zBxL W7&ciVCnڤ~^˙OYhWfAHw`|\%0_!_CzA3\d26"E Q3Odˀ~rsith:PbѠ:ԐN0Q`] ⋍=L5=Z$*_E3Ƈ6ǧrn'YhDY}j&>΍1x^a/$K1;g YI.$v s%%ΐGbc RAGF=$r&uN4Ec Ue)f0JI6I-ֽZ3 l+"| Eq\\35P…ݡR왻0I o[ZI+NDhXZ j(\>}1akVH9oGJ=excs5&O*څqn _C.i6<ʣvI t9T.Q#޿ctFbKFEo;)6xzo=c$ gW45z{\S,•/="&yIW " %0=_GZ6 &BA92dYQO, Y!1v{UK4anr` .<7Styι^BqD't-1&lV^,D/cmW #˃yŮ) Rך8]'Z9T+3qbh5K0> UD 1Xi&dcο)-1DLROCxx Lok=Rw8Fڬ5< XBcC: * BR )W ǯbh\e~| u+ԦWA[7a J gHatkŗۍ0ya$ vZ]~:5k;ʴP8,X K <h5'TcPANg҄o佪]9fKeXh+vآHJ@BGiqgscm 42/ixw\+);Sڳ,($y ̓鶫 vB']e=qآ*?,s3U A3AW*S VwJ:A8n-Y0}5pF[#r'2^tY"g'+[:/}?b%` 5j,~gE?2C7{Ư<85=CDMnJ* ErGַvc-϶yDI`;Rc =3RPq$hBinFۿ!fG7ɅhjDvptBO0jԕO_= K%թ vJEX>lف #np;LAﺑ9Bg591o\AG᷻KR@Fӓ1RTM},rd`C[#ZVNĀőEm@K`wqRBvŅG WDt]s''(R+B'FFeRdKd+^&JQrcIΙlh򼡯M'/=z(l%j.WVeXNIfC?y頶7V=Y+Z'-~&&w0çd iP:D3:ЎtgiBlgl/b[:h;耹[ƱAOZΛA(窓YMw;E*Jrc=WM4P/Ҁ:7OJǭ)ҳ&z B4 6!LXHS(JAҮChV'LWp(3!V|!~ PzEao?;ixU/&p'h/Ìhh부Q-n5XȐutbsv}sI=Tkn 1))1ֈ9rRe!Sw"-,P!x!voht)BMpT SC I|o7|7|7^_>Tb(pfK"\AzHD6~boTS%! 8d9GJǒk $E:+|V,&NE R`a QY'`u0hw43=2O?Hykd'VuIϤo{A@I\HJ\Ʋ2ȣ}p-,Ew%j~;a wR;}Lod湵ָ+2g0끘Sf JĿj+'Dc`Ñ[pjGb@ǥ nO+g_j׾Rdug/W s&~%A8hZJ9͎pAD\5M}!,K ؄si5N.|mf [P}PҧsKPCJyOc_8鋛iYbk,"gC`_ vNhǜPgpPrٚvkJE;~Ft'wRG!ɥIl(|N] 0ҦdƵLv @uA9 k7@6+{YvGParN9|/O~Ob}*;X[JtSe{[N1Im wI#E >"lbGQPCm&e^:uT15Hz`u1'_fQŖ5nƶV[#R}5M);׮vmP(F_D\\e#_ Gb w"0XV8qӅo5c\+?+TYZfƝ_˅S$.'*Zu>g*iDb;),ͭjmHxgBL t\NfQ^޹uaȖ:-ӱ$0k`f˿شP8Q~V( o1]{y{1QⲼ _ O99tBkj@Y( "J4FdZk0>NC9>إЈEri֪+OD;z` Orq?y2-o 2,?GCUSsA|A,4c %h{ tI\}p:V-Ċ_!(WBɋ.ZfHOa|dž/)4֣My}$I*"T1`pK]sÊfE7;rt5f5DE"uBT#)|u.~ۋ [f7[!ɻ,OY l+v"b -ͷ/[ ~ &d@ T;^\\yyo+WpΰK9Oa ⴽ,fkOzc>Qnw;IQ_Eȿj:כw2,=Ʊ%YoYah̊Yp^+Zjz Y,[u|7|7~8@\f ;]l q3@_*G\^d~  }n-0DYRs0*a!AU7[QZnM؋P΂)1' ?w@bz_7|7BV|7|7ϣ+V^sg V|7|>1 GrNr?-FooTᙓUN</0P 1V*\Όڄ}hh,FG8 ~la $p@0M@dK_u4{{_*-k(;2КZoSBhV(<Ʀjd0ar`#[4o} ˌH7$0 z:ݢ(&3PRojF0ԺTG/PoC낇x wʒI#~wW){$Nh,A uɈ,i0eA,ngFľN 4W2D͂+=^Li ,V2Ӟ^}ۚ>kiP86|<̽ NgnCgI8Hط7ӈT?;{x0²Z)`F:>)3[PȳȈxEN 8jmdr`ƛ @-k*cu t/+ ȭFG<A\ZǥbxuKpҺU*$,/Ր /l% ІߧTI!mX#8TO5d| Q^sJ CR8yjL_[숹IЖIS 8Ϡݓ`2Q/JltshCuwV 'Vj}L0B]}3*.Wyn -K@tYPPHHQi]"TKhpkLܘƽRkWL77-@0XJO0LgY{ N`J5m}@Jr}N7 ,+BmYIwY,.l Zá4mѝӒ8b_!Wڌl%ۯzтoN3-r9#o))[a~ƛdvtePuY~1KY K+ y!b"{h~ t.k!+|z h-t{Xj(APV۳qy`};<膄^O6 W-+bs*=n:0W7r+k%H͏[-s>v;ry( \^ؒuridD _wX@o 1_,ʐK[ԃ<$D#kV92NЭ_0ⅸgNYzkbgL}>3;7B*8 qzȼ"x=SMTiu7;ei75鎦 -̇:#etK):ߦl_f\{\ 9v] )"UUpd'*W-&Q͒H v{9[REU7 1nYLi``dte 0@2F *6R`d<|KIθ@I1I\4Wf XWk tη#McFqi%O^uGG;ɯnq!oWC +XKSuhe~ËEQ.:R-k6;A|&@ZV2=~u[eR=f q%ƚomfV06 TK+j{ ٹi_Ir 4H }I@朠lm˾2@&Ț{~1BO␽fVYG\={ ȫ3 Ie1\6e+NC\e$e[MqV<5D&LФFhVYSwf\p˘x`p,\l2ӗo)@gD1ۨ߁ax^P!W7-0O,޿kULLo=\=`ya^J嶗|]-)%:@#p&MTg_B=`?;}s~oTD(2 Cp:&~3]fHPαEͅ#Z3&тǺNgB2u@Ι)M~jsXdZ3qV\/]@sUߥmYzҮ*k~5Us޽hSZ ,jV=3!qB5a([O[™b,V,^^1S I#Nƥ sk}\idqL5G/4AJ*e4Y*(5.ίaʄ ,5՞-gr:Q/a桍HK* k;ޡ8][indջ1FГE͓."0Mhozȏv9+=`PJK(DEHe2'}o&a/ \M\;w7 i^FL[ts+&HY|u<&\A?'(x=S" o(AoU$.Exuz4ۥG@pxQD'eVExLf$d ]+)VݩuqNn,1\nٹk+\]e55S<R 9 }[L9hT59,"S0m4a|GuW@V~UP>jn];oMT,bo48hyVgT.ed;b-\=#:/ L3Q}jIԫ2@ D\"$.Lo/g̗u~^`5͜&2> o߮aND뒛B4؏egX2kE֮'"dU]/ˣ0FomHF AZWTJhq)|e}N=^ zFѲNxq9Zo" /k,kLcj{sXp$D:/ .;EIsr_V},K}a5kM90yl.1'5eZ*Iv)G3$Mx\[K[pSh;cP}x:P7Q~׍Ȥc E>M [ǒgwPv"%XaR?m5+Q7,7骠y40/ ÎbWcuԵWy{G)s[pJhcrL DŽ\_a<1} ! rUMsFwC-?Oו83HBJu]JXϻxA*Ic[A9c Y`qݣo9=C.?:Tnj>kNDg[WΏV7. 򹬯o/v|^RmQIwc=E:\~tIF|e;=eJDel4=1 'rtևzb 78@ xKg|y/]gT;XNVnAiRod(b"Ԅ2Y^90GU a饈șFlw%:d[ySyX}Σ2F@TaՊp2;g{vN k<•Bk 4q7^[{}dNA J!?L;53.t[F$uG8P'SgW*/fCtxduP0<Š *R,(z wj[ӆbAo"9e8,5:)"2`AdJE,r_d_}/*pDWdzRo -&v_@E^ |@@_'NO/$FDL_ڜ3Gd ^sr}|@@z@dQ΅[3j^I%.Wˌ}|\A!!1R.[cы{7d]g`,10DŁ$ȉOoZᄌokv)5!Hq<):a;j6|a "_^jV&ɪ*, NӍ<U:X 9*`ͲOQ'm`+N ZFM9\O,c'/xQūN Hx7q zio @A:An)魕% Qʯ66!\ýB+3darsPuN=LGqUX'ܠ.o~el^7`xRHԻh/$on ˽;k{We(H7ٽxN, !l$ɖRcJIov00ΩMMuYFPVq>П5w/9B2),As}` n# ,ڿ(dEkG;HHi;Ya:@7H<Ġ$Q/F0bs"?ږK79F}eC41E"LoM̨_!rOwwFc@⾭``kwSJQ^绿B>[e/X(yn_ D͖P3*,30"6E/Ighpfl!l]meS j-Yl ًԉA](b!گ0{~24xT6 }Pw³_eȹϋ[Hԣ*!]դ%C)+|?vO P30"B'Q·SpIIK!Dk<߳\w1?J l.RFjYPrGx_W&ː2mv 'k(^VJ] *FYdxޭ2 P2ۉNȿXް]ID UG< Tj&J5~e"<ϼ! ]w|0@9K,6Ţ)Rϒ,+殺6LJ=qz0y0w|d3oͻ LT|qb6ڧDqYP`[?A{+K %ŀ ~Q QY579α;D/AEl<"sVy PwdBhגcݞt jYtTMDq( =?_*heAcM8&LJsͭ͵Fo$7v&'"dih]ral:$Q}Zۓ7kI:A((IZţuƦ=xȂQj_^ybʘ/=c2x1)J)Pg.c:S:_=XcR-ʴŸ 9Dk@-|U{ gDZb52 mO& ༯g 33=K=RL4Y(ʟ&Ws1 08xt|1zސjslAevFu9B:xb(N6}/ӕ{sЕ^p$.O~ )F2R2.+y'D1Dg|R9-U#Vib񐓊0!Dii}xWu 3<|?L!pq *`CxɨszNjnfdaƩ3"7ُ}To|!7v y=k@ػl.B:z$<7){OR8Q'nc}|qN~&6mƈ6iPOb$FLcq&`m`EzQ䖅rS?!LHN }~p}tFX3ҷ_D8P6A%D`%~#{)jၒwSj!,2#W`G7A-`˝qS*h_Yuniک tFpY q ):s' W|بNO@OH:; ŗ92(H>F-( +0 ݳ}'NߡXC+]kAٮ- 8N5҆mZ?ecOZz.%n,n֠/^Ύ%殏EV4QOB|+; 4AAո&ԣFK[1ڶQ?7jE.4xE=_"P,ozqtį28ypf]JX]Ua+g;°(>ISivͰ(aZrtyUa=M([j6ɉ8Ȁ1x/Όxfw9nCf*uA&jJ^fъ 9Һ}YEfeڀ5qlQj4if):.F'^ąJW7՝0b}Y gʖN l̍_Xo tFZ|EQE]h}sHrDz2k~{5V`vcDsY}"`upFx>x?£W \0&1;iXP;(IJꉱr4P̅_O7QKcԵIЊhSpס'O1Bؿnfv\qM̹< Õ~ 欽R8-WT7X2IC@n$)Ȱ؜Cdž"J@>9"7g3A4\($`s$,T筁4%;^㥗"g/pŷ \%@;Aퟤ͎kwK`l}YMA=,}ﱁGlпlG_l&Z6D.&0~mV@Xs-95b4m1I_YTx΍!b]B\ %?'` |P"Y-39J +t2^l!ZcRLukNo1pz1~ze[Ë~ p٬UܓYBR]؁}zXrO Z1O*ZvzpM٦u2`t/vl x+z t4&Eo&Au6.i$4p1>dNM1 -HW'z~{:ބ_᭻ԿNLg ~>wΗMi5hbձyw޸[KGrUrZ@6]RMo쀉cDۦ';kLZ" *#1YC͔&WR6V_Q+ V3_&eoMkULkR)/tlMۿVW*DB /CO7o'T*Y=&v;F,mЇ7L ֙6LOLc34$j:c>r~j $b Unf8!YH`JUʐL[B[\v,N-Ҏ蒝 @EO8R %DS.-) y Ic5Wr>9F~Bt6 &{Cj Nm=yam֜8&3wzvQgFu_wZ6juWٴ2?T)q:~!z awq^@O}լ$<]SS& ظ|_EW1laxW{>J3#4ԬKg[SÎXL?SvkX;+adufHY3u2zmCʕa~*K :eŁIyr;#FfÚ̚ggKs,IQg7ˈJF֌<MɣڒV8I3 VvasDKz"f7^}1W) XxbʜC]0YG=P`O=B{!Fk]2NW@yhr N15я `a.oI Yܪwԙ86`4)dwUN1Y<ȎdZTsI^=]dmak}~dX en|䲱Z"f? bg|v!0"rz 7 ̰]va8m゘XTlmFI@٘pIEh=UqoDd<, @͂S ϒc7 e'N_-xc~ʊwFuF;tt<v]G^ H؇/bHo[9Sn;IP||{-+O{}p l鯴H߽cQ@M zߩmrSWX|n7H5I=nv2Ao$wV2;&&;Ӹ̔jpo:s@B.kb򨤾O(rM`& 䤜#ZD*mm_ @O]4Ff]f][ g}.>Eo!(@cR]\6lmc3u8m.2Vl֓N?8U`B_q" U/[>5ueES#hG3Hh*ߣb4A6 D1ˏT sTJe0A)RTXr!W:2/++hEJ&@^wCG5|I H1ahV93v!D$VGUo/G",%IM9•WĻM#jW{KNEqݓSsb/ t 4LFTxMť(RuanIڶXu"$H^K"fܮВH{!r8urqV}%U˫P:s;C`Ӯ~$qfkT9 U jך7Xz=Y΁_~ 'aWH,{5PMPDK)UL*vz2*$*mj!KTZhcX}9\GGwDA"J7"`<[f.7wEQ!ė9\wF P8^ ҜZ ^ߐ&Eɭ|=+S`^w r7 okMB)wdN:{12+-pC 1>իC4kwZƎN=|E"e<"(Q)}œ#z&>U!'Qj+~v;pY,5_=CZߺ*MK̴ZMxQf3$N࡟ց]lWK27w86L;L$vWEJ[T4SKPadgm%]e qwE}C(QB=Uҩ~< 3o48}O4Ϟ$S*QW|ᾪzcRX~zq~-;xG_  Mx(,$b{o#̾;% 5}rι64恪ˍnZ2n?B]h0&,)QÉl*x΃Ryi%j#z?x^Ü :Vߺd9ֆ D.T|_ <?g>!9򳟦''AaWŢOy95Qe>dڬV=v @~'ZPC]hi^xOIj5Q % h+ lVRMc#~{*rJH Ǘ$5&t&di_'{رM]|7|7/eaj[Dd5Ii7~N .2|Vc/QAPّAyUC$D&~9,Ϗ]Yf$uPa0OPQg 6vJ\˴9hTR6F:RQe u. 4-D~\H'4+KM?  dRDoMo_N/@j)`"Ȧc |DAbooXZ)OgBJN Ja/@j)`"Ȧc |DAbooXZ)O3ˀ7 $!Q%λSbjhxk  m*؃B6PHB됞/B:FG_S TIBuuXx|-G20<XbouVME@BTͫ%R^bܻlO)չ4sT+uqĒlA< 7q WYEթ 66ďA6vo4u TB S [YFk.~ev+S1JcD侃=H(|I&m7M]mi(#.C"}cvARN[.;%u3QoxH(;yan`v}4Ȫ;eM-K ~ $%hltC_P[g Jz|SLavNH45j^ئp $ٴO*$(c~ ΄:cx)8p"$f[dk:*-SipZasŚxBOzM$A[{a$b?sDd@^0Q6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%Mn`ǏB%M`T|D@A#H٫8i.*mMUf'ƠE荤`EcΒNH34 `[qs-rȳ ~Lbj=C1M3H"Oe 9CYR'#EYP胪)Ca?@NӪ"Bp=GCM<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@üو A݈ D܉ A߉ Axu m.... / / 0 0 00 11 11 1 2!22!22!33!33!33!33!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m         !!!!!!!!!!"3?)D;ڇ>üو A݈ D܉ A߉ Axu m耋 ꁌ 삎       !!!!!!!!!!"l8mk`occccccccccc_(IoXtYtXtWtXtUt$titotmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtmtjo4yy3it32(OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^ ^ _ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]/"/D//"/$/@// ˀ/Ԃ 0 ݁܀ 0 0 0 0000000000001111111111111111111111111222222222222222222222222222222222222223333333333333333333333333333333OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^^_ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/D"$@ ˀԂ  ݁܀    ÁÁāāāāāŁŁƁƁƁƁƁƁƁƁǁǁǁȁȁȁɁɁɁɁɁɁɁʁʁʁʁʁʁʁʁʁʁˁˁˁˁˁˁˁ˅˅ˁˁˁˁˁˁ˅˅́́́́́́́OeOPQSǫTVӴUݤVڟWϜWƜXYZ[\ ] ^ ^^_ a bŵyz bǴ~zutqoopsx~ a~{yvwy~"]"/D"쀎$쁎@삎탎 ˀ턎Ԃ  ݁܀    񎑄񏑄񐑄򑑄򒑄򓑄򔑄󕒄󖒄󗒄t8mk@ '046777777777777777777777777777777777777777777777777650# >! =/_9 qBaJ#`M&_O(`O(^O(_O(`O(_O(`O(`O(`O(_N(`N(_N(aM(`M(_M(^M(^L(^L(\L(\L([L(ZL(ZK(AK(+K( !J(CJ(#J(1I( YXQ[iU `23/-%pd]3eV# &UyU'?Qpm=ciCI;Eץ8氠X{% 0 PO2giO"[#91Z.ld$Xh۔O+om_Y{_Y*N5K\]LgDjt,R?zf }an;#ä&ݚO3-3oZb=R>&ZϢ ˜T%[@Swf*>-WC)'I /kd:D95n< 11>G)[ ^8&mgҸUG MXnMi6q0'V˜+/ -k ;vXV0xz;Lq7 ,y2 ы ?+<][j(邮R݋;5u'urU@ P8DcqAIȠ;guU=;YXkC}76555piݎ.%&{ȴ-+ 2& d E(zU^Oٶ/HSn.>tFcP7QP'"HEPawMsՀEO_NO3Lǐ< caE);auM&}n).%+t10u0`(Q"a{1Qc8/_d(_5eȀCPe¥L4ӅS69ʾ%=p(L[Aɰ"ju?jY7{fn2 _lpS.p!/*mr`监bkWBhes>?W .8֭rJd 0?SA庻C̍l b.ўޢ(PPŤ>LK&j0?7 b~1FXel?ͯ|[-"#4ڛI#*ßrzII QmrdLQb 2U *}?b9k|FHC2mѻ4 oUZ91|K- {u6D](Ab+6܃iHϲ;yεK/'!G>kLVؗKpl¯]lŎ}F:ٗtrCŰp.jKCUDE~u  9S?sE}'wH rd8b &'{yRv?_(y* Bvy&Ց~Eܨ?SHi!zeTXd2}[pSoԎ'oZ̫( ?[,bNred}j>kfg()1n'&0i_lI.*?bxo&:٬do2I3g*13'I U5 03;#PHʠ^Q >뫤?څe?qDWD!RWyZ`aBX0q;8suR |?8*92a?q1KQ՝Rud$\xGXAUCED=?3 ªG ˭2mlFF<?qbEDE +bk<޵Z0 0Os!ĵÓ>笢BPeˤϵ -ٞ-[zv`[?ɫR*g@N >MHT\Ǧ߫U}6fC h[AwNH¡fk60h0kz[ivJ̃zhFN]}y(le@J/f#u3y(z" ZEskf߅E/X0F<5?]\+1q~}z;Q;2,޼=p{c=) l mo'/YO;{o5R[06E!a}l}A[YsA*i/)+ &ш޳y8ҀM2F ڳf(xmd \ {v9K%|9Bk?|0ħ"0UŤ\GQ2AtT–*`?8{᧖o,ZytH@s;u;@o]!؉v~JO*c; _йg/)Jo]>\w*ʐ!==}H'eo}R 0hS$]vI xӺd*RCyN,dK"׶N%~s୺ -dsr=h@keUCG뎜cWf_КZ'wStA5n@T#C}$uw=`bJ7MC-EPDl-<FdY}[HTB6yC^r4Tj0Nzbˋm{P@-g[Q'U]nҕTk5$?]qͷ$I$( Xn~޾p 4rI$RCcaU 2Eֵ!bW'3y0K17)W,r|.e'a $ `byx:)n%wxNQ(G ] /X +eN fo Sj(.R̵Ųqc aJ tw.Ut--p#*F2r| Ok1b WU1Q /Ԋ]4u! ?P(M<8I6BFVDZN=_ԻSI|ߥgP4w:!9$VJ8SȃR~3sb*>u' :|њ%m6\q󳑱2N`J(^]Jh3>AhiU";dGdd|~Vg_{3|Z|Skw~542d`?cCE}Uzō Uk℁q [ JB{t{&g{U=Am䞒fG.2%-ېy ~!- (m@ Adx'Վt0,J 3،SSRԁDi1?lk/Bt;֞{G5֞jq~4o< STX|¿3݇5_kؓ 1`_K? qC\ܠ|ӹѻgSl2@ *\R ^`IBbb{kR}$ 5F{~XI#B]Gbwu6üp>/T9]r?45^ KT(_LƕrDR;Ǎg&4j T OEZ7etx- yRЂb9BcGHuQ,yKtk#Ě!Ev-ݺ( 4hEӺxă&6V*VRܞQ$w4hH_E8 "F~9ELwXfJ@G~f7=UْwܹB\#"fHl3 6RHh7N&H>F/C@f'Lv5v@M:%peLF~̨Z@.ߑG,(s4Wiگ X8HyRxVnsAU h:ď + Ϊ2`}LLtvxM^^,ȾgxuZu!2-?lxB|nZt[[!ip,q+ rnU Sb݁ ,auwQW,l|+X!^j_'M~%60 }\n-H|0Bi$m2:ꩡ%}pA g-5l/sY,Jj 5Bӯze(DĂ]' fOBѴ 3πLS%'yUGX}^^HR `"w;=0D2&KֲJ+W?Qr+4-Qs'oQ {Xz~U?AĽd\!&'K$ݛys>p_Xh@YwKV Cd I ᦐ@ ay**).ct}fM+C'bӶ*b ]_!0@!r~ r# KH٫iլ e`) tؽ̱cVCE#eXsdmم~T^v5:*q{@v/=T @?잞3Ǘ]U1u?h3Uh"|~J4|r_zC/4>O[.T|+^;$jiC'=&ր!zbg| :hو0_(.4(usp@yV-#qϬo~G@&ee9IFc !ס]do'0g#s #,%|G¹qIb5=Lzq\ۂRz, ЫBwT"v{<]\`j1Y餼?귷WVB $j|IkQtHZwxsC1]lF֍Veݔfּ- Fw9EL=sUC/=-AaO"kb΃qQIt Ǹ5QǗ}qS?6TTlΙFX]wˈ`ZlP*4Et3[֌/= YvuwӞ Lz#QwN"Ķ S5L "ئ Gm"yԷa#lPP_724d+)'X-Mr漆IۭyDI\;cB&n:B3h ; B s񔊢.n "4 =ݡw.mNnC!͉02Ш qV"hsTROL$n9[U"M}ŻR~wR-Ys ٩1ADM Fco*.S@[ 2ʝDQvuvh0~v9⎸_$# O`R;Gɏ~6M`^gBL/ʫ2}>!e2#9ϡǫy5NpЃx=͸Ş^J/y1/5:@0X}wz+FauAu!QUSC*{o\3kmpͯLApԔaכ>%?˥_U- ~9dtJl$Kܡa{Yc#^9!Hv&U;kw9ǶIځ,ه B:uĺ0**RI#ߔ$xI&R[GYEu1 EArZ5Iq XE j2kAoC9Ub3T bZMy6mml%PP0#ثb6BqƤCӾ!uXWWU6}{6FDXM=pLeF巔eq8S=Oӳ dՂxq_ Y^tKn? ۨҿ\z 3woM #ѧ𪿅WL2d$?&KhC2֠Y*Q;-bnZ4>,A oU~ &;0pFVYkdK46J aC4Z+F!@cBGMp.oi0K{*0EW831jwS˧ksDE%cG lύsDd"ZJ U}\<2oLldV9NǛ.X4-zo]5A6T#S v `}Um*3Ѵ* G ںs ;,!.Ƭ+Rf;C>S ڌ+)*)o g.&E~|b}ͫM!=h 5J`iМ>g\"7CL YӆRlp9l s@F ,y goOٱ,[-^dživϤqH?.J^gu?nm"Pi"$y"?:dLĬ>^NH z&L(5NfwTZPcۺ+ԣl0?`?Z Z@|o W [U4\dvMBZ/^;yx]81^r :`r$X@mɹ1n" @.0D!+AޙWLgar,UmQBð*L^= :{dT$Ŗ`zGVxՃ'z+zhfFwajY^rċxJAk00XcY)ᨛ>~[V/:%`Տ&+kY(\*QqI:҈c{0CgSVre455zM+WyȀpXUrd3 .ʈAlCAFR۟1a&cE~t %Ӑ!I% (+FqpBOF&̮D4ר?޿JNhŸBa\ws)q*Q꟔ig>\W9;JƍKIxJKè!\>V[7{8k0`X˷#Ʌ#"Q r:˚Vt5-:4E꜏ʈ@qY L %}3X%s9)Hb|cNr4փ)(({2Sʽ$q ܱ{iCpv.4B(+yU^Cf"tIEuG"O:,SR]gڪ]Ia'z)V)\-~XN0ۣ lTo- E~{}7/?Hmo; #J9LM$jzY!kpSiAb%;)4MM F'nSSFz۩4|I[ "̶@x2 Ndh`'wBzDža7plrquqO_&l (Tj/$g茱${ IN*𢓻6t햰 .6ص諭S q2[ò9cRm;cR6]=jڶ ,$n)ky2c+OҜ S(fs;` w]# '̥o;nɪ:S |F{a } UUUUTdTLܺ"Q(J %vt]5UBݨh:I82pjj` \>jF(>='Sb\/O*v?KKP=\SP xq6E{Zo)ZefܷOv`'qWYIL}tc+DK \ };p]YH Mi#/Ö6zb *ED3PVhWhΖ;z H7ڲLq{;2MӅ%I# p Сg7q巊֝aIDQ(D(KY*0T,̳b,V3a!,f}i$a:o@3USTV*mݻ6^EN$  *&Xa)KH8Ḛ̇9``ov\TH5a ك;ۿcK&A$WuLI4V#ɤ(I+wٞ`:C!-1À"H\kH-`Uv\civڅ&ƩcaMjgV?#xD~ Ǖȯt`aF偤0].*0H} \j9?jԫ4UCHG\c<=V{,ڲZU/OV_}'ׂ,$!߷fTͲyPN1Y]/Y|h#"A'd':n'rit &6 ԕ Ű.CLTyY^t7?s.08{%ŝzåͭ@kg PWrjꄃxb ֮W5d\Cjtg4~)/=.*;k t.Bef5jC4')}lԮ ꗸX@,A<`|w:, dkrRw'2xB´NYU{rsN{IU8D}WքIι"ɩ`4Pp+NwmPêF|mNGO^-g)f s.I֓ ,] !i^'|PmfgB2C?u_!YE[ɼ.kw̞OHMAn4k8&B1ٻ~-@`]Ϋ 4%A'ɗjb@ՌBO%T=FJۯ/ѹ JOA)Fω'S^lkFqO\:9[An9ut"gpmo{4}xDzD}G%9".䝳./S#[Ý)اQ6v`ҕ)C+0I]b%[d>لn:2ҋ? ]0D]HSl(smgLt7M2,--bv$MJ^IaƇ :Yn'ZJb9.Cc#Th0^ \Y83S]/#8ʀN6665Ǧxߧ0W,|\BA_cr7-KX2]zߏYTG;*j8 GKI G J?R9=kFY=kSRN*-Y)BCX60ȠZ-%uhz@7z&IF.YaI?}c PWjO3zg2(֜KW7!G" •~<+D'}H=ѼYeֲq5uZeq k}AF V~^?jP1D-0[a濓o;˻ݨ @OyGvBsƶ^,4@Oj{+57A~\@->ND+t(ٯ,^CC2}`F ه [1[0ME]np25,PŸ5ihE}դ]p2#A^2g@!Zc"Y^I6hwz`Eq)J\{ tq]ƿ;1`6eW`ی ?eK}=q-dwcʟzcޡUҤC's(h*8IL= a=w/qgKDɕ0znANJ43P(6mr_֞mVxU#凒P U(3nPGA;E3upoH79(K- 2}r(TЊք1h@2P^XA>눈D]54zyfg(yxllfPOF &N}$Wi5YcnjP[/BT1D '⦔6w ZQ:AKi]wGʤYjtZ|g3Uۃoэ.=xn~M;$t -j3jɲK;/`$Ͷ&K:G<ǭ@6 y3nro..@"b@ r ւo`FYĕ@IF@܇vybtew&{QZ. %9 A:a!$l`Z>n>g+Uk ğBPiXăr0~r>_*0Am8B_N԰N|e8T UZ@0c;1 O$}`8D啚>:*XJ&@a ȷ L nTcfyڽrJ0jɸ)FeFFHa_ ݜtq_3ֱ@a ӏQZlP>?! p[N $c;ʆ?G:C p H H @=X!mK5C˞sXAI(fQssQZ)աÄghnbdاQ6v`ҕ)C*,yCRxm󕅨wKBVt(]UM\ ;ַ{Jw*G$J\tALS!W:NJN6665Ǧxߧ0W,|\BA.j ڏC@a֫D4OQB9'f&oEРUUUZ CI;>\iN+rW._*V.2m|;S$3˸8fˌ+ȷ(H EUPz74w>_igN_k;Sg78.IyQUR:bV][KJd \?lk+mW1[:ZiE 'J+=llяY DURh ԊX)v¥s Y+3Ar‡ ~?q#, MI*/ ƕBxHK gg%tnA d hNlAFӥuЀa!*zЅ 6GMĂGwy^[L30WFHWʙՏe6*]F_W5p珢 =}qG;V_ ҤO4u UY5>'Ӄ=X:eE:)PZWѡufa1@U RQ,ē-}] n!Sԁh Fi5¥!!/TY;9T k+?9 I7ꥆy|w"%NJN6665Ǧxߧ0W,|\BA_c ~D=$%uQ1/O㬀L%H@y8M1ygb\t`Z|._*V02?S4|Kn܄ MUݡ=W+i?<~[_R)l&:|=8ތNN.^"U*+""t.T9XW5_ً[u|lLx w.8cm/g5?o\B=]o3*$=ܕL4B߳˯*yo?-3ɚT1q#w(C5-8`eRn.ZJ_ڗ;ְYU+uN|7&KQƔMW2[.tՂ.T;fǚNX%U1ku|7|7|kv;;^^^^^^^^IEǙ҆ P;pG֦ 7Kޞw>ðds 2q-4^^^^^^^^^^WN9"uce`HKZR#<4a[04#Xo $a\'>|ٞ O+/Z6[4CحooFkh}&rR?C `"R M 4E0AL8`aB/0߄vʲW0ZuDJR#c o=4354OK(-‘dAbo]ؑ֋@ y6&^_4TX zE q y5&{Q,L@qob423iZq&,՞|#USW#dů7}>r/T[f(VRSlW:}KA+2!x xfN0Tق.EfnP;# +3Jy'pKF~{t!'roY(8`ATb/hŨގP}qs0E Yp ԿLYv!@S:scj>X" $Y/Ys/sic09{ jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 BՒ@rpF$|g_.jNk@p"*64*CDBwPcc;VDݑqo)  fRB~]qg&\yf !]Ducv2hfᔻ{i`c>6jL ?wv-PubGByM`fIDWl X)K] G k3*p[}/Riax䒖j9.eW:xGygvO#2D-22tZ廆@{@޲_{+)3IbG'\.8xBG`|wns#^xƷs&:;r U5`pQ2N^.Obe.( ) ^&[ g͏ÇP.;Dr&O)"8L)픟B'!eqv y:{]>%<9@Ov!,e_uI1KQ{H#=NQԚy?G ?|o+ jPF~Ej8F L09pBZK5[3bn%!X*Qf--FpREt")/ &;H]89fUoz@"/[k4#4ceU4'ܽry? D/d߁o"OTv?Bb4\!Ҡ*/S}ɑ{~0yޚwx,)RxB[KN9H4PNAy q˸T?Bq q)$"2f^;@'%9' "SE #/_dCIڒ@[Rc]T @nT Qzs ?:䁓|uG31YJfuL?p~ \d.ܞ@//6?Gz ?&!=Ac)%q[E$<\IfGA$@ݒz40`}]j¡G/'ilg3Iu.VtoEP8xE"<ɤjfAA$VS,'eb$v}9Jճ40FUNF-$mb'~Q~|MnX$x|+iș9q/Fkɿ׷9 Wca$I#']#OkiM8䳫R[iw}G޷Ȗ \&qN ),cfG?@A[>y B\%D0 WvY)TiM^Xܐ/L*6M,N8_Q]MPCm}SP1{)|Fa*ڈa.abцb'k&8`^? w·Fts<D >vBI^4[JɈ.VgrjɃk`'d%De W1rq>:k_i^`=:l R@vi(-aϐ߭g%nR.k }GtנG@j&^@;$b(_QMo>׼`y}߽ @V\_/Wl0ߐ[EKDm)H--[|-PENgڭ"JKL}#RIO] !mGZDDSdk 4Ytη~Ѽ@?0<  ;"?+?xL"#M?":{`qq(~AtEO8ۊم:4Gy_I5bjGLm!%%k* 6h+Xdw{caYPz6>N6g-/煕JEt(PmBw W^=UH{Ql1tWiuujLk]!?moK2[NU^2R!^ڝuU973ȧz r˩3.DDjҰ\xnVp]@LNfR) 5u5`[j[hCq[pUĚCR=#:1T&;cCv/j@lr"xI3tmBSYCqzqp^w_jxJk72Xd HG}1ek7 %uI_P -Y+98Lxd:kDq+ZOj_A`jQaȇHۓWs%~D+=̫b&Ytܺ`~mtTOe:M8KjRM{7: q01O^pEN'|@ Hޙ. xzbmePVU/ 7k 8.O#.Mۮ䒋Sߝ5B+l#}Y ]=lӽtj7Γ2G㰂jJ12o6@1!6TߦF*N4AMؔIffHTB6yC˄h;9U4MֽY6 "{" V;O q&+I$I$&ԭT7eC;KEMCcaUɓR2 3Zk$8 wfxy ?)֘K7}E^g+},%Lc陔 *WyjXuڠZ0548{,}YK(bp:28&:j!ECk86CC#UůA( *]hØH ԥ:R0aEb)_IJ _MZ8_Ԑ Λ8 :)NA}A4a-ZR{e0 >v"o3vgZ'LM3^­Q x!DޙRKE>iuI^߳3 ! KòiM%[كYOa5 #} ~.-4GUbu,m흋,$1Oq LCцlfFR73aqO]oT~/Q72LC'8'49`a4xPO4)ehR}d;E IgP/\MX3;:#}{/J (dSkj.xUE~0bsPaj!3%dB:SVadDx!l`Uxe##=fLgZ;w >tR:r{XQO9C>{i^K/Ib5W_t1 bGPV-דU- CA 'D/Hs^⍜/SFUJ,{E ^Zp/Zgs<ƋIIEW"n?0?p|]"I})5:d;P'O+Vb!n$u2ƣ$8R^&^a 23!2D@KJ(-`Z |"z>kʨZ %MNu ?`f~һHyUi&LO-"*w<^ 6@}xY|SzI6~YCݾn=sGHHn3)<(-Px]/ mysN`3GPHNvuB{#tF=aik~ 9ϝal@FL %ʢ¡_5$ߠ)Hݩ}ȂE|l;$7UCUUU[EBSNqȅyyaP򆱋&z:G(2l%0iDt9}]a]xbQp*si%1tN`ZQ@ KP7Q`ΛپmT,ѾB[Ѫ -CƚFe4G 9Й $y71~?Ń4og_:I}lx]Hcb;C袐{@.B=Npë( : i.7e=E#>*7Uq|cFăgͻ*wÀBQvg0(ʋ덷VIVlg-ԟ<$~ZZO%<',JLQ`BX֌ǪP밆pB톜)4QJ_6",{40 Ƅ%^Gq.&lMDldsaK{h~T5Tb<(Z=/\Mk lgCTynĺuXV5Pj^pJ2+3] PpuQ,/rke$Vɳp3&f@pByGOlD`~8WZK OUU|S=4u 9F^^זă.+DR|3}#݈>:B9S8cOt?G|;bMf;G>$)1  YKsu*܋qy&dlsqaz-e\fQ/f]ON1\GD]k6,<[dZ73% ^EzytYr/6jz{r}q<llJᧈٜ*6l,W(Dx[?)Ia%;[1$T/ Sbg:q¸'@ϯ ό{xϣFgA^m=J6‚Fj-'zC695^z fLdblXS)J^P.BRh?nNTDNC)d1Jtpa}\K]]R5@B '7 ꃵsRHn%< a b  ) AQz]Wn4k;,<x.vT*͋)Wш'cZs%|9T$S[kQX$D ZG7TT3јy2J q1L@ƗRKL_/@k:Ka ^z~&+b&|`&Iew^ J!&㌟%JmvK'p~TJukw;:9Kt<#9lQ2 s+|5iY=qbU<`ŘF/֏U ZB?eRiAM)rYGE5]`g5OZU7 XD ;v!."0 YQH 6oF,{(yҖeԊ@OVm%ĉ=^읥NnvTS* 'o:eJ*I>} tew ̽^$=8u ~3Q?<^#*)pVECeFܯ0@~q-EYm?e mm(gr}3眝Y'CQӴɹǰڬqsd)Խ;BMs$ݿ|G^&ȔA(I WeAw KMc>2%[gyG]5Zǣ2tU8zo='st%"::z`p,q{Ȅ\f.2Z(ȧ(;-i}A?M(ǑD 傲s[{xwhReS gA (kWyFl8{4/`سuP<ŚR/#X-G\eސ?ƉgЀ]ˎw:{#NF߆Oo=o/h+?L_C q|\V1brCC8c*xkB&Msط@bWP ,PxBJM E|3s dUGc<ʫ!3dس:86LF0 c#4Kx}*Eյ7=Z9:E=MF@Pm~ '=\p̿F%7)߅R`uF7^g(z@ )JQ=TWod/MޱQ}|CoЪ8jtkڕ!v'Ҕ&W?i6,?Bޱǎ}kpXL^F)K 65$Ξrq Sa(4lrkp˜ @|̆y -Wé@8e >3`xkf ք:f{~LWF.ghPB_qf7o;^x},Dʶ&z`TVˇ1lzKsMEjMnˤ_.5Q7wVNxznVO\6m0 =}<*eFZ ` 6{J>1q]&+ҩo&Hv%:>7Sëlct- Tz<`p+$ AH39L`b?j.m= Z&,s~5)?r 3szhwj@|I.2qu(!iNNB{{D\TxŅۼ ͻqgRpԵ} R1Ûub,wA|7|7|ߊ!8tK Ydzlzv}B ǷX%Xah{ 25Ee=mE)o4~wH a_}Ubh^1o4I@d ~+T[psߨ!=1)X81Q}مtHZ[0Y fq1B;i$7[Dn2 O`${ 8Ҵ O]o}-:E7t:e;l5eæj;(wRjwd-FPQkS1{CBu?Ⱥ ori@+qBP$Oz|]7Ha0i?{tJ%1I@8C 6~Hh'O;Kq W #08j=/dbFζhL= Fh5vV<֙jUo@YK}fRzk涳uF+-WY/?ׁvLa-^]<xԺBD^Ж*Vu~q||)IC{a_}5 vp ')hɎ t+Nܑ*sA 3TnفoǨ >fq|4UNSlg:A+tTlZWMx6 +\։3R./~P|J^ 6Jqy!Wª,|0Տy-cpv_yhU`KiրE5|rz )%3xޮ?7PC E ݆C=v%YƦ1cax(-6!31FDCS\*|:O6N0򙂘$1Mewe Du dvf 6xL?@n$4PXؚQHɈw=Hv g}WC=L:SqWjx>7:gXwf|tщZ oJ7?|If|jPLWl}OP o]c+ϥ.:bPz9 oQ \SpZ/vWNV + 'd,U%;TW#+ T,.aY1Ϻֽ4M΍eZvpPrc񻚯vgR1*JqxbNY;M0:f e;L,\O[T `C/zg)CBoB4VA1RrfuIUEۜ~ 8C. U^K{f76m`~@2 +,3/kZȯJx3c` nh*ok,\6V$#ϼ=r}+7Y! Yx)н%>ɎnAވ98 \0VE%fg,9j|0MDŴO0VÒ9 㾥Dߥ:1$K-woK[1SصD^vM>}>nX7r(@K(cφQ? m]i[u{iO=bFz0fMB]iX2ch#z̄wqEIlDvF+krKsp2hThԴMnuH{Vo܌6]@jC5رyƵն!˚3z1W>M(ՆZEm5aI`@E6;Z^|r20=WδKD:&jܭ tv } I0R0NԸZI^ X6"\߶X69CJN!$E6BkqYʁ-Hʐ+0AΠ oT=&`-ewv9pOY[gthz29z >& P"jOl.W&6􍹴qs"-s@8f>aAB@mV -x2ۥ~޳,ma@; $s薞tQg4X6kI4 1hJ+q 5hVā娹r8peSGQ7J~2&\,5̢ߜP#r/]RIkJPMwxV[U-{甛=Ss!uL Rk;mw!OQdqRZj:;T[ooO0tMff4ZC\|w',/Fg d?BtaSy혺\7{ ASPNb0$ MUR+AWy9 e! I: o49[pǰ/X$9JipY§ R0&g DDq KD\g4KJ-6b~Eo-AeM*ۜG A|l@a ]P`Ҭ7KrG)3QEp U i,h=,M%H)̰ocZgvi3;7 m~U?ǰZ'$!⢶]Qw/pH"*k?,X:=IC3[{6Pb3?"Ԙd &bCȰG9 _ ƞ\;S/pѡ4ҡz⑞Vr|gM$Y-صZT Ϻ}rN[Q&/<!½wWtRlk\ ~i,0x2wwJ:y<@~'2W Qgi+9 E1Jos@+3Hry2TIF9~. |i^Cs3=ʯ!mTB hƤ"2Ւ3+Dv4 t;ll KQv!kU+Tŭzav`RdIY~!0ɼpt!םd䦘Eȍ+J*],Jt4V-'{ڋ8Ah=qJ.r$_I,b>> vinKbk4 XS-Sm-ppBCVl^𳭜'P|bBp&`RAiA T.aD'7&?"A`B`96yQC@7.a8YE*GIJN6665Ǧxߧ0W,|\BA_YBn |c]g֩d)i\g4WbҪ?0 /Wyo ~$ZlpQ(nMUf^84 aTP!*9UVMAu?0AHmYCNAL+{Ģg@8k څa(PtfTt=FׁbTWCG]ֿ]d2xyya+gT "3YaI?,(Z=8ٻY-t0%$MPklC\^M.c…%O2{=~Մqv'8<~v`>)^5] H% r~dh--6ܭL}Aۨwwa}A{n?hgm}\i#Dl/;d'.L܄!d(5>_uѪgQR:EZ= 5vWZOmV;7RDbA6%h."4_y뱬i9Cd߶_L "͏-^+鑰,Vk+eEvȇZ_Aʜ'] "ālwŃWL[up>dC-B䉝6p8%iUml/}cC[vKGA$Th@ rM]>?g!%"*h o N,>s544gM-KxHyT;?ttCc7&O UE۴WdP [GȜ,0{o(t3{U^N4MZ0KЧV9< ;QX(vxudHg" NP53r+gS(e3%UM3Yj3unVC:c# r]-W<.!?&eB=ZRj/(rw]Z%2lKj,;G1%TL=Z_"Ik մVߞB1<(N<35I+b^M;c)NvJ̏?qɂ3ZnA=gIvJ_AC1x7w rf9ߋ3J(IV6dcaࣛW"xh1UX`>?ճiGGo5J>bc7`e ykT<&w %Q[)d{DҠ?1ykQ=^Z~u% ⇂A)߹j{P-LdP0)o( R hYnLz/9nOU <`e@BL¡ߧxGuڰ8)ou X" ZI6/^  EVM >/a",\n?)wHK=ߑ6 wJK³/ ( 0]t&)=BW I:ž:pY\{݀SۆIh̅/=<$pM:I!K.H<&}u>ա4ڎjVrikHkS2x2e.D]=6(I Bp3֩C9GDJhlb xH`x"򞳴&o%VP0X\,) 󘓝,e@9KBԂ+o5nlN7-*ʯ^Oa%~$%87)a åsgl.a Z3$֡\اQ6v`ҕ)r MGHQ1"3Fs`ۀjz-3tl͘#xʁ+-aă$SxD 9z͵IVVVO#mWf[+{ޜ0bmtA 6 ^NU$ nƏ=I cH{6\"V{e}ZefQ(-$J%w z|{w00fYM|} Eup $j…k !iL$UaK?{ $)f3$F9M.Oe"l7CPoEk$IҺy# fK(_K5];7xhr.XzbӎN'xW@ ,r,RG}\ڥK}Q*ўzY䚡kEhi[J\" 3tUmh|a|D{zW@&PvUJ~굂&!8S7#M{JN۰kܵEE^9BK+)auėb&0f @0>% ̹`jOFāU'U(#>q@ \[{G_OsRT/s#$~^*oy#&y0/iHC^\׺q"63.,3EshVUUU+$!41Uj fAƨ y8l&S=;IΐC-2ď" 8GM}f (kdVQ[00NƦ31d1sIg_mq%a6FV騖&F*'t@;o"IcF{l)tRVxH\7|QVwy(͔jfLHXa@325#uN2[): )>[ڷJқ9;f+ґL)աnИ+ Aw?hnU ,v_(^|7|7|7k#YȀ>t*wR@&)P $! FִnS<ۏšOZMq䲮? v$ B00 SX#3vy O+*ὊN". Z%dX}TNq^>&up 2_7|7|7Ɯ޼ _C/Uڣ.e^4B:j\ÏY6(͡qsY/6Y %aDS U6^kΝ6] FBZ;g HuަRVgj͛->PF R`<$1l-!lT<`X{Ӱ%X?&nABUSG^mX dx )Ce AQq7E@`'\>Gi Gv m0=-+ϡ9N $窾t-nǭ85 Nמ@"Ϫrȳ~S*(4rna0V^sK7j0Z}iS4NYjs/6v@/G,$yo.)Vei{UwAxYy9DJˍ;-_yp;2Y!PKY] n9)>ܞE$^G/pCnIы~>0Y1zUr"MUBJ=!+רx!ETрR]//\lm>ﵾmd_h 7ϡۦGS!t_kBx;þJh Jm=i ~{_LtFaX z}D UdFh/#z6(&FDMH38h?ʄҬ2b!7ޔ}AayR"Fp]bJF c` 'jQ8,>})r/` ڏTVR"lCYeG űAVq y>kXT-,&VERB64ӷ;nh,7Z[c"=D0mj>Lʔ\yqsQ"X2/nV/i1])j1M(,Bg8BK&KkC•Ӭ&5ח `\ۃf9`v3 N.?xF8M|3kMsbO,/epX伈K3OUp[\p!G{<0Co1OUPR'FYG]) o!dzrD3)əF#e(/u8!bnIRu9Z,h v-j{\7h!L''rt[-yH:#aΏh=+o[LRΨ89ߔ]k<4Y&kRxI(T-Wi@!c[Vf"9OzvYhTqA#V'Nn$Ju3!o>9/ zu~x*UwC& |/b1ڀ#8lA(j;},Q 2t& ?Fn+>8N xHg̕;WL'YpxYɒSF6_$âHƑJ\BD|/1LO jě5p~构,oyCq=IshzZInh|(̘'O_^z=Q#M z?" /LrH6(/L8CWT)[y:[Kium.մW8}o 7=LkK^R򗔼-N˥iwHB8/kQ FQ_s:[Kium.մ!.zV얁*fj֤mFp] C? YA(>7Ŭ=)5 Ln]e@J2`v _PG CY/w+JWr *Ã+yU$(MbW-.0o5׿3ֺ$\ T' %q%_̵  $֐ѐ78e'bUQbuV][Kium.մ-#'/¬= p D&uf'[ium.մIӸP߿X걻0 i]6$0]wgt$a򗔼/)yHq u&T·?̇7ܩ)yIe1ڬS>.nR;Y~@yi9*s47%nwK,䂫EiKwVS8 g3.=KSh3xv#zY\N]Ww5XrCt_#b%  68@h'fe0#Oc *~_Gg%48YQL 1Y"oo#\yAؔhj~Ml-G&S־>zB$Cwp; ÜOs->kE[:u-"SYM\E 1<13xZ S 2%v0䵌5 m[mpm Unξo],x10>c\0es7؊)sUD_hڦF ux B Wۑ d|: .;hx͐}lkV][Kbhl{n]]YX_P˫iuo~J0-TuU꫏4eQLL˻9E/&t( WEZ# Z5>jTK8X jĹ5(,bn\)}|kڧp4u8@FiKpi.C6?4H,5IAnexMr`RjREwf{(E>*@\b;:))l֏|Rl\3'$)0[%MU_S7Viw4p s`fO 2`oXfy>!!A 㚒n#'kX1YVTgǁ4p s`fO 2`OX@UzC,&4DFaXHS^}ѱŭoaSvS?qQ)03EW)wU dƒ'S(}ڳkV5ГU5k<'=˚i/K؊"|Է7fѲ L(N>iz᪎MeOX߲B*,H?@'aVeITŁw e@)ofVǃhM>g%d!}%~t^<&Y4"zl=!Đ+sWQZFBi @F؆JƿpΛ/M?J$k?X='Y'D$w"; l(@)s&mR#5{|ٳ8tc1`rpTCe~M"i{Q.遯 D/+֚Yq$NӚN@+dtR+DS/ẛ5^E#5$ؘ:[f8q!oazvs@ zUt߷~<a/,%KRE~^EŸ3>-JwwCA1Ue;X]#I]i1$[#[ܻg,~5KO|Ʒ"5=z1tIУ dP)=`ޡlǑ3$XAw("^` sbeپqkF>int71L^MzC=>8ަ5[\ӏk)Lv.+I;Ě8 24<]71VYaf|/*a@RA.m;Y$Q V1W1+I%Y1 ?Kv/&}㪲u/@4}33(U%P([(r Kȯ9ƈVaw!Wh Wv~D@Bի\r92XQk$\B6+* _f:'UÚgxkmGf Ҁ amiyxYôI7Xf Ӌqg*K`W>N3-8.v]?PۿT `ʰ} /? .=q~TFvF-)!"yH0Z d:2TX4H'##БZSy;܌[@0Kth]A !oaILMc3&vZf86~ߪN\q[mK~ɫ7 E9IOc *~_Gg 1\zdjK2rǻn՜'ҺyB^~":[S(ߜC~Rʃ '-kuM 0 bA>1#gj>pOhKTnxSkTZM܂!t|8T~\ua9u{RKcFZЭ+f`r86,W^m4 b `-JN666-qn9'B*c:]Hc'z7EŬu$} tE&46%3Dqs2ޕћ\^\"Ig?fS_4,y(mtLN\'c JhDfވDcD.B/j7JUs"]GX Qׯk0{k{f/;5%7Up‡"3"lE FS+9`2irx;TYEC;Ay ^v۟H }(ڡM.[䕑4U!A' ToCwc VhOŗC4T[^@ܮW+?[ ֳױuY{(TOE|cIݽæv6O$eܴGRU!:= FJPIlqeÕ1UIvCv2kQ{70U] ?)Z+= |+6 ˚;Ƽ01/w_i=nP@'Ѻj+C %SW[$zhpW C*-jow s; L(~L_Ṃ[p^6t`$N}whdP@P}Y B#|7 09Gw|؈},HFĐD- pJ"Mxm$% $#,a!/ B1EPgQZFNYG3@l3+ . ư愻a{spZJX>AtΚo%M/݅ _t]fH[tb#TOB01$ߐ jkg Cr Q(`M/PtoUV* R qI`:v;1[:ZXWZR>"`<0x"4!LRD:f766Ւ3G$L?Uɕ|COٰF!2P~^$xwa'ilr-ߋ /dLYv?W-AeiūEb;cW`4``U1 w tj=PcNW8) Gq" V"#euN ?."{,MmYzeyq0KmܬD^q4Zۂl%#pi3-*|877vk '+ oiHMr@%DT+=a\dEнm=DϩVb,}>П5w/9B2),AswdND w,ܯX.=] VSHHi;Ya:@7 `E#r14>%HwmJw*^*9(1w|"AKXk٩4|KVJ}V([ԢMZ*8$o}uqqo@;8'n a)NpuS03YJoި]mOc Að˱!ɧW)+i+ y)q$IjU>/+[oKa0BbZu* r.p?.T+0Qx2@$&ZdY? 7R3Ds(p#,sU:Q9" >}t%^Ft YYm BԻ γBpW-JN666-qn+b(l̶8eÙp\9`Ԅ/WEV=$63\tNigYa[=Z>8ğZJ 7Lf  p < }^^uձR`t9Ux "B1DMh؉G̍gz(gM)g7JSvjg*]-K"l\8HAFylh=*I_W!~ Cڝ_i2k |?h|G}7zw})O_G!&f~'_P-Ѱ举cRM 0q66gۏp&x͜tFp2t9 נ`/&NqR2F@rPda8@gxթfL+Tp!iǐRO?ԡx(n^?З% Hj]zR Z<_~ WVxK0io&*q11U-aP81KR{A1YN,$M=Ea x\m{4|DCDi!4G>Kmn 9b坟/hזUtkwr*5w!Ɍ[N\CS^0dJDNޓY# OeQ`҃_rz`1op\9eØ5#ԂxwwB /x#02x.LM&S3{=k݂BlKˡFT(5yZǃI_@0]>CkhGܠ&j& .»Eu΍eSvq|pD4"'bJ210k!r?^4!$Pm^Zɺ{+Kϗ>#V&6 ŏ2@mӱ!Lv:T|Gq(m))NNqRͧ%a|K{ Y@8zNqR3M}Z  h‰ CDi!4Hh$4FfF_F .x*1Xɺ^z@S ވ)9_ *8 o1e@/#Ii8.z%yn(~KPfՂح&nMIѰ#Q ~Ym? (YHYgI hz i%nqc_&MʥBX,mvd6@nfip:#Eۧg"Q(\VeÙp\9Rȯֽv%? D1ȋ€=7X1o#\;dnC6u>B|;Q#JC~*xpyZw0VąPT8 #z/AΚݰ=o˅M޴N`413$; kyy~,bKF0WԜޣP*߇.H n+T]G( ST<&#v 90?O0G3+9Us$%l0 #Na!'8# a!$`a!#0=P3-dB_Y $%O@a!.f|HHa!# a!c #y$% P54WmK QJ><0jo }/Tz#9 \Ą.n]sNqfżbi@o&]+ôxA9s4Nqfżar#Z1BʀN666-qn+r1=|*O[~rq:_ӯlQs=>zr~}w7 /} ~rO_ >@0 8WNKyuMiz8T䫅yQh7OO| 0$$4z8^V7I (扯 Tρ,@.@H26A[ נ`uNqfCͻ?rPliʲO/7˔z+3U(ވ,̎o ǵ^ tf.1}qdYE')jiok Oۤj28 քmZ:7y,ff c88%dzFhdYZ<_~ WVxK0io&*q11U-aP81KR{A1YNqfCÝ1\S ?,AM% X TvaU QhS|%IJbYX:C!hX1/ƬZm4qN`sZYmL #uh1B/ 3e rk S*'sypH r@%Cɚ)]+ÕU%<`,@m"m6_/>5 Nqf {ʀN666-qn+V[(`_fFFQ{[kt>^3 x~< 3o48}O4Ϟ$S*QW|ᾪzcRX~zq~-;xG_  Mx(,$b{o#̾;% 5}rι64恪ˍnZ2n?B]h0&,)QÉl*x΃Ryi%j#z?x^Ü :Vߺd9ֆ D.T|_ <?g>!9򳟦''AaWŢOy95Qe>dڬV=v @~'ZPC]hi^xOIj5Q % h+ lVRMc#~{*rJH Ǘ$5&t&di_'{رM]|7|7/eaj[Dd5Ii7~N .2|Vc/QAPّAyUC$D&~9,Ϗ]Yf$uPa0OPQg 6vJ\˴9hTR6F:RQe u. 4-D~\H'4+KM?  dRDoMo_N/@j)`"Ȧc |DAbooXZ)OgBJN Ja/@j)`"Ȧc |DAbooXZ)O3ˀ7 $!Q%λSbjhxk  m*؃B6PHB됞/B:FG_S TIBuuXx|-G20<XbouVME@BTͫ%R^bܻlO)չ4sT+uqĒlA< 7q WYEթ 66ďA6vo4u TB S [YFk.~ev+S1JcD侃=H(|I&m7M]mi(#.C"}cvARN[.;%u3QoxH(;yan`v}4Ȫ;eM-K ~ $%hltC_P[g Jz|SLavNH45j^ئp $ٴO*$(c~ ΄:cx)8p"$f[dk:*-SipZasŚxBOzM$A[{a$b?sDd@^0Q6yؾ ]lh e(uu)&vߝϲYTm:艊niY@Y,JWi =Y]80V}ƕU):#Nw508BB@tkަwix'>:#Nw508BB@tkަwix'> ̈BsK ]Mb!^dP!TQƜd?4&coH%MK'_ :A-M Ĵyށ/:&uyc UD7d6͑%Mn`ǏB%M`T|D@A#H٫8i.*mMUf'ƠE荤`EcΒNH34 `[qs-rȳ ~Lbj=C1M3H"Oe 9CYR'#EYP胪)Ca?@NӪ"Bp=GCM<s`,o)FZ3ZRvatth#H'ѣҺl\*Qt=zw`}+WG@T|$|9E\,(XTQRbYbEɠsV͢͞+ {K".V9=e][k!xD0!9ʗ8\1J@>N)'qsܡwVWK5y+CEt")ٺ64, Am l2MtgZE{S2L f7 I{]cTXUldLtPAf wm1jٯU5_һ́aJ M;tZ:Ē7`FqW2QI$3$Kw zy Z jߠF+B sx2ސuyI-xG۴[x@:x%ZVF #PKQ6CPK4WR3com/kreative/ual/eawt/OldApplicationAdapter$1.classVk[W~AW6+" HE V㥔zk(6n,ݘ݀^[^j@?yZ1>ćsvCe;Ι=o {qD>1 eTWƫ$/'eTᔌ8#u!  26 ӳ8'$Ceač $%)G%e4bԍKxK;ƻP%"!*!&UീK0.aA9<WM t2tƴ*UKsucD\{cj t:] }F3l i:HMGxrDIPXFqUdމ[6Zc4z:Cu^~R$IGM 2M-ّKi6e]6R(wlvz`RQ =7LMք)hOA;&L!(TbS9IJV ] + D3"RpF¬ưs!+ߓ븡&n1.)V6 ⎂!Csl*^J#||J*1ٶ&O>/𥂯p_  *xG  Si!nPRx,ݓRPRǬ*P8$ז;o~\^ XeiD7-@E]"ߴVl`,b&wV@Z3\?䩹ǹ]:M}՛wmآ':oTpdR&jd*.l zŲJ˴ C X.5g`zs/ x- [0xjjđ׎T? ~kCŏFQ;ptTuOe뷶y4f2 a]+|)TKGZ Q4!FNh+@?ʊ}Oҵ;%AytW0 A{9zlil*:M1&=t2:L#Fg%d֦e )!D@#YZ sOc$D&~ pV_$Am_="#0m4\ʐKaS =r牊8/M{ OD~G@G̓ƞ .R*S=!З8D[Zu[A5:PK"xox.K PK4WR4com/kreative/ual/eawt/NewApplicationAdapter$11.classTn@=qBҸ@HUUR(HTHJ \Yªe]PhI%GmO987P% w$f^(%G9"ƑQX=EM70eXk8RU?t ,Ѱp -,²P&Ca MB sTQ "#dpwz6|C5n!@?؅tW9]c_8>:}KxXUb˨`r>PKRA[PK4WR3com/kreative/ual/eawt/NewApplicationAdapter$6.classTkOQ=-mW[@@k(F%$MJ5VHxvnKn#W4&(ӂn7ٹ7s93;{2ŒcfCc.y(00$$ans]txql&}l-0F[C4W ajĐ-VͺBmq]$ ]4jaw4C3l'Bzf̚`5CZh><[he9UJmQ:>q A9[̎ZNDG&itC^+b\w1fY(vbNT@ިꦥ;5I*c 2"8s2FpMu7qaEm_^NJVBJn;ʞR?zwBF w^̐@պd݌ Ʉ'o'[A݄J\a_gHIRCRG$mdi^h7 =a H/81+R <ޒ}GdE\5˸ T!tyBo< PKckPK4WR4com/kreative/ual/eawt/NewApplicationAdapter$12.classTnQ=(+۵P+Xk eA4iH&? ܔmw2! ƹ +Mvfwf̙/xB +Z6abwL$qw6o`@z&|"dp0Dm{)m_va ݣ}WhXCt"{ wڼFǞ6C0bBo-uOF)zox'KEW}_ꝧ:6T !Nň ш|鶴CFIn C0_^Kx&ɿtJ߹ y21iZ^^uzN;S0t3DLw>"vsgH;!O~&&q CFWrcKPK6PK4WR4com/kreative/ual/eawt/NewApplicationAdapter$10.classSO`~mRY"N Ƅ&MdviL$DM72^;(ٚ7hOCN.%{*X}4$H,KSC=ξ*Oe^@AW }O3GլCVǏTȣKG[~lV8aD3r,^*q@NiwpإFl^g`ΐt&`>ךH)\∩bR4 W<``OO܁ƹ/Z%S.ry wÞv?6I^/i,+[Xw5kiˬkn8F=A#~_P!y9J_QyϨp 3 7quy>v +vPK㿬8*PK4WR3com/kreative/ual/eawt/NewApplicationAdapter$4.classSmkP~nZkW6o[_ B}&9viӤ4i?Kp ($m*m <99_p4x 2UA2ϗ}*t([r 9 vwƧ 逼ңkfN8[~hH΀t 4uc1{5[v9[B'MٺycRR.#y5~%( 1q8N\p#eH$+wq漙YΉDl,(5z<ڷUT4TqaY kH`wS53阆5`p C}kf,ιwM32SST <= 6(P*|f1fz`o_|r|z%4`Z-\憉&f2tֶ =!y$3owdO)#]R6RcbY~%P)'ԃd0WءM |#ٗqFӹ* un'vhg4Q\BF*1%d.|| sz 6X( #Q߆\Qe˨hη49@M7Bǽ}y>Yq~4RCU^(^+P֘w֛_Ugfkg6= 8VkNo([E9Z#~}.->nר待E _WF'qf|cw fq}6p&glO*PKk cPK4WR3com/kreative/ual/eawt/NewApplicationAdapter$9.classS]o0=Nfm`PA`i-+@H4ĤOGlS%n N&"rm_s|_a(ksB&,bB+S]L2L xt|=~U{B}v 9cga Hp'4rOoz"(ڼR_)Kw,䅚*a[0{f@3LMT3@HE])E81C%IH$Y~|ͱ_Z7Iڑ }y!T7lڨa\1F QLXmlӑ&6fp*0FG ń!7DRPé5LRjca(B s{Rg\msh.VR#;Ͱ2#%[ci5UkkY$VXӗ־|Ӟw/f/5sv~ν`,ܢ֨w44EUhP|*>t8| Tq"O]㸊OSRxh(wUs*>a-s_/ܫ>~<ye|ECqWU|M==Z|SqRCRz<T|[v<Oa7<{,:⌊譖Qq ״װP f 1c ux6,MشC1œn, afm׆i$nkf&a:P<EߑiP(Y7P,ߧ`ѽubdft )zPBO  rg,j5_H= 34@åsᶰk.t6Gc (X.5ܡ*̠6tt[:"F|N?Ut!]m1#T:ЮbL t,fod(8 !71OTTg&؇x?ⴘ0f2{/NvK"sQWVVX52qwnu8WpAx18ϼ:o>3\AA0~#02otbm3\AMF~#Ba2S(_83n7t :oTV{;: ]dn:.T觇 *O̪l fzᓇԋkRM'ULiW{(&iC/Q~-\hRtÍQ%˧ɵVN[)I*PN; )Es,1XfsH1kT*i/y?$:ih{gS҂dbl$ 1~A:- GLK& ( ԂYHrj+fG *je)tζpsoS[[֎]A))4AZ w56hH_Y dC㲓J|=DP9 (Fn%FEg\@zƐ?Kv*Sj5>Dc7P<%cȩxb~T{y j+C O??HkȫEJ$ 䳠}_2 TT@(,X$TX"K` \` RV j`uiTz,(s܀-Zz\&|I`!EB7bQ܌H( y`4LVq\xw܇?~RROr- RWPQ5]Zz'6(4{u}˲$> >QhE W^rj}x,gcT$Yƨ3'd!a1֓qFYU~ʓȥ*^RM3Ŝ2jq5Ig^ELbhcdC<&ms[s%DZA&kD},1 $:YS!F?MEAS $S%ŐGxm<)M5O5%;+r nHb)Lv TT>5'Ut8][)|:u0@1.N cvstQ.O ^_^뫽~ׯ2_hPK|PK4WR1com/kreative/ual/eawt/OldApplicationAdapter.classVkWW0HDGEAQCҚBԂFQ|ɕ8~o/kiEk]/ZQ]gΌÝɹ{sν;u"0'5pC2̇q+(0Dы2ya,D=B~|L>ƒe)L(TICĴJa唆2Rꡣ \VQH)㱛-l`h/ZSyv3hX5bRZ`X(s/(GcH .Jݢj+ʚ1 T'f@$؎Ŝ}~e䍶cZn nJQl$OҘ'Qa,­U(e,LPO\ p{NMO,m_TU;q2v6!yyt浨"IY&3<RK ʙ3 tO.AE`zYYn#ȱ? gZ0訥;R{d[ PHX?Bao!_c-'Q-@4WH,5r 4N5\kXE;Ca=#?𷓚#;hm>5"~?7dP=l$aGAH}cH8}دc/Fu`!Ґ\G\:/uPFDždH!FQG:vc'+lӣov eV^05Tgх˴bsC>9GhSA>;}ޤyZ>ȇh!n,O1])ue =P fp1MC5'r y6B56wle5<7PKjЬ PK4WR3com/kreative/ual/eawt/NewApplicationAdapter$3.classSOP=* B 1d! H,A?/Pxk251~2޾`֤s)&Qe<ֱXA1KUSS҈K3 +#>?IOI9{D7G"H:>-1xEЏg k7;$!HEw)mGI|~kMXP=P{b$EC3ɖ]3;<~Gq 7/~ ]vJeuO"fi5M;XyUPKBkW>PK4WR4com/kreative/ual/eawt/NewApplicationAdapter$13.classR]kA=d6Vkk\KХ!$VCɴ۝ew6_ ""_ŻAAaf=3sϝ~ !Lc7d,要FAn2psi'9qϵByKk1yP:1Ԟ~Pn0T:* + #1}8y;I"p-UyEzPD$nD*/T ܵ] ui>*\܈w<I4Uh2ҽH 7+O>bzq,NijLd 4d^~="RcՎ7N{gSa^JChQ%*`F׽c{ZF-F" (>]}1?叨ToQyUK %&Р22\'B`c5Zo4 ]PKUPK4WR5com/kreative/ual/eawt/OldApplicationAdapter$1$1.classRn@=8u u[n-zC B"U*TP=4nv-&?QqBd=:3sf?~~Y[nc)r;! \:+1Tj9 $՘ґ)ɷ>=NQh1nN. Oe=QFSn 6'ehاkFol9|9R^٭Q&MF#;*3z*k<mm' \cQl߱CƾB[ͯhF$FЗ& f:7f PK0qIPK4WR3com/kreative/ual/eawt/NewApplicationAdapter$8.classSmOA~oGKAhLhRCM{pkwDqJ%Vٛg?..la',FBłE3x%)XƊUC]ŰT==nSi5Dx"uk5\`Ȗ Uo[' ]KDq鸎Mvm_:#_1̱#*gH :8"8u,Y0 dz\"dq""Sj5"2?lNȖPaӠaJxsq^ O"S xF2FW=Nri֏M(>iVFr B P W(9'HN4]tYCqJ)֑ AP܅ z(l[/7_\ Md Hz4&iz Z:n7OUOΕ+g`3$H~$m^+B+R*9 \8A/)\Hp0Kaw5ڦ0@K $lyF~o);FIɞ'4dsc爐VdES燳q<_E&!O#̈́|=+$+Dʬ˖C/pES%Jȃ*2D֕P+rլQAPKx KPK4WR!com/apple/eawt/QuitStrategy.classRoP.-t*:ӹi*>A- &ZIRhg%h4{2e29}=~ iXSp(PͦBMx(## CXnM}°l:ÁaBUV8Cʐ-3asYb6 Q:3i,XsrѠvϧ)nzP#6|;T>KB pxMqS?`H[^?hD\_2A4HC5FmJ<[y: 7SQĖ{XPAVEYeA Iu[ӧĶzGs}{<^/wVhgTZ4awsϗF@G}A'M9EOįJA,EU|NW)K孥3>_&Kd/H^H~C$ )qq0A0-Y`{+ԑZ\0,c%PKUےPK4WR-com/apple/eawt/AppEvent$FullScreenEvent.classuJ@Vk+  R-T7z.I7!IRP/|JMu/vg|{ϷwҐB5$ֳȢN(ҷcI?]u׽$5!vU Z™42s[9{3ayhb锋gsBTmYTKBg+y3 ++{JZS$;vԞ𼫙T~ԨCGCUȝihq3uȗR9XRRo;"d@"$-e 4FlYc '..\:bIa 7A,|1>?Չy\){4cQyFOuCdLb9,ce:gH8-ێS6Z1gl"JƖQ^Z>q^:kRd9(йej\UHB8s꼖 c*!Zb;MhcW|9!k$FrHI"nPKFZPK4WR-com/apple/eawt/AppEvent$PrintFilesEvent.classuP]KA=ciZ=ZaD`R/ 11.3z z#A̜s_N [ 5+j,3+J?q\a Ůg>QꤊҺ!ߏCu(NganDS']jvZѥTQ,I.B x$Q"E?e{7Fje4?YZSMPK/PK4WR%com/apple/eawt/ApplicationEvent.classun@!nJЄ ,$\n a+gR\DC!fX;;3;~ 1]YEwUAb%>ʼnW^#0A'T#Jv*4ḏ@<huN(0;@q/2~4I 䈻Oi,j]S_%Ow47hρ/4~NEDU%/v=&dfbf-ȼ5Fiw'P秤#F KհA4%O/UJ ,2톧Z( aȸ6r =ރ8Cs|#F&\Yw-[V=t.l1]a >Y;g❰op>@,x3WW1wΛ,{p6XR{9b%o/PKsPK4WR'com/apple/eawt/AppEvent$QuitEvent.classuAK@ߴMBcb[DA= Q"oVݐIGI'{'Slcaa0v\kU\;m@74ye|ʆ"ghNAn0ՆŌG5+%lSZMzQUWK6E-U!b.2UU%g^}{ѾsL:/saOaP"qh]'&;a*[džh NPKh,IPK4WR!com/apple/eawt/QuitResponse.classMA 0Dh %܊ cJKջJLplL c{0Zi3lJ j˄EvGwo}ׄ!XVyv74l@(S%8LM=PKܪPK4WR'com/apple/eawt/PreferencesHandler.classNA Ⱥ( G&=Z0;Y<<qYcbm|m=nb+Bơd:`cS1잴=aγb+%})лpI_OF3 Vn" jGAJ̇\rJkB_E 4p M5pY6ZƁPK&MPK4WR(com/apple/eawt/AppEvent$AboutEvent.classuO=K@}swI0& `#ja 'bߜSvCvs.+'-}3lbaaJ8n nq~IB[2PU~sm (OLjwA8m_NZj!&,2Su]qgogm}OHpW9v dǁ(FCQD \/9$r9@6%؅M~PKDKPK4WR!com/apple/eawt/AboutHandler.class A Eo|JNqQ ~\ew(qFɅܛzGف O(SHpYDŽLkGJFGvgG!@`y0,z_ +OǓbB.6(YF򂄒z+{?Pe^E)BQ dm!ck HPKM*)PK4WR.com/apple/eawt/AppEvent$SystemSleepEvent.classu?K@]wQ8- "HT8hs&d?`CVf~|}|8N!& ǵV&>. tCҺF&WeGL[ݜӣ0JG&o延s}FHmk EU]-6'Oj"!$Le2zi?٫k Hȿ(Yujs,{rD>FD}CDt]юxI{,m`K3uk7PKp MOWPK4WR*com/apple/eawt/AppEvent$OpenURIEvent.classuPJ@=KjczV[͇6gEP}[YI7![ Gx Μ3g]l(`v~[@jv}eDɈDŽ麼< ȡ" JZ@="3URf2{LUo2Ιݷɑ8'~[R2Ssfӱh}PK3NhBPK4WR(com/apple/eawt/SystemSleepListener.classPN@}b't14P}i&X [ >"C$fg{3"PTO_3pͥPhiկsKBsX={CdnMQXl?Ի];uZ1ͦwVWPJy!xÔ&3 {'ۯH:rA jkuBM@dTw J017PKPK4WR0com/apple/eawt/AppEvent$AppForegroundEvent.classuOK@ߴM1 oK"HP/jvt7&sy<P$M0͏} vctя0CxvZ9;y]膐fJ*WE~smtuA螜^fLjwjA !݂i˲^ΞZ%@L-jʲ1jX:~r6df P޳'3Pnɲ>C JA$2D@m p_iP 5cq PK=:[PK4WR'com/apple/eawt/ApplicationAdapter.classMO@gA(Cz1!~Q4ܷK`۔-.O&(@M}}fv;?_p:dAK} B u =1غrdP5Ļ`jĭ )W. -7P N y4)OKas%\y3Gza5=IEA{H%83A%R*41sc勱dz qہrRp3(m?MHXy]oG7mJpO 93l 7vk65?ڌbPдh(4EG_vwZ02@3(B8ڦ7:rP)/(_I`5Z:XH`1IDp7,%Y؋/PKvN_rPK4WR'com/apple/eawt/FullScreenListener.classJ1ձѱե ׮DZ . RRbft|6>%Er$璏Ϸw78TU(t ǕA(ə>3~{g 0I_2ǚM]يڰpT-(-ֱ% t%oН?яSN^}TtV8 iE X/"BMY/t{ByJ4PK9lPK4WR%com/apple/eawt/OpenFilesHandler.classK AAFH$I4N^|7 {E)8~4 #'PKtFPAPK4WR*com/apple/eawt/AppForegroundListener.classKAƿgfR]x ;U(F}\,;y菊!|0},ܡP8R8&$y5]ʳ-TIh?$>{}5 ݇Gbl>3-->{4_" L#Mnr`%4 ZdΡ~eBp[PړW*A V!h >NPCPKȳPK4WR.com/apple/eawt/AppEvent$UserSessionEvent.classuAK@ߴM1 C`. Ra%݄ݤ.O?Jx0occ10G9Z[+M tGHʸFPe~KmtsEON 0׆ZByj?u}aӜ?J0YULu&sHsv>O$_̌a9vɽ=9WL=DݖXԓ ak1m׎q PKň9fWPK4WRcom/apple/eawt/AppEvent.class[SA{-E * FIPY%SJ MrZfS{g?eB*,)odgS`o`L&oݑ@!]ZcTrXsD:]GDXaSh]AvOYD3]߫ 32X ˡ7R-.Pt$vO}vTvɾM7 z'ٖ/:ze[A}P.,4,'qĖGXm w^| }T Dg7udxFoXEIaV)<*Gn3 l*;iQ'T>DkƲdDa5K͐QR%Yp{mpMƒ-c,Cv9ų&nYSË/)a)_&ݜ:7#Yh`|`+I8-G9j2Fwk/ rt[}3:b"S92MN3,!ϓs"9O^"d+]%Ku?PKgFlPK4WR(com/apple/eawt/ScreenSleepListener.classAKBA5uijnU-tQV" Iq myykGEקHB||~裭PWTh!ɘ`ǖ9UhZq1/Pv5!p ]nE|YU+6Z r*8aZ'3Bnu$a׈fưM ;?מ*gcxah6l"~gN%w!Pv5PK#ʼSPK4WR(com/apple/eawt/FullScreenUtilities.classMK@mDkU z0xPR)~m2Ȗd$wy<Ql ,҅fygOWkn^]Fieo'Ф$Ѝ*S gJJf>:lDZ`OLrn0xqJ2M\JKՌjGZRVe**/Z E3_kko){޻xx@ ߯>6@sJ]w~PKlPK4WR com/apple/eawt/Application.classVWWFЄ!R @,V#MޤC[ўQ=wfI&/gƼ}7 _fMM`A=5dkV!= kQ6Z:(#V\mua8+nՠҠ/-+j=Mc:nCKikZ05 Y/ǜHtI r [ȪpH2_|0~ +UY6hQgPU6T1x5wZI9buY m)]:2gJӽ4aԨ([Jb:pȦ3p^&䖰 :!d0%9D&6ɏu>o\֎)91[4cl٢n[A^q!'BזU7IJhPþ0e+/mG.jrh'V YkpN}cDZ{ph 컲oҮ[ >~؉`ԸKm[tӵ {=ZJN{OTf֩fCD5vW#9%5FD܈OQDEFg3=ElsBjaQ^uErp:x/_R$Weڣt ) t5c_Kӑetӝ2E= i.2wTyg窍7-Ϯ 4- o{n|ZM>LG-Vp/f)fڴ&MgҘt\o7kɠCx.ca9C8 4L2%gZT$=+xl_x׻x6-փ}'(=9K2o*pgm{{z=== vXJ$/`<(wHBo)O*Brʨz|GIIHn;T$wܧ*n.ɝUrU܁$wNPq$Y}W聒5J<U'c0O"K~U m+t%H1 UBYDO3 !"Tfxv"͘P FB¾3J:Ҿ6'ǩSQSuwB7, =t|*͉8xW#-\j8u?US̀FZnnJ?NPz{WVQSjga<ED2 7>&R{Jt#aYiOehܹS? zrh*cO9.pcc`+>k^3 RƩiM^=1G4ۗg-eG,_LYa-PKEPK4WR(com/apple/eawt/UserSessionListener.classOKBAUseeY:n%Z .D"O^owkCEWAIhqY᜙g*T.lE } 6l=:~lcGGaMƬ|xKx}yz,B0IYoQ̄s9] ձK=8'JM 7_Bh@BA(\(J8D+[KPpgFPK%PK4WR&com/apple/eawt/FullScreenAdapter.classJ@)`1x xM%݄$m}-/|J-Blԋݙϯ8ž *[Ur'm? ځG0(zLi/utBnD-ԘOϝ)Dx5Em_1͞>9$g 9zzcʨzH#/*Y(CFS~0\*G%<W#9EQ8Y*,P6K=t#rʬP8p+H4xy\4[OQ/ ^y#0M&:!۝y3XޝPdoj-ԿPK,EPK4WR%com/apple/eawt/AppEventListener.class;o>CNv6vvvFҢT̜TFQǂײԼԼ"IJDF\ĂT}te  9yIY% `Ғ}l L@ ,@PK'9~PK4WR(com/apple/eawt/AppReOpenedListener.class;o>CAvnvv^FĂTԼv~FGkYj^ #g^^jsNbqqj1#Or~>PcN~jby>P X ^k0FҢT̜TF $%>%@H/+,A Tt@$'e&'50M  :AR6FF& f"# #  &؁4PAPKrIpPK4WR#com/apple/eawt/OpenURIHandler.class;Qx]3QBqV_k"{o ?Q ̜w&s( 8Y,t$'&O? #;2VAN*k5KVPv}\ 83oRZ1Dbf"(*ɶ&3|d0CY8Hb6,BH"Ov!CoסTD1/!U.5"#Wdˆ& BV KۧmJlI-6pTeHs"H-NxMQЙm{췤KbHt( JvͽkͺcKyK! ~k~+7Jxc97h-ahŏC,sN$iZSȢ49$tq?-Ply.Yq'0w{;{ ӿPD %bs #;v0oH$,xBʉZfDMb!`PKo HPK4WR.com/apple/eawt/AppEvent$PreferencesEvent.classuAK@ߴM1 C`^ A6nnR'??JD<{7oxp} FVEg!ii\La?T]0H'& of`ll׺⋪ZO_JE@H2QUUpN~[~f&g E3cئraeroOΕ8/SthnJw("~b;E[SvoPK PWPK4WR&com/apple/eawt/AppHiddenListener.classOK@ߴۦmPES)--z q~~(4Hcv~o?/)tz .mdl6lwZmN讬t,pSĚ6b(c #ܳ}/o S"&q/r7&) c08:2M_C%TIaH_t I Ԥ >L@:&.PKzPK 4WRjava/awt/desktop/PK4WR.java/awt/desktop/UserSessionEvent$Reason.classSoP=J[Jdͩ|8p`KHK?VI'+K[R8g(}4n==w}|`OQENBZ]X cNWe$9ޓ!c} b͆Rֶk3ez}A9V{YCo͢/Y[XlzkXgmh9xkA CkCNvvvFьļ̒̒ F; IJD}"ײԼkrAyũ֚a \Eɩn9  iMEz 2XK$'e&120201# #3 $PKdPK4WR'java/awt/desktop/AppReopenedEvent.classmO1N@Mb[1 ( Q UD DAoq`,B'(((yoAY_hfgfwߏOX 0aXqUrYik.N tIO2.Uye6z="cm;&wRBgb3& i孚3[|qR7l 6-ظP=tvgd\=:[$ jI"a|\gk @O0f}[]PKA(PK4WR'java/awt/desktop/ScreenSleepEvent.classeO1N@c[$ t@E"R1?'+q`9P! 643;Z)$kvZ9Z[s? 5a8\ l3mãПF7m\SE)NJb;;f咍?yTK5ASOVkοw'z 좏Pf$X4޺@0]lPK(PK4WR#java/awt/desktop/QuitStrategy.classRQo`=-*:d-3#YFLJ:b_)Kh2ޯJ~|IXUp% Y wXa]ƂBu+#= Cc>{0]qdmP9tƯNV0gƐm6 <2-ima\(p2)NEIl~x3ȧHF"FE**aB7@ eV/ZLVp+şPK_tPK4WR#java/awt/desktop/OpenURIEvent.classePJP=M];mkEP) jp!ڋDMHnEp~8 E|lfs̝y|}0PbKz"@|'A]*P%Z(Q*qwv~J08 T{Wb,<%?n@z~SmCI%ӛO`Rj/Z0/~0:GT\K'2X.F̬V{C\0~ NM92&0<, A}2!{p2rm=xdrr/f_ Erp&gw`<|[X8PK2PK4WR#java/awt/desktop/QuitResponse.classMA1?Ɣp{6$U?Qm3nPb|^^R` 0$'__7m |OF;ηUi0InMEo0MPՑKAoo;b !CJwȁĮ)PKŋPK4WR)java/awt/desktop/AppForegroundEvent.classmON@Mb[ P`#(hB:C'5!$ >?Kkj>?a%E˄QN2gWkk tBL2>We&h@nmLiݥq<խXW:q1ќ߽UsRf3ೂ;o=aRC$3A"l D;o lqbKPKW#,PK4WR*java/awt/desktop/AppReopenedListener.class;o>CnvvNv.FĂԼF5 IJD}GײԼk0FҢT̜TF $%>%@Hd# >`jrRK * cdad`a`؀$;PK1QPK4WR)java/awt/desktop/PreferencesHandler.class;o>CNvvvFļԀԴԢԼbF5 IJD}$ey%֚a \Eɩn9 HJ<遌adPgT)#XUNb^RVjr ##00203X @ PK" PK4WR'java/awt/desktop/SystemSleepEvent.classeO=KAI  h!XJ@؜^1Y{,+!? _`+6f13&hc@[6R9+zhJ莵N(ç|  [Z܋Y$ӕykYle/Zrb):BB8y*^]:gt&,wPyBCNvvvFļTǤF IJD}kYj^f#Wp~iQr[fN*# XlDH+#,v9yIY%l L b1I&6PKܗ"PK4WR%java/awt/desktop/OpenFilesEvent.classuQNA)*/_(d"hܘ 5=2Kvgj1zhg?oP{Ġ襻{&ID17"X"CVK8;`0r5W-OD?ފ+C ϐm!7-zfS;R* TRVVʞِK-H T뷅seMS\{ۿŪ_X枴D92r~ɦ9K1B;Jo ,1 I ~ͮpϵ=00,1F)F:B10ALa4-aXy KD[)O%;pRl G(dCT$O!ZA5$3dgOPK.(qMPK4WR*java/awt/desktop/SystemSleepListener.class;o>CvNv.vnF\ǤҒF5 IJD`:ײԼk0FnTFҢT GIO&Z2A0 `e9yIY%u]@202020i6 g3pPK5zPK4WR%java/awt/desktop/AppHiddenEvent.classmO1N@Mb[Rh(= D-̝_((hA< e}J 1GDX' *.S.+m@Ě)R>>^_6ڍ ^JLlƄ6|U?θQ\F \g9wp檋Ą'jᒌg-a 2-A 3B$l{ w lckKPKg$PK4WR'java/awt/desktop/OpenFilesHandler.class;o>CNvvvF<̜bF IJD}kYj^f#Wp~iQr*HA#1/%'Hd#"n jrRK@b`L lPK$PK4WR'java/awt/desktop/UserSessionEvent.classN@K /R?gѠ&AlLnIx&>/=A7;/oOPI#4((cH <`4~J ŐWwk _9l7v>CIpD9~%?X3>5~zB^&VK;2XN G:&ÊwYf׽`5)]Kԩ>lV3L 焜Րd yd~E3~l;1hfզ j@ 2Ɛ E#ȓ-PdQ#(bT )KILt|ºGKBVC8eKnPK"\iPK4WR java/awt/desktop/QuitEvent.classeOJA&?,!$""zLz{{U|J2s[|70?+GL 0aXӪUښل@ؚ+sU}ׯcB|~N m~QBZ%x5gg -5ֿpT!Z A$3B"ӂ DP lj_PK:F0IPK4WR(java/awt/desktop/PrintFilesHandler.class;o>CNvvvF̼̜bFU IJDkYj^fPSp~iQr*HA #1/%'Hd#*rRK@b`L lPK̓PK4WR,java/awt/desktop/AppForegroundListener.class} @gF mEbcRJTdh,|JADXofv 5 :-Z a#g2},ϑOpATX2M9ң2 f {-ϱdz dB;ǃߔӄ Ew{?˝`h/%LPK~"PK4WRjava/awt/desktop/AppEvent.class]N0ӟT!ZlHFEH TX֪\%Ny*& U8{sp;5gC,4YD<\ 3JD.! xǵGCvNv.vnF<ǤҒF5 IJD`:ײԼk0FnTFҢT GIOfqIj^jTF|22$'e&`Y T vL'##3}@4P$PKG6PK4WR!java/awt/desktop/AboutEvent.classeON@MPL zGH@"hgŁs~' /fvgfgyy}p}11kʜF[ssqJ)a4qʸ\-˯j3!i×C*JQ+ַ|;ug 6nN-$nԣ;[ewnUyOJ@DPf$X6~ 9}`(yÑPKPK4WR*java/awt/desktop/SystemEventListener.class;o>CNv6vvvFҢT̜TF\ײԼL 3/H/+,AD'觤gcQ V\ *-GQ $XPK >s~PK4WR*java/awt/desktop/UserSessionListener.class;o>CvNv.vnFԢ<̲ĒF5 IJDPZײԼk0F$KS2sR$td遌gdPg L-#XYNb^RVjr 6@`t1202013L, , @ DA PK'h(PK4WR&java/awt/desktop/PrintFilesEvent.classeAK@6icI/`K9yEVF6'1z<]Md=͛fa>bkt B%TB@h mSz>&#Bw7 Veq ;K q>v<+g\YIcnakȭ yiezFi[x!= [60a_OEj\yQ&'۬8oҐ&"Gr\PK p[ wPK4WR%java/awt/desktop/OpenURIHandler.class;o>CNvvvFԼ OF% IJD}kYj^f#Wp~iQr[fN*#0T#1/%'HA)Pe `9yIY%l L b1I&6PKc2@PK4WR!java/awt/desktop/FilesEvent.classmRJA} ,I\^gC DE xl63a'yUT75`$0]{]E;]li C(V5z IGؒma;2O anjsf1UN|=1/!ҵ.뮒ޒc˞ɕk ]bi Uejr)i(zV*?#@s~:DXwQ\,=!0C/Zi#)IlYoPKgPK4WR(java/awt/desktop/AppHiddenListener.class;o>CvNv.vnFĂ̔34com/kreative/ual/eawt/NewApplicationAdapter$3.classPK4WRU4'7com/kreative/ual/eawt/NewApplicationAdapter$13.classPK4WR0qI5T9com/kreative/ual/eawt/OldApplicationAdapter$1$1.classPK4WR՗-3h;com/kreative/ual/eawt/NewApplicationAdapter$8.classPK 4WR=com/apple/eawt/PK4WRx K #>com/apple/eawt/QuitHandler.classPK4WRUے!D?com/apple/eawt/QuitStrategy.classPK4WRva0J-Acom/apple/eawt/AppEvent$FullScreenEvent.classPK4WREW.,Ccom/apple/eawt/AppEvent$ScreenSleepEvent.classPK4WRFZ(~Dcom/apple/eawt/ApplicationListener.classPK4WR/-Ecom/apple/eawt/AppEvent$PrintFilesEvent.classPK4WRs%wGcom/apple/eawt/ApplicationEvent.classPK4WRh,I'Icom/apple/eawt/AppEvent$QuitEvent.classPK4WRܪ!Jcom/apple/eawt/QuitResponse.classPK4WR&M'Kcom/apple/eawt/PreferencesHandler.classPK4WRDK(Lcom/apple/eawt/AppEvent$AboutEvent.classPK4WRM*)!/Ncom/apple/eawt/AboutHandler.classPK4WRp MOW.9Ocom/apple/eawt/AppEvent$SystemSleepEvent.classPK4WR3NhB*Pcom/apple/eawt/AppEvent$OpenURIEvent.classPK4WR(&Rcom/apple/eawt/SystemSleepListener.classPK4WR=:[0^Scom/apple/eawt/AppEvent$AppForegroundEvent.classPK4WRvN_r'Tcom/apple/eawt/ApplicationAdapter.classPK4WR9l'{Vcom/apple/eawt/FullScreenListener.classPK4WRn;%Wcom/apple/eawt/OpenFilesHandler.classPK4WRtFPA&Xcom/apple/eawt/PrintFilesHandler.classPK4WRȳ*Ycom/apple/eawt/AppForegroundListener.classPK4WRň9fW.&[com/apple/eawt/AppEvent$UserSessionEvent.classPK4WRgFlw\com/apple/eawt/AppEvent.classPK4WRп(_com/apple/eawt/ScreenSleepListener.classPK4WR#ʼS,?`com/apple/eawt/AppEvent$AppHiddenEvent.classPK4WRl(acom/apple/eawt/FullScreenUtilities.classPK4WR(^D; bcom/apple/eawt/Application.classPK4WRNW.hcom/apple/eawt/AppEvent$AppReOpenedEvent.classPK4WRE,icom/apple/eawt/AppEvent$OpenFilesEvent.classPK4WR%(kcom/apple/eawt/UserSessionListener.classPK4WR,E&mcom/apple/eawt/FullScreenAdapter.classPK4WR'9~%ncom/apple/eawt/AppEventListener.classPK4WRrIp(pocom/apple/eawt/AppReOpenedListener.classPK4WR(ŋ/#pcom/apple/eawt/OpenURIHandler.classPK4WRo H(qcom/apple/eawt/AppEvent$FilesEvent.classPK4WR PW.scom/apple/eawt/AppEvent$PreferencesEvent.classPK4WRz&tcom/apple/eawt/AppHiddenListener.classPK 4WRvjava/awt/desktop/PK4WRG.Cvjava/awt/desktop/UserSessionEvent$Reason.classPK4WRd"xjava/awt/desktop/QuitHandler.classPK4WRA('yjava/awt/desktop/AppReopenedEvent.classPK4WR('{java/awt/desktop/ScreenSleepEvent.classPK4WR_t#G|java/awt/desktop/QuitStrategy.classPK4WR2#~java/awt/desktop/OpenURIEvent.classPK4WRŋ# java/awt/desktop/QuitResponse.classPK4WRW#,)java/awt/desktop/AppForegroundEvent.classPK4WR1Q*&java/awt/desktop/AppReopenedListener.classPK4WR" )java/awt/desktop/PreferencesHandler.classPK4WR4"4('java/awt/desktop/SystemSleepEvent.classPK4WRܗ"#<java/awt/desktop/AboutHandler.classPK4WR.(qM%java/awt/desktop/OpenFilesEvent.classPK4WR5z*هjava/awt/desktop/SystemSleepListener.classPK4WRg$%߈java/awt/desktop/AppHiddenEvent.classPK4WR$'java/awt/desktop/OpenFilesHandler.classPK4WR"\i'java/awt/desktop/UserSessionEvent.classPK4WR:F0I java/awt/desktop/QuitEvent.classPK4WR̓(Սjava/awt/desktop/PrintFilesHandler.classPK4WR~",java/awt/desktop/AppForegroundListener.classPK4WR[Qw̏java/awt/desktop/AppEvent.classPK4WR)1('0java/awt/desktop/PreferencesEvent.classPK4WRG6*mjava/awt/desktop/ScreenSleepListener.classPK4WR!xjava/awt/desktop/AboutEvent.classPK4WR >s~*java/awt/desktop/SystemEventListener.classPK4WR'h(*java/awt/desktop/UserSessionListener.classPK4WR p[ w&java/awt/desktop/PrintFilesEvent.classPK4WRc2@%java/awt/desktop/OpenURIHandler.classPK4WRg!Șjava/awt/desktop/FilesEvent.classPK4WRi(java/awt/desktop/AppHiddenListener.classPK\\bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/universalJavaApplicationStub-MacOS10.15000077500000000000000000002430201506470510200300000ustar00rootroot00000000000000 H__PAGEZERO__TEXT@@__text__TEXT0' 0__stubs__TEXT==__stub_helper__TEXT|>|>__cstring__TEXTh?Ph?__unwind_info__TEXT?H?__DATA_CONST@@@@__got__DATA_CONST@ @8__DATA__la_symbol_ptr__DATA__data__DATA`__bss__DATA%H__LINKEDIT@@"0@@HP@`AXBD8 PD0 /usr/lib/dyld+3(ī2   a*(< 8d/usr/lib/libSystem.B.dylib&@B)XBUH5/)# H5! <]fDUHH}uHEHE}H@4 @uE=@=HMHU}LcBD AD unLEA4_A4@uLA4B:<bHEHHEMM4]f.DUHH}uHEHE} H5EM=@= ʊ ʈE ʈ  DEADEM HUD A1D HUHHUMMI]@UHHPH`H HHEHHK DžH1HHϺH HhH`xptHEH0HEHHEHHHǾbDžH + H HUH9щHP]  f.DUHH}Hu1H}E$1HMH9EHEHH;EMEHEHHE1H}EHEH8ME"HEH@HMHHEHHE]ÐUHHPH HHEF HcHH HH5H)HH=KPHHϾHHϾ1HLH HHHHb1HcHHLDHHH HeHKDžLHH5J HHXHH;D1H H9H+HcHH+ DžH > H HUH9щHP]$ fUH]f.UHH`}HuHEHHEH}H=RHEH}'HH8H5/1ɈE}aEYH BIHHϾH 'IH HϾAcH IH{HϾHlIEHHH{H)1ɉHE|HUH9HHH HEHHH|HǾ HHHLHǾHhHHLHǾHNHHHǾH4HH6HǾqHHH6HǾgHHHdHǾ=H=H5CH[HGH6HEHGH¢HǾ}HGH¢HEE HcHEH} HEs}H=044=4 >>>>>>>>>>>>???"?,?6?@?J?T?^?] (8tYgVk:DP5ܗ=J}[HGRwOFpn2Hy30mapoQf5`hiq3m Ҟ8ky5Q=jABRrr "=U_з*k/oA8'}:C/OI Wnu#hIk䡏]Uӥ_Q#9qQ%*e ߗ!j}cu8g5,.9$Dm4 Q e#x7)I!V]qIy+0+-Dfż=s8dГlւ,[)bpPND.=xhM5@+A{*2{mֱsmC2iᾯpUێ͊ÁVPnb$ Rqq6s _OlT6R/CJ[OxFye_y3$OѲ9z:A jAŤůt`B^,vyoBLF'HiJl,L%u~PuZNl[!R"yWz@q\zUWnnϙ/2t֡i{5Q7A hŪf2S h%&خ:>Qaѧ;ƴci;>AU4v QS07!s{ 0Ll#%hLiĹ[ ,ka Nw @pVα L}<=t-N)UHy9)'jƄ)$#-' *=dws8Q+o_Ҡ9/ , ΛD)!'mK }rߊ)j^ekc&n4qYp + :9mygSUA{vjƻn'Azogm{%w.g1>CE慙M"kǕ1 X)oڪ) (JYGcnH'P k>p.ltETGŜQ4z{A.{E#Slj;V/&PuPH,Y { a6Qw ̀\w&^ⲗ͆l^*AsG̸A-o%6B 88kWR%BMRR*ւͫij ݮG@cj\ŏef3QD7{TWZ&7xs).xd V*.u?;+=W7moO320`һE(?n]@ЏUʨ}i]ʕbe= ,,f84`!Eb@<׵2Aj5TX7#Yd֘`Q/;}#$:/N1ue;Vju58dƲ -?4{D!xN2EcM̼CŅ{@3G,Dݣ0 /2X/ KTʌ=@eߐVB=eM&oF3I50T$=oTBЂIW2虽Vwk\5}ziQXqS;\=Lުg$}M]V_j~\^hȢد8,`*gNP_$7ᅜ H> as2'O kWO{KosMSĀSusw@IIqB 툌9T`&Cl⎩vDW檈wSMCwFc5 jFj %\KKgduuh%K =bWG.3d2$n}aA#B%'H2*\3Ex L +kwzٍ2usozi k=.[())-\H0`e17GFsm>{[JŸZ\m֣~8:->:,rրHˈv pbCUn鰉A#U\P{^! )xהXܬ uOGސ"!Iڹ*Wp^t - M Y4ޣ%Gdvf@m'\VV"Yw9Xi_Q8r] k Fw>_؀A6G˦sw*2-^=I,Τ̳&>VNE~*-%M]O/`F'[W L@[aCa ;p5^"2*I?檛5Wm7+ndCQD;.Ad갱eV!YvaDG(-_Vݼat ~CzvH;_v z x5W^\S`(,ST"QUwHhg=DVj7z>F*3ajIVvJTUӫk>`WG68 /\l?_̊s;*Vo&lLs$ApZ0~Y) `Dl!91+}UQU s0rQ3Rx%q c/ |Ĭ}$ -͇ćb2i]orЫbXqQ}%)_ÅQ@Uɱgn^hI7fw0ו1"ZVsaUCش8i^eWKd|Jt>\84̂Uu#ΌO(1E!2|)ؓ$9nΚ0W0Ff%aﮏŠ'Ǜ)?UoZMىՅg&Q`'_GT%Xg6*w.6*TŁYr_ݕRldSY"X]~n`}ُk33ysj3,!nfۯ)d>BH<B.+~h3.qj*讕Y̙yt/|d UtABĭ[=%.`Wf]Y܁"K"Ln 0qql-uhx ɎF沠-Cd~32x >"'P.oP$z &N?ܹdgN~*Xب3tXmu^ڴ}EujM hd#9G}1O K(wShk짹Wy89KAds,@ݡ;D/p"_8.4msIaDE ) v4c7,' K*1-7}*8Knz}4su,忰)}۸V]uCOJkB?Ofh>{w 1ulyz gJ᪁qYGMnglAE* wkғ$.,C"X0¿*[H4X3~`*Gm^J(IM_aƪzlXٷdY0iM,X 1Z(^Ikgr1=)V]jB˦If#/u0CFw[}|ujZ1pKf|H 𳑝׀t'ՀB1w!.6NiKwurTfÚ3>[6#Lp](E)G߿``ڡ`]R]^FD6Z8<T#mOfN-# x9{xj,e1idnBK;{O۪dRz fuP t`;C$N-(25ov]+DC^^؋Ũ+kgux ޫ[:+~E,s mBj|b*pVaXG8dOF2[H7+=w:s 8S#z*"yTCẕ̌ Yb=©oO[?eQ{~}ӈ 㩨[qe L8Xdş, 8T55Թ0pٴ"hw'7 `R0YԧlF#* ;jPv.4(AUͧ}nM,rW;A {= \Kɂ'qj'#)[wgԣ|{߳@)`U_-Eoo)-ַ< qV=]H6wVS?&%x}Aoŕw7vP*n(KC)V L~wgM'K\40]x} B s~ɑ#mᛄkX7FE'b1Srs:ܲ]2T7Q|L| ;. *?G`u++բ\>z"\Y`pejѵ\'"PXIAuŮ-X :A2g; 6YY-y[Ѓ;;s{(j$ggWP&H%,s"Խ%R'D_Ig4W4_q`E "EFtfY30"[tBZʨZ2 So r\29A3Ю rAƴץt߶e ƐB“+uFAE@db5Ś ep }vS@I ~!՗bh`_Bex1F/L1J_({jVV8el_nuZs6FwOkԛH*lm׃LD݈m\YON )B*}S2s!D-дj &]E y ܰF|XSc[vGƭиN4z9U|Pʘj{ +zL`X޷qc[~7O9(eN3_@Pdƴxek@yDV)B>?&fl^.k䂲vi!:,m6gRZxPS/ua\"VG 3ӧ۠[H\v2Qưjؽiw`ADGu=KmXy¿CSp8Nk:@ݗBoipO$\LUT⏑ET[la]a_g%oR6 \5mwqJ:qF~yLJ-01*73x@x-l'l{K؎Jxݴׂ"Sa}4'}#{xfVqb8L.xg_5 )t*|5ƻ9j{CsGk=Mv!*(r .G,ym$|qg-&ki 61'G!5Ae+Y kRjVc)jr X~]Y#ZolQ $O/oLΎ*TS)Ϩ|BÇͥ_kJK U $QSuNsIb2bCL-j:{Зg8 A}d%X/_s.sB,H̪Brj&45g 5L 61vS=>VxO糉ג7FW9VW*5N@ݼ7Vp^M7l**kefIaY՞(~j_L_gxOQTiǯ+GX=3āΜo' >'`QGYmwu];IN -=y+q|um.fS*# L—*yng3/U^kicp,ym= =nT9%'ݽKb̘eb:b 1Nw9NJW-I*@㠻 dDD] Y4D*AI6ؑŽK֍z\O[H/< Mތ.H&0V1cDӎp6Ȥ@VY--wNޣJx+]*w5o[.&og>2{/پ-I=vTpufكkb∓~W=&SDL=%h=ؗr2{ÆPDCq*@ym'^W'.B8N_K Brݕ_E^VH* ey-Rz3'&ΟGa2%C憧8#EEk a[*0mZ.0#i}j-hլ%7dd8]-kqނ 2,Ƚ3{~Q$szߞථo@;;s Il6BhU/F)m0&GIəZl&ڱdәb54ah]T2n ^f^E*Ƽ9݂B$=& &b_A^1Ai&BJ\d+ lJ ,v3 H6;Vd|w`SK=WV{ n|n>oAp. 0;ҵ5UDj ApKp#žq6 ANλIF] | os-W8LTrqbnO:t#U:Ye> /n؈^4j>e0$\N|%Af=o&`igޔ6Lbps|Vxm{ntR*$-rtT#{"K ⪋gBqW % :QxulKPxR`iYD@y]\ Q6.ПNF)v>!@q 8 eYiЕ_4?_+JNi'ӭ$ ܻbq3fv<8HKbBh/L2~M3$p m7'?Otٝ+Ljы[KlfGl]@ F0wBzߴQ[48ߛ8sk\SO]E-fDf|/]_TӨJHWK ;9ϼwGGpХd'XJx h$;o@/ImV~Kw??(RNmng/4hc,O;Bt\R /e;KcS/BP"DHw,K}HGռ!q"ۜ8r20ז2,h{Bea{hBw>[ 50PX,eAhB)J9R*3p X{PHƚЇ^8=)h*̖W`~jhP^Z|@0d) ]'iS7A#S^(_]EeX?9DRU_$EqxQ5cJ>e-T~*2ר`8ӽRǞU"oTg+$F @c80_k؍nz#tTm^= [D2ߜg@xNpԔ-+.7R w7&. q?m~f5&<}WکOѹQ4șjoz37+(s,iP& I^ar,ΌkL@Po ң0:*FTblFgt)5=Ef["8Z\P~o$ȟt^KxfqIfV@o\g4,,ZGf3#z 璍;3ӉqLn]xsd}ri@m2)eg =SgVI IO{a~}./ ] F;vV>q/O [P-D;qÆ|R$e@z77RF ݂Qi}Jt q(mg}2R6 4 {a= H^EԤ0e. eN램ڭś!X.ĭ'<%'w2lSJQ:uOCh8Sj@,y?aT*)Δ+.9w3U~2MBL ěڦJe O٧hjPS{ 5|4\G>G|(864u=]->hJ`~Mc+lOrg37Yz3?nsEjbZG*W\ӁbaO&HJ >AV:EoZac+or4XCLif{XH2fI5 _NC Du s!ANZ 5Gf_))ز WDjhQ1D^Ecd}ʳH"@~.Ex`ΑR/%I nV[$Q |:]( n+uH{cMrm,˛JbA´le6Ȣ; I^7ߠgTQx?hQw&h2%Ev VMkG\{-5*yKݒpvEBr =}zK)|MjRW Ά0J)Jn"/]/HYИóIFAsfЄ4PZ8-d0cޫn Etfza4^ poKJbϬLáFUܛc aɈ(iabw ;9ӎO\l;> *Wkc 荈62";!˿0M01>pkҩ"T J▨@LO UEL&z֞R5!kX0tomb1e\D*~6j^,sᦂ lCDI}G28dA_G5 o֭IND^!:#5#?.%0WF[P bc8M&_JIU7Y=wNc:T{i(@av6 mDD*&md^+VM8!8@*o IZq2ѐARj} )EkP>ӍF98f_Ωt) GU={We-k}"ÝI><1Ea8r{U3@nτ[%f\ pe_C 9 ya'Gq|^\E}5ž66)0ӭy98Zo?H!"1k D95)vAc{yMOJD);A3p4T7iA^$|9r:%\h[-ɇ(zFrkTg"llls'&MTRFtu7tl9d;-Bq)ѤgD%*'\#hL I B2~VqNTwI]7x)5;T"E4fЇgOLW Qe%v~& iy9u`QW{A'|[5Bl=,@~U:ap/500VKb99s$4E;ɇ1k>BJO.;a\@K xʠF4xp3=Lvd $<v0~4/ClS~dgAjBAНu߯b!ͿV2 D _=$T9pѐɲm|&n4\-K!`6DwBu\~Fc Xk7|JpTs3tk"^WcrP Dք wQM!;;Eo.DtvE\XOOe 䶭^\~uƬ'<ט N(3\5%ȤPa$*#k;Ң`*83'UQ~9A#↚{P<L@2L؊+z,-Xg!(RjR71MBjvH)@'Fz2Y*3aw;bNvt@(tC#HY&ryvoO,~= ѼzMs(>:ŵEmA,k tpc0t^ct=k qFy=$]O J1fqOn'H[ = Pq@9H՟/e]Fv9YBO}>%l(i77SDE3ҐIkU,j{u %#Cr*3;RCgF\뺪KR^$ܖp, 2 A?Pp'@[(6kdj QEReP@DO5zRiP0a1/GYAPC6+sjz_"F1Td6&` I,6%i<S8qij7,h5 WXbPڣj] ;/YQTwer,A̓L#ޓX!@N)=- ^cp7eT26u̎Uno|'΋ݯ1 #2nj&woop'DQjexf9d@rrXΩneSm l+<z#@)7#!i:6v#.0c1\B1tF H8AcE| _036Ps*OȓjRp8كtM'טģ_:K?vG|Mm A O~ ߚIךɳ@im(= [Ԣ0Xn> ԟ ̝kN֏:;8PQ>wƀU%5|;Md:]G !x8'X7&B̃@f컁v6p^dBBa좟P[{5}Z23-]In]P uD|I^Z Dcr fhd_ݛoޞ}כ1{7Jem+\M1PQ$s>f19/]c&CcW40bFo,;Rmr,݃kj^[\d HgD'Kc26(6xn4Wrf0sx?# c(!N \P풢hࣞ3d&3u {K|?~I%$6 _G PUrc(EB5}&T;C V \|L < JV| wʗ(%i$; š 2_ FkyIzQk>̡xk*i&΢͐J#-XnBM׸nOd?=wJDˇ :x) "o08ͩpw"e%$5T17nVK>hEz,[qYdr٭5RvOҳm+؁a!ƽHM϶SAHEcPZ-l <;eiK9'I>l j)Bn \CY{gt*4yp. A`ZT aLmnE>BΪI+rR3rUg°[.PXBbF>wmti:(D>C) 2e&wNYÎa"hHt}tKJ1̌"}7U_dz_C NDָ-F˨̸Eѿ_=ۻ<ןZϋ.ϖn뭬*ȬbJ hRꃤM)TI$*F롰! ~r #)a啁;.$mZh\\PCu GihtZE=$ #?;: \ -74Bn:I#Hp"9hF(ucazGn hTkACQb VmEv'4-J1(Dw6LJc$0y{E8NY9ٗ]j9Iy-S=]]. QX?Vc+aǦ<+&4Y@_&,fW'AjM(|咲3^@xe{,#z9R)ѫIMZwb/1!)\X (bYK #`4L7fXy՜X>Gi@G,4zͽ yi[UDa5DFRxZit]R5zrȀ:XyQֺ@d~ kQiQU!2L\fJz Cg#~5zMr|a0|LyIs~hjzE|r:f+Q=t* o8wsׅ[v(1Sq=k9Ͽ gf#~ 1Z!`e_\]C\4xDWz_7+x_,}"ͳ#k0Z`gp.'-2u#;Ao#'Y }6 5$%5ў;"1J.=l0GIIɢxE3Tb2xksqR#g;D`S3k+r-& ܨWxњ)5 -!Dj*IzN;`C"_[WmqZ_ wIstV:u.7z% *+ʮ m6;bw/_jGC݊IQԜ}R!wb}~lhTȸ=տo N`!ڔrQyx{rV[&1waeEs9d`iaQ 5o.=m&}8y87;&o{P(Y OrFjCg\})tOKZ2}FK幋Uܧ ~/R,M Q[r"N -*AiKKȿ;63pk9@yЌ Wڇ_b8T8n}GB1y9Cf!P&DrxV+xZ?T2>Yx8ƗyBYZLJld>K:*bzgXmr 8Yu`t:ˆ^%郸dJ # @6%GWddq0QMZv2cGY| yxPbP}tb#+4B })~~F>3 H?5Ho< 4'/2 2/΁fZ4n N6.!n^r1({PDfNN)F:[1f8E+&Ov"9Ԉ4~AD[o*KԺR>ejn$;e 53_4i }!QMսbX ٢W?a8j}^UʰҊyꊦ5͒r<#e'-9z~FdKo`j;vƵ t-dKaN$2%qin*Vض|P38)e dSi،\!T~C6KF+y:%JTd2eL)26ͪw mE4 3'C "Pw81ӡ o}C\6d9f1y7_dULY=uqaN > PNM.ˆ3,Cۮsm{hzIYS隮s qꡝ¨><7&2M5] WXd,ۭF^^P&p׹P5(PSU%B{^z&aJY_ܻs[ Tr_*rzF dr)DL'Zm0u0c`[1W~^zSĴq>9dc.a#go^k*E8TXl430l֜RԽYD+sT< i KFQQbyb XE3]j8VPQ3=ra[ֵ*84V1QO`bT!Ǣ/7.I_Nz)IC5cig?-4Xc3fB :.Uv!nt9/嗀;ɮKޓgP)VmY:JŰ5-9ng~Wu!,8,'CXqN[ڦӡ]?Zow3.dg0]bdtZ ʳ(C?.!`.9S b $2%6RڃGHMI: ?ݽEc;x&W|<#*W67@c}ƭ  4Žmݹ> O!ɿX <7\ [3k[R>1j%kd6x/A89b s) U끺 N*Ky*[K#X)_>Ћ{(Сe'Z:{OUՠ?ʗ[`xJ3#.?i=<"`b8TB_&~B?8K&sO˃- 'я~<(~[y-Jh<t? `zO2aBȕgT$5Ҋ4h2A]`CRSh:KJZAME0pw{"0I5;$ g؁7T R-F@}CC6!7ڎnB: [B_OX75I YH?^|˲16XݟYߋO/kR, 9= pTQ Rd16V0Q$rơRvn?c4c9:kƂZY_Z MT r`*x )YTHĀ2&L4=E幡/3Ū6)$ K xUe>n"EΓjX:5zf>~drr9xBIz([4kc?eoa@wH5xnnڬWn2]3۷X0_z[͒+Tr#J̗&8ݼ: ]:UX5Eˮً )`L&Ti0H*kEf[GǫW71aٵ0)D[ 'WAV)ZHJ*Ypg{(}:w\OdLTBx JFZϊ0lВȉ%Ɠw :ČkDn҃R#P{r4z =Յ $ NLK=cIIh].U}h}a [«=Cسr7z52 Fk?geL[낼=qMNUuf @Ň % SHܛ[#кYUGbKgMo\R#րc a$A艟u@BbEO_3MvOv|i9csY^ +y=]ϕ8 &Pgg/C+`xC)5}EtE^}2U Nq h8^sRh@V8kymum.oQjs˄߃rg|Pwe YTL$~WR#wU@ Km$u..Νd"G"HŻS7u\ndKPн6Ft/[< iS&/06(arUG\hR0_.WLtglm*dz? =M]WVZ+FB=ʡBo.EQ=bS|jkl*::T([q0 6pPz7H})E*l5٨~Ci6zd7bt. 6 QI[z)!J=(CTЌox@&n?PODzBRo2y]ŲN似],,qs 4Mg9,DēwkK2uBvH>Ʃ tgu}C$`7,YwU*C`$_ Fag=7tMe6OC!*8qL1z\@Z&ʴnMN$Kn~ˋ qM LL+2|@R =QD]g2`DC8`uX7p缇H_z ;AySz3euI^#Y"j#sX=יL p{oʊTs˺;Ov9H6; &bю2(Yċ_RTi~d)0ٕZv(xLz.xq7.1F]rB2aHri7pŁ`c C ޟd!U;yb_"bS? {[!5Rŗfd=iD'g.4ߤTZ&VVs\{ ^{Zݪg_Ӳ44(a{rЩS׉v Zߞzp/oEzs{\vԯ r퇾ӿ׎7)y͕ C;Ll9({ H%bmS GE-Abj?V|{⦉T8d-؁SY J"SB2fw&QICŊ3CF( %O?/ڂQw}8MG "M38vJR7hzeMDBH55oufG* Gd4,Ή0t = 8i^tŻJNă:yWx,m~yқhg?B2&6KVH +Ui. ՙ Cc2mK7N ;GtV抜&g~jΒ,Ct[?){` "qd zs}{w= 8`C8aK,+ Vv`Z6>5Q:y^% “ {=z0yП!<09z`]ϤI NFQ{gRD B)T"[7G+#د=8dֿuO[٣<q޸=ԓhDrC/Uh&,(,Sg.2HܪElW5XDb.  K&<ҴDN31 KSs!TgF/_1%dǴ#:nQr1I3ƺ sTGOai c4xp~k+Ɓ|ƺo!x(::!DK,.!Nl+3P}Tߵ46xģI1 !@iX B73iJsAAe^BlT҄h|D,l4^9pzK |t6pXM(+]-Powl 5%JIG蝄4N@RBi*n#iLC94f<]%ӊ7I>oǬ+yg,dp*'vXnɹ\?$25t 'gZt `3s~`n^E(K| 9  JUI KjHL-ŗ*+]ξAIpFE&2Ŏ7B-aEws|)U~qYXN1]ғjuo{H'HUeWι^>bXkK>Ej{ |[2Q5B]r: "(~ȪH|:NJ ρ15Գ;nsLA݌uRX k,χvQ{0H;VD̊!B=CR5g%DG(C.W5-= MS^]OGZdF8ShF0SL>T, r W|fW3Aƹc=Ae|D:j=[G`FN,bh^669RBA&[_Q?>< kKi=!06TٷGiXb+5.fNr$jD0f _(4w:ƕj(Mm{!Znb q/P?1&qT2y !{`#ţQة2xS(俴3#i>\@sZE7AwIcʤw8RV^/'KYDTn#tMB:x-stD-,1]Q3YKo9VTl-Y8Y̅ Gu{gV (ɀED ڴTQto#/ז/ Չ<@bpj H tP?_QfDƸj,vVs?rgҤo#ح1mFI$'^U*uR̓huG![^gYPX7HJTS>Ÿ įK([ڎllvD<@TO:o)1)_lMadڣ1Xr!U B>!ViAQ/!+cika{ZVq@$$FB??1ӆ3߸BFʎ1(|s>=7'6аAApYM=-6࿤W'YQXMT&qң9.srkܟ(̱Qθ"(LNRչAJ;{{]>i8jfϰnR}C uݓ˨a^ƺaNo8LdxK #x0Y,89|8nO>RQL^. Y1iL!WslKI*!iukGeGߺxY3 wZ쎧*ՅAK1_8q;/)m2"ڤ}MĪd7OvҹqH?!Ϝiz`P8iMChE?Ho׹c_l^3̢_FO̰ _OpxIq{ߞXrLٴ@w>C77oRG{mnMxl'/)QW~ t~P['/=Qq 2۬DQ 9MWgz]| Nu ݉a 温:a&[{w'VVY܍0L NČc cjW YPev7oVRCg1+7`}#>JM [ǯ4xdGP>r^jTG`۫F:Y*T&0/ݲo[ⷍb&_(RZz>/3h4ϼTC.@Q _Y w ]l#TD^.9?hMقΐޢp0#yyOnuh &\G̫j^8`?WL W:g1K5qJv31ѼUv[CI&RvlId|oc!+щYPzcmHjm*hۈn1Fs/1y،2_WVРΝŧ+b dS7tr 9}HMHPAf3{}aH}aKO|zA%}z`O48ESL0Ny*l8pȝd㍪P.ЯDh|[3mʳg)?ډU]8~'A35`;~%īXq:ת_dIDOQ1yXn̿ai ">w8ZA]淅 "\ץ\ZjMs/# FbП42Lҝڽ ­ǎ&t41]CgbE_љ+Ʊ; *޷6a(I^eZv zȌ9F0$6Lq O4I"+_P~.W",boH> A^~jngr͂`h I{Irt $ Zu0u9&)2VOojκuzx4* (Fx |᱋D]pQEИW#Xt$ldjO}5>\#h8  ܳj4kpf{|JEnms/ C>v:9|%\N#ފ _~M+ttLZnxq]dsS79cޭ.ot*3<~|/d ) /Q8漅R6GL| 4ǁdxTЃECLdPG8/ơ4[NQ'* jԁ]fTdt+ƶ UK0qzc-Hm 'M%fHХ߰Rfu4(ැRY4\}qQ 9 mw]I{#rٗ xSETu(VMRJ&Zx J# coUyG_x1O}@P$v/f!پz0꼵u9h "2lp̘3R@BWX1c0)ZJC~/s!Ba )Pz!D~S{Z&62k 19-5jlF (a]Ae_ߌkQ7,'b?._d6yÿkf(=B%Pz+X.'iR7E_Ubf{!]߯A-lQ_ī9;5L9/e#ٔ/`.C*Kt\EBU tR-HI49!voB-O8zz6V k t jbx?k`S!KK_XϫpdO<֧IBQ*;{d+~AdW}>viH6g>G_a3AUo4v-J汭zszL S1M5Z2zg`5$"X2Wf4P| y=y ] r őjujAl-iqLm-tr& Y8*\mK46H21DP>dM#ꚹg!?>"vA;ݝܺMM $^#P!f= x[qu3@ժX,>O8 tzN<;ˇ38P _S߁]2MA^ yCt|J-^oyf4o9(/m't rRŠaG*u{.r^IqLM x~ܽn!8VTo"L v[E .s6KfsIr|N6fS4(7Z/NWRubr_k۾ pz7d);9< &m n ayCSva#o̕*a`B`y+ǣ|%i仜?u@ q\M=<)^QԨjFNjm}sQoȐo |o vZip˽B2aOkvdbEEk<)yfۈ. C}Hf+};qK0韟qN_,HE|J#1P؆6 }lF'`',@ć =yiC5wVæҟT]c꿐riJP53j'ф&SiP㷶},r_?ӭ^q Ja!gP& # sS]"CSjC1íMs{8w8,lmI}"kW`#kzbnGڶ~K:gx[; ŲW9:+ `~i%$l" 1K mվnU䐸ScUz!g)a28'FMCA@v,mjKwcy}nOODP 2K+pB*r畮u죃Uk2L74 0EB7؍_A~YTHB`W3joȥktkf!LԨߵP9o^sy'o>,CM{vHkJA}"|47wndn&rrSl`[c~Y  g.(H`(aն l]H]X8_KQe z}djG4%J68{%EN4QZ660P0b#6BYXܸ*C}q+7 UU#"[@Acp3~$U?{Y=31F}`CL=$+P!_i+٣4t+ȇAQ"g *ێ^3LNXVjog6ԛ : N) ܇sO܌tn8伾߅⤠2o9!s5rM-f-grpq4PJũ=} »FdO?ǣX.Fu}"w Ɵ|?5 ý.#"&]5;;<1ܽq]nA PzDwS6MDkaP8-dOXlI sBWI蜹07 qi;,/]am] x@eAgt[鵚Hi%4?bޚL|qn]Q!zSm؄ԡO%~kҐ:5mtb 4N݉.~avD2,5.d7xtђ|0?Uw*=4cy(!M oCF<.R_!luӬw`|+7@bе pK?uityU? , (fqw b  ޽Po1E E9D5ys蟾'5׭/NPEaEEcp.p*<Ǎ8²­ر}O˻~q4 g^dڱ #_ Jh|)\?wKu1?C/l_e$86*:J>JP6hV lOϜ.W 2vl+>2A_HE> X(N0校Hdl'}Mbȥ BD> @hbH=&u&՞ c4) 2K;44D#IWX$o]pPʸman+kTrI$AZ){L-IVؽ'iĉ P%xgqe`i3佷x g|x g+^:gRtnٖ<3'٥ke{~Z R*R+-$9%Y `Qi`XbQ{Opv?o^5\ h'~ |o?B_M!8P0sVL 1صQnH;\qSuY 秒YfOT.<[1J wG\-KAk]p2t=]MXuZĩ?SWG2M]<BN_`XKM׶HտjV`K`RsRL*NWr4V^ tle$UΥzA&i \b=mIQ,F\7ў&r7d R+EXmb4o2c WyR֜<˕ B?Y9rܭ]l_=jBpí/Mud Jpta۱6E &E&G{i9,N{1?2jT>"P}R* ,I+;3#S{WИfu;'Not+OƔԆ3gB&zU W~ X{ wJ9 "'C2xb@YCQ"` x"F*(2DlhF 7)śhL{ 3)zލ9@~5K=eGޅHZIĖd}wHf'4 7aTW!Ajjx(b)`f]%hIEqȅ*4P`*W4#y(lr52ҳXBhBPcHg6;hV`([힕gK! {dLպ &m.K1zW,X&oDezDe4Iy:]X{M;ai 9˳(,h{T .H .RfRv-Rs6w7wyJڙ`Nͦ_|:>yV 5Tpe:1Ƒ%،!|N*9 r֌rW&_g^hqERCYXJѽ$B ˎr_cj԰m@ WVOtZ4h n. ;Ƞ1eZ2mPqR4 p|.*X>LV~ҕ~2e QP\\s@n02\J/lrno#@GCXOo&4_t4oW톢d&v"ڀf*tOYH 2]3J$&hF#@(.;dՇ 3ݰj)Zoܻ"^w^2vs6|f.f!A_:E`IӲߔr1:נ *lG7)L;%Z,t?VȀ*[N\xt˳U7a tROαgZ_e&u2:dMxv7nȸYIF)]PrpuVTV#yرO17-GsfxA$j֫Cm$,~r3&-bDh7 }՞,p%ƲI[iVƂd4n/B`x ?yQv#/'V̞|U``<M?V<>9 N|SҙhB?n5Cm6UQ> "MFe3F}@ >8S޻s*=/|akry=PU'=)~<3 -DGI%M#s jkwHȿq%#â3aMS*MSՀ<'P +.R![Ċ ޯrf\&::;6_J.3bȶB?}W2u^doCp ?Хk&JG܃?ؖ#;!^J{_ZKz[#֟a):ec&#Ձp&a?O["v]5f_W`D c’W᧧6, D.}(4BԔp@s3 ?߅9x@Us5*2S89*dȨXE5ͽ.m1BؒG ӨLqu틅hx?_]h/Ӯ<0x)e,kJ+jYuL!VQ%W%m 811ٔ}J,8!Ra&W_f.Xsj!C { xζAb v;9<@hsAKp<i9q$2,gVgcOf\w"1?]x+vۖoJ.cknX;!>ZT 0>]P~"eQpqLvu(PIڼaXFT8XiyioHU1Z6Z !pp[z@w^oB!4xF|ffj[sm]fC6QA?nB3݀GE Bגtⰲ17Uz/}, X)s ɳw} 6.N>TqTgQЪ=Z32We)5sCU$GK̃:`6aq2%'7Se7L.?[@-_҉}'߆[O؍>$W0BSZ,%(C3a-BNs-l[Iu½Hz/oX>?ɮg$[Bπ\wX*VjnW+i1GXLq:wLēIA'= g^e6~쥔pklԠ,4;S|=4 o)Ըe44kcFN nOb~A{k۵M)><"kS?r&CE%gl58i'EDfAԼA!K R>W*_ DsE4̛( XHo!IQCâ=T2~vE1czU#:nK# Ҵ;Q/ ̢2Ǵ*Wqq!`aTP:*-?/O\6:f "!k=\r|xwжHw7%񉀍]+;m樨W>طxRωfj\>_!lc2Kl{҇r03|6n߶M, $;(CVW 2^_ږ;fmz'5#ds2pOAr$ș+ ˸]!ƍa x{,П̉= _[ t ˸:bkkGY)O|t-nN kk{.9}l4K.pMLb,vg>V塑(䇆g6>dy4:HkL_WB&\ ֶHNI?[w: uwl>?a[Gﲌ}jBO oHdq +jVTFұuV>]=6@S/@PH!) +kY6HڪׅNyi>ݤa/xbDSa~!q a a{丑)O7)YNCY` @SX-Ngri6,o~DP?X MO=s+ȊB 1ZqZAi7`{u:@j l k۶Wkbpfs? MD=x_o"ZzQs2ʶAE ,,ՏRNNؘ%K!K?,j6ezUdԳ\^Ű|1= T-}Ӫyll4^) .>.ٹ\4Ics5)U!¿Ti\zіLٸհR rb0=/#>b<&.3τd{Lx:^*Fмܦ _.}v"׉D /amukz)}, i5OC/#49A2LbM;~q֒^YB.7sG8Hv ,D˛`ip^H$~pQ#TVbpYm=-ʀ٩ɢ?DŽ}}k;]+.d)$ͻߎzw]zRiv[C&&=E\p=R4/̉,@]1׋} 5-I3ʝ{QȖ*ͦ {bK$7hK '/!Ik3ow|.PWCi'E'LvUH?㄂2"m Q8+%r o.K8^3%Vѧuyq7BQxד!=So:KcӀqL,pkҰKNe kambAV{ -OD{g@SȎ+Ow%@zyhH+FKyiEQہZ"C%QiִJ<%r:gքCSWft-q}[Ȭ:,U5w.1p3USyg Baّj"oF?e8JS0|ssQqر.U[uh?wS4)@x{"V8ݦ[L'xM** Vv) EaouuuFcA-f[EX|C' bGoOWt٘e6),k^dRcݷ'tr_FgPKBvۣz9۝4(%>chXgk%J;ţ!F$]UX[Vz3'7t>h_RĐ75x#P𶿤m=[2e`+(L֒OIP؏G $v8#1(^7u'f T25 /i&-w静H;Tiauglq{d:x,ư,|QaVrWJgY4 nA݁~Y-v=֣dRY,I7l)9y~xYPlqΒ|~WxJlg;eJ߀9Ag1ߌ ψp9k}=Hʳ#)L՘=AKL;wlKZgbr:<бNb/sM?`(TCo..|D>PG "TnH%#o'=!Ε \p&Y&2CT q7WLEFu ܉ K0pVpG5_t݅^\q)816'L;+ENke5}s j1 r(`h)]za=i`,..h2^~Ը+!ňD'wϕ\B4,[̩/~mY}P//QXgŚPFkL줱<-tܕFHϚB+ӵgKugmtMaXZTys!Uv/ܳ R>i!F3j_ş4I:$jBU~g5ޠduɨ~u.C` |/ =xA!)X ---kPpS22%N7`? $:P]hl! EEx9˰c|+Ɖ:k {S/YTZ!rМg٘c@kek:r̺d#U0Hu)덧hfbf751<V.g9pvX8$`}BL;0Lt<~}2]qz?ۓcGލ$5B1s$O!)T7kWr .U ZVffO|7VtL{塏D`FU6F #~tJ?YQ$`"7zԎ M0-;2Z-YMT?s;С4N܇\,qJN&5*O$t ֥FGi#;2l[UOuCb*k8[W?ddkwTI-E˰鹈1,ɞZQ{B0+7ݺo z1 x 6ix8nmOMW;#`@___stack_chk_guardQr@___stderrp@_environ@dyld_stub_binders@___errors@___memcpy_chks@___memset_chks@___sprintf_chks @___stack_chk_fails(@_atolls0@_callocs8@_execvps@@_exitsH@_fprintfsP@_getenvsX@_getpids`@_mallocsh@_memcmpsp@_memsetsx@_putenvs@_sscanfs@_stat$INODE64s@_strdups@_strerrors@_strlens@_time__mh_execute_headeraP "<BEa!/=L^q|    __mh_execute_header___error___memcpy_chk___memset_chk___sprintf_chk___stack_chk_fail___stack_chk_guard___stderrp_atoll_calloc_environ_execvp_exit_fprintf_getenv_getpid_malloc_memcmp_memset_putenv_sscanf_stat$INODE64_strdup_strerror_strlen_timedyld_stub_binderradr://5614542bitsnpicas-2.1.1+ds/main/java/BitsNPicas/dep/universalJavaApplicationStub-MacOS11.0000077500000000000000000002430201506470510200277130ustar00rootroot00000000000000 H__PAGEZERO__TEXT@@__text__TEXT0' 0__stubs__TEXT==__stub_helper__TEXT|>|>__cstring__TEXTh?Ph?__unwind_info__TEXT?H?__DATA_CONST@@@@__got__DATA_CONST@ @8__DATA__la_symbol_ptr__DATA__data__DATA__bss__DATA`<H__LINKEDIT@@"0@@HP@`AXBD8 PD0 /usr/lib/dyldۀɔ0̎FdA2   a*(< 8< /usr/lib/libSystem.B.dylib&@B)XBUH  y s  l H5q Z R <]fDUHH}uHEHE} H @4 @uE= @= HM HU}LcBD AD  LEA4 A4@u A4  <bHEHHEMM4]f.DUHH}uHEHE}/ '  H5% EM= @=  ʊ ʈE ʈ  DEADEM HUD A1D HUHHUMMI]@UHHPH`H HHEHHK DžH1HHϺH HhH`xptHEH0HEHHEHHHǾbDžH + H HUH9щHP]  f.DUHH}Hu1H}E$1HMH9EHEHH;EMEHEHHE1H}EHEH8ME"HEH@HMHHEHHE]ÐUHHPH HHEF HcHH HH5H)HH=KHHϾHHϾ1HLH HHHHb1HcHHLDHHH HeHKDžLHH5J HHXHH;D1H H9H+HcHH+ DžH > H HUH9щHP]$ fUH]f.UHH`}HuHEHHEH}H=RHEH}'HH8H5/1ɈE}aEYH BIHRHϾH 'IHHϾAcH IHHϾHEHHHH)1ɉHE|HUH9HHHHEHHHHǾ HHHlHǾHhHHHǾH=NHH=HHHǾzH#HHHǾpH HH HǾFH=H5dHGHHEHGHoHǾ}HGHoHEE HcHEH} HEv}HEGHHǾ=4HGHH0HGHHEHFHPHǾ'HFH!HǾ HFH<HǾHFH<HǾHFHHǾH=H5HGFH<HEXHEH} HE2H} H<H EH!HUHHHκHHEm=S(HEH} HE1HEHH}LEHHHEHEEHEHHMȋUԉփuHcH}3m#H EHPHMȋUԉփuHcH=V#HDHlHMȋUԉփuHcHHEHMȋUԉփuHcH=DHEȋMԉʃUHcH=DH<} E܉E 1EEE؋E;E1HEM؉ʃUHcHHuȋMԉʃUHcHHDHHMHcUHHuHTH CHHMHEH`]fDUHHPE}Hu}HuH HUHBH9HEHH}HUDAHgH cHEHM88HEH1HEHEHMHyHEHEH@HEHHEHEH}H5HUHMLEIIAEDHP]Ð%B%B%B%B% B% B%B%B%B%B%B%B%B%B%B% B%"B%$B%&B%(B%*B%,BL-BAS%hhh#h7hLhdhqhhhhhxhnhdhZhPhFh 044=4 >>>>>>>>>>>>???"?,?6?@?J?T?^?ʤ-Zx,gu,_v& RvBv4YC0!j<ma>)V@1? ^D L= '5Sh<ĥx CxĠ,?hЍ*Ò` Ȋ ׎.޽lˉl̮DS%z_ohJP6%s͑'*<{($[͸s)oU|nbfq969J=dgނ^f\Wped*wֳanPjZz<k5}D-kʲx8)Ph|.JSbG0)&Єڇ PLn^Bjs)7RO;1qd -DQ_NvxwQm2[)(}x| #gEYxhFѡé./|kɣ5\1x0! z*Y KsHt{fLRw)MӹHvMRDmhNVf)&zz<P`PJ2fm㡚iQɞ!=oY/]/ᡅo$* GTlqbL>?wbS%q%%Cs>Yܟ AZ2'%"d~=L~u>#FտDwDR_֑yỴU8P]yX?D{aW{A/ \#{N\֙h<ʑ!:7e=R1]iC找A̒0EzFEoP^:I|NN30ؿ>`D,r ?m]WMn>sXAY}z$qodw05~TiLX2}j@ՋBJ(w)ptC.yzL?$]Ϗ$eHū}m 'D ScuZA_GE( sR^U,t,v[Һ1!v]8S9ܽ./&^6:Yr 3LY5x Q+k1['R|d))6C &`%g-5i4بSq5JlDmA_)v~FH66I )`OeJ,k dM?к}}ziTK/ F)zߴPxkڥ8R6w:)G<9I&׉ ƾ1F/8[B{m; |÷)&J}m'krn,NҞېԉ.-frp٣6-O…"ppa! j1vv5uX/` fnÙ{IR :&Ft!qjX3ؑ*a.kY&-R.tuMHT,b\fNC?)-Nݤ*yQmP50}CvLpXKi22PFb\T)}_T&g?(*oBO"P綐wdAosN ^ٻ`M]BI| (b)Y L ; ΟJl8%_~`b!FSB'J+iZ٦WndT4 q:/϶Rl-C2ܦ& 8NzWhg֛T2ߖOBm@EHKc(uߟTd'1Gc=[="' 6c?mVh:f4&\#y%f1#hZPn_|#UU?Oe!dSd﹫\ Jn ]Tu\W,<-wZl)#h0)*[叱lNOrh23`6&)^igoȅ1Tƻ(=5HগDK~WlN`ETȟ'-1}4]VjZ(h }j4TC>~2ُc:22sL`~m|JZ<3BzCtFyop;b ??/ i1=pqIG&%1P^L*"HؒNa3U[ f,.9fGN0:\ϻn֎u-/<GrdjV9̤TB\G{@QF<DXnOݬ'c2W-=0WX^6Cp9 bSXhװgk~Ku򱞚a]$=_n2YUwzj=M`v!e%!d\kM,ӠPlvon{'9(\ʼnXݞ[.~E ǟ8!ukOw'Xw_,\_i"' wgDmRب );05(G & ̈.fTz@v>38%+PbP!F& *`!b=rIufE1Qܡlh`\fKJTRAh~o`с;lBvA-SbKҜ"9g3U*wuw: yܯ/==ݿ [ཅ#Wɲl(aCnz 偸ab@]#=q Y^L7cg4ڵA By<eohE̶d4û0G J[  Cy,FՒ^41a =c[@"rPݸ#ZӺ-+?劯"t (]ϣZ0 orD%fL!aǖ{SY ,i/,M9c! y%΍I aV#idkhm(N875VA7oai, ud˓&\d\1 y6 S3]Gۦ-N#fUŧqmfe`u nlΚ.lǔB3"*nFu՟r $^jL7Ol|49VCf &@tzfE^)OstmKʠ8 8id!N2넻=1CT%KDz.'"ݪ.59{xD^VZ`{XwyL*]vĥh࠸@nbb@~<~0n 6 qefycNKgHni(]s֦$Z 7jhTJp\-4w(֦ KA=qf؊pzȱNO|41B؊e"pPe3m?R,,]1rMlՑDhAv4|>xFK%lI% ?j6VˊhRb~R=W\b3 iVDDf ;-cB'CBqPҹMf[@DMBROLPcα 0D$F #4>(+ۨBXs3vb*lN((Q?~v2M {3 c^yi ܕ儶wj83kC#N&Z"jg¢vrF$NTy%3[K$218b%lό&>ƈxֆOnp7N?)U➬=|}+βlj!+~8 {IyC}A0sDU?O,% @usM41MʱkENF6lpʊ?Xwu7Cեvl2 4K80bF,}mo]/r pj>̤xG2,H稤d'k@RFԡ/^t5#_zx=%NXOm waɝߐp BRoau+V&Lܕ_I:gE=uZp`/iըI(9|$#^'l)>v yNvJydO-:=4qBwhv)06m%Ї"&y32uP3ם#򰖊¹ ^!|TC omACnl.QG,+" , q"Ҭh@z75ؕ%|=+YqmhvJ[ Yy4մVCUC`!o ] h\ 7u4M}( :ի-^Z+:K((pďA? LH3""JlkkEϐlpKn*Ew)[wل@*Ct>Q .n4t@TjF7g.I%<]ϡm%DH}A$J[ʕTOFڧšYCԯLط>Z;eK36i!ISo{͋N9YJCDoա8zU :Ͻ2:&dB焕 g/sAs*bdzxSܞF2wW"uT j^s. ^2%Xοجׂs~mnj|XD[S}E7I̲MF/p+U_nŸ5, A\ <AzՃ1:3{!=يn8` towRhPֿc>glaTDZȪ;I Q4ZJ>ė R.tGD^X:L8@Wn{.mu@ԈؙUWt{tipAam` rojfZe`V;cd2BWlhъ-}: uW)% '+do*<8ϲ]%BI$ʜ凓^!vMLu]sK6$ٹ)VASX%dZi͠o,h>xZץtR@G~kdO/*\9ů,*bAߣsN^!D9k뫷2oV5vggLg &9V8zi0q._oYڝ6ޮ{t'ݶq>q 09DM~5K[uK)kP}/~P~lAχeumiSz^ {WW~>D1襟M> .5cejh< Eı/}pE&ǒUұSlm\_ɯ; x} )4n]Mp8QO_ÇсF}W 8U$&Uxſ Y T~ʤ,֎Ƴ a00Un0lFvsԗt^mW]<h \F'N>\cqLfaYzz_A\c?_/"aÎg8n3S@0i=lEV,|:^tɾJ~r^-Zwi}Yze'4QdBH5nfRvj6y8I釧sVI8ozZ/!][XOt5l,l/~* XuUS` yzb8PR ǿBTi1tR8K{TbUeD]kQ_Hwݵ38O)Η+ ŢܮYe}Q/f"T౅"fO'U>ws.M 9"N)b?;0 ӺوqGTF")o#Ub6 {/G?a;AˋKO:*״>I楲5!x^)&Y5j 7fhChoD)#6k|FI#]C מּ%Atd=Qql@?8* VB9=wX~|í$djSһ~-M6NnI=֯3gBC|__, `UE;r⦬c7LXZB$zdark#GNf ^_Ծ>;z.(`}A]dR p%=,*f^Oە^-:}KP6HYM2*ljf 2iyZTIo"yEVv&?j۳$nsS'OJ[M][yvZ[%_l^ Ĩqgo7.U{H qF͆L07[mcҟQU?bEҋ|ɍ8Q>D&wpH8_(G]Z)p'_o赩=:fW %7һhl"YvF [`Q{H3(YƹXtR Oʰ6p䉞t)KI~:VS1aLCem,A37V#A&r۵+S.vV+Ut%F,0fzAH2KG8!ANy>ѐ G·\ 6tP|"3m!#ggq}z?/²d֊oAyEJq3NkI$"vŢ#"cF?u35o|舚qum ~I'${I}iNv &*Ɇml4OS^)FYjmo^̓mKs=*ʦ( hZuת[ܗs-Kb(rsAi0xG]s=hYL|dq&k@t,p]-3bZ[* ['F 8gKd,VNu7 ATzz`5ўI$WqO# Jc3qwD9!kpx0I [-LgOb1-N;Tn\^Aq@SSpK~I6^-l[]7Wb}Ls`2?c9jC UbѰvܟJw8Htə9$GP~[穧7y/(09Np:kS +!]fR=ŠZ \VSG@ зʋ\gMӶFZ̭5Uyy` \m:5Ext#0,QFC;QbJgw =:vya N~"ރIb]R029d>DN~Ae7l)'v5_Ίu+ Gdcqa>=t}-S .nvw:2~Qt!c6¤Y9xlTl"V^:G:u— )u& g յz Xh)"FJ/o$'6?mD rj0c&˅?I:`sZWT'8*M9>R1>5N6V ݎO⚶N Ƙ@v41ߥ*1,`rn[xObٜ<$:.H]zsPaԤut>K0_FBrHڪ#"F)]QPb=wn'L")LLQ 78: Ik}k9g1 ^ gQ◢k4]a2^KDkݳc~)h;}?NET0S"רKavݤ qf2;a4hPp pl2~"Hû1Y0_u~py@3sm vS SYqV;~]O %',MoK~tգ!Rqǔ)ۆ0dN!ū(pJ`OqBpMF<)&r;,0ϳ*,< ImCクFd~BvM7jX;!Vބ!yjG"Xzşv!;5,Jkv._x<Zy_oj4x ̠R&`{WVsW13l183NNPlb*w琔1o=#ev1boZelocNHß~jb7#_nk1jW^@wq O k1\&F7K{P`]qOVdex-3IqSO>\c(O( _|E/=J yV ^;PS|_rw6hsCA*lj}I.C!QƽsvgScIAʵu:m֞n V)Fce~ɷje z+t 5Ibrހߓ8ak&-z |ȝ'?@`zgGN1F]6X0iQT}kb3g)QW"2(TJ\\eG~:^;l.:|1t ?"dRX\-ZnSv1y k`KD V׶4m:#a}¹Lį< |wg-^8.[.y*v~'ұvwH>ÁFLI'45Q{__f\lP1W(۳l-/H!iK(:! a~޾[b5Fsol '5#gq}z0~? uK3VISMgg@߮ڪ(i4'N8o5{!^'xw e^]d\{Yù6t֛i:_5fHat;:@uyqila hܷ_\Ka+ƈ[f4˗[.b؎w?Ɔ,{빎7R90ӷڐ96Yvsno&(o#fI,An V: :ܢxPVANPhBa@1L6L0 ʀ— X3q{TlH(s3$B:i?-6o]r2ư̜y 8*V AAAP'WA4qfZ~B[V$`6fjw>K;$h/$,;K8 39ws[,ױHCn`gMm ;IM('e QfK p*y"KP q!T6uW/_lM5GJbe-`Hxbm:NMk3-P@BKsqf[q 5)eWdSCmžMo7z]VQNQITKl[,}!9RLj*BD g4Ùr7m!@q1Ƥn?RC-7-y[Ѣ,tTطGzl=TnC*+3K"\֡JF}`p'5'F^8|TƔ얦^z6BQ7a;ҵ_c `]}ׄ*cH @T 9^jwic_$,E"XR3v͜DmI#<>bB_f-Έ8nn{ SMO8#?ov"*TAKT2OK7/0V['s*g6o7Nx|̊$w~AX3f\Oy#K5A\A/`A|bc%r~- ɔ#-ҠȖ>^z/匽A!@uvLP [`wm>b̀1 l.0q` z"BTy.=̝)ㆊ7hޤH ><?QM|_۴-EX7s/ )36[P#8V`SFsg%yðf@U hzF @R LJE͸J;x ?x!3)JmO=kI"vq QR\k Kk落p*_7<0KD|{Ԗ@ΡBdX9FBF8)$:/ ǚUe,!bXgdcps)ꙉ rF^7# ԋ+f W:Ay⩁ed&/SJ]NF`Q؝!lZ_vsӕ' :_E߂k{k[.TALפ8cN"1'D~jO̠]D!)qy-kEԾNd`39:ec;=MT,_Vp K&3^Oյq= O`R)T{{HH;OҢ%MP+ CL9…ak^c[BB z%wA.ِC Uxdmu)2R %w3FKJU4'tbA:9.& rE2SR{>/ 9_A.Z8)X8꡺V^eLMU*TiU3{.+-+{P4/KX|tI``֣T_6akv-x _au*;* CL7qDY V Kn>vr+w^Tr%]JI?H$94#KT)YgorfȰUFnKE=~ bnIGOK2ek3z\-Ce k*pkˑۂkx C\L2d5:;s՗0 8[v IX%z~s?FŒ^v9݆=oDՍCSu`Ʀ@X༠UcAi}LY͑ng$^R|tTB ݥgչ {^g4fR´6Sm8uW2Fŝf_Bhj_Gl\ޱOժjFdJI'|ٻ3-ۡ$[ʄdݖ?<)mp&6G4ڙl෵ixF})@XcS-tiabeB*# YH%ݟ 0 r)zmChmV&۾C0g.; |0{,n ryoR Uʶ"%:B t]9:̌?:` eG<6l|g:HJ $ |CI,XASDj!Ol?` +|PAT%R/B-v\Mzg*4.OÊ\O kLsFwlul.WA5TS}1Sk17 8žͱ=z(Hbgqv(C͢9x8h`[u\-4iD] Uz W9B_+?ԙ:}Dm-gꮧjyFԻ:K2 0%.۬)M5Jzp+}t !f'?f!D㚏_-0k~Bgq*=m&.Gu]DgZ O0U-%[ZYUbkij3=&6a_IhR4()JaΑu3vhF)eNh2)=%6aO_<,_(l @z*%39#C}נwbéihea|swJvAOogOOv1}vf~j;r<9ٽ^= /NI(I؄\NQgZ㎶LEDS:| 6Ds'5*-]U!E]pyib^_6;Iï| wHH*T`6rrwluWYj+WOv9l~k0l'*_c=Fz"F$UT\菴FUׂ꽋|,iaC&6Q,ݚ3)LqTllVӔ^VGLGmHn L@΀&p$/bצ?ó}Q'La|G ;Eӯ8t],+Z.7Ge/ Tawo|0iq'hOOCϸsBb6,XX+ #ehOŞu=3HHZ24 ׶,\EC!zG`{цf=y-xf̊A2b`]37m|8v^]J Ӫ_59 ے5+y(˪#Hb?/,8BqV7"NFVߧ%t]08^ q4zF'G1B8v zʤǦ~k[/)mPu8ʅ~i ܰ.h+}!VPXsY[-1;s^8>;\qՀJROgHݮBqPy~c0t}~^St^PhEPV݌n] 7ab'B`ې q.^Wwt |jNʑ. VΙ? OsfyOie/Żֹ3[l:[M0Z5C+i,xTW VLq̩J/o{4>6d1/JzR{!YٍҘ^Ԯ~qHn!X,9!bHFuɖk߹`LXkJޤ%34Y0{x5 _"hfۓ3b=E;4Qq쑶P9ymD@oIЉ lyϺ*4C˻4z@K5o w# w-]oϘ ȚCe> G#,"H'9 *;",m{Caz?V(oHaSA|Hd%߇_Wcb[뵒bFS;`f*C* mƫġ$TJlj=тcTՊK?2iSx ;C!R6G?LM8$F&2|>zchȼCCq}Y?~U  2X"chHq2*9p$&MzKig}x\+Ozmv3txhZf;tQh1x'~{ kvIpEG ^) ڽ@#jJTN +}?ac#L5* 0p*moz9O>б3#VD1?:I) PlG.u`mĖ>Cw]}'BKoA<6AyKfnvoBkeY9(7ƫxJ(_H_^6gc!?[ǁ.aru?I_vJrQ& ]iݛ6폴.X!7yIJ v$9ATG%5D$(. ,M2P7T!d; v%FMۑW9?T3X萮J.l1 P"7O",6ؓ.($⛭Di!궏\ @_BT_R ]w:oD8+&m=5' &Ҝ)  A).*xۍ̝ω+7d<$mɯ! JTzpznݻ(o+BiZosjF;>H?i 4 K&y1F@q;[+Ś73=ɳ~;G=@oc`tS:R!ln]ȧ< ALUDS\/75).{CJ>q2"@h ̀lU!YzHާnAXA+<>g{w+Rq3K! SpxWWq'I!'IMX̲*phiY)(!:޻h0jlds-x2)TG?L'9}gȹs7®!q+FOx£Đߞb [OB:,Afjˡ}[SzįbF؂HsիjW&,i=]`~+wJ/ke.{؁ddOZ2"%˪ȫ@'|[^P؀u„FLp{>SfNډ`D*qM#v V_@t$=DX< -OTzᎦDqb4ĵtۡЏV`^fӹ#c]ƐD7͹S)DnW/9Q6\%,A* OFkI*^tUYNc8 h7+V~_c-kOiŠ#ŋ5!h 0mT<.XG :04ҬQdtS፤0(Q?caJ) | Ŧ>>\%3grP.ӐT mdSC0 L:jX{P `l YE~  xMR-P;ZJvFM{y ?~nc_ҊZq`Zjm0\ȅW=Ǔ6Kg$È`eNd8 =K'\m:i$SCbf9͖f]diw(ЂLlTVy[>p 0zu_gB7%VVX#Q-'1F&Z@ʄ.+): D̒Qv1U}4xCR3OxT;R|ezfˀFښ mKx~39-+\U8UPWzvvl2a0fprm㔜 fjјJBbG$E0:laiw Zxb$Uu2 Dn-njc5,yxE,6]~B-tA^CJLA1Žzx&ܐ/)Z0P*!hl4 yG3r,tj)<ؗ ؾrv Kt>ۅO."L}s_[\v2%lw/y@4jAMJKaʜg"S#m<7yyf>'mBǐgoz^[Y65gUжYcjQFEQΤ\ K0KZ1.pcA$l33`1p4BQp_w8n-N8z)<]L35QQ=$! N@knFC 2*6$'J. {A[ h4Hs cy7JaB+|"tH!|Y[!._قGƋ>4W*鞥0K`i z*zhѬ |L5 "M5]kiWz]9k}19wA?RŻp-§",V%%|)A)ZwE=^Wn(#>?!IX"n)oVzpjg Ug9s\  .wKId;HjЀvpߪoTVG9bV1<Ã'mm-P{L@~m3/bHE\c;`R`p6֒3@pU cH\% gF̐=h'~"0ޭ 8kAU0{+_&bs GOK1G2ԩ*Ym`f((Kcxn3$z>dYs$8C|D.'`ɍiaq|, j@{a:&xA7jRް4&?Y9 9NmHʠLxsk<i]\#W5C4F,?JCN6Gώq#bҡdva\qtÎ#=A;JXv||=!' kPFHpA@*?xC&!L<U*Lr =**T] /9[ :ojQ~KykԼF?i9EPf*&`X'޺S.3_q-[8Y|x(vS(Jh#\KiUJ;G4Arid!1 g~}ԣ o>L9Zqέ0be' pTU04bX#@O̜nswL[ƋDgߏ dID(r, p68J ~z >N gkuhн+2g+38N瀇j[P~o/K%v⺾ؠeqBr]}~CиVᴛ0 O6Moƙd[j0/f-G Tow4+Yo<se-ߑxuFY€gIȰPZ=N9L9Cb3Nn/L}$N^$7O׸cYTmNVdlR 5wa~RSy|L{9u 4E+6Z,SHϡpZXǾUէ/Ays󽻩}iZEUTw%$G*]4Zl"5J&D(Dt`.MƇ8q%_Hu"/8 Pl 0Rnk)H4er}pЧA_߃V{#r?Aٜ5eC/L0u}rzNQ=HkޗQ&GоD4vldDsvϧ]0[T\LP0r|ͿF_@GhR$m&Qߎ!K>}UqHW1dl2pH%&&i"42ڰJQѣ1vg3}znv^q;>>7F(wZoVo1 _QXzܞgCJ}046.d0|SQbASapgyh7?I&׶sZUQcM}f㠀02̼#d!Sʺsr ?3; lܨ8s[,H}8!5~G5I饴k9ϐfa/ToIŹTzJn˧m.9JkAa")BpZL_?_k!QkSzn&V- Q|`&{x8wz?A@, "n;3$XZɹ'br7M_btqp3,r1 p6nnMht+r+FW׼$ڜ`;;U.n39 ,ᄋ({;zuFrV.NO %NƑ;AznLbf٘Q>uPaoDmu!5hCGw6 ͳH.=3Hk{HĂz3O}&lmbK'>:G|ޓATj: \<,5U>apJ*MKuq}v/D-S'59fũ {< S6БArqYqѤPxdPh5?ώ"=-~S9Q @}+ܳUp@̴lup")MtWxTm9>'Av$Y7#'lӍЍ17: 8IMJkg9ܣ/qح-P+9_+'nԿ"P4b8j)E4HxvDh15; ٩ 94n_} !B"bƘTfa8Ea{ҡ=đ o$&wf@_VnHɚ]uq:bђT§rB3 )RVٟѭ i1H߲fo"%|z+L-t=)%ӖY)EއN y|BLkhaI~E xαE2л܀87/<v#Y@i]b !7TW#Eu0a/VIXWSN"uie ɵ0a;U"OLȽTR /ϮZOs#= eQSf3Nx(=Ӑm媱J) |~2@2+{~7HD%}l\S4I(}y0h6HUɜn @WFDwFMJV beЀjWt(CZU]GEfq~H\]mo#Hp&To/44;ULb-tZι{eazG`&* R.9k8J!zL-znPC, A.CIE c8 %&( )Tfm.$ƲF7Mug '>QS cP˗|\rجRgwE^SMQJ:H9V+CCl2n#h^Xy~ld ꖟ1Q h}񧆉L, \ڣXr|ƅ91A չKUodRN(Gz yJp8 Q% ^ Y( >c1w6N?se 5xr06/KuE{ r"}37#80csp $e1=2nGiIDm?C>D,Y *k}u_wrZJ*Q7ۺ pdž>s Bߴ 7,/L/I-~&rgXaYÝ*u"s@U_8 =Ti1OXs3B%0*#FoȊcBus IEQሞLpߠV\6lg$Cfk>{G-tq|ނ??dPXy4z*kC!^0;}'eE3Ys2{om9T$O%[@F\4~DmNZ%rpi@c'|e/6UH(jdhMϑ o+Ecc:2 CtjP)_ZGePX?!` ȲCWr-,?mjPPB[l&׀H%GhOi@ΠCuc,~c\b^KN, 7}3_eldqZ눺BYGjۯaIGGIDWhE6 G"}f{BAA0iXjW^G6%'$8:VK/fuX}/6mjTWՈr߆jy[^#<=#.:Eq&VȌ*\m?n̉a}ȟ"l#,Wj:`rv3ɲe$6d,@n03k} j^zTIde쏬\l .GLuq-wZ;#dsMez{D ESi= Ϭb0刀iCu#lV4KU =lCf l{Nb[钇#.?//NQ#,ssGy44TǓdX`=p~~&zVZbo$wvWG*gOBSGRGR24ϊ؛@<Ѥ'g|9-wRk[dowīi]ؿ>5%[z=3Rl/tI&}qK s6X6p:8^d`0Won~xd^gzrzzƹD,xgh#U]J)eD_LsU2q{uf`) lZ*k!M;mJTj2oeE^wVL'(F#BpcHN|vcR,2\:ho5:Q7RL4 λum1[7 }6vO}Ha'čӮDI|Zxn m8QE. Jv뇵p{շzB4O7\,E=l)j (Kl.`=I _[=*ce(2#!+H5ME01@oQfΡ,@3rv('_^3Aud[CCGdoK{}dǧOci<;TnUޏGeGfF/Ҙ=^dw<O%7 uRFzv V.P(S۹$8L;d6=Jc9cEI!hO D:DMX* hyV0dB>p+VPr]֗3%6Q16̪F;[J6ҍn^ 28Sԇ\άD}j<9ARoѠǃ ,BHrQr&lqВZq8k.}2@]&Q]i0-{_p| %6aƣinEY9i Yrhb˸7Α_(thqC`\}ZnZq fjYMٰtk_&|lPyE(N!YOplr#׸cdޒb}~}ӲƂ/WKj `hƞPFI"_ns3ZՖ^RTvaJXhzGBC0EwO4<.);':7vnBTHXhRHޢk8QN~R;WژH!B,7R):6;jC=}9t-DtZ&>720IJ@ݹwyv]ŽeFɔKAGL SGŔ5u`lr=38w"ҢYd&耵X'ܩ"I rN+UgCCiIRBٌ6V:n>H?Ҟ1u0hk&Q\\S2n"R"AqZ'tĬxSW -e_7 oɉg.k0 Xe5wM ۗlj-|OpZf0iHJ=tYccē9*1Ŀ; '+# .gHHTgYuaG#uΉQк?=d!nCP~Gms!Y.,>vT"aPLʼ?b~n{UCb5Q;9+- Xt; e$&h-IT!,i_9nqW:'~XJY%Mr!7U!iD~=ŷjwqZ8)1Cs#0io:?/SO`z!I,ۘN@]mMZ;^-톶௤ł1qQdx(TbxEn6`"aɴh-ˈʅ9C/o]é.C?9%1%Bx|_Аdr|7||L yu}fj{>Pj6BQ GޚN2f\<_ 4ӯH!l yn%%]aDlZ)e$E*Yԍ\~xf݂OhBT ,? ]ʗKkq`/pt/Ud0U !0; :Q_Jl,$v]^զv.:HG Qpc&%ڝ~8I/l9N[(d2F|x7TܜDxY9Hd(m ,I{!K ,v5ID6LcCAPa }zVQPso h=C?y^{8krk:H|`&|K(Gl_dD?K#W9{Fy%5IBY >\2Su+67V)vf=Oe9r[0RgR` #{Znō}JZdd/}_{~@xLhUG-T.EpQL_(#4>rn0~kAĤa߬"صW6+.!ϪGÙo%q! !rX$L@6Eh+[՜A$vɯ9=z_^gTRoiLHdx}FSNֈql30@=bRǿvy5iZN5A yV:2%hB+J8<+@˛-xܙ៞-N 1NWw%w }O4R _Hsty28R+.&;m >5cbQ=O9kM`xo_'譐'>^pw+l<\ a46Fݓs<D7 <:jD~Y!WO 69.!VQ4VL0wV FQ38>3tR'Zy|K YdSK҅Db*L0K1*uY%a94Ҧ K9 idc0|mQ*oZ|44ւpchv25nq^X}΅S з"O 9mqtbQA^qk'qDVLޗ| ڳZeɳ}AE$X"DzŬ%8.[@ }oFT5{`*..ꘆkGx*w?6B[FW7Kbm{M11,㵬N@x70c_N(. `PM.ƞ.EMt%dn\LΤ&fCo_;ucd\. ~EG(h~N%%è$̓n؃Ls NZȁ@OgC\c~QA"ҥ9?mo-Qf5턫DwI;`!qN1v[5o cC,*{?eaߙN`ǹ1gy<<>bD~NDӦ+6_xW?HP8/$k"ي2#@it=ǂp ӟQ0Oe|sl88 v?qwure3L N<bgBB/(EI8KV#_:rE¹!I;VrD#2 BjW\&ݚM$OB_ `TzEAs,ʅ)o8okz#͖% J~H > KYWk8i"8$:v]=ђyv~D?ʎYnŞ#Y8@"p%uvv녵BĪnqwc߾#W6brԇF%Z~O]94IS`t.f"k:0e ؟>x p%:p5F ZNMxG ^랅/2W|Q@%.Ӆ[μz+mX9[AyeP.5 Z [7<; c9ySU E~M2>B1xQ!,g8ұOF'kg!ļ([-J {BM!&T*4tNy !d?'K[k-YEO(DYԺu/L,4o'Ư$Yw}ooڪt#'H jYՋK 3@ nE'ہKTTޡOE]ۭC@DNCLm1fn0k05j<<@b-6hl& S ߑs:sNߕm`ObobHYS!Dx@@ϛgIK9mUbiQ{;yڡv!NeN2(fmv}\ SqS׿͟غYFi{+δ;NGu$?:E)` Rb< l';O)\aF).c1~ @ie]<}%!0fdŹsRH~  WOv_1rȚ5EB4 dT(ߵ!p9*ƮHj*A*MpKߦ/d'~Zv"BNđLD a` ;:K]49TLwN~DŭP'Zf~_CyI)Ek](yIZ176Fo?9El5[}Z,j+f_ VP}1 0c8SzJnwYS0p@)ʿFiT0I+48;oj^W5Y1 'v1< S4٫("(rC媜eT 'O5/2ɮLDRg|^%S8ZOߢ #0~p{攮3ndnn1b 7^8\ t]s`X7s(9"1 ,/|I98%8 vz"3|fkc@;3g;6e Z/Z9MeR,Gc: w8꾁xCt0@OJ1R|9C>!nDP""k0N:Vݴy&ޔ7:h'4^8|6YWؚaIpžhYU[; mc4IIX6 .ͯYF$?- іoTV4XSCMAJdzD=5lLMcxrW:7|Ls+umdRO])*3 * 5;Oı7ka`Ss׌xMF:鹖.{fȰ5Vi5FPŞx)P0!V0ǥ+&V PM 7Rv8k ;|G3 ub-R@qϐu^'沦f7XG$hL1mdA̢52#ww&J01@d)mJ,@6D X(jK/:;&}W۽Pܾ 怙yQANEYP@ Z@6O& 9lk:4D^]~)Lܞl M~QzᶈNSD}:E}nFm4{H}撇]ӕp,2ÀG]LGuֿY:[w[53Tqu$e$m|-eMM[I|H+`U}hlxYELm6NM@|Urƴ8!xDeCmK<5!eEf0Muᙽ k,AvY7^lgȟFAWFL뇻M:0ZBbz5mG밫Gfc>sбGP-Hi4yDTj_ pX!,őڦ}j@=)Mr6W^M߷;0WTdU wjY}w)bFd=9$3>\ruxT-ijɉ+7ՐH9)j`M>O#UF=E1ojp\.a. 7 FSD⍡g:cEFi5xGt6v)& S/;@U a2vbu8EA~O-aP1ɞm)|l{KV!PPۃm]L|4VK%( Ǖ:F]vvȑ/`FUBB78(AlJ= yLw})Q)r-SH3 γ<<`[-m {Z'Qu)XDW< 8"ǞH*g`DMA`Yþq{(/U-V,x×$[9Y,|xR'֢i\E6O>IS|ZN i$\ތEICAfH>tXAzÀ@ éz%-PC)Dw]7F&ExYQcfI+H ;BA5% Dg[bat^,tW㯍Wkp<"lfD`+a)Y% q\-Ї'1]V$O>3~>67/xJ/h]1\)y>3@ [ņO(4ja9.*%b(_wz%X\ ?Dz $x/'9"«kM*3) d*۠+QB]t+}'C9ߜ,AwmݢD/}.-31ɇL%Dn_ "|"#O B{aBP1IjT끨 .MVQO^#Y?xW$،Wb\MG2NAf}2Qg"5<:օoeG'p8*Oľ@TN%"@_`cRgPxnJU'ψt%סO;UKŲ[g7 S*p p Q8v@O'udvIBe<(%)x :6G(bAG%sDݐb@1g0miw= ]C-J"z"e5r!Q(H퇻wc3bp%ort J6 ME.A,1Rd.Ҍ~aa^TAG~:.)234Ix&T8nXyBg3⚫9Fн+%ǟv ^c1=QW! 4H/4iJ'iʫ{s*πM~~ӭGsiK](S_gWؿ\2X\qg $;,GCR=@&uc Wxɕ,NH ԓzs 8yȸ /N޼'DuFߢ@mGC}\_b` t{KkN1g/ƋQhLct\hrWB]1# miHٖ?r^0{{Am'ls `_n|n :4Ck~G7&E 󗱢oF OLTQ0Vnk,E[JU) ~#}0cS{ӑ %Є&GJ RF)=X.ИK1i-vpm^tY5\nhxLa\Jqu{5z\a\!/3ϯ?_-svôdӂ/ހ~(N$B$ ZZBwμq &')RxyNL@4J"Y3m|tZfh{~!5mzѾ3]UTشkCu}R$_؛{L9cZytAWY0MMo/bږןԃDѦN뵗 o}7P _]lŒLc!t T"o}C؈ >NV|j4l0̴OLL%~~@d#)4?kgNG~y\̎h:UcRlA;\Pm>Xy[5YAUޗ{pLQ?O6Jrz-H\ Jn2{r~^%Aĩ 7\y)O@A()vX';8 Fox2ގU3Wdx'k?:|g=#)/Zc+r/RFj[ +\9.:ښqd+x4+Kk{ݒKHI!S7jo0r,WYc1I_77cE]CdƕrghM w{(}1\*f .wX]C`τo :.yv;^x.,li+?kQDF?&ɌB|l,S!>6Fz*,Q\#9>A,k 6qOwWyZ?& bNKSǠ5GPN7}RmP)\ M0 Mf:O󤐒7uda񠝍cK^{կbb6ĨSBr(̎G3X[?$Ca xk9M=̯0C]am/I!/)>?4,Ed @nE·Z8OY{&Z(_/t|#uh?P!Gӛb}_3k9WU: #p)OeP"֤A38|79 2uT<9}LQ,R)@C3A%{n*ڳ/ eLRh~fb~׹yX9I YC' :> :ce:p`H bR9CK?Z'a;ߓH(Z}riQγ2(R h6(ٹً[a%VJ 01ŊW5F-։cX],°krgS]4+Rd> zwF 5/* Ȯ:m|&l64Ne)Š78p1L?/^&QfeYloN{o}nAH$f% Aw^z\tk>O9=OuSΕi݊G,js ap EL%gqT= ^oe7Je5}l&C7WrSGWFO3pp@` Ҹ >ɪ>jo4_\VhE62C)k{?@&A9< bm')Ha,d0ZNsBǥC.7_$ū3X3'q_YvYjc3/WT:zC->kN@1ȀbyI}LQt1ĩOvӤ<:0#ի,V@cη$-pڰ$+A+œ9W>J0׶Ha֑njX*#=CvaiwsN\َ/6£ڀ4fڭJzC6.i1"U=z{72QG" %ǃg ;WQvd1UhzD"Gr͂?gbcX a-273PW5Nntn]Q}#fh(9f];WLfeYxeiÜsJK r_C] tBFG5/Dm F;i*55#wȔFI"}]CĹ:{;^8Z pEM?h .Ә>"*2ŀn2JZR€MMqkF wɦH7-¤2[)0o~g 'uM"t%KR>6;%8H,N#&!)MޤbܡKވ}{}:up}ySWحӞu/W@m*Q>fŎ3"X]1nBSAm;y\J"$J0VNZ/6#$ o9n8485O\Fmde)pjp[йdT0 @Y@pȯ "ƈh wpXgk,T˥8Kжɒ i*qRpf>dn~5- a&>/%cX l =0Fz>$@ʌ8-I*BB`蘻}]S}QRas:36 EgVKMISkGFfbAw綘8O+Jd?;6k2q7ـlm0κaϙZ7`ΛzDY824`?ziσ\{հ{̋`-peNxtQ/K]EF-бXgJ v:.vq h4v`yMѣBJ# ]qvY[aMkƕlKܿaK s~riƩu} %Me0j)dst`On];eL.w% c-J iVhlW콑͡H=ެLxu Us@hV;sڍio)U)&JLGV0Qt[ Pj*VM(/,L .; |ŃӝKʱC(2"!3!lf<סGzuqlј8c/Y3'_h`*zM>F-ꍬ9ď"ƠjY,` K HEPȖW$E>A! Qƙ2@XSĕ+0uXBY|SoNZޗ]x xj\3ʣ0Q!m˩?[]FcJ^1xY6x R/טX`.8 -ܽԮA!HI՗͔ymJte],o!<(Ʊym#HמR$=+%p\72ϩ +yOx Q YC>2M+o9d:|\75w.\K~ dNi6NwDYKG?^3dCxhE $ͱ I|=u k-: ұNwƿc]{N c+^`Au~ .Eذ{a6ĠHrD 篷P{,m C!}Htbn̼'}`8ڸCÈ@R52 A)`pŽkQm6^o&Fԙ>AhucӥF։Uā(4+yFa\8y/2{-'#쪌=:kW*V5T _2z ˅Pkx] {+0ԜSa5rȿC5@Jzb+6(g`!)jMQs ғL%koد-$YVCV~U`L_!1ȽC_(nhQXJ5) 3?;wcP*GJ!4}+8(L$XAx5z %IV&0w4% ̍n‡%Z t/vjY&MAU@] 9F;]b5 "j ФkiyR߲ݡ)l_=F1 8SUho.iC}db.О e=GMX^$?ypm-a'FU&˶qMأZ!G݉hԹ -|Z]MUsP2"r2si񐹎2YwkܾTMEBKuC{0Czx0v>vsikˡ7YHSv8?<xhsSce> mx7D/l"N9ۯ(]\|?ษy8gUQ uy#-R K ̣X6^:?;#.h\ |PP+fuW>\{ 9I@svu9h>!*P(^4A얛'/ѵ!!`@iF+7 3o ͘My hCPH(J| >W=CB4Xqe` N/>3{+5ެsiՅ-.}#bŒq)?\hAm qg9f;U#n_?ukMIw2+,md6|ɊfBDlz;plpUl*+iJYF!ClrFеyuQOE n{ XԾ.>9|[%e_owE*t c56-zTT  ^i_g-xƝIm?UdAE ~4}E4^tg\\˘ꂁcݭ'2t&|Ӂ"]>$R05Ȑ|/b(MI3i@w^DOߓ/o5g  HheͣI}`B3|=шs sx9fU|CS^_/i{J1!/dYvҨoHnz]!J A<;ӱ.}B[%OXCfl.6II%٪9쌱Aim*ei6`ZSQ;"Ⱥxj 0ݢQ_,2@JS+1Plgbj e?_ČXVǢLTCÄgg :6t9(-б:CHtGtxIhZֱ]ruZe/%8qLи< Q$ !a ?+@RE\*L\1= ,NNnLׁ)ޚqlT& $˔6|UcTY`eJ;\e4Y}531y2h*;!a kd dϰtᬓx_鎦'(':nwV,%߿=exlJ&\`0az 8X7μt\E\Bx=?# Tкf4 *SByI3n\ֲ~p98ż!C:IaVy R!.GwY-ů*7=Sʬ5IMlJ9D},-QþZXyGqMЇ*fJg6~[!Kf&ZXt+!zXw!miMMO_ܹhG}t|f0a]#ډL:6N&,Q4N`b"ť~kx!sN(-|-دv~NZ_;њI[R@aǩVm)Aqa~GpD1:l3Aܯ緰:5KaZ~Q[2WkwF#GNFY:KL@y1FC%@09%ӬUSDHr`)ƽR }V<l2'eFm7<^O$O`6?YYW` G~/|¹t~BK_6DI͕gnsV.~X͙M-_AO,2D įZ}o6eH4T*6=һ7qvb7M p&/H/Qy1׎ Av3%}]+=9 4NocY#?fy6ѝt3]܏uUI!"2ۜ5XS_ \(.*\)$' 2>/dev/null) if expr "$link" : '^/' 2> /dev/null >/dev/null; then PRG="$link" else PRG="$(dirname "$PRG")/$link" fi done PROGDIR=$(dirname "$PRG") stub_logger "[StubDir] $PROGDIR" # set files and folders ############################################ # the absolute path of the app package cd "$PROGDIR"/../../ || exit 11 AppPackageFolder=$(pwd) # the base path of the app package cd .. || exit 12 AppPackageRoot=$(pwd) # set Apple's Java folder AppleJavaFolder="${AppPackageFolder}"/Contents/Resources/Java # set Apple's Resources folder AppleResourcesFolder="${AppPackageFolder}"/Contents/Resources # set Oracle's Java folder OracleJavaFolder="${AppPackageFolder}"/Contents/Java # set Oracle's Resources folder OracleResourcesFolder="${AppPackageFolder}"/Contents/Resources # set path to Info.plist in bundle InfoPlistFile="${AppPackageFolder}"/Contents/Info.plist # set the default JVM Version to a null string JVMVersion="" JVMMaxVersion="" # function 'plist_get()' # # read a specific Plist key with 'PlistBuddy' utility # # @param1 the Plist key with leading colon ':' # @return the value as String or Array ################################################################################ plist_get(){ /usr/libexec/PlistBuddy -c "print $1" "${InfoPlistFile}" 2> /dev/null } # function 'plist_get_java()' # # read a specific Plist key with 'PlistBuddy' utility # in the 'Java' or 'JavaX' dictionary () # # @param1 the Plist :Java(X):Key with leading colon ':' # @return the value as String or Array ################################################################################ plist_get_java(){ plist_get ${JavaKey:-":Java"}$1 } # read Info.plist and extract JVM options ############################################ # read the program name from CFBundleName CFBundleName=$(plist_get ':CFBundleName') # read the icon file name CFBundleIconFile=$(plist_get ':CFBundleIconFile') # check Info.plist for Apple style Java keys -> if key :Java is present, parse in apple mode /usr/libexec/PlistBuddy -c "print :Java" "${InfoPlistFile}" > /dev/null 2>&1 exitcode=$? JavaKey=":Java" # if no :Java key is present, check Info.plist for universalJavaApplication style JavaX keys -> if key :JavaX is present, parse in apple mode if [ $exitcode -ne 0 ]; then /usr/libexec/PlistBuddy -c "print :JavaX" "${InfoPlistFile}" > /dev/null 2>&1 exitcode=$? JavaKey=":JavaX" fi # read 'Info.plist' file in Apple style if exit code returns 0 (true, ':Java' key is present) if [ $exitcode -eq 0 ]; then stub_logger "[PlistStyle] Apple" # set Java and Resources folder JavaFolder="${AppleJavaFolder}" ResourcesFolder="${AppleResourcesFolder}" # set expandable variables APP_ROOT="${AppPackageFolder}" APP_PACKAGE="${AppPackageFolder}" JAVAROOT="${AppleJavaFolder}" USER_HOME="$HOME" # read the Java WorkingDirectory JVMWorkDir=$(plist_get_java ':WorkingDirectory' | xargs) # set Working Directory based upon PList value if [[ ! -z ${JVMWorkDir} ]]; then WorkingDirectory="${JVMWorkDir}" else # AppPackageRoot is the standard WorkingDirectory when the script is started WorkingDirectory="${AppPackageRoot}" fi # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME WorkingDirectory=$(eval echo "${WorkingDirectory}") # read the MainClass name JVMMainClass="$(plist_get_java ':MainClass')" # read the SplashFile name JVMSplashFile=$(plist_get_java ':SplashFile') # read the JVM Properties as an array and retain spaces IFS=$'\t\n' JVMOptions=($(xargs -n1 <<<$(plist_get_java ':Properties' | grep " =" | sed 's/^ */-D/g' | sed -E 's/ = (.*)$/="\1"/g'))) unset IFS # post processing of the array follows further below... # read the ClassPath in either Array or String style JVMClassPath_RAW=$(plist_get_java ':ClassPath' | xargs) if [[ $JVMClassPath_RAW == *Array* ]] ; then JVMClassPath=.$(plist_get_java ':ClassPath' | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs) else JVMClassPath=${JVMClassPath_RAW} fi # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME JVMClassPath=$(eval echo "${JVMClassPath}") # read the JVM Options in either Array or String style JVMDefaultOptions_RAW=$(plist_get_java ':VMOptions' | xargs) if [[ $JVMDefaultOptions_RAW == *Array* ]] ; then JVMDefaultOptions=$(plist_get_java ':VMOptions' | grep " " | sed 's/^ */ /g' | tr -d '\n' | xargs) else JVMDefaultOptions=${JVMDefaultOptions_RAW} fi # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#84) JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}") # read StartOnMainThread and add as -XstartOnFirstThread JVMStartOnMainThread=$(plist_get_java ':StartOnMainThread') if [ "${JVMStartOnMainThread}" == "true" ]; then JVMDefaultOptions+=" -XstartOnFirstThread" fi # read the JVM Arguments in either Array or String style (#76) and retain spaces IFS=$'\t\n' MainArgs_RAW=$(plist_get_java ':Arguments' | xargs) if [[ $MainArgs_RAW == *Array* ]] ; then MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments' | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g'))) else MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments'))) fi unset IFS # post processing of the array follows further below... # read the Java version we want to find JVMVersion=$(plist_get_java ':JVMVersion' | xargs) # post processing of the version string follows below... # read 'Info.plist' file in Oracle style else stub_logger "[PlistStyle] Oracle" # set Working Directory and Java and Resources folder JavaFolder="${OracleJavaFolder}" ResourcesFolder="${OracleResourcesFolder}" WorkingDirectory="${OracleJavaFolder}" # set expandable variables APP_ROOT="${AppPackageFolder}" APP_PACKAGE="${AppPackageFolder}" JAVAROOT="${OracleJavaFolder}" USER_HOME="$HOME" # read the MainClass name JVMMainClass="$(plist_get ':JVMMainClassName')" # read the SplashFile name JVMSplashFile=$(plist_get ':JVMSplashFile') # read the JVM Options as an array and retain spaces IFS=$'\t\n' JVMOptions=($(plist_get ':JVMOptions' | grep " " | sed 's/^ *//g')) unset IFS # post processing of the array follows further below... # read the ClassPath in either Array or String style JVMClassPath_RAW=$(plist_get ':JVMClassPath') if [[ $JVMClassPath_RAW == *Array* ]] ; then JVMClassPath=.$(plist_get ':JVMClassPath' | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs) # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME JVMClassPath=$(eval echo "${JVMClassPath}") elif [[ ! -z ${JVMClassPath_RAW} ]] ; then JVMClassPath=${JVMClassPath_RAW} # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME JVMClassPath=$(eval echo "${JVMClassPath}") else #default: fallback to OracleJavaFolder JVMClassPath="${JavaFolder}/*" # Do NOT expand the default 'AppName.app/Contents/Java/*' classpath (#42) fi # read the JVM Default Options by parsing the :JVMDefaultOptions # and pulling all values starting with a dash (-) JVMDefaultOptions=$(plist_get ':JVMDefaultOptions' | grep -o " \-.*" | tr -d '\n' | xargs) # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#99) JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}") # read the Main Arguments from JVMArguments key as an array and retain spaces (see #46 for naming details) IFS=$'\t\n' MainArgs=($(xargs -n1 <<<$(plist_get ':JVMArguments' | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g'))) unset IFS # post processing of the array follows further below... # read the Java version we want to find JVMVersion=$(plist_get ':JVMVersion' | xargs) # post processing of the version string follows below... fi # (#75) check for undefined icons or icon names without .icns extension and prepare # an osascript statement for those cases when the icon can be shown in the dialog DialogWithIcon="" if [ ! -z ${CFBundleIconFile} ]; then if [[ ${CFBundleIconFile} == *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}" ]] ; then DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" elif [[ ${CFBundleIconFile} != *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}.icns" ]] ; then CFBundleIconFile+=".icns" DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" fi fi # JVMVersion: post processing and optional splitting if [[ ${JVMVersion} == *";"* ]]; then minMaxArray=(${JVMVersion//;/ }) JVMVersion=${minMaxArray[0]//+} JVMMaxVersion=${minMaxArray[1]//+} fi stub_logger "[JavaRequirement] JVM minimum version: ${JVMVersion}" stub_logger "[JavaRequirement] JVM maximum version: ${JVMMaxVersion}" # MainArgs: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME MainArgsArr=() for i in "${MainArgs[@]}" do MainArgsArr+=("$(eval echo "$i")") done # JVMOptions: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME JVMOptionsArr=() for i in "${JVMOptions[@]}" do JVMOptionsArr+=("$(eval echo "$i")") done # internationalized messages ############################################ # supported languages / available translations stubLanguages="^(fr|de|zh|es|en)-" # read user preferred languages as defined in macOS System Preferences (#101) stub_logger '[LanguageSearch] Checking preferred languages in macOS System Preferences...' appleLanguages=($(defaults read -g AppleLanguages | grep '\s"' | tr -d ',' | xargs)) stub_logger "[LanguageSearch] ... found [${appleLanguages[*]}]" language="" for i in "${appleLanguages[@]}" do langValue="${i%-*}" if [[ "$i" =~ $stubLanguages ]]; then stub_logger "[LanguageSearch] ... selected '$i' ('$langValue') as the default language for the launcher stub" language=${langValue} break fi done if [ -z "${language}" ]; then language="en" stub_logger "[LanguageSearch] ... selected fallback 'en' as the default language for the launcher stub" fi stub_logger "[Language] $language" case "${language}" in # French fr) MSG_ERROR_LAUNCHING="ERREUR au lancement de '${CFBundleName}'." MSG_MISSING_MAINCLASS="'MainClass' n'est pas spécifié.\nL'application Java ne peut pas être lancée." MSG_JVMVERSION_REQ_INVALID="La syntaxe de la version de Java demandée est invalide: %s\nVeuillez contacter le développeur de l'application." MSG_NO_SUITABLE_JAVA="La version de Java installée sur votre système ne convient pas.\nCe programme nécessite Java %s" MSG_JAVA_VERSION_OR_LATER="ou ultérieur" MSG_JAVA_VERSION_LATEST="(dernière mise à jour)" MSG_JAVA_VERSION_MAX="à %s" MSG_NO_SUITABLE_JAVA_CHECK="Merci de bien vouloir installer la version de Java requise." MSG_INSTALL_JAVA="Java doit être installé sur votre système.\nRendez-vous sur java.com et suivez les instructions d'installation..." MSG_LATER="Plus tard" MSG_VISIT_JAVA_DOT_COM="Java by Oracle" MSG_VISIT_ADOPTOPENJDK="Java by AdoptOpenJDK" ;; # German de) MSG_ERROR_LAUNCHING="FEHLER beim Starten von '${CFBundleName}'." MSG_MISSING_MAINCLASS="Die 'MainClass' ist nicht spezifiziert!\nDie Java-Anwendung kann nicht gestartet werden!" MSG_JVMVERSION_REQ_INVALID="Die Syntax der angeforderten Java-Version ist ungültig: %s\nBitte kontaktieren Sie den Entwickler der App." MSG_NO_SUITABLE_JAVA="Es wurde keine passende Java-Version auf Ihrem System gefunden!\nDieses Programm benötigt Java %s" MSG_JAVA_VERSION_OR_LATER="oder neuer" MSG_JAVA_VERSION_LATEST="(neuste Unterversion)" MSG_JAVA_VERSION_MAX="bis %s" MSG_NO_SUITABLE_JAVA_CHECK="Stellen Sie sicher, dass die angeforderte Java-Version installiert ist." MSG_INSTALL_JAVA="Auf Ihrem System muss die 'Java'-Software installiert sein.\nBesuchen Sie java.com für weitere Installationshinweise." MSG_LATER="Später" MSG_VISIT_JAVA_DOT_COM="Java von Oracle" MSG_VISIT_ADOPTOPENJDK="Java von AdoptOpenJDK" ;; # Simplified Chinese zh) MSG_ERROR_LAUNCHING="无法启动 '${CFBundleName}'." MSG_MISSING_MAINCLASS="没有指定 'MainClass'!\nJava程序无法启动!" MSG_JVMVERSION_REQ_INVALID="Java版本参数语法错误: %s\n请联系该应用的开发者。" MSG_NO_SUITABLE_JAVA="没有在系统中找到合适的Java版本!\n必须安装Java %s才能够使用该程序!" MSG_JAVA_VERSION_OR_LATER="及以上版本" MSG_JAVA_VERSION_LATEST="(最新版本)" MSG_JAVA_VERSION_MAX="最高为 %s" MSG_NO_SUITABLE_JAVA_CHECK="请确保系统中安装了所需的Java版本" MSG_INSTALL_JAVA="你需要在Mac中安装Java运行环境!\n访问 java.com 了解如何安装。" MSG_LATER="稍后" MSG_VISIT_JAVA_DOT_COM="Java by Oracle" MSG_VISIT_ADOPTOPENJDK="Java by AdoptOpenJDK" ;; # Spanish es) MSG_ERROR_LAUNCHING="ERROR iniciando '${CFBundleName}'." MSG_MISSING_MAINCLASS="¡'MainClass' no especificada!\n¡La aplicación Java no puede iniciarse!" MSG_JVMVERSION_REQ_INVALID="La sintaxis de la versión Java requerida no es válida: %s\nPor favor, contacte con el desarrollador de la aplicación." MSG_NO_SUITABLE_JAVA="¡No se encontró una versión de Java adecuada en su sistema!\nEste programa requiere Java %s" MSG_JAVA_VERSION_OR_LATER="o posterior" MSG_JAVA_VERSION_LATEST="(ultima actualización)" MSG_JAVA_VERSION_MAX="superior a %s" MSG_NO_SUITABLE_JAVA_CHECK="Asegúrese de instalar la versión Java requerida." MSG_INSTALL_JAVA="¡Necesita tener JAVA instalado en su Mac!\nVisite java.com para consultar las instrucciones para su instalación..." MSG_LATER="Más tarde" MSG_VISIT_JAVA_DOT_COM="Java de Oracle" MSG_VISIT_ADOPTOPENJDK="Java de AdoptOpenJDK" ;; # English | default en|*) MSG_ERROR_LAUNCHING="ERROR launching '${CFBundleName}'." MSG_MISSING_MAINCLASS="'MainClass' isn't specified!\nJava application cannot be started!" MSG_JVMVERSION_REQ_INVALID="The syntax of the required Java version is invalid: %s\nPlease contact the App developer." MSG_NO_SUITABLE_JAVA="No suitable Java version found on your system!\nThis program requires Java %s" MSG_JAVA_VERSION_OR_LATER="or later" MSG_JAVA_VERSION_LATEST="(latest update)" MSG_JAVA_VERSION_MAX="up to %s" MSG_NO_SUITABLE_JAVA_CHECK="Make sure you install the required Java version." MSG_INSTALL_JAVA="You need to have JAVA installed on your Mac!\nVisit java.com for installation instructions..." MSG_LATER="Later" MSG_VISIT_JAVA_DOT_COM="Java by Oracle" MSG_VISIT_ADOPTOPENJDK="Java by AdoptOpenJDK" ;; esac # function 'get_java_version_from_cmd()' # # returns Java version string from 'java -version' command # works for both old (1.8) and new (9) version schema # # @param1 path to a java JVM executable # @return the Java version number as displayed in 'java -version' command ################################################################################ function get_java_version_from_cmd() { # second sed command strips " and -ea from the version string echo $("$1" -version 2>&1 | awk '/version/{print $3}' | sed -E 's/"//g;s/-ea//g') } # function 'extract_java_major_version()' # # extract Java major version from a version string # # @param1 a Java version number ('1.8.0_45') or requirement string ('1.8+') # @return the major version (e.g. '7', '8' or '9', etc.) ################################################################################ function extract_java_major_version() { echo $(echo "$1" | sed -E 's/^1\.//;s/^([0-9]+)(-ea|(\.[0-9_.]{1,7})?)(-b[0-9]+-[0-9]+)?[+*]?$/\1/') } # function 'get_comparable_java_version()' # # return comparable version for a Java version number or requirement string # # @param1 a Java version number ('1.8.0_45') or requirement string ('1.8+') # @return an 8 digit numeral ('1.8.0_45'->'08000045'; '9.1.13'->'09001013') ################################################################################ function get_comparable_java_version() { # cleaning: 1) remove leading '1.'; 2) remove build string (e.g. '-b14-468'); 3) remove 'a-Z' and '-*+' (e.g. '-ea'); 4) replace '_' with '.' local cleaned=$(echo "$1" | sed -E 's/^1\.//g;s/-b[0-9]+-[0-9]+$//g;s/[a-zA-Z+*\-]//g;s/_/./g') # splitting at '.' into an array local arr=( ${cleaned//./ } ) # echo a string with left padded version numbers echo "$(printf '%02s' ${arr[0]})$(printf '%03s' ${arr[1]})$(printf '%03s' ${arr[2]})" } # function 'is_valid_requirement_pattern()' # # check whether the Java requirement is a valid requirement pattern # # supported requirements are for example: # - 1.6 requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88] # - 1.6* requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88] # - 1.6+ requires Java 6 or higher [1.6, 1.6.0_45, 1.8, 9, etc.] # - 1.6.0 requires Java 6 (any update) [1.6, 1.6.0_45, 1.6.0_88] # - 1.6.0_45 requires Java 6u45 [1.6.0_45] # - 1.6.0_45+ requires Java 6u45 or higher [1.6.0_45, 1.6.0_88, 1.8, etc.] # - 9 requires Java 9 (any update) [9.0.*, 9.1, 9.3, etc.] # - 9* requires Java 9 (any update) [9.0.*, 9.1, 9.3, etc.] # - 9+ requires Java 9 or higher [9.0, 9.1, 10, etc.] # - 9.1 requires Java 9.1 (any update) [9.1.*, 9.1.2, 9.1.13, etc.] # - 9.1* requires Java 9.1 (any update) [9.1.*, 9.1.2, 9.1.13, etc.] # - 9.1+ requires Java 9.1 or higher [9.1, 9.2, 10, etc.] # - 9.1.3 requires Java 9.1.3 [9.1.3] # - 9.1.3* requires Java 9.1.3 (any update) [9.1.3] # - 9.1.3+ requires Java 9.1.3 or higher [9.1.3, 9.1.4, 9.2.*, 10, etc.] # - 10-ea requires Java 10 (early access release) # # unsupported requirement patterns are for example: # - 1.2, 1.3, 1.9 Java 2, 3 are not supported # - 1.9 Java 9 introduced a new versioning scheme # - 6u45 known versioning syntax, but unsupported # - 9-ea*, 9-ea+ early access releases paired with */+ # - 9., 9.*, 9.+ version ending with a . # - 9.1., 9.1.*, 9.1.+ version ending with a . # - 9.3.5.6 4 part version number is unsupported # # @param1 a Java requirement string ('1.8+') # @return boolean exit code: 0 (is valid), 1 (is not valid) ################################################################################ function is_valid_requirement_pattern() { local java_req=$1 java8pattern='1\.[4-8](\.[0-9]+)?(\.0_[0-9]+)?[*+]?' java9pattern='(9|1[0-9])(-ea|[*+]|(\.[0-9]+){1,2}[*+]?)?' # test matches either old Java versioning scheme (up to 1.8) or new scheme (starting with 9) if [[ ${java_req} =~ ^(${java8pattern}|${java9pattern})$ ]]; then return 0 else return 1 fi } # determine which JVM to use ############################################ # default Apple JRE plugin path (< 1.6) apple_jre_plugin="/Library/Java/Home/bin/java" apple_jre_version=$(get_java_version_from_cmd "${apple_jre_plugin}") # default Oracle JRE plugin path (>= 1.7) oracle_jre_plugin="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" oracle_jre_version=$(get_java_version_from_cmd "${oracle_jre_plugin}") # first check system variable "$JAVA_HOME" -> has precedence over any other System JVM stub_logger '[JavaSearch] Checking for $JAVA_HOME ...' if [ -n "$JAVA_HOME" ] ; then stub_logger "[JavaSearch] ... found JAVA_HOME with value $JAVA_HOME" # PR 26: Allow specifying "$JAVA_HOME" relative to "$AppPackageFolder" # which allows for bundling a custom version of Java inside your app! if [[ $JAVA_HOME == /* ]] ; then # if "$JAVA_HOME" starts with a Slash it's an absolute path JAVACMD="$JAVA_HOME/bin/java" stub_logger "[JavaSearch] ... parsing JAVA_HOME as absolute path to the executable '$JAVACMD'" else # otherwise it's a relative path to "$AppPackageFolder" JAVACMD="$AppPackageFolder/$JAVA_HOME/bin/java" stub_logger "[JavaSearch] ... parsing JAVA_HOME as relative path inside the App bundle to the executable '$JAVACMD'" fi JAVACMD_version=$(get_comparable_java_version $(get_java_version_from_cmd "${JAVACMD}")) else stub_logger "[JavaSearch] ... haven't found JAVA_HOME" fi # check for any other or a specific Java version # also if $JAVA_HOME exists but isn't executable if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then # add a warning in the syslog if JAVA_HOME is not executable or not found (#100) if [ -n "$JAVA_HOME" ] ; then stub_logger "[JavaSearch] ... but no 'java' executable was found at the JAVA_HOME location!" fi stub_logger "[JavaSearch] Searching for JavaVirtualMachines on the system ..." # reset variables JAVACMD="" JAVACMD_version="" # first check whether JVMVersion string is a valid requirement string if [ ! -z "${JVMVersion}" ] && ! is_valid_requirement_pattern ${JVMVersion} ; then MSG_JVMVERSION_REQ_INVALID_EXPANDED=$(printf "${MSG_JVMVERSION_REQ_INVALID}" "${JVMVersion}") # log exit cause stub_logger "[EXIT 4] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}" # display error message with AppleScript osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}" # exit with error exit 4 fi # then check whether JVMMaxVersion string is a valid requirement string if [ ! -z "${JVMMaxVersion}" ] && ! is_valid_requirement_pattern ${JVMMaxVersion} ; then MSG_JVMVERSION_REQ_INVALID_EXPANDED=$(printf "${MSG_JVMVERSION_REQ_INVALID}" "${JVMMaxVersion}") # log exit cause stub_logger "[EXIT 5] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}" # display error message with AppleScript osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}" # exit with error exit 5 fi # find installed JavaVirtualMachines (JDK + JRE) allJVMs=() # read JDK's from '/usr/libexec/java_home --xml' command with PlistBuddy and a custom Dict iterator # idea: https://stackoverflow.com/a/14085460/1128689 and https://scriptingosx.com/2018/07/parsing-dscl-output-in-scripts/ javaXml=$(/usr/libexec/java_home --xml) javaCounter=$(/usr/libexec/PlistBuddy -c "Print" /dev/stdin <<< $javaXml | grep "Dict" | wc -l | tr -d ' ') # iterate over all Dict entries # but only if there are any JVMs at all (#93) if [ "$javaCounter" -gt "0" ] ; then for idx in $(seq 0 $((javaCounter - 1))) do version=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMVersion" /dev/stdin <<< $javaXml) path=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMHomePath" /dev/stdin <<< $javaXml) path+="/bin/java" allJVMs+=("$version:$path") done # unset for loop variables unset version path fi # add SDKMAN! java versions (#95) if [ -d ~/.sdkman/candidates/java/ ] ; then for sdkjdk in ~/.sdkman/candidates/java/*/ do if [[ ${sdkjdk} =~ /current/$ ]] ; then continue fi sdkjdkcmd="${sdkjdk}bin/java" version=$(get_java_version_from_cmd "${sdkjdkcmd}") allJVMs+=("$version:$sdkjdkcmd") done # unset for loop variables unset version fi # add Apple JRE if available if [ -x "${apple_jre_plugin}" ] ; then allJVMs+=("$apple_jre_version:$apple_jre_plugin") fi # add Oracle JRE if available if [ -x "${oracle_jre_plugin}" ] ; then allJVMs+=("$oracle_jre_version:$oracle_jre_plugin") fi # debug output for i in "${allJVMs[@]}" do stub_logger "[JavaSearch] ... found JVM: $i" done # determine JVMs matching the min/max version requirement stub_logger "[JavaSearch] Filtering the result list for JVMs matching the min/max version requirement ..." minC=$(get_comparable_java_version ${JVMVersion}) maxC=$(get_comparable_java_version ${JVMMaxVersion}) matchingJVMs=() for i in "${allJVMs[@]}" do # split JVM string at ':' delimiter to retain spaces in $path substring IFS=: arr=($i) ; unset IFS # [0] JVM version number ver=${arr[0]} # comparable JVM version number comp=$(get_comparable_java_version $ver) # [1] JVM path path="${arr[1]}" # construct string item for adding to the "matchingJVMs" array item="$comp:$ver:$path" # pre-requisite: current version number needs to be greater than min version number if [ "$comp" -ge "$minC" ] ; then # perform max version checks if max version requirement is present if [ ! -z ${JVMMaxVersion} ] ; then # max version requirement ends with '*' modifier if [[ ${JVMMaxVersion} == *\* ]] ; then # use the '*' modifier from the max version string as wildcard for a 'starts with' comparison # and check whether the current version number starts with the max version wildcard string if [[ ${ver} == ${JVMMaxVersion} ]]; then matchingJVMs+=("$item") # or whether the current comparable version is lower than the comparable max version elif [ "$comp" -le "$maxC" ] ; then matchingJVMs+=("$item") fi # max version requirement ends with '+' modifier -> always add this version if it's greater than $min # because a max requirement with + modifier doesn't make sense elif [[ ${JVMMaxVersion} == *+ ]] ; then matchingJVMs+=("$item") # matches 6 zeros at the end of the max version string (e.g. for 1.8, 9) # -> then the max version string should be treated like with a '*' modifier at the end #elif [[ ${maxC} =~ ^[0-9]{2}0{6}$ ]] && [ "$comp" -le $(( ${maxC#0} + 999 )) ] ; then # matchingJVMs+=("$item") # matches 3 zeros at the end of the max version string (e.g. for 9.1, 10.3) # -> then the max version string should be treated like with a '*' modifier at the end #elif [[ ${maxC} =~ ^[0-9]{5}0{3}$ ]] && [ "$comp" -le "${maxC}" ] ; then # matchingJVMs+=("$item") # matches standard requirements without modifier elif [ "$comp" -le "$maxC" ]; then matchingJVMs+=("$item") fi # no max version requirement: # min version requirement ends with '+' modifier # -> always add the current version because it's greater than $min elif [[ ${JVMVersion} == *+ ]] ; then matchingJVMs+=("$item") # min version requirement ends with '*' modifier # -> use the '*' modifier from the min version string as wildcard for a 'starts with' comparison # and check whether the current version number starts with the min version wildcard string elif [[ ${JVMVersion} == *\* ]] ; then if [[ ${ver} == ${JVMVersion} ]] ; then matchingJVMs+=("$item") fi # compare the min version against the current version with an additional * wildcard for a 'starts with' comparison # -> e.g. add 1.8.0_44 when the requirement is 1.8 elif [[ ${ver} == ${JVMVersion}* ]] ; then matchingJVMs+=("$item") fi fi done # unset for loop variables unset arr ver comp path item # debug output for i in "${matchingJVMs[@]}" do stub_logger "[JavaSearch] ... matches all requirements: $i" done # sort the matching JavaVirtualMachines by version number # https://stackoverflow.com/a/11789688/1128689 IFS=$'\n' matchingJVMs=($(sort -nr <<<"${matchingJVMs[*]}")) unset IFS # get the highest matching JVM for ((i = 0; i < ${#matchingJVMs[@]}; i++)); do # split JVM string at ':' delimiter to retain spaces in $path substring IFS=: arr=(${matchingJVMs[$i]}) ; unset IFS # [0] comparable JVM version number comp=${arr[0]} # [1] JVM version number ver=${arr[1]} # [2] JVM path path="${arr[2]}" # use current value as JAVACMD if it's executable if [ -x "$path" ] ; then JAVACMD="$path" JAVACMD_version=$comp break fi done # unset for loop variables unset arr comp ver path fi # log the Java Command and the extracted version number stub_logger "[JavaCommand] '$JAVACMD'" stub_logger "[JavaVersion] $(get_java_version_from_cmd "${JAVACMD}")${JAVACMD_version:+ / $JAVACMD_version}" if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then # different error messages when a specific JVM was required if [ ! -z "${JVMVersion}" ] ; then # display human readable java version (#28) java_version_hr=$(echo ${JVMVersion} | sed -E 's/^1\.([0-9+*]+)$/ \1/g' | sed "s/+/ ${MSG_JAVA_VERSION_OR_LATER}/;s/*/ ${MSG_JAVA_VERSION_LATEST}/") MSG_NO_SUITABLE_JAVA_EXPANDED=$(printf "${MSG_NO_SUITABLE_JAVA}" "${java_version_hr}"). if [ ! -z "${JVMMaxVersion}" ] ; then java_version_hr=$(extract_java_major_version ${JVMVersion}) java_version_max_hr=$(echo ${JVMMaxVersion} | sed -E 's/^1\.([0-9+*]+)$/ \1/g' | sed "s/+//;s/*/ ${MSG_JAVA_VERSION_LATEST}/") MSG_NO_SUITABLE_JAVA_EXPANDED="$(printf "${MSG_NO_SUITABLE_JAVA}" "${java_version_hr}") $(printf "${MSG_JAVA_VERSION_MAX}" "${java_version_max_hr}")" fi # log exit cause stub_logger "[EXIT 3] ${MSG_NO_SUITABLE_JAVA_EXPANDED}" # display error message with AppleScript osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_NO_SUITABLE_JAVA_EXPANDED}\n${MSG_NO_SUITABLE_JAVA_CHECK}\" with title \"${CFBundleName}\" buttons {\" OK \", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTOPENJDK}\"} default button 1${DialogWithIcon}" \ -e "set response to button returned of the result" \ -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \ -e "if response is \"${MSG_VISIT_ADOPTOPENJDK}\" then open location \"https://adoptopenjdk.net/releases.html\"" # exit with error exit 3 else # log exit cause stub_logger "[EXIT 1] ${MSG_ERROR_LAUNCHING}" # display error message with AppleScript osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_INSTALL_JAVA}\" with title \"${CFBundleName}\" buttons {\"${MSG_LATER}\", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTOPENJDK}\"} default button 1${DialogWithIcon}" \ -e "set response to button returned of the result" \ -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \ -e "if response is \"${MSG_VISIT_ADOPTOPENJDK}\" then open location \"https://adoptopenjdk.net/releases.html\"" # exit with error exit 1 fi fi # MainClass check ############################################ if [ -z "${JVMMainClass}" ]; then # log exit cause stub_logger "[EXIT 2] ${MSG_MISSING_MAINCLASS}" # display error message with AppleScript osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_MISSING_MAINCLASS}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}" # exit with error exit 2 fi # execute $JAVACMD and do some preparation ############################################ # enable drag&drop to the dock icon export CFProcessPath="$0" # remove Apples ProcessSerialNumber from passthru arguments (#39) if [[ "$*" == -psn* ]] ; then ArgsPassthru=() else ArgsPassthru=("$@") fi # change to Working Directory based upon Apple/Oracle Plist info cd "${WorkingDirectory}" || exit 13 stub_logger "[WorkingDirectory] ${WorkingDirectory}" # execute Java and set # - classpath # - splash image # - dock icon # - app name # - JVM options / properties (-D) # - JVM default options (-X) # - main class # - main class arguments # - passthrough arguments from Terminal or Drag'n'Drop to Finder icon stub_logger "[Exec] \"$JAVACMD\" -cp \"${JVMClassPath}\" ${JVMSplashFile:+ -splash:\"${ResourcesFolder}/${JVMSplashFile}\"} -Xdock:icon=\"${ResourcesFolder}/${CFBundleIconFile}\" -Xdock:name=\"${CFBundleName}\" ${JVMOptionsArr:+$(printf "'%s' " "${JVMOptionsArr[@]}") }${JVMDefaultOptions:+$JVMDefaultOptions }${JVMMainClass}${MainArgsArr:+ $(printf "'%s' " "${MainArgsArr[@]}")}${ArgsPassthru:+ $(printf "'%s' " "${ArgsPassthru[@]}")}" exec "${JAVACMD}" \ -cp "${JVMClassPath}" \ ${JVMSplashFile:+ -splash:"${ResourcesFolder}/${JVMSplashFile}"} \ -Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \ -Xdock:name="${CFBundleName}" \ ${JVMOptionsArr:+"${JVMOptionsArr[@]}" }\ ${JVMDefaultOptions:+$JVMDefaultOptions }\ "${JVMMainClass}"\ ${MainArgsArr:+ "${MainArgsArr[@]}"}\ ${ArgsPassthru:+ "${ArgsPassthru[@]}"} bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/000077500000000000000000000000001506470510200207075ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/000077500000000000000000000000001506470510200214655ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/000077500000000000000000000000001506470510200232775ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/000077500000000000000000000000001506470510200254365ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/Base64InputStream.java000066400000000000000000000055551506470510200315330ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.IOException; import java.io.InputStream; import java.text.CharacterIterator; import java.text.StringCharacterIterator; public class Base64InputStream extends InputStream { private final CharacterIterator ci; private final InputStream in; public Base64InputStream(String s) { this.ci = new StringCharacterIterator(s); this.in = null; } public Base64InputStream(CharacterIterator ci) { this.ci = ci; this.in = null; } public Base64InputStream(InputStream in) { this.ci = null; this.in = in; } private int word = 0; private int count = 0; private boolean eof = false; @Override public int read() throws IOException { for (;;) { if (count > 0) { word <<= 8; count--; return (word >>> 24); } if (eof) return -1; readWord(); } } private void readWord() throws IOException { for (;;) { int c = -1; if (ci != null) { c = ci.current(); ci.next(); } if (in != null) { c = in.read(); } if (c < 0 || c == '=' || c == CharacterIterator.DONE) { padWord(); eof = true; return; } c = b64d(c); if (c >= 0) { word <<= 6; word |= c; count++; if (count > 3) { count = 3; return; } } } } private void padWord() { if (count > 0) { for (int i = count; i <= 3; i++) { word <<= 6; } count--; } } private int b64d(int c) { switch (c) { case 'A': return 0; case 'B': return 1; case 'C': return 2; case 'D': return 3; case 'E': return 4; case 'F': return 5; case 'G': return 6; case 'H': return 7; case 'I': return 8; case 'J': return 9; case 'K': return 10; case 'L': return 11; case 'M': return 12; case 'N': return 13; case 'O': return 14; case 'P': return 15; case 'Q': return 16; case 'R': return 17; case 'S': return 18; case 'T': return 19; case 'U': return 20; case 'V': return 21; case 'W': return 22; case 'X': return 23; case 'Y': return 24; case 'Z': return 25; case 'a': return 26; case 'b': return 27; case 'c': return 28; case 'd': return 29; case 'e': return 30; case 'f': return 31; case 'g': return 32; case 'h': return 33; case 'i': return 34; case 'j': return 35; case 'k': return 36; case 'l': return 37; case 'm': return 38; case 'n': return 39; case 'o': return 40; case 'p': return 41; case 'q': return 42; case 'r': return 43; case 's': return 44; case 't': return 45; case 'u': return 46; case 'v': return 47; case 'w': return 48; case 'x': return 49; case 'y': return 50; case 'z': return 51; case '0': return 52; case '1': return 53; case '2': return 54; case '3': return 55; case '4': return 56; case '5': return 57; case '6': return 58; case '7': return 59; case '8': return 60; case '9': return 61; case '+': return 62; case '/': return 63; default: return -1; } } @Override public void close() throws IOException { if (in != null) in.close(); } }bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/Base64OutputStream.java000066400000000000000000000034001506470510200317170ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.IOException; import java.io.OutputStream; public class Base64OutputStream extends OutputStream { private final StringBuffer sb; private final OutputStream out; private final boolean pad; public Base64OutputStream(StringBuffer sb) { this(sb, true); } public Base64OutputStream(OutputStream out) { this(out, true); } public Base64OutputStream(StringBuffer sb, boolean pad) { this.sb = sb; this.out = null; this.pad = pad; } public Base64OutputStream(OutputStream out, boolean pad) { this.sb = null; this.out = out; this.pad = pad; } private int word = 0; private int count = 0; @Override public void write(int b) throws IOException { word <<= 8; word |= (b & 0xFF); count++; if (count >= 3) { writeWord(); word = 0; count = 0; } } @Override public void flush() throws IOException { if (out != null) out.flush(); } @Override public void close() throws IOException { if (count > 0) { for (int i = count; i < 3; i++) word <<= 8; writeWord(); } word = 0; count = 0; if (out != null) out.close(); } private void writeWord() throws IOException { for (int m = 18, i = 0; i <= count; m -= 6, i++) { char c = b64e[(word >> m) & 0x3F]; if (sb != null) sb.append(c); if (out != null) out.write(c); } if (pad) { for (int i = count; i < 3; i++) { if (sb != null) sb.append('='); if (out != null) out.write('='); } } } private static final char[] b64e = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', }; }bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/BitmapFont.java000077500000000000000000000107571506470510200303610ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.Graphics; import java.awt.Point; public class BitmapFont extends Font { protected int emAscent, emDescent; protected int lineAscent, lineDescent; protected int xHeight, capHeight, lineGap; public BitmapFont() { this.emAscent = 0; this.emDescent = 0; this.lineAscent = 0; this.lineDescent = 0; this.xHeight = 0; this.capHeight = 0; this.lineGap = 0; } public BitmapFont( int emAscent, int emDescent, int lineAscent, int lineDescent, int xHeight, int capHeight, int lineGap ) { this.emAscent = emAscent; this.emDescent = emDescent; this.lineAscent = lineAscent; this.lineDescent = lineDescent; this.xHeight = xHeight; this.capHeight = capHeight; this.lineGap = lineGap; } public int getEmAscent() { return emAscent; } public double getEmAscent2D() { return emAscent; } public int getEmDescent() { return emDescent; } public double getEmDescent2D() { return emDescent; } public int getLineAscent() { return lineAscent; } public double getLineAscent2D() { return lineAscent; } public int getLineDescent() { return lineDescent; } public double getLineDescent2D() { return lineDescent; } public int getXHeight() { return xHeight; } public double getXHeight2D() { return xHeight; } public int getCapHeight() { return capHeight; } public double getCapHeight2D() { return capHeight; } public int getLineGap() { return lineGap; } public double getLineGap2D() { return lineGap; } public void setEmAscent(int v) { emAscent = v; } public void setEmAscent2D(double v) { emAscent = (int)Math.ceil(v); } public void setEmDescent(int v) { emDescent = v; } public void setEmDescent2D(double v) { emDescent = (int)Math.ceil(v); } public void setLineAscent(int v) { lineAscent = v; } public void setLineAscent2D(double v) { lineAscent = (int)Math.ceil(v); } public void setLineDescent(int v) { lineDescent = v; } public void setLineDescent2D(double v) { lineDescent = (int)Math.ceil(v); } public void setXHeight(int v) { xHeight = v; } public void setXHeight2D(double v) { xHeight = (int)Math.ceil(v); } public void setCapHeight(int v) { capHeight = v; } public void setCapHeight2D(double v) { capHeight = (int)Math.ceil(v); } public void setLineGap(int v) { lineGap = v; } public void setLineGap2D(double v) { lineGap = (int)Math.ceil(v); } public void contractGlyphs() { for (BitmapFontGlyph g : characters.values()) g.contract(); for (BitmapFontGlyph g : namedGlyphs.values()) g.contract(); } public void setAscentDescent() { contractGlyphs(); int adjust = guessBaselineAdjustment(); if (adjust == 0) return; emAscent += adjust; emDescent -= adjust; lineAscent += adjust; lineDescent -= adjust; for (BitmapFontGlyph g : characters.values()) g.setXY(g.getX(), g.getY() + adjust); for (BitmapFontGlyph g : namedGlyphs.values()) g.setXY(g.getX(), g.getY() + adjust); } public void setXHeight() { contractGlyphs(); int xh = guessXHeight(); if (xh != 0) xHeight = xh; } public void setCapHeight() { contractGlyphs(); int ch = guessCapHeight(); if (ch != 0) capHeight = ch; } public Point draw(Graphics g, String s, int bx, int by, int scale, int w) { return draw(g, s, bx, by, scale, w, (lineAscent + lineDescent + lineGap) * scale); } public Point draw(Graphics g, String s, int bx, int by, int scale, int w, int lh) { int cx = bx, cy = by; int i = 0, n = s.length(); while (i < n) { int ch = s.codePointAt(i); i += Character.charCount(ch); if (ch == '\n' || ch == '\r') { cx = bx; cy += lh; } else { BitmapFontGlyph bm = characters.get(ch); if (bm == null) bm = namedGlyphs.get(".notdef"); if (bm != null) { if (cx - bx + (bm.getCharacterWidth() * scale) >= w) { cx = bx; cy += lh; } cx += bm.paint(g, cx, cy, scale); } } } return new Point(cx, cy); } public Point drawAlphabet(Graphics g, int bx, int by, int scale, int w) { return drawAlphabet(g, bx, by, scale, w, (lineAscent + lineDescent + lineGap) * scale); } public Point drawAlphabet(Graphics g, int bx, int by, int scale, int w, int lh) { int cx = bx, cy = by; for (BitmapFontGlyph bm : characters.values()) { if (cx - bx + (bm.getCharacterWidth() * scale) >= w) { cx = bx; cy += lh; } cx += bm.paint(g, cx, cy, scale); } for (BitmapFontGlyph bm : namedGlyphs.values()) { if (cx - bx + (bm.getCharacterWidth() * scale) >= w) { cx = bx; cy += lh; } cx += bm.paint(g, cx, cy, scale); } return new Point(cx, cy); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/BitmapFontExporter.java000077500000000000000000000001641506470510200321010ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface BitmapFontExporter extends FontExporter { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/BitmapFontGlyph.java000077500000000000000000000221351506470510200313560ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.*; import java.awt.image.*; public class BitmapFontGlyph extends FontGlyph { protected byte[][] glyph; protected int x, y; protected int advance; public BitmapFontGlyph() { glyph = new byte[0][0]; x = 0; y = 0; advance = 0; } public BitmapFontGlyph(byte[][] glyph) { this.glyph = glyph; x = 0; y = glyph.length; advance = (glyph.length < 1) ? 0 : (glyph[0].length); } public BitmapFontGlyph(byte[][] glyph, int offset, int width, int ascent) { this.glyph = glyph; x = offset; y = ascent; advance = width; } public byte[][] getGlyph() { return glyph; } public void setGlyph(byte[][] glyph) { this.glyph = glyph; } public int getX() { return x; } public int getY() { return y; } public void setXY(int x, int y) { this.x = x; this.y = y; } public int getGlyphWidth() { return (glyph.length < 1) ? 0 : (glyph[0].length); } public double getGlyphWidth2D() { return (glyph.length < 1) ? 0 : (glyph[0].length); } public int getGlyphHeight() { return glyph.length; } public double getGlyphHeight2D() { return glyph.length; } public int getGlyphOffset() { return x; } public double getGlyphOffset2D() { return x; } public int getGlyphAscent() { return y; } public double getGlyphAscent2D() { return y; } public int getGlyphDescent() { return glyph.length - y; } public double getGlyphDescent2D() { return glyph.length - y; } public int getCharacterWidth() { return advance; } public double getCharacterWidth2D() { return advance; } public void setCharacterWidth(int v) { advance = v; } public void setCharacterWidth2D(double v) { advance = (int)Math.ceil(v); } public double paint(Graphics g, double x, double y, double scale) { Color c = g.getColor(); int rgb = c.getRGB() & 0xFFFFFF; int a = c.getAlpha(); int w = ((glyph.length < 1) ? 0 : (glyph[0].length)); int h = glyph.length; int[] glyphPixels = new int[w * h]; for (int k = 0, j = 0; j < h; j++) { for (int i = 0; i < w; k++, i++) { glyphPixels[k] = ((a * (glyph[j][i] & 0xFF) / 0xFF) << 24) | rgb; } } ImageProducer glyphProducer = new MemoryImageSource(w, h, glyphPixels, 0, w); Image glyphImage = Toolkit.getDefaultToolkit().createImage(glyphProducer); int dx = (int)Math.round(x + this.x * scale); int dy = (int)Math.round(y - this.y * scale); int dw = (int)Math.round(w * scale); int dh = (int)Math.round(h * scale); g.drawImage(glyphImage, dx, dy, dx + dw, dy + dh, 0, 0, w, h, null); return advance * scale; } public PathGraph convertToPathGraph(int size) { PathGraph pg = new PathGraph(); int w = ((glyph.length < 1) ? 0 : (glyph[0].length)); int h = glyph.length; for (int j = 0, y = this.y-1; j < h; j++, y--) { for (int i = 0, x = this.x; i < w; i++, x++) { if ((glyph[j][i] & 0xFF) >= 0x80) pg.plot(size, x, y); } } return pg; } public PathGraph convertToPathGraph(int xsize, int ysize) { PathGraph pg = new PathGraph(); int w = ((glyph.length < 1) ? 0 : (glyph[0].length)); int h = glyph.length; for (int j = 0, y = this.y-1; j < h; j++, y--) { for (int i = 0, x = this.x; i < w; i++, x++) { if ((glyph[j][i] & 0xFF) >= 0x80) pg.plot(xsize, ysize, x, y); } } return pg; } public byte getPixel(int x, int y) { byte[][] data = getGlyph(); int ix = x - getX(); int iy = y + getY(); if (iy >= 0 && iy < data.length) { if (ix >= 0 && ix < data[iy].length) { return data[iy][ix]; } } return 0; } public void drawLine(int x1, int y1, int x2, int y2, byte v) { byte[][] data = getGlyph(); int gx = getX(); int gy = getY(); for (int i = 0, n = Math.abs(x2 - x1) + Math.abs(y2 - y1) + 1; i <= n; i++) { int ix = x1 + (int)Math.round((x2 - x1) * i / (double)n) - gx; int iy = y1 + (int)Math.round((y2 - y1) * i / (double)n) + gy; if (iy >= 0 && iy < data.length) { if (ix >= 0 && ix < data[iy].length) { data[iy][ix] = v; } } } } public void drawRect(int x1, int y1, int w, int h, byte v) { byte[][] data = getGlyph(); int gx = getX(); int gy = getY(); for (int y = y1, y2 = y1 + h; y <= y2; y++) { int ix1 = x1 - gx; int ix2 = x1 + w - gx; int iy = y + gy; if (iy >= 0 && iy < data.length) { if (ix1 >= 0 && ix1 < data[iy].length) { data[iy][ix1] = v; } if (ix2 >= 0 && ix2 < data[iy].length) { data[iy][ix2] = v; } } } for (int x = x1, x2 = x1 + w; x <= x2; x++) { int ix = x - gx; int iy1 = y1 + gy; int iy2 = y1 + h + gy; if (iy1 >= 0 && iy1 < data.length) { if (ix >= 0 && ix < data[iy1].length) { data[iy1][ix] = v; } } if (iy2 >= 0 && iy2 < data.length) { if (ix >= 0 && ix < data[iy2].length) { data[iy2][ix] = v; } } } } public void fillRect(int x1, int y1, int w, int h, byte v) { byte[][] data = getGlyph(); int gx = getX(); int gy = getY(); for (int y = y1, y2 = y1 + h; y < y2; y++) { int iy = y + gy; for (int x = x1, x2 = x1 + w; x < x2; x++) { int ix = x - gx; if (iy >= 0 && iy < data.length) { if (ix >= 0 && ix < data[iy].length) { data[iy][ix] = v; } } } } } public void invertRect(int x1, int y1, int w, int h) { byte[][] data = getGlyph(); int gx = getX(); int gy = getY(); for (int y = y1, y2 = y1 + h; y < y2; y++) { int iy = y + gy; for (int x = x1, x2 = x1 + w; x < x2; x++) { int ix = x - gx; if (iy >= 0 && iy < data.length) { if (ix >= 0 && ix < data[iy].length) { data[iy][ix] ^= -1; } } } } } public void setToImage(int x, int y, BufferedImage image) { int w = image.getWidth(); int h = image.getHeight(); int[] p = new int[w * h]; image.getRGB(0, 0, w, h, p, 0, w); byte[][] data = new byte[h][w]; for (int dy = 0, py = 0; dy < h; dy++, py += w) { for (int ix = 0; ix < w; ix++) { int pa = (p[py + ix] >> 24) & 0xFF; int pr = (p[py + ix] >> 16) & 0xFF; int pg = (p[py + ix] >> 8) & 0xFF; int pb = (p[py + ix] >> 0) & 0xFF; int px = (25500 - (30 * pr + 59 * pg + 11 * pb)) * pa / 25500; data[dy][ix] = (byte)px; } } setXY(x, -y); setGlyph(data); } public void expand(int x, int y, int w, int h) { byte[][] data = getGlyph(); if (data.length == 0) { setXY(x, -y); setGlyph(new byte[h][w]); return; } int gx = getX(); int gy = getY(); int gw = data[0].length; int gh = data.length; int ex = Math.min(x, gx); int ey = Math.min(y, -gy); int ew = Math.max(x + w, gx + gw) - ex; int eh = Math.max(y + h, -gy + gh) - ey; if (ex < gx || ey < -gy || ex + ew > gx + gw || ey + eh > -gy + gh) { byte[][] newData = new byte[eh][ew]; for (int sy = 0, dy = -gy - ey; sy < gh; sy++, dy++) { for (int sx = 0, dx = gx - ex; sx < gw; sx++, dx++) { newData[dy][dx] = data[sy][sx]; } } setXY(ex, -ey); setGlyph(newData); } } public void contract() { byte[][] data = getGlyph(); if (data.length == 0) { setXY(0,0); return; } int gx = getX(); int gy = getY(); int gw = data[0].length; int gh = data.length; int cx1 = gx; int cy1 = -gy; int cx2 = gx + gw; int cy2 = -gy + gh; while (cy2 > cy1 && rowEmpty(data, cy2 + gy - 1)) cy2--; while (cy1 < cy2 && rowEmpty(data, cy1 + gy)) cy1++; while (cx2 > cx1 && colEmpty(data, cx2 - gx - 1)) cx2--; while (cx1 < cx2 && colEmpty(data, cx1 - gx)) cx1++; if (cx2 == cx1 || cy2 == cy1) { setXY(0,0); setGlyph(new byte[0][0]); return; } if (cx1 != gx || cy1 != -gy || cx2 != gx + gw || cy2 != -gy + gh) { int cw = cx2 - cx1; int ch = cy2 - cy1; byte[][] newData = new byte[ch][cw]; for (int dy = 0, sy = cy1 + gy; dy < ch; dy++, sy++) { for (int dx = 0, sx = cx1 - gx; dx < cw; dx++, sx++) { newData[dy][dx] = data[sy][sx]; } } setXY(cx1, -cy1); setGlyph(newData); } } public static BitmapFontGlyph compose(BitmapFontGlyph... glyphs) { int x0 = Integer.MAX_VALUE, y0 = Integer.MAX_VALUE; int x1 = Integer.MIN_VALUE, y1 = Integer.MIN_VALUE; int advance = Integer.MIN_VALUE; for (BitmapFontGlyph glyph : glyphs) { if (glyph == null) continue; if (glyph.x < x0) x0 = glyph.x; if (-glyph.y < y0) y0 = -glyph.y; if (glyph.advance > advance) advance = glyph.advance; if (-glyph.y + glyph.glyph.length > y1) y1 = -glyph.y + glyph.glyph.length; for (byte[] row : glyph.glyph) { if (glyph.x + row.length > x1) x1 = glyph.x + row.length; } } if (y1 < y0 || x1 < x0) return null; byte[][] g = new byte[y1 - y0][x1 - x0]; for (BitmapFontGlyph glyph : glyphs) { if (glyph == null) continue; int bx = glyph.x - x0; int by = -glyph.y - y0; for (int y = 0; y < glyph.glyph.length; y++) { for (int x = 0; x < glyph.glyph[y].length; x++) { if ((glyph.glyph[y][x] & 0xFF) > (g[by + y][bx + x] & 0xFF)) { g[by + y][bx + x] = glyph.glyph[y][x]; } } } } return new BitmapFontGlyph(g, x0, advance, -y0); } private static boolean rowEmpty(byte[][] a, int row) { for (byte b : a[row]) if (b != 0) return false; return true; } private static boolean colEmpty(byte[][] a, int col) { for (byte[] b : a) if (b[col] != 0) return false; return true; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/BitmapFontGlyphTransformer.java000077500000000000000000000002111506470510200335700ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface BitmapFontGlyphTransformer extends FontGlyphTransformer { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/BitmapFontImporter.java000077500000000000000000000001641506470510200320720ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface BitmapFontImporter extends FontImporter { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/FileProxy.java000066400000000000000000000060101506470510200302170ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import javax.imageio.ImageIO; public class FileProxy { private final File file; private final String lcname; private boolean checkedMacInfo; private String macType; private String macCreator; private byte[] contents; private boolean checkedImage; private BufferedImage image; public FileProxy(String pathname) { this(new File(pathname)); } public FileProxy(String parent, String child) { this(new File(parent, child)); } public FileProxy(File parent, String child) { this(new File(parent, child)); } public FileProxy(File file) { this.file = file; this.lcname = file.getName().toLowerCase(); this.checkedMacInfo = false; this.macType = null; this.macCreator = null; this.contents = null; this.checkedImage = false; this.image = null; } public boolean hasExtension(String... exts) { for (String ext : exts) { ext = ext.toLowerCase(); if (!ext.startsWith(".")) ext = "." + ext; if (lcname.endsWith(ext)) return true; } return false; } private void checkMacInfo() { if (!checkedMacInfo) { macType = MacUtility.getType(file); macCreator = MacUtility.getCreator(file); checkedMacInfo = true; } } public boolean hasMacType(String type) { checkMacInfo(); return type.equals(macType); } public boolean hasMacCreator(String creator) { checkMacInfo(); return creator.equals(macCreator); } private void checkContents(int length) { if (contents == null || contents.length < length) { try { byte[] buf = new byte[length]; FileInputStream in = new FileInputStream(file); for (int i = 0; i < length; i++) buf[i] = (byte)in.read(); in.close(); contents = buf; } catch (IOException e) { return; } } } public boolean startsWith(byte... data) { checkContents(data.length); if (contents == null || contents.length < data.length) { return false; } else { for (int i = 0; i < data.length; i++) { if (contents[i] != (byte)data[i]) { return false; } } return true; } } public boolean startsWith(int... data) { checkContents(data.length); if (contents == null || contents.length < data.length) { return false; } else { for (int i = 0; i < data.length; i++) { if (contents[i] != (byte)data[i]) { return false; } } return true; } } public byte[] getStartBytes(int len) { checkContents(len); if (contents == null || contents.length < len) return null; return contents; } public boolean isImage() { if (checkedImage) return image != null; try { image = ImageIO.read(file); checkedImage = true; return image != null; } catch (IOException e) { return false; } } public BufferedImage getImage() { if (checkedImage) return image; try { image = ImageIO.read(file); checkedImage = true; return image; } catch (IOException e) { return null; } } public File getFile() { return file; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/Font.java000077500000000000000000000405561506470510200272240ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.text.*; import java.util.*; public abstract class Font { /* * line , ------------------------------------------------------------ <- previous line's line descent * gap ` ------------------------------------------------------------ <- line ascent * / ------------------------------------------------------------ <- em ascent * | ^ A i M M k * | | __A________________________MM_MM___________k________________ <- x-height * | em | A A mm m i ggg aaa M M M oo nnn k k eee y y ss * | size | AAA m m m i g g a a M M o o n n kk e e y y s * line < | A A m m m i ggg aaa M M oo n n k k eee yyy ss * height| | =================g=====================================y==== <- baseline * | v gg yy * | ------------------------------------------------------------ <- em descent * | line , ------------------------------------------------------------ <- line descent * \ gap ` ------------------------------------------------------------ <- next line's line ascent */ public static final int NAME_COPYRIGHT = 0; public static final int NAME_FAMILY = 1; public static final int NAME_STYLE = 2; public static final int NAME_UNIQUE_ID = 3; public static final int NAME_FAMILY_AND_STYLE = 4; public static final int NAME_VERSION = 5; public static final int NAME_POSTSCRIPT = 6; public static final int NAME_TRADEMARK = 7; public static final int NAME_MANUFACTURER = 8; public static final int NAME_DESIGNER = 9; public static final int NAME_DESCRIPTION = 10; public static final int NAME_VENDOR_URL = 11; public static final int NAME_DESIGNER_URL = 12; public static final int NAME_LICENSE_DESCRIPTION = 13; public static final int NAME_LICENSE_URL = 14; public static final int NAME_WINDOWS_FAMILY = 16; public static final int NAME_WINDOWS_STYLE = 17; public static final int NAME_MACOS_FAMILY_AND_STYLE = 18; public static final int NAME_SAMPLE_TEXT = 19; public static final int NAME_POSTSCRIPT_CID = 20; public static final int NAME_WWS_FAMILY = 21; public static final int NAME_WWS_STYLE = 22; protected SortedMap names = new TreeMap(); protected SortedMap characters = new TreeMap(); protected SortedMap namedGlyphs = new TreeMap(); protected SortedMap kernPairs = new TreeMap(); public abstract int getEmAscent(); public abstract int getEmDescent(); public abstract int getLineAscent(); public abstract int getLineDescent(); public abstract int getXHeight(); public abstract int getCapHeight(); public abstract int getLineGap(); public abstract double getEmAscent2D(); public abstract double getEmDescent2D(); public abstract double getLineAscent2D(); public abstract double getLineDescent2D(); public abstract double getXHeight2D(); public abstract double getCapHeight2D(); public abstract double getLineGap2D(); public abstract void setEmAscent(int v); public abstract void setEmDescent(int v); public abstract void setLineAscent(int v); public abstract void setLineDescent(int v); public abstract void setXHeight(int v); public abstract void setCapHeight(int v); public abstract void setLineGap(int v); public abstract void setEmAscent2D(double v); public abstract void setEmDescent2D(double v); public abstract void setLineAscent2D(double v); public abstract void setLineDescent2D(double v); public abstract void setXHeight2D(double v); public abstract void setCapHeight2D(double v); public abstract void setLineGap2D(double v); public boolean isEmpty() { return characters.isEmpty() && namedGlyphs.isEmpty(); } public boolean containsCharacter(int ch) { return characters.containsKey(ch); } public T getCharacter(int ch) { return characters.get(ch); } public T putCharacter(int ch, T fc) { if (fc == null) return characters.remove(ch); return characters.put(ch, fc); } public T removeCharacter(int ch) { return characters.remove(ch); } public SortedMap characters(boolean copy) { if (copy) return new TreeMap(characters); return Collections.unmodifiableSortedMap(characters); } public boolean containsNamedGlyph(String name) { if (name == null) return false; return namedGlyphs.containsKey(name); } public T getNamedGlyph(String name) { if (name == null) return null; return namedGlyphs.get(name); } public T putNamedGlyph(String name, T fc) { if (name == null) return null; if (fc == null) return namedGlyphs.remove(name); return namedGlyphs.put(name, fc); } public T removeNamedGlyph(String name) { if (name == null) return null; return namedGlyphs.remove(name); } public SortedMap namedGlyphs(boolean copy) { if (copy) return new TreeMap(namedGlyphs); return Collections.unmodifiableSortedMap(namedGlyphs); } public boolean containsName(int nametype) { return names.containsKey(nametype); } public String getName(int nametype) { return names.get(nametype); } public String setName(int nametype, String name) { if (name == null) return names.remove(nametype); return names.put(nametype, name); } public String removeName(int nametype) { return names.remove(nametype); } public SortedMap names(boolean copy) { if (copy) return new TreeMap(names); return Collections.unmodifiableSortedMap(names); } public boolean containsKernPair(GlyphPair gp) { if (gp == null) return false; return kernPairs.containsKey(gp); } public int getKernPair(GlyphPair gp) { if (gp == null) return 0; Integer o = kernPairs.get(gp); return (o != null) ? o.intValue() : 0; } public int setKernPair(GlyphPair gp, int offset) { if (gp == null) return 0; Integer o = kernPairs.put(gp, offset); return (o != null) ? o.intValue() : 0; } public int removeKernPair(GlyphPair gp) { if (gp == null) return 0; Integer o = kernPairs.remove(gp); return (o != null) ? o.intValue() : 0; } public SortedMap kernPairs(boolean copy) { if (copy) return new TreeMap(kernPairs); return Collections.unmodifiableSortedMap(kernPairs); } private static final char[] BASELINE_CHARS = "HXxZzAMNTYilmnEFIKLPRhkrvwVWBDbduftCGJOSUaceos2147035689ÞÆæÐØø¥£ß&!?.%@±".toCharArray(); private static final char[] CAP_HEIGHT_CHARS = "HXTZAMNUVWYEFIJKLBDPRCGOQS5714023689ÞÆÐØbdhklþft¥!?&£ß%@".toCharArray(); private static final char[] X_HEIGHT_CHARS = "xzuvwymnracegopqsµæø".toCharArray(); public int guessBaselineAdjustment() { for (int ch : BASELINE_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphHeight() - fc.getGlyphAscent(); } return 0; } public double guessBaselineAdjustment2D() { for (int ch : BASELINE_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphHeight2D() - fc.getGlyphAscent2D(); } return 0; } public int guessCapHeight() { for (int ch : CAP_HEIGHT_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphAscent(); } return 0; } public double guessCapHeight2D() { for (int ch : CAP_HEIGHT_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphAscent2D(); } return 0; } public int guessXHeight() { for (int ch : X_HEIGHT_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphAscent(); } return 0; } public double guessXHeight2D() { for (int ch : X_HEIGHT_CHARS) { T fc = characters.get(ch); if (fc != null) return fc.getGlyphAscent2D(); } return 0; } private static final List MONOSPACED_CLASSES = Arrays.asList( Integer.valueOf(Character.UPPERCASE_LETTER), Integer.valueOf(Character.LOWERCASE_LETTER), Integer.valueOf(Character.TITLECASE_LETTER), Integer.valueOf(Character.MODIFIER_LETTER), Integer.valueOf(Character.OTHER_LETTER), Integer.valueOf(Character.DECIMAL_DIGIT_NUMBER), Integer.valueOf(Character.LETTER_NUMBER), Integer.valueOf(Character.OTHER_NUMBER), Integer.valueOf(Character.DASH_PUNCTUATION), Integer.valueOf(Character.START_PUNCTUATION), Integer.valueOf(Character.END_PUNCTUATION), Integer.valueOf(Character.CONNECTOR_PUNCTUATION), Integer.valueOf(Character.OTHER_PUNCTUATION), Integer.valueOf(Character.MATH_SYMBOL), Integer.valueOf(Character.CURRENCY_SYMBOL), Integer.valueOf(Character.MODIFIER_SYMBOL), Integer.valueOf(Character.OTHER_SYMBOL), Integer.valueOf(Character.INITIAL_QUOTE_PUNCTUATION), Integer.valueOf(Character.FINAL_QUOTE_PUNCTUATION) ); public boolean isMonospaced() { T space = characters.get(32); int monoWidth = (space != null) ? space.getCharacterWidth() : 0; for (Map.Entry e : characters.entrySet()) { if (e.getValue().getCharacterWidth() != monoWidth) { Integer cc = Integer.valueOf(Character.getType(e.getKey())); if (MONOSPACED_CLASSES.contains(cc)) return false; } } return true; } public boolean isBoldStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("BOLD") || s.contains("BLACK") || s.contains("HEAVY"); } else { return false; } } public boolean isItalicStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("ITALIC") || s.contains("OBLIQUE") || s.contains("SLANT") || s.contains("ROTALIC"); } else { return false; } } public boolean isUnderlineStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("UNDERLINE") || s.contains("UNDERSCORE"); } else { return false; } } public boolean isOutlineStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("OUTLINE"); } else { return false; } } public boolean isShadowStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("SHADOW"); } else { return false; } } public boolean isCondensedStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("CONDENSE") || s.contains("NARROW"); } else { return false; } } public boolean isExtendedStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("EXTEND") || s.contains("EXPAND") || s.contains("WIDE"); } else { return false; } } public boolean isNegativeStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("NEGATIVE") || s.contains("REVERSE") || s.contains("INVERSE") || s.contains("INVERT"); } else { return false; } } public boolean isStrikeoutStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("STRIKEOUT") || s.contains("STRIKETHR"); } else { return false; } } public boolean isRegularStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).trim(); return s.equalsIgnoreCase("") || s.equalsIgnoreCase("PLAIN") || s.equalsIgnoreCase("REGULAR") || s.equalsIgnoreCase("NORMAL") || s.equalsIgnoreCase("MEDIUM"); } else { return false; } } public boolean isObliqueStyle() { if (names.containsKey(NAME_STYLE)) { String s = names.get(NAME_STYLE).toUpperCase(); return s.contains("OBLIQUE") || s.contains("SLANT"); } else { return false; } } public int getMacStyle() { int s = 0; if (isBoldStyle()) s |= 0x01; if (isItalicStyle()) s |= 0x02; if (isUnderlineStyle()) s |= 0x04; if (isOutlineStyle()) s |= 0x08; if (isShadowStyle()) s |= 0x10; if (isCondensedStyle()) s |= 0x20; if (isExtendedStyle()) s |= 0x40; return s; } public int getFsSelection() { int s = 0; if (isItalicStyle()) s |= 0x0001; if (isUnderlineStyle()) s |= 0x0002; if (isNegativeStyle()) s |= 0x0004; if (isOutlineStyle()) s |= 0x0008; if (isStrikeoutStyle()) s |= 0x0010; if (isBoldStyle()) s |= 0x0020; if (isRegularStyle()) s |= 0x0040; // useTypoMetrics s |= 0x0080; // weightWidthSlope s |= 0x0100; if (isObliqueStyle()) s |= 0x0200; return s; } public void autoFillNames() { String fname = names.containsKey(NAME_FAMILY) ? names.get(NAME_FAMILY) : "Untitled"; if (names.containsKey(NAME_STYLE)) { String sname = names.get(NAME_STYLE).trim(); if (!( sname.equalsIgnoreCase("") || sname.equalsIgnoreCase("Plain") || sname.equalsIgnoreCase("Regular") || sname.equalsIgnoreCase("Normal") || sname.equalsIgnoreCase("Medium") )) fname += " " + sname; } StringBuffer pnb = new StringBuffer(); CharacterIterator ci = new StringCharacterIterator(fname); for (char ch = ci.first(); ch != CharacterIterator.DONE; ch = ci.next()) { if (ch > 0x20 && ch < 0x7F && Character.isLetterOrDigit(ch)) { pnb.append(ch); } } String pname = pnb.toString(); if (!names.containsKey(NAME_FAMILY)) { names.put(NAME_FAMILY, "Untitled"); } if (!names.containsKey(NAME_STYLE)) { names.put(NAME_STYLE, "Regular"); } if (!names.containsKey(NAME_UNIQUE_ID)) { names.put(NAME_UNIQUE_ID, "BitsNPicas: "+pname+": "+(new GregorianCalendar().get(Calendar.YEAR))); } if (!names.containsKey(NAME_FAMILY_AND_STYLE)) { names.put(NAME_FAMILY_AND_STYLE, fname); } if (!names.containsKey(NAME_VERSION)) { names.put(NAME_VERSION, "Version 1.0"); } if (!names.containsKey(NAME_POSTSCRIPT)) { names.put(NAME_POSTSCRIPT, pname); } if (!names.containsKey(NAME_MANUFACTURER)) { names.put(NAME_MANUFACTURER, "Made with Bits'n'Picas by Kreative Software"); } if (!names.containsKey(NAME_VENDOR_URL)) { names.put(NAME_VENDOR_URL, "http://www.kreativekorp.com/software/bitsnpicas/"); } } public void subsetRemap(Collection sr) { Map oldChars = this.characters; Map oldGlyphs = this.namedGlyphs; this.characters = new TreeMap(); this.namedGlyphs = new TreeMap(); Map newChars = this.characters; Map newGlyphs = this.namedGlyphs; for (GlyphPair gp : sr) { Object oldKey = gp.getLeft(); Object newKey = gp.getRight(); if (oldKey instanceof Integer) { T glyph = oldChars.get(oldKey); if (glyph == null) continue; if (newKey instanceof Integer) newChars.put((Integer)newKey, glyph); if (newKey instanceof String) newGlyphs.put((String)newKey, glyph); } if (oldKey instanceof String) { T glyph = oldGlyphs.get(oldKey); if (glyph == null) continue; if (newKey instanceof Integer) newChars.put((Integer)newKey, glyph); if (newKey instanceof String) newGlyphs.put((String)newKey, glyph); } } } public void transform(FontGlyphTransformer tx) { for (Map.Entry e : characters(true).entrySet()) { T glyph = tx.transformGlyph(e.getValue()); if (glyph != null) characters.put(e.getKey(), glyph); } for (Map.Entry e : namedGlyphs(true).entrySet()) { T glyph = tx.transformGlyph(e.getValue()); if (glyph != null) namedGlyphs.put(e.getKey(), glyph); } } public String toString() { if (names.containsKey(NAME_FAMILY_AND_STYLE)) { return names.get(NAME_FAMILY_AND_STYLE); } if (names.containsKey(NAME_FAMILY)) { if (names.containsKey(NAME_STYLE)) { return names.get(NAME_FAMILY) + " " + names.get(NAME_STYLE); } else { return names.get(NAME_FAMILY); } } if (names.containsKey(NAME_WINDOWS_FAMILY)) { if (names.containsKey(NAME_WINDOWS_STYLE)) { return names.get(NAME_WINDOWS_FAMILY) + " " + names.get(NAME_WINDOWS_STYLE); } else { return names.get(NAME_WINDOWS_FAMILY); } } if (names.containsKey(NAME_MACOS_FAMILY_AND_STYLE)) { return names.get(NAME_MACOS_FAMILY_AND_STYLE); } if (names.containsKey(NAME_WWS_FAMILY)) { if (names.containsKey(NAME_WWS_STYLE)) { return names.get(NAME_WWS_FAMILY) + " " + names.get(NAME_WWS_STYLE); } else { return names.get(NAME_WWS_FAMILY); } } if (names.containsKey(NAME_POSTSCRIPT)) { return names.get(NAME_POSTSCRIPT); } return "Untitled"; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/FontExporter.java000077500000000000000000000005131506470510200307420ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.*; public interface FontExporter> { public byte[] exportFontToBytes(T font) throws IOException; public void exportFontToStream(T font, OutputStream os) throws IOException; public void exportFontToFile(T font, File file) throws IOException; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/FontGlyph.java000077500000000000000000000023601506470510200302170ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.Graphics; public abstract class FontGlyph { /* * | glyph | * | glyph <-width-> | * |<-offset->+-------+ ^ | * | ^ | *| | | * | | | ***** | | | * | glyph | |* * | | glyph | * | ascent | |* * | | height | * | v | ***** | | | * |==========|=====*=|=|========| * | ^ | * | | | * | glyph | | **** | | | * |descent v +-------+ v | * |<------character width------>| */ public abstract int getGlyphOffset(); public abstract int getGlyphWidth(); public abstract int getGlyphHeight(); public abstract int getGlyphAscent(); public abstract int getGlyphDescent(); public abstract int getCharacterWidth(); public abstract double getGlyphOffset2D(); public abstract double getGlyphWidth2D(); public abstract double getGlyphHeight2D(); public abstract double getGlyphAscent2D(); public abstract double getGlyphDescent2D(); public abstract double getCharacterWidth2D(); public abstract void setCharacterWidth(int v); public abstract void setCharacterWidth2D(double v); public abstract double paint(Graphics g, double x, double y, double scale); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/FontGlyphTransformer.java000077500000000000000000000002041506470510200324350ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface FontGlyphTransformer { public T transformGlyph(T glyph); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/FontImporter.java000077500000000000000000000004451506470510200307370ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.*; public interface FontImporter> { public T[] importFont(byte[] data) throws IOException; public T[] importFont(InputStream is) throws IOException; public T[] importFont(File file) throws IOException; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/GlyphPair.java000066400000000000000000000034421506470510200302030ustar00rootroot00000000000000package com.kreative.bitsnpicas; public class GlyphPair implements Comparable { private final Object left; private final Object right; public GlyphPair(Integer left, Integer right) { if (left == null || right == null) throw new IllegalArgumentException("null"); this.left = left; this.right = right; } public GlyphPair(Integer left, String right) { if (left == null || right == null) throw new IllegalArgumentException("null"); this.left = left; this.right = right; } public GlyphPair(String left, Integer right) { if (left == null || right == null) throw new IllegalArgumentException("null"); this.left = left; this.right = right; } public GlyphPair(String left, String right) { if (left == null || right == null) throw new IllegalArgumentException("null"); this.left = left; this.right = right; } public Object getLeft() { return left; } public Object getRight() { return right; } public int compareTo(GlyphPair that) { int c; if ((c = compare(this.left, that.left)) != 0) return c; if ((c = compare(this.right, that.right)) != 0) return c; return 0; } private static int compare(Object a, Object b) { if (a instanceof Integer) { if (b instanceof Integer) { return ((Integer)a).compareTo((Integer)b); } else { return -1; } } else { if (b instanceof Integer) { return +1; } else { return a.toString().compareTo(b.toString()); } } } public boolean equals(Object o) { if (o instanceof GlyphPair) { GlyphPair that = (GlyphPair)o; return this.left.equals(that.left) && this.right.equals(that.right); } else { return false; } } public int hashCode() { return left.hashCode() ^ right.hashCode(); } public String toString() { return left.toString() + "," + right.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/IDGenerator.java000066400000000000000000000026161506470510200304510ustar00rootroot00000000000000package com.kreative.bitsnpicas; public abstract class IDGenerator { public abstract void setRange(int min, int max); public abstract int generateID(Font font); public static class Sequential extends IDGenerator { private int id, min, max; public Sequential(int id, int min, int max) { this.id = id; this.min = min; this.max = max; } @Override public void setRange(int min, int max) { this.min = min; this.max = max; } @Override public int generateID(Font font) { int newId = id++; if (id >= max) id = min; return newId; } } public static class Random extends IDGenerator { private java.util.Random random; private int min, max; public Random(int min, int max) { this.random = new java.util.Random(); this.min = min; this.max = max; } @Override public void setRange(int min, int max) { this.min = min; this.max = max; } @Override public int generateID(Font font) { return random.nextInt(max - min) + min; } } public static class HashCode extends IDGenerator { private int min, max; public HashCode(int min, int max) { this.min = min; this.max = max; } @Override public void setRange(int min, int max) { this.min = min; this.max = max; } @Override public int generateID(Font font) { int id = font.getName(Font.NAME_FAMILY).hashCode() >>> 1; return (id % (max - min)) + min; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/MacUtility.java000066400000000000000000000052251506470510200303710ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.File; import java.io.IOException; import java.util.Scanner; public class MacUtility { public static File getDataFork(File file) { if (file.getName().equals("rsrc")) { File parent = file.getParentFile(); if (parent != null && parent.getName().equals("..namedfork")) { File gparent = parent.getParentFile(); if (gparent != null) return gparent; } } return file; } public static File getResourceFork(File file) { if (getDataFork(file) != file) return file; return new File(new File(file, "..namedfork"), "rsrc"); } public static void setTypeAndCreator(File file, String type, String creator) { try { String[] cmd = {"/usr/bin/SetFile", "-t", type, "-c", creator, file.getAbsolutePath()}; Process p = Runtime.getRuntime().exec(cmd); try { p.waitFor(); } catch (InterruptedException e) {} } catch (IOException e) { // Ignored. } } public static String getType(File file) { try { String[] cmd = {"/usr/bin/GetFileInfo", "-t", file.getAbsolutePath()}; Process p = Runtime.getRuntime().exec(cmd); Scanner scan = new Scanner(p.getInputStream()); if (scan.hasNextLine()) { String type = scan.nextLine().trim(); scan.close(); try { p.waitFor(); } catch (InterruptedException e) {} return unescape(type); } scan.close(); try { p.waitFor(); } catch (InterruptedException e) {} return null; } catch (IOException e) { return null; } } public static String getCreator(File file) { try { String[] cmd = {"/usr/bin/GetFileInfo", "-c", file.getAbsolutePath()}; Process p = Runtime.getRuntime().exec(cmd); Scanner scan = new Scanner(p.getInputStream()); if (scan.hasNextLine()) { String creator = scan.nextLine().trim(); scan.close(); try { p.waitFor(); } catch (InterruptedException e) {} return unescape(creator); } scan.close(); try { p.waitFor(); } catch (InterruptedException e) {} return null; } catch (IOException e) { return null; } } private static String unescape(String s) { StringBuffer sb = new StringBuffer(); char[] chars = s.toCharArray(); int i = 0, n = chars.length; if (chars[i] == '"' && chars[n-1] == '"') { i++; n--; } while (i < n) { char ch = chars[i++]; if (ch == '\\' && i < n) { ch = chars[i++]; switch (ch) { case '0': ch = 0; break; case 'a': ch = 7; break; case 'b': ch = 8; break; case 't': ch = 9; break; case 'n': ch = 10; break; case 'v': ch = 11; break; case 'f': ch = 12; break; case 'r': ch = 13; break; case 'e': ch = 27; break; } } sb.append(ch); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/PathExtensions.java000066400000000000000000000456571506470510200312760ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.CubicCurve2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.IllegalPathStateException; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.util.Arrays; import java.util.List; public class PathExtensions { public static final int CHORD = Arc2D.CHORD; public static final int OPEN = Arc2D.OPEN; public static final int PIE = Arc2D.PIE; public static final int WIND_NON_ZERO = GeneralPath.WIND_NON_ZERO; public static final int WIND_EVEN_ODD = GeneralPath.WIND_EVEN_ODD; private GeneralPath p; private double lcx, lx; private double lcy, ly; public PathExtensions() { this(new GeneralPath()); } public PathExtensions(GeneralPath p) { this.p = p; Point2D p0 = p.getCurrentPoint(); if (p0 == null) { p.moveTo(0, 0); this.lcx = this.lx = 0; this.lcy = this.ly = 0; } else { this.lcx = this.lx = p0.getX(); this.lcy = this.ly = p0.getY(); } } public GeneralPath getPath() { return p; } public Point2D getCurrentPoint() { return p.getCurrentPoint(); } public void execute(char operation, Number... operands) { execute(operation, Arrays.asList(operands)); } public void execute(char operation, List operands) { double p0 = (operands.size() > 0) ? operands.get(0).doubleValue() : 0; double p1 = (operands.size() > 1) ? operands.get(1).doubleValue() : 0; double p2 = (operands.size() > 2) ? operands.get(2).doubleValue() : 0; double p3 = (operands.size() > 3) ? operands.get(3).doubleValue() : 0; double p4 = (operands.size() > 4) ? operands.get(4).doubleValue() : 0; double p5 = (operands.size() > 5) ? operands.get(5).doubleValue() : 0; double p6 = (operands.size() > 6) ? operands.get(6).doubleValue() : 0; switch (operation) { case 'M': moveTo(p0, p1); break; case 'm': moveTo(p0 + lx, p1 + ly); break; case 'H': horizTo(p0); break; case 'h': horizTo(p0 + lx); break; case 'V': vertTo(p0); break; case 'v': vertTo(p0 + ly); break; case 'L': lineTo(p0, p1); break; case 'l': lineTo(p0 + lx, p1 + ly); break; case 'Q': quadTo(p0, p1, p2, p3); break; case 'q': quadTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly); break; case 'T': quadTo(p0, p1); break; case 't': quadTo(p0 + lx, p1 + ly); break; case 'C': curveTo(p0, p1, p2, p3, p4, p5); break; case 'c': curveTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly, p4 + lx, p5 + ly); break; case 'S': curveTo(p0, p1, p2, p3); break; case 's': curveTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly); break; case 'K': timmerTo(p0, p1, p2, p3, p4, p5); break; case 'k': timmerTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly, p4 + lx, p5 + ly); break; case 'U': timmerTo(p0, p1, p2, p3); break; case 'u': timmerTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly); break; case 'A': svgArcTo(p0, p1, p2, p3 != 0, p4 != 0, p5, p6); break; case 'a': svgArcTo(p0, p1, p2, p3 != 0, p4 != 0, p5 + lx, p6 + ly); break; case 'G': arcThroughTo(p0, p1, p2, p3); break; case 'g': arcThroughTo(p0 + lx, p1 + ly, p2 + lx, p3 + ly); break; case 'I': gerberArcTo(p0, p1, p2 != 0, p3 != 0, p4, p5); break; case 'i': gerberArcTo(p0, p1, p2 != 0, p3 != 0, p4 + lx, p5 + ly); break; case 'J': gerberArcTo(p0, p1, p2 != 0, p3 != 0, p4, p5); break; case 'j': gerberArcTo(p0, p1, p2 != 0, p3 != 0, p4 + lx, p5 + ly); break; case 'R': appendRectangle(p0, p1, p2, p3, p4, p5); break; case 'r': appendRectangle(p0 + lx, p1 + ly, p2, p3, p4, p5); break; case 'E': appendEllipse(p0, p1, p2, p3, p4, p5, (int)Math.round(p6)); break; case 'e': appendEllipse(p0 + lx, p1 + ly, p2, p3, p4, p5, (int)Math.round(p6)); break; case 'O': appendEllipse(p0, p1, p2, p3, p4, p5, (int)Math.round(p6)); break; case 'o': appendEllipse(p0 + lx, p1 + ly, p2, p3, p4, p5, (int)Math.round(p6)); break; case 'P': appendRegularPolygon(p0, p1, p2, p3, (int)Math.round(p4), (int)Math.round(p5)); break; case 'p': appendRegularPolygon(p0 + lx, p1 + ly, p2 + lx, p3 + ly, (int)Math.round(p4), (int)Math.round(p5)); break; case 'X': appendAsterisk(p0, p1, p2, p3, (int)Math.round(p4)); break; case 'x': appendAsterisk(p0 + lx, p1 + ly, p2 + lx, p3 + ly, (int)Math.round(p4)); break; case 'Z': closePath(); break; case 'z': closePath(); break; case 'W': setWindingRule((p0 == 0) ? WIND_NON_ZERO : WIND_EVEN_ODD); break; case 'w': setWindingRule((p0 == 0) ? WIND_NON_ZERO : WIND_EVEN_ODD); break; } } public void moveTo(double x, double y) { p.moveTo(lcx = lx = x, lcy = ly = y); } public void horizTo(double x) { p.lineTo(lcx = lx = x, lcy = ly); } public void vertTo(double y) { p.lineTo(lcx = lx, lcy = ly = y); } public void lineTo(double x, double y) { p.lineTo(lcx = lx = x, lcy = ly = y); } public void quadTo(double cx, double cy, double x, double y) { p.quadTo(lcx = cx, lcy = cy, lx = x, ly = y); } public void quadTo(double x, double y) { this.quadTo(lx + lx - lcx, ly + ly - lcy, x, y); } public void curveTo(double ccx, double ccy, double cx, double cy, double x, double y) { p.curveTo(ccx, ccy, lcx = cx, lcy = cy, lx = x, ly = y); } public void curveTo(double cx, double cy, double x, double y) { this.curveTo(lx + lx - lcx, ly + ly - lcy, cx, cy, x, y); } public void timmerTo(double ccx, double ccy, double cx, double cy, double x, double y) { timmerTo(p, ccx, ccy, lcx = cx, lcy = cy, lx = x, ly = y); } public void timmerTo(double cx, double cy, double x, double y) { this.timmerTo(lx + lx - lcx, ly + ly - lcy, cx, cy, x, y); } public void svgArcTo(double rx, double ry, double a, boolean large, boolean sweep, double x, double y) { svgArcTo(p, rx, ry, a, large, sweep, lcx = lx = x, lcy = ly = y); } public void arcThroughTo(double cx, double cy, double x, double y) { arcThroughTo(p, cx, cy, lcx = lx = x, lcy = ly = y); } public void gerberArcTo(double i, double j, boolean large, boolean sweep, double x, double y) { gerberArcTo(p, i, j, large, sweep, lcx = lx = x, lcy = ly = y); } public void appendRectangle(double x, double y, double w, double h, double rw, double rh) { Point2D p0 = appendRectangle(p, x, y, w, h, rw, rh); lcx = lx = p0.getX(); lcy = ly = p0.getY(); } public void appendEllipse(double x, double y, double w, double h, double as, double ae, int at) { Point2D p0 = appendEllipse(p, x, y, w, h, as, ae, at); lcx = lx = p0.getX(); lcy = ly = p0.getY(); } public void appendRegularPolygon(double cx, double cy, double ex, double ey, int sides, int skips) { Point2D p0 = appendRegularPolygon(p, cx, cy, ex, ey, sides, skips); lcx = lx = p0.getX(); lcy = ly = p0.getY(); } public void appendAsterisk(double cx, double cy, double ex, double ey, int sides) { Point2D p0 = appendAsterisk(p, cx, cy, ex, ey, sides); lcx = lx = p0.getX(); lcy = ly = p0.getY(); } public void closePath() { p.closePath(); lcx = lx = p.getCurrentPoint().getX(); lcy = ly = p.getCurrentPoint().getY(); } public int getWindingRule() { return p.getWindingRule(); } public void setWindingRule(int rule) { p.setWindingRule(rule); } public void append(PathIterator pi, boolean connect) { p.append(pi, connect); lcx = lx = p.getCurrentPoint().getX(); lcy = ly = p.getCurrentPoint().getY(); } public void append(Shape s, boolean connect) { p.append(s, connect); lcx = lx = p.getCurrentPoint().getX(); lcy = ly = p.getCurrentPoint().getY(); } public static int getOperandCount(char operation) { switch (operation) { case 'Z': case 'z': return 0; case 'H': case 'h': case 'V': case 'v': case 'W': case 'w': return 1; case 'M': case 'm': case 'L': case 'l': case 'T': case 't': return 2; case 'Q': case 'q': case 'S': case 's': case 'U': case 'u': case 'G': case 'g': return 4; case 'X': case 'x': return 5; case 'C': case 'c': case 'K': case 'k': case 'I': case 'i': case 'J': case 'j': case 'R': case 'r': case 'P': case 'p': return 6; case 'A': case 'a': case 'E': case 'e': case 'O': case 'o': return 7; default: return -1; } } public static void timmerTo( GeneralPath p, double rx, double ry, double sx, double sy, double x, double y ) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) throw new IllegalPathStateException("missing initial moveto in path definition"); double ax = p0.getX() + (rx - p0.getX()) * 4 / 3; double ay = p0.getY() + (ry - p0.getY()) * 4 / 3; double bx = x - (x - sx) * 4 / 3; double by = y - (y - sy) * 4 / 3; p.curveTo(ax, ay, bx, by, x, y); } public static CubicCurve2D createTimmer( double x0, double y0, double rx, double ry, double sx, double sy, double x, double y ) { double ax = x0 + (rx - x0) * 4 / 3; double ay = y0 + (ry - y0) * 4 / 3; double bx = x - (x - sx) * 4 / 3; double by = y - (y - sy) * 4 / 3; return new CubicCurve2D.Double(x0, y0, ax, ay, bx, by, x, y); } public static void svgArcTo( GeneralPath p, double rx, double ry, double a, boolean large, boolean sweep, double x, double y ) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) throw new IllegalPathStateException("missing initial moveto in path definition"); Shape arc = createSvgArc(p0.getX(), p0.getY(), rx, ry, a, large, sweep, x, y); if (arc != null) p.append(arc, true); p.lineTo(x, y); } public static Shape createSvgArc( double x0, double y0, double rx, double ry, double a, boolean large, boolean sweep, double x, double y ) { if (x0 == x && y0 == y) return null; if (rx == 0 || ry == 0) return null; double dx2 = (x0 - x) / 2; double dy2 = (y0 - y) / 2; a = Math.toRadians(a % 360); double ca = Math.cos(a); double sa = Math.sin(a); double x1 = sa * dy2 + ca * dx2; double y1 = ca * dy2 - sa * dx2; rx = Math.abs(rx); ry = Math.abs(ry); double Prx = rx * rx; double Pry = ry * ry; double Px1 = x1 * x1; double Py1 = y1 * y1; double rc = Px1/Prx + Py1/Pry; if (rc > 1) { rx = Math.sqrt(rc) * rx; ry = Math.sqrt(rc) * ry; Prx = rx * rx; Pry = ry * ry; } double s = (large == sweep) ? -1 : 1; double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1)); if (sq < 0) sq = 0; double m = s * Math.sqrt(sq); double cx1 = m * ((rx * y1) / ry); double cy1 = m * -((ry * x1) / rx); double sx2 = (x0 + x) / 2; double sy2 = (y0 + y) / 2; double cx = sx2 + ca * cx1 - sa * cy1; double cy = sy2 + sa * cx1 + ca * cy1; double ux = (x1 - cx1) / rx; double uy = (y1 - cy1) / ry; double vx = (-x1 -cx1) / rx; double vy = (-y1 -cy1) / ry; double sn = Math.sqrt(ux*ux + uy*uy); double sp = ux; double ss = (uy < 0) ? -1 : 1; double as = Math.toDegrees(ss * Math.acos(sp / sn)); double en = Math.sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); double ep = ux * vx + uy * vy; double es = (ux * vy - uy * vx < 0) ? -1 : 1; double ae = Math.toDegrees(es * Math.acos(ep / en)); if (!sweep && ae > 0) ae -= 360; if (sweep && ae < 0) ae += 360; ae %= 360; as %= 360; Arc2D.Double arc = new Arc2D.Double(); arc.x = cx - rx; arc.y = cy - ry; arc.width = rx * 2; arc.height = ry * 2; arc.start = -as; arc.extent = -ae; double acx = arc.getCenterX(); double acy = arc.getCenterY(); AffineTransform t = AffineTransform.getRotateInstance(a, acx, acy); return t.createTransformedShape(arc); } public static void arcThroughTo( GeneralPath p, double x2, double y2, double x3, double y3 ) { Point2D p1 = p.getCurrentPoint(); if (p1 == null) throw new IllegalPathStateException("missing initial moveto in path definition"); Arc2D arc = createArcThrough(p1.getX(), p1.getY(), x2, y2, x3, y3); if (arc != null) p.append(arc, true); p.lineTo(x3, y3); } public static Arc2D createArcThrough( double x1, double y1, double x2, double y2, double x3, double y3 ) { if (x1 == x2 && x2 == x3) return null; if (y1 == y2 && y2 == y3) return null; double d = arcHK(x1, y1, x2, y2, x3, y3); double h = arcH(x1, y1, x2, y2, x3, y3) / d; double k = arcK(x1, y1, x2, y2, x3, y3) / d; if (Double.isNaN(h) || Double.isInfinite(h)) return null; if (Double.isNaN(k) || Double.isInfinite(k)) return null; double r = Math.hypot(k - y1, x1 - h); double a1 = Math.toDegrees(Math.atan2(k - y1, x1 - h)); double a2 = Math.toDegrees(Math.atan2(k - y2, x2 - h)); double a3 = Math.toDegrees(Math.atan2(k - y3, x3 - h)); Arc2D.Double arc = new Arc2D.Double(); arc.x = h - r; arc.y = k - r; arc.width = r + r; arc.height = r + r; arc.start = a1; if ((a1 <= a2 && a2 <= a3) || (a3 <= a2 && a2 <= a1)) { arc.extent = a3 - a1; } else if (a3 <= a1) { arc.extent = a3 - a1 + 360; } else { arc.extent = a3 - a1 - 360; } return arc; } private static double arcdet(double a, double b, double c, double d, double e, double f, double g, double h, double i) { return a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g; } private static double arcHK(double x1, double y1, double x2, double y2, double x3, double y3) { return arcdet(x1, y1, 1, x2, y2, 1, x3, y3, 1) * 2; } private static double arcH(double x1, double y1, double x2, double y2, double x3, double y3) { return arcdet(x1*x1 + y1*y1, y1, 1, x2*x2 + y2*y2, y2, 1, x3*x3 + y3*y3, y3, 1); } private static double arcK(double x1, double y1, double x2, double y2, double x3, double y3) { return arcdet(x1, x1*x1 + y1*y1, 1, x2, x2*x2 + y2*y2, 1, x3, x3*x3 + y3*y3, 1); } public static void gerberArcTo( GeneralPath p, double i, double j, boolean large, boolean sweep, double x, double y ) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) throw new IllegalPathStateException("missing initial moveto in path definition"); Arc2D arc = createGerberArc(p0.getX(), p0.getY(), i, j, large, sweep, x, y); if (arc != null) p.append(arc, true); p.lineTo(x, y); } public static Arc2D createGerberArc( double x0, double y0, double i, double j, boolean large, boolean sweep, double x, double y ) { // Handle the 0° / 360° case explicitly. // Elsewhere we can assume 0° < extent < 360°. if (Math.abs(x0-x) < 1e-6 && Math.abs(y0-y) < 1e-6) { if (large) { double r = Math.hypot(i, j); if (r < 1e-6) return null; double t = Math.toDegrees(Math.atan2(j, -i)); double e = sweep ? (-360) : (+360); return new Arc2D.Double(x0+i-r, y0+j-r, r+r, r+r, t, e, Arc2D.OPEN); } else { return null; } } double r1 = Math.hypot(i, j); GerberArcCandidate a1 = new GerberArcCandidate(x0, y0, r1, x0 + i, y0 + j, x, y, sweep); if (large) return a1.arc; GerberArcCandidate a2 = new GerberArcCandidate(x0, y0, r1, x0 + i, y0 - j, x, y, sweep); GerberArcCandidate a3 = new GerberArcCandidate(x0, y0, r1, x0 - i, y0 + j, x, y, sweep); GerberArcCandidate a4 = new GerberArcCandidate(x0, y0, r1, x0 - i, y0 - j, x, y, sweep); GerberArcCandidate a = null; if (Math.abs(a1.extent) <= 90 && (a == null || a1.deviation < a.deviation)) a = a1; if (Math.abs(a2.extent) <= 90 && (a == null || a2.deviation < a.deviation)) a = a2; if (Math.abs(a3.extent) <= 90 && (a == null || a3.deviation < a.deviation)) a = a3; if (Math.abs(a4.extent) <= 90 && (a == null || a4.deviation < a.deviation)) a = a4; return (a != null) ? a.arc : null; } private static class GerberArcCandidate { public final double deviation; public final double extent; public final Arc2D arc; public GerberArcCandidate(double x0, double y0, double r1, double cx, double cy, double x, double y, boolean sweep) { double r2 = Math.hypot(x - cx, y - cy); this.deviation = Math.abs(r1 - r2); double r = (r1 + r2) / 2; double start = Math.toDegrees(Math.atan2(cy - y0, x0 - cx)); double end = Math.toDegrees(Math.atan2(cy - y, x - cx)); if (sweep) this.extent = ((end < start) ? (end - start) : ((end - start) - 360)); else this.extent = ((end > start) ? (end - start) : ((end - start) + 360)); this.arc = new Arc2D.Double(cx-r, cy-r, r+r, r+r, start, extent, Arc2D.OPEN); } } public static Point2D appendRectangle(GeneralPath p, double x, double y, double w, double h, double rw, double rh) { if (rw == 0 || rh == 0) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(x+w/2, y+h/2); p.append(new Rectangle2D.Double(x, y, w, h), false); p.moveTo(p0.getX(), p0.getY()); return p0; } else { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(x+w/2, y+h/2); p.append(new RoundRectangle2D.Double(x, y, w, h, rw, rh), false); p.moveTo(p0.getX(), p0.getY()); return p0; } } public static Point2D appendEllipse(GeneralPath p, double x, double y, double w, double h, double as, double ae, int at) { at = Math.abs(at) % 5; if (ae <= -360 || ae >= 360) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(x+w/2, y+h/2); p.append(new Ellipse2D.Double(x, y, w, h), false); p.moveTo(p0.getX(), p0.getY()); return p0; } else if (at < 3) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(x+w/2, y+h/2); p.append(new Arc2D.Double(x, y, w, h, as, ae, at), false); p.moveTo(p0.getX(), p0.getY()); return p0; } else { p.append(new Arc2D.Double(x, y, w, h, as, ae, Arc2D.OPEN), at > 3); return p.getCurrentPoint(); } } public static Point2D appendRegularPolygon(GeneralPath p, double cx, double cy, double ex, double ey, int sides, int skips) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(cx, cy); p.append(createRegularPolygon(cx, cy, ex, ey, sides, skips), false); p.moveTo(p0.getX(), p0.getY()); return p0; } public static GeneralPath createRegularPolygon(double cx, double cy, double ex, double ey, int sides, int skips) { if (sides < 3) sides = 3; if (skips < 1) skips = 1; GeneralPath p = new GeneralPath(); double r = Math.hypot(ey - cy, ex - cx); double t = Math.atan2(ey - cy, ex - cx); for (int n = 0, j = 0; n < sides; j++) { for (int i = 0; n < sides && ((i == 0) || ((i % sides) != 0)); n++, i += skips) { double a = t + (Math.PI * (double)((i+j)*2) / (double)(sides)); double x = cx + r * Math.cos(a); double y = cy + r * Math.sin(a); if (i == 0) p.moveTo((float)x, (float)y); else p.lineTo((float)x, (float)y); } p.closePath(); } return p; } public static Point2D appendAsterisk(GeneralPath p, double cx, double cy, double ex, double ey, int sides) { Point2D p0 = p.getCurrentPoint(); if (p0 == null) p0 = new Point2D.Double(cx, cy); p.append(createAsterisk(cx, cy, ex, ey, sides), false); p.moveTo(p0.getX(), p0.getY()); return p0; } public static GeneralPath createAsterisk(double cx, double cy, double ex, double ey, int sides) { if (sides < 1) sides = 1; GeneralPath p = new GeneralPath(); double r = Math.hypot(ey - cy, ex - cx); double t = Math.atan2(ey - cy, ex - cx); for (int i = 0; i < sides; i++) { double a = t + (Math.PI * (double)(i*2) / (double)(sides)); double x = cx + r * Math.cos(a); double y = cy + r * Math.sin(a); p.moveTo((float)cx, (float)cy); p.lineTo((float)x, (float)y); } return p; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/PathGraph.java000077500000000000000000000300231506470510200301600ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.*; import java.io.*; import java.util.*; public class PathGraph implements Cloneable, Serializable { private static final long serialVersionUID = -9041484459040713072L; private HashMap> graph; public PathGraph() { graph = new HashMap>(); } public PathGraph(PathGraph pg) { graph = new HashMap>(); for (Map.Entry> e : pg.graph.entrySet()) { HashSet s = new HashSet(); s.addAll(e.getValue()); graph.put(e.getKey(), s); } } public void plot(int size, int x, int y) { ImmutablePoint bl = new ImmutablePoint(x*size, y*size); ImmutablePoint tl = new ImmutablePoint(x*size, y*size+size); ImmutablePoint tr = new ImmutablePoint(x*size+size, y*size+size); ImmutablePoint br = new ImmutablePoint(x*size+size, y*size); add(bl, tl); add(tl, tr); add(tr, br); add(br, bl); } public void plot(int size, ImmutablePoint p) { plot(size, p.x, p.y); } public void plot(int size, Point p) { plot(size, p.x, p.y); } public void plot(int xsize, int ysize, int x, int y) { ImmutablePoint bl = new ImmutablePoint(x*xsize, y*ysize); ImmutablePoint tl = new ImmutablePoint(x*xsize, y*ysize+ysize); ImmutablePoint tr = new ImmutablePoint(x*xsize+xsize, y*ysize+ysize); ImmutablePoint br = new ImmutablePoint(x*xsize+xsize, y*ysize); add(bl, tl); add(tl, tr); add(tr, br); add(br, bl); } public void plot(int xsize, int ysize, ImmutablePoint p) { plot(xsize, ysize, p.x, p.y); } public void plot(int xsize, int ysize, Point p) { plot(xsize, ysize, p.x, p.y); } public void removeOverlap() { Iterator i = graph.keySet().iterator(); while (i.hasNext()) { ImmutablePoint src = i.next(); Iterator j = graph.get(src).iterator(); while (j.hasNext()) { ImmutablePoint dst = j.next(); if (contains(dst, src)) { remove(src, dst); remove(dst, src); i = graph.keySet().iterator(); break; } } } } public void simplifyPaths() { Iterator i = graph.keySet().iterator(); while (i.hasNext()) { ImmutablePoint src = i.next(); Iterator j = graph.get(src).iterator(); while (j.hasNext()) { ImmutablePoint dst = j.next(); int yd = signum(dst.y - src.y); int xd = signum(dst.x - src.x); ImmutablePoint newdst = dst; boolean foundEnd = false; while (!foundEnd) { foundEnd = true; ImmutablePoint[] candidates = getAdjPoints(newdst); for (ImmutablePoint candidate : candidates) { int cyd = signum(candidate.y - newdst.y); int cxd = signum(candidate.x - newdst.x); if (cyd == yd && cxd == xd) { remove(newdst, candidate); newdst = candidate; foundEnd = false; } } } if (newdst != dst) { remove(src, dst); add(src, newdst); i = graph.keySet().iterator(); break; } } } } public Rectangle getBoundingRect() { ImmutablePoint[] pts = getAllPoints(); if (pts.length == 0) return new Rectangle(0,0,0,0); int minx = pts[0].x, miny = pts[0].y, maxx = pts[0].x, maxy = pts[0].y; for (ImmutablePoint p : pts) { if (p.x < minx) minx = p.x; if (p.y < miny) miny = p.y; if (p.x > maxx) maxx = p.x; if (p.y > maxy) maxy = p.y; } return new Rectangle(minx, miny, maxx-minx, maxy-miny); } public ImmutablePoint[][] getContours() { Vector> v = new Vector>(); PathGraph tmp = new PathGraph(this); while (!tmp.isEmpty()) { ImmutablePoint[] firsts = tmp.getAllPoints(); for (ImmutablePoint first : firsts) { if (tmp.graph.containsKey(first) && !tmp.graph.get(first).isEmpty()) { Vector w = new Vector(); int lastdx = 0, lastdy = 0; ImmutablePoint p = first; w.add(p); while (true) { ImmutablePoint[] candidates = tmp.getAdjPoints(p); if (candidates == null || candidates.length < 1) break; ImmutablePoint q = null; if (lastdx == 0 && lastdy == 0) { q = candidates[0]; } else { // looking for point going counterclockwise for (ImmutablePoint candidate : candidates) { int dy = signum(candidate.y - p.y); int dx = signum(candidate.x - p.x); if (dy == -lastdx && dx == lastdy && !candidate.equals(p)) { q = candidate; break; } } // looking for point going straight if (q == null) { for (ImmutablePoint candidate : candidates) { int dy = signum(candidate.y - p.y); int dx = signum(candidate.x - p.x); if (dy == lastdy && dx == lastdx && !candidate.equals(p)) { q = candidate; break; } } } // looking for point going clockwise if (q == null) { for (ImmutablePoint candidate : candidates) { int dy = signum(candidate.y - p.y); int dx = signum(candidate.x - p.x); if (dy == lastdx && dx == -lastdy && !candidate.equals(p)) { q = candidate; break; } } } if (q == null) { for (ImmutablePoint candidate : candidates) { if (!candidate.equals(p)) { q = candidate; break; } } } if (q == null) break; } w.add(q); tmp.remove(p, q); if (first.equals(q)) break; else { lastdy = signum(q.y - p.y); lastdx = signum(q.x - p.x); p = q; } } if (!w.isEmpty()) v.add(w); } } } ImmutablePoint[][] a = new ImmutablePoint[v.size()][]; for (int i = 0; i < v.size(); i++) { a[i] = v.get(i).toArray(new ImmutablePoint[0]); } return a; } public byte[] getGlyfData() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); Rectangle rect = getBoundingRect(); ImmutablePoint[][] contours = getContours(); int[] endpoints = new int[contours.length]; Vector coords = new Vector(); for (int i = 0; i < contours.length; i++) { ImmutablePoint first = contours[i][0]; coords.add(first); for (int j = 1; j < contours[i].length; j++) { ImmutablePoint next = contours[i][j]; if (next.equals(first)) break; else coords.add(next); } endpoints[i] = coords.size()-1; } try { dos.writeShort(contours.length); // number of contours dos.writeShort(rect.x); // xMin dos.writeShort(rect.y); // yMin dos.writeShort(rect.x+rect.width); // xMax dos.writeShort(rect.y+rect.height); // yMax for (int ep : endpoints) dos.writeShort(ep); // endpoints dos.writeShort(0); // instruction length // instructions (there are none) // flags: int run = coords.size(); while (run >= 256) { dos.writeByte(9); dos.writeByte(255); run -= 256; } if (run > 1) { dos.writeByte(9); dos.writeByte(run-1); } else if (run == 1) { dos.writeByte(1); } int last; last = 0; for (ImmutablePoint p : coords) { dos.writeShort(p.x-last); last = p.x; } // x coords last = 0; for (ImmutablePoint p : coords) { dos.writeShort(p.y-last); last = p.y; } // y coords while ((bos.size() & 0x3) != 0) dos.writeByte(0); } catch (IOException ioe) {} return bos.toByteArray(); } public void add(int sx, int sy, int dx, int dy) { this.add(new ImmutablePoint(sx, sy), new ImmutablePoint(dx, dy)); } public void add(ImmutablePoint src, ImmutablePoint dst) { if (graph.containsKey(src)) { graph.get(src).add(dst); } else { HashSet s = new HashSet(); s.add(dst); graph.put(src, s); } } public void add(PathEdge e) { this.add(e.src, e.dst); } public void clear() { graph.clear(); } public boolean contains(int sx, int sy, int dx, int dy) { return this.contains(new ImmutablePoint(sx, sy), new ImmutablePoint(dx, dy)); } public boolean contains(ImmutablePoint src, ImmutablePoint dst) { return (graph.containsKey(src) && graph.get(src).contains(dst)); } public boolean contains(PathEdge e) { return this.contains(e.src, e.dst); } public ImmutablePoint[] getSrcPoints() { return graph.keySet().toArray(new ImmutablePoint[0]); } public ImmutablePoint[] getAllPoints() { HashSet s = new HashSet(); s.addAll(graph.keySet()); for (HashSet t : graph.values()) { s.addAll(t); } return s.toArray(new ImmutablePoint[0]); } public ImmutablePoint[] getAdjPoints(ImmutablePoint src) { if (graph.containsKey(src)) { return graph.get(src).toArray(new ImmutablePoint[0]); } else { return new ImmutablePoint[0]; } } public PathEdge[] getAllEdges() { HashSet s = new HashSet(); for (Map.Entry> e : graph.entrySet()) { ImmutablePoint src = e.getKey(); for (ImmutablePoint dst : e.getValue()) { s.add(new PathEdge(src, dst)); } } return s.toArray(new PathEdge[0]); } public PathEdge[] getAdjEdges(ImmutablePoint src) { HashSet s = new HashSet(); if (graph.containsKey(src)) { for (ImmutablePoint dst : graph.get(src)) { s.add(new PathEdge(src, dst)); } } return s.toArray(new PathEdge[0]); } public boolean isEmpty() { if (!graph.isEmpty()) { for (HashSet s : graph.values()) { if (!s.isEmpty()) return false; } } return true; } public void remove(int sx, int sy, int dx, int dy) { this.remove(new ImmutablePoint(sx, sy), new ImmutablePoint(dx, dy)); } public void remove(ImmutablePoint src, ImmutablePoint dst) { if (graph.containsKey(src)) { graph.get(src).remove(dst); if (graph.get(src).size() < 1) { graph.remove(src); } } } public void remove(PathEdge e) { this.remove(e.src, e.dst); } public boolean equals(Object o) { if (o instanceof PathGraph) { return this.graph.equals(((PathGraph)o).graph); } else { return this.graph.equals(o); } } public int hashCode() { return graph.hashCode(); } public String toString() { return graph.toString(); } private static int signum(int i) { return (i < 0) ? -1 : (i > 0) ? 1 : 0; } public static class ImmutablePoint implements Cloneable, Serializable { private static final long serialVersionUID = -274454806715511788L; private int x; private int y; public ImmutablePoint(int x, int y) { this.x = x; this.y = y; } public ImmutablePoint(ImmutablePoint p) { this.x = p.x; this.y = p.y; } public ImmutablePoint(Point p) { this.x = p.x; this.y = p.y; } public int getX() { return x; } public int getY() { return y; } public Point getPoint() { return new Point(x, y); } public boolean equals(Object o) { if (o instanceof ImmutablePoint) { ImmutablePoint p = (ImmutablePoint)o; return this.x == p.x && this.y == p.y; } else if (o instanceof Point) { Point p = (Point)o; return this.x == p.x && this.y == p.y; } else { return false; } } public int hashCode() { return x ^ Integer.reverseBytes(y); } public String toString() { return x+","+y; } } public static class PathEdge implements Cloneable, Serializable { private static final long serialVersionUID = -7710603668134471572L; private ImmutablePoint src; private ImmutablePoint dst; public PathEdge(ImmutablePoint src, ImmutablePoint dst) { this.src = src; this.dst = dst; } public ImmutablePoint getSrc() { return src; } public ImmutablePoint getDst() { return dst; } public PathEdge getReflection() { return new PathEdge(dst, src); } public boolean equals(Object o) { if (o instanceof PathEdge) { PathEdge e = (PathEdge)o; return this.src.equals(e.src) && this.dst.equals(e.dst); } else { return false; } } public int hashCode() { return src.hashCode() ^ Integer.reverse(dst.hashCode()); } public String toString() { return src.toString() + " -> " + dst.toString(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/PointSizeGenerator.java000066400000000000000000000034761506470510200321060ustar00rootroot00000000000000package com.kreative.bitsnpicas; public abstract class PointSizeGenerator { public abstract void setRange(int min, int max); public abstract void setPointSizes(int ...pointSizes); public abstract int generatePointSize(Font font); public static class Fixed extends PointSizeGenerator { private int pointSize; public Fixed(int pointSize) { this.pointSize = pointSize; } @Override public void setRange(int min, int max) { // Nothing. } @Override public void setPointSizes(int ...pointSizes) { // Nothing. } @Override public int generatePointSize(Font font) { return pointSize; } } public static class Automatic extends PointSizeGenerator { private int min, max; public Automatic(int min, int max) { this.min = min; this.max = max; } @Override public void setRange(int min, int max) { this.min = min; this.max = max; } @Override public void setPointSizes(int ...pointSizes) { // Nothing. } @Override public int generatePointSize(Font font) { int size = font.getEmAscent() + font.getEmDescent(); return (size < min) ? min : (size > max) ? max : size; } } public static class Standard extends PointSizeGenerator { private int[] pointSizes; public Standard(int ...pointSizes) { this.pointSizes = pointSizes; } @Override public void setRange(int min, int max) { // Nothing. } @Override public void setPointSizes(int ...pointSizes) { this.pointSizes = pointSizes; } @Override public int generatePointSize(Font font) { int size = font.getEmAscent() + font.getEmDescent(); if (size <= pointSizes[0]) return pointSizes[0]; int n = pointSizes.length - 1; for (int i = 0; i < n; i++) { if (size <= ((pointSizes[i] + pointSizes[i+1]) / 2)) { return pointSizes[i]; } } return pointSizes[n]; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorFont.java000077500000000000000000000047641506470510200304100ustar00rootroot00000000000000package com.kreative.bitsnpicas; public class VectorFont extends Font { protected double emAscent, emDescent; protected double lineAscent, lineDescent; protected double xHeight, capHeight, lineGap; public VectorFont() { this.emAscent = 0; this.emDescent = 0; this.lineAscent = 0; this.lineDescent = 0; this.xHeight = 0; this.capHeight = 0; this.lineGap = 0; } public VectorFont( double emAscent, double emDescent, double lineAscent, double lineDescent, double xHeight, double capHeight, double lineGap ) { this.emAscent = emAscent; this.emDescent = emDescent; this.lineAscent = lineAscent; this.lineDescent = lineDescent; this.xHeight = xHeight; this.capHeight = capHeight; this.lineGap = lineGap; } public int getEmAscent() { return (int)Math.ceil(emAscent); } public double getEmAscent2D() { return emAscent; } public int getEmDescent() { return (int)Math.ceil(emDescent); } public double getEmDescent2D() { return emDescent; } public int getLineAscent() { return (int)Math.ceil(lineAscent); } public double getLineAscent2D() { return lineAscent; } public int getLineDescent() { return (int)Math.ceil(lineDescent); } public double getLineDescent2D() { return lineDescent; } public int getXHeight() { return (int)Math.ceil(xHeight); } public double getXHeight2D() { return xHeight; } public int getCapHeight() { return (int)Math.ceil(capHeight); } public double getCapHeight2D() { return capHeight; } public int getLineGap() { return (int)Math.ceil(lineGap); } public double getLineGap2D() { return lineGap; } public void setEmAscent(int v) { emAscent = v; } public void setEmAscent2D(double v) { emAscent = v; } public void setEmDescent(int v) { emDescent = v; } public void setEmDescent2D(double v) { emDescent = v; } public void setLineAscent(int v) { lineAscent = v; } public void setLineAscent2D(double v) { lineAscent = v; } public void setLineDescent(int v) { lineDescent = v; } public void setLineDescent2D(double v) { lineDescent = v; } public void setXHeight(int v) { xHeight = v; } public void setXHeight2D(double v) { xHeight = v; } public void setCapHeight(int v) { capHeight = v; } public void setCapHeight2D(double v) { capHeight = v; } public void setLineGap(int v) { lineGap = v; } public void setLineGap2D(double v) { lineGap = v; } public void setXHeight2D() { double xh = guessXHeight2D(); if (xh != 0) xHeight = xh; } public void setCapHeight2D() { double ch = guessCapHeight2D(); if (ch != 0) capHeight = ch; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorFontExporter.java000077500000000000000000000001641506470510200321270ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface VectorFontExporter extends FontExporter { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorFontGlyph.java000077500000000000000000000145261506470510200314110ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class VectorFontGlyph extends FontGlyph { protected List contours; protected double advance; public VectorFontGlyph() { this.contours = new ArrayList(); this.advance = 0; } public VectorFontGlyph(Collection c) { this.contours = new ArrayList(); this.contours.addAll(c); if (c.isEmpty()) { this.advance = 0; } else { VectorPath p1 = c.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double left = b1.getMinX(); double right = b1.getMaxX(); for (VectorPath p : c) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double pleft = b.getMinX(); double pright = b.getMaxX(); if (pleft < left) left = pleft; if (pright > right) right = pright; } this.advance = left+right; } } public VectorFontGlyph(Collection c, double width) { this.contours = new ArrayList(); this.contours.addAll(c); this.advance = width; } public Collection getContours() { return this.contours; } public int getGlyphOffset() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle b1 = p1.toGeneralPath().getBounds(); int left = b1.x; for (VectorPath p : contours) { Rectangle b = p.toGeneralPath().getBounds(); int pleft = b.x; if (pleft < left) left = pleft; } return left; } } public double getGlyphOffset2D() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double left = b1.getMinX(); for (VectorPath p : contours) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double pleft = b.getMinX(); if (pleft < left) left = pleft; } return left; } } public int getGlyphWidth() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle b1 = p1.toGeneralPath().getBounds(); int left = b1.x; int right = b1.x + b1.width; for (VectorPath p : contours) { Rectangle b = p.toGeneralPath().getBounds(); int pleft = b.x; int pright = b.x + b.width; if (pleft < left) left = pleft; if (pright > right) right = pright; } return right-left; } } public double getGlyphWidth2D() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double left = b1.getMinX(); double right = b1.getMaxX(); for (VectorPath p : contours) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double pleft = b.getMinX(); double pright = b.getMaxX(); if (pleft < left) left = pleft; if (pright > right) right = pright; } return right-left; } } public int getGlyphHeight() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle b1 = p1.toGeneralPath().getBounds(); int top = b1.y; int bottom = b1.y + b1.height; for (VectorPath p : contours) { Rectangle b = p.toGeneralPath().getBounds(); int ptop = b.y; int pbottom = b.y + b.height; if (ptop < top) top = ptop; if (pbottom > bottom) bottom = pbottom; } return bottom-top; } } public double getGlyphHeight2D() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double top = b1.getMinY(); double bottom = b1.getMaxY(); for (VectorPath p : contours) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double ptop = b.getMinY(); double pbottom = b.getMaxY(); if (ptop < top) top = ptop; if (pbottom > bottom) bottom = pbottom; } return bottom-top; } } public int getGlyphAscent() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle b1 = p1.toGeneralPath().getBounds(); int top = b1.y; for (VectorPath p : contours) { Rectangle b = p.toGeneralPath().getBounds(); int ptop = b.y; if (ptop < top) top = ptop; } return -top; } } public double getGlyphAscent2D() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double top = b1.getMinY(); for (VectorPath p : contours) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double ptop = b.getMinY(); if (ptop < top) top = ptop; } return -top; } } public int getGlyphDescent() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle b1 = p1.toGeneralPath().getBounds(); int bottom = b1.y + b1.height; for (VectorPath p : contours) { Rectangle b = p.toGeneralPath().getBounds(); int pbottom = b.y + b.height; if (pbottom > bottom) bottom = pbottom; } return bottom; } } public double getGlyphDescent2D() { if (contours.isEmpty()) { return 0; } else { VectorPath p1 = contours.iterator().next(); Rectangle2D b1 = p1.toGeneralPath().getBounds2D(); double bottom = b1.getMaxY(); for (VectorPath p : contours) { Rectangle2D b = p.toGeneralPath().getBounds2D(); double pbottom = b.getMaxY(); if (pbottom > bottom) bottom = pbottom; } return bottom; } } public int getCharacterWidth() { return (int)Math.ceil(advance); } public double getCharacterWidth2D() { return advance; } public void setCharacterWidth(int v) { advance = v; } public void setCharacterWidth2D(double v) { advance = v; } public double paint(Graphics g, double x, double y, double scale) { AffineTransform tx = AffineTransform.getTranslateInstance(x, y); AffineTransform sx = AffineTransform.getScaleInstance(scale, scale); for (VectorPath contour : contours) { GeneralPath path = contour.toGeneralPath(); Shape ss = sx.createTransformedShape(path); Shape ts = tx.createTransformedShape(ss); ((Graphics2D)g).draw(ts); } return advance * scale; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorFontGlyphTransformer.java000077500000000000000000000002111506470510200336160ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface VectorFontGlyphTransformer extends FontGlyphTransformer { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorFontImporter.java000077500000000000000000000001641506470510200321200ustar00rootroot00000000000000package com.kreative.bitsnpicas; public interface VectorFontImporter extends FontImporter { // done } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorInstruction.java000066400000000000000000000020221506470510200320010ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; public class VectorInstruction { private final char operation; private final Number[] operands; public VectorInstruction(char operation, Number... operands) { this.operation = operation; this.operands = new Number[operands.length]; int i = 0; for (Number n : operands) this.operands[i++] = n; } public VectorInstruction(char operation, Collection operands) { this.operation = operation; this.operands = new Number[operands.size()]; int i = 0; for (Number n : operands) this.operands[i++] = n; } public char getOperation() { return operation; } public List getOperands() { return Collections.unmodifiableList(Arrays.asList(operands)); } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(operation); for (Number n : operands) { sb.append(" "); sb.append(n); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/VectorPath.java000066400000000000000000000056011506470510200303620ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class VectorPath extends AbstractList { private final List ops = new ArrayList(); public void append(GeneralPath path) { append(path, false); } public void append(GeneralPath path, boolean connect) { double[] vals = new double[8]; for (PathIterator pi = path.getPathIterator(null); !pi.isDone(); pi.next()) { switch (pi.currentSegment(vals)) { case PathIterator.SEG_MOVETO: ops.add(new VectorInstruction((connect ? 'L' : 'M'), vals[0], vals[1])); connect = false; break; case PathIterator.SEG_LINETO: ops.add(new VectorInstruction('L', vals[0], vals[1])); break; case PathIterator.SEG_QUADTO: ops.add(new VectorInstruction('Q', vals[0], vals[1], vals[2], vals[3])); break; case PathIterator.SEG_CUBICTO: ops.add(new VectorInstruction('C', vals[0], vals[1], vals[2], vals[3], vals[4], vals[5])); break; case PathIterator.SEG_CLOSE: ops.add(new VectorInstruction('Z')); break; } } } public GeneralPath toGeneralPath() { PathExtensions p = new PathExtensions(); for (VectorInstruction op : ops) { p.execute(op.getOperation(), op.getOperands()); } return p.getPath(); } public String toString() { StringBuffer sb = new StringBuffer(); boolean first = true; for (VectorInstruction op : ops) { if (first) first = false; else sb.append(" "); sb.append(op.toString()); } return sb.toString(); } public boolean add(VectorInstruction e) { return ops.add(e); } public void add(int i, VectorInstruction e) { ops.add(i, e); } public boolean addAll(Collection c) { return ops.addAll(c); } public boolean addAll(int i, Collection c) { return ops.addAll(i, c); } public void clear() { ops.clear(); } public boolean contains(Object e) { return ops.contains(e); } public boolean containsAll(Collection c) { return ops.containsAll(c); } public VectorInstruction get(int i) { return ops.get(i); } public int indexOf(Object e) { return ops.indexOf(e); } public boolean isEmpty() { return ops.isEmpty(); } public int lastIndexOf(Object e) { return ops.lastIndexOf(e); } public boolean remove(Object e) { return ops.remove(e); } public VectorInstruction remove(int i) { return ops.remove(i); } public boolean removeAll(Collection c) { return ops.removeAll(c); } public boolean retainAll(Collection c) { return ops.retainAll(c); } public VectorInstruction set(int i, VectorInstruction e) { return ops.set(i, e); } public int size() { return ops.size(); } public Object[] toArray() { return ops.toArray(); } public T[] toArray(T[] a) { return ops.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/WIBInputStream.java000066400000000000000000000022351506470510200311200ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.IOException; import java.io.InputStream; public class WIBInputStream extends InputStream { private final InputStream in; public WIBInputStream(InputStream in) { this.in = in; } private Integer repeatData = null; private int repeatCount = 0; private boolean eof = false; @Override public int read() throws IOException { for (;;) { if (eof) return -1; if (repeatCount > 0) { repeatCount--; if (repeatData == null) { int data = in.read(); if (data < 0) eof = true; return data; } else { return repeatData; } } int data = in.read(); if (data < 0) { eof = true; return data; } repeatCount = data & 0x1F; if ((data & 0x20) != 0) repeatCount <<= 5; switch (data & 0xC0) { case 0x00: repeatData = 0x00; break; case 0x40: repeatData = 0xFF; break; case 0x80: data = in.read(); if (data < 0) { eof = true; return data; } repeatData = data; break; case 0xC0: repeatData = null; break; } } } @Override public void close() throws IOException { in.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/WIBOutputStream.java000066400000000000000000000043101506470510200313150ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; public class WIBOutputStream extends OutputStream { private final OutputStream out; public WIBOutputStream(OutputStream out) { this.out = out; } private ByteArrayOutputStream dataRun = new ByteArrayOutputStream(); private int rleCount = 0; private int rleData = 0; @Override public void write(int b) throws IOException { b &= 0xFF; if (rleCount < 1) { rleCount = 1; rleData = b; } else if (rleData == b) { rleCount++; } else if (rleCount == 1) { dataRun.write(rleData); rleData = b; } else { writeRuns(); rleCount = 1; rleData = b; } } public void finish() throws IOException { if (rleCount == 1) { dataRun.write(rleData); rleCount = 0; } writeRuns(); } private void writeRuns() throws IOException { byte[] data = dataRun.toByteArray(); int n = data.length; if (n > 0) { int o = 0; while (n >= 992) { out.write(0xFF); out.write(data, o, 992); o += 992; n -= 992; } if (n >= 32) { int m = n >> 5; out.write(0xE0 | m); m <<= 5; out.write(data, o, m); o += m; n -= m; } if (n > 1) { out.write(0xC0 | n); out.write(data, o, n); } if (n == 1) { switch (data[o]) { case (byte)0x00: out.write(0x01); break; case (byte)0xFF: out.write(0x41); break; default: out.write(0x81); out.write(data[o]); break; } } dataRun = new ByteArrayOutputStream(); } if (rleCount > 0) { int base = (rleData == 0x00) ? 0x00 : (rleData == 0xFF) ? 0x40 : 0x80; boolean pat = (rleData != 0x00 && rleData != 0xFF); while (rleCount >= 992) { out.write(base | 0x3F); if (pat) out.write(rleData); rleCount -= 992; } if (rleCount >= 32) { int m = rleCount >> 5; out.write(base | 0x20 | m); m <<= 5; if (pat) out.write(rleData); rleCount -= m; } if (rleCount > 0) { out.write(base | rleCount); if (pat) out.write(rleData); rleCount = 0; } } } @Override public void flush() throws IOException { out.flush(); } @Override public void close() throws IOException { finish(); out.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/WindingOrder.java000077500000000000000000000052471506470510200307070ustar00rootroot00000000000000package com.kreative.bitsnpicas; public enum WindingOrder { LTR_TTB (false, false, false, false), TTB_LTR (false, false, true , false), RTL_TTB (false, true , false, false), TTB_RTL (false, true , true , false), LTR_BTT (true , false, false, false), BTT_LTR (true , false, true , false), RTL_BTT (true , true , false, false), BTT_RTL (true , true , true , false), LTR_TTB_BOUSTROPHEDON(false, false, false, true ), TTB_LTR_BOUSTROPHEDON(false, false, true , true ), RTL_TTB_BOUSTROPHEDON(false, true , false, true ), TTB_RTL_BOUSTROPHEDON(false, true , true , true ), LTR_BTT_BOUSTROPHEDON(true , false, false, true ), BTT_LTR_BOUSTROPHEDON(true , false, true , true ), RTL_BTT_BOUSTROPHEDON(true , true , false, true ), BTT_RTL_BOUSTROPHEDON(true , true , true , true ); protected final boolean bottomToTop; protected final boolean rightToLeft; protected final boolean vertical; protected final boolean boustrophedon; private WindingOrder( boolean bottomToTop, boolean rightToLeft, boolean vertical, boolean boustrophedon ) { this.bottomToTop = bottomToTop; this.rightToLeft = rightToLeft; this.vertical = vertical; this.boustrophedon = boustrophedon; } public int[] getYX(int rows, int columns, int index, int yx[]) { int y, x; if (vertical) { x = (index / rows) % columns; y = (index % rows); if (boustrophedon && ((x & 1) != 0)) { y = (rows-1) - y; } } else { y = (index / columns) % rows; x = (index % columns); if (boustrophedon && ((y & 1) != 0)) { x = (columns-1) - x; } } if (bottomToTop) { y = (rows-1) - y; } if (rightToLeft) { x = (columns-1) - x; } if (yx == null) { return new int[]{y,x}; } else { yx[0] = y; yx[1] = x; return yx; } } public int getIndex(int rows, int columns, int y, int x) { y %= rows; x %= columns; if (bottomToTop) { y = (rows-1) - y; } if (rightToLeft) { x = (columns-1) - x; } if (vertical) { if (boustrophedon && ((x & 1) != 0)) { y = (rows-1) - y; } return x * rows + y; } else { if (boustrophedon && ((y & 1) != 0)) { x = (columns-1) - x; } return y * columns + x; } } @Override public String toString() { String verticalDirection = bottomToTop ? "BTT" : "TTB"; String horizontalDirection = rightToLeft ? "RTL" : "LTR"; String lineDirection = vertical ? verticalDirection : horizontalDirection; String pageDirection = vertical ? horizontalDirection : verticalDirection; String direction = lineDirection + ", " + pageDirection; if (boustrophedon) direction += ", Alt"; return direction; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/XMLUtility.java000066400000000000000000000104211506470510200303230ustar00rootroot00000000000000package com.kreative.bitsnpicas; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class XMLUtility { public static String wrap(String tag, boolean close, String... attrs) { StringBuffer sb = new StringBuffer(); sb.append("<"); sb.append(tag); int i = 0; while (i + 1 < attrs.length) { sb.append(" "); sb.append(attrs[i++]); sb.append("=\""); sb.append(xmlEncode(attrs[i++])); sb.append("\""); } if (i < attrs.length) { sb.append(">"); sb.append(xmlEncode(attrs[i])); if (close) { sb.append(""); } } else { sb.append(close ? "/>" : ">"); } return sb.toString(); } public static String xmlEncode(String s) { if (s == null) return ""; StringBuffer sb = new StringBuffer(); int i = 0; while (i < s.length()) { int ch = s.codePointAt(i); switch (ch) { case '&': sb.append("&"); break; case '<': sb.append("<"); break; case '>': sb.append(">"); break; default: if (ch >= 0x20 && ch < 0x7F) { sb.append((char)ch); break; } // fallthrough; case '"': case '\'': sb.append("&#" + ch + ";"); break; } i += Character.charCount(ch); } return sb.toString(); } public static String parseString(NamedNodeMap attr, String key) { if (attr == null) return null; Node node = attr.getNamedItem(key); if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; return text.trim(); } public static Integer parseInt(NamedNodeMap attr, String key) { if (attr == null) return null; Node node = attr.getNamedItem(key); if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; try { return Integer.parseInt(text.trim()); } catch (NumberFormatException nfe) { return null; } } public static Double parseDouble(NamedNodeMap attr, String key) { if (attr == null) return null; Node node = attr.getNamedItem(key); if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; try { return Double.parseDouble(text.trim()); } catch (NumberFormatException nfe) { return null; } } public static List getChildren(Node node) { List list = new ArrayList(); if (node != null) { NodeList children = node.getChildNodes(); if (children != null) { int count = children.getLength(); for (int i = 0; i < count; i++) { Node child = children.item(i); if (child != null) { String type = child.getNodeName(); if (type.equalsIgnoreCase("#text") || type.equalsIgnoreCase("#comment")) { continue; } else { list.add(child); } } } } } return list; } public static EntityResolver entityResolver(final String pubName, final String dtdName, final Class resCls) { return new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (publicId.contains(pubName) || systemId.contains(dtdName)) { return new InputSource(resCls.getResourceAsStream(dtdName)); } else { return null; } } }; } public static ErrorHandler errorHandler(final String name) { return new ErrorHandler() { @Override public void error(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void fatalError(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("FATAL ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void warning(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("WARNING on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } }; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransfer/000077500000000000000000000000001506470510200301145ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransfer/ClearMenuItem.java000066400000000000000000000004721506470510200334540ustar00rootroot00000000000000package com.kreative.bitsnpicas.datatransfer; import javax.swing.JMenuItem; public class ClearMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ClearMenuItem() { super("Clear"); setActionCommand("Clear"); addActionListener(TransferActionListener.getInstance()); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransfer/CopyMenuItem.java000066400000000000000000000010151506470510200333320ustar00rootroot00000000000000package com.kreative.bitsnpicas.datatransfer; import java.awt.Toolkit; import java.awt.event.KeyEvent; import javax.swing.JMenuItem; import javax.swing.KeyStroke; public class CopyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CopyMenuItem() { super("Copy"); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, skm)); setActionCommand("Copy"); addActionListener(TransferActionListener.getInstance()); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransfer/CutMenuItem.java000066400000000000000000000010111506470510200331470ustar00rootroot00000000000000package com.kreative.bitsnpicas.datatransfer; import java.awt.Toolkit; import java.awt.event.KeyEvent; import javax.swing.JMenuItem; import javax.swing.KeyStroke; public class CutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CutMenuItem() { super("Cut"); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, skm)); setActionCommand("Cut"); addActionListener(TransferActionListener.getInstance()); } } FileListSelection.java000066400000000000000000000041521506470510200342630ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransferpackage com.kreative.bitsnpicas.datatransfer; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Vector; public class FileListSelection implements ClipboardOwner, Transferable { private java.util.List myList; private boolean isCut; public FileListSelection(File f) { myList = new Vector(); myList.add(f); isCut = false; } public FileListSelection(File[] f) { myList = new Vector(); myList.addAll(Arrays.asList(f)); isCut = false; } public FileListSelection(Collection f) { myList = new Vector(); myList.addAll(f); isCut = false; } public FileListSelection(File f, boolean cut) { myList = new Vector(); myList.add(f); isCut = cut; } public FileListSelection(File[] f, boolean cut) { myList = new Vector(); myList.addAll(Arrays.asList(f)); isCut = cut; } public FileListSelection(Collection f, boolean cut) { myList = new Vector(); myList.addAll(f); isCut = cut; } public boolean isCutOperation() { return isCut; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (DataFlavor.javaFileListFlavor.equals(flavor)) { return myList; } else if (DataFlavor.stringFlavor.equals(flavor)) { String s = ""; for (File f : myList) { s += "\n"+f.getAbsolutePath(); } return ((s.length() > 0) ? s.substring(1) : s); } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.javaFileListFlavor, DataFlavor.stringFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return (DataFlavor.javaFileListFlavor.equals(flavor) || DataFlavor.stringFlavor.equals(flavor)); } public void lostOwnership(Clipboard clipboard, Transferable contents) { //nothing } } ImageSelection.java000066400000000000000000000020011506470510200335610ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransferpackage com.kreative.bitsnpicas.datatransfer; import java.awt.Image; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; public class ImageSelection implements ClipboardOwner, Transferable { private Image myImage; public ImageSelection(Image image) { myImage = image; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (DataFlavor.imageFlavor.equals(flavor)) { return myImage; } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.imageFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return (DataFlavor.imageFlavor.equals(flavor)); } public void lostOwnership(Clipboard clipboard, Transferable contents) { //nothing } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransfer/PasteMenuItem.java000066400000000000000000000010211506470510200334710ustar00rootroot00000000000000package com.kreative.bitsnpicas.datatransfer; import java.awt.Toolkit; import java.awt.event.KeyEvent; import javax.swing.JMenuItem; import javax.swing.KeyStroke; public class PasteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PasteMenuItem() { super("Paste"); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, skm)); setActionCommand("Paste"); addActionListener(TransferActionListener.getInstance()); } } TransferActionListener.java000066400000000000000000000032551506470510200353350ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/datatransferpackage com.kreative.bitsnpicas.datatransfer; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.text.JTextComponent; public class TransferActionListener implements ActionListener, PropertyChangeListener { private static TransferActionListener instance = null; public static TransferActionListener getInstance() { if (instance == null) instance = new TransferActionListener(); return instance; } private JComponent focusOwner = null; public TransferActionListener() { KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.addPropertyChangeListener("permanentFocusOwner", this); } public void propertyChange(PropertyChangeEvent e) { Object o = e.getNewValue(); if (o instanceof JComponent) { focusOwner = (JComponent)o; } else { focusOwner = null; } } public void actionPerformed(ActionEvent e) { if (focusOwner == null) return; String actionName = e.getActionCommand(); if (focusOwner instanceof JTextComponent) { JTextComponent c = (JTextComponent)focusOwner; if ("Cut".equals(actionName)) { c.cut(); return; } if ("Copy".equals(actionName)) { c.copy(); return; } if ("Paste".equals(actionName)) { c.paste(); return; } if ("Clear".equals(actionName)) { c.replaceSelection(""); return; } } Action action = focusOwner.getActionMap().get(actionName); if (action != null) { action.actionPerformed(new ActionEvent( focusOwner, ActionEvent.ACTION_PERFORMED, null )); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/000077500000000000000000000000001506470510200263635ustar00rootroot00000000000000BareBonesBrowserLaunch.java000066400000000000000000000053111506470510200335060ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; /////////////////////////////// // Bare Bones Browser Launch // /////////////////////////////// import javax.swing.JOptionPane; import java.util.Arrays; /** * Utility class to open a web page from a Swing application * in the user's default browser. *

* Supports: Mac OS X, Linux, Unix, Windows *

* Example usage:
   * String url = "https://dnajs.org/";
   * BareBonesBrowserLaunch.openURL(url);
*

* Latest Version: * https://centerkey.com/java/browser *

* Published: October 24, 2010 *

* License: WTFPL * * @author Dem Pilafian * @version 3.2 */ public class BareBonesBrowserLaunch { static final String[] browsers = { "x-www-browser", "google-chrome", "firefox", "opera", "epiphany", "konqueror", "conkeror", "midori", "kazehakase", "mozilla" }; static final String errMsg = "Error attempting to launch web browser"; /** * Open the specified web page in the user's default browser * @param url A web address (URL) of a web page (example: "https://dnajs.org/") */ public static void openURL(String url) { try { //attempt to use Desktop library from JDK 1.6+ Class d = Class.forName("java.awt.Desktop"); d.getDeclaredMethod("browse", new Class[] {java.net.URI.class}).invoke( d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {java.net.URI.create(url)}); } catch (Exception ignore) { //library not available or failed String osName = System.getProperty("os.name"); try { if (osName.startsWith("Mac OS")) { Class.forName("com.apple.eio.FileManager").getDeclaredMethod( "openURL", new Class[] {String.class}).invoke(null, new Object[] {url}); } else if (osName.startsWith("Windows")) Runtime.getRuntime().exec( "rundll32 url.dll,FileProtocolHandler " + url); else { //assume Unix or Linux String browser = null; for (String b : browsers) if (browser == null && Runtime.getRuntime().exec(new String[] {"which", b}).getInputStream().read() != -1) Runtime.getRuntime().exec(new String[] {browser = b, url}); if (browser == null) throw new Exception(Arrays.toString(browsers)); } } catch (Exception e) { JOptionPane.showMessageDialog(null, errMsg + "\n" + e.toString()); } } } }bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapEditFrame.java000066400000000000000000000015351506470510200322270ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import javax.swing.JFrame; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; public class BitmapEditFrame extends JFrame { private static final long serialVersionUID = 1L; private final BitmapEditPanel panel; private final BitmapEditMenuBar mb; public BitmapEditFrame(BitmapFont font, GlyphLocator locator, GlyphList gl, SaveManager sm) { this.panel = new BitmapEditPanel(locator, gl); this.mb = new BitmapEditMenuBar(this, sm, font, panel); setTitle(locator.toString()); setJMenuBar(mb); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); GlyphEditFrame.addActions(this, panel, BitmapFontGlyph.class); panel.getGlyphComponent().requestFocusInWindow(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapEditMenuBar.java000066400000000000000000000231431506470510200325250ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Arrays; import javax.imageio.ImageIO; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class BitmapEditMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public BitmapEditMenuBar(final Frame frame, final SaveManager sm, final BitmapFont font, final BitmapEditPanel panel) { add(new FileMenu(frame, sm, font, panel)); add(new EditMenu(panel)); add(new GlyphEditMenuBar.ViewMenu(frame, panel, BitmapFontGlyph.class)); add(new TransformMenu(panel.getGlyphComponent())); } public static final class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Frame frame, final SaveManager sm, final BitmapFont font, final BitmapEditPanel panel) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(frame)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); add(new BitmapListMenuBar.ExportMenuItem(font)); addSeparator(); add(new ImportMenuItem(frame, panel)); addSeparator(); add(new CommonMenuItems.FontInfoMenuItem(font, sm)); add(new BitmapListMenuBar.PreviewMenuItem(font, panel.getGlyphList())); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static final class ImportMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; private String lastDirectory = null; public ImportMenuItem(final Frame frame, final BitmapEditPanel panel) { super("Import Image..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FileDialog fd = new FileDialog(frame, "Import Image", FileDialog.LOAD); if (lastDirectory != null) fd.setDirectory(lastDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); if (ds == null || fs == null) return; File file = new File((lastDirectory = ds), fs); try { BufferedImage image = ImageIO.read(file); if (image != null) { panel.getToolHandler().pushUndoState(null); Font font = panel.getGlyphFont(); BitmapFontGlyph glyph = panel.getGlyph(); glyph.setToImage(0, -font.getLineAscent(), image); glyph.setCharacterWidth(image.getWidth()); panel.getGlyphComponent().glyphChanged(); } else { JOptionPane.showMessageDialog( null, "The selected file was not recognized as an image file.", "Import Image", JOptionPane.ERROR_MESSAGE ); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Import Image", JOptionPane.ERROR_MESSAGE ); } } }); } } public static final class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(final BitmapEditPanel panel) { super("Edit"); BitmapToolHandler handler = panel.getToolHandler(); add(new UndoMenuItem(handler)); add(new RedoMenuItem(handler)); addSeparator(); add(new CutMenuItem(panel)); add(new CopyMenuItem(panel)); add(new PasteMenuItem(panel, false)); add(new PasteMenuItem(panel, true)); add(new ClearMenuItem(panel)); } } public static final class UndoMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public UndoMenuItem(final BitmapToolHandler handler) { super("Undo"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handler.undo(); } }); } } public static final class RedoMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public RedoMenuItem(final BitmapToolHandler handler) { super("Redo"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handler.redo(); } }); } } public static final class CutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CutMenuItem(final BitmapEditPanel panel) { super("Cut"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); BitmapGlyphListSelection sel = new BitmapGlyphListSelection(Arrays.asList(panel.getGlyphLocator())); cb.setContents(sel, sel); panel.getToolHandler().pushUndoState(null); BitmapFontGlyph glyph = panel.getGlyph(); glyph.setXY(0, 0); glyph.setGlyph(new byte[0][0]); glyph.setCharacterWidth(0); panel.getGlyphComponent().glyphChanged(); } }); } } public static final class CopyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CopyMenuItem(final BitmapEditPanel panel) { super("Copy"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); BitmapGlyphListSelection sel = new BitmapGlyphListSelection(Arrays.asList(panel.getGlyphLocator())); cb.setContents(sel, sel); } }); } } public static final class PasteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PasteMenuItem(final BitmapEditPanel panel, final boolean into) { super(into ? "Paste Into" : "Paste"); setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_V, CommonMenuItems.SHORTCUT_KEY | (into ? KeyEvent.SHIFT_MASK : 0) )); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(BitmapGlyphListSelection.flavor)) { BitmapGlyphState[] content = (BitmapGlyphState[])cb.getData(BitmapGlyphListSelection.flavor); if (content.length == 1) { panel.getToolHandler().pushUndoState(null); BitmapFontGlyph glyph = new BitmapFontGlyph(); content[0].apply(glyph); if (into) glyph = BitmapFontGlyph.compose(panel.getGlyph(), glyph); new BitmapGlyphState(glyph).apply(panel.getGlyph()); panel.getGlyphComponent().glyphChanged(); return; } } if (cb.isDataFlavorAvailable(DataFlavor.imageFlavor)) { Image content = (Image)cb.getData(DataFlavor.imageFlavor); BufferedImage image = SwingUtils.toBufferedImage(content); if (image != null) { panel.getToolHandler().pushUndoState(null); BitmapFontGlyph glyph = new BitmapFontGlyph(); glyph.setToImage(0, -panel.getGlyphFont().getLineAscent(), image); glyph.setCharacterWidth(image.getWidth()); if (into) glyph = BitmapFontGlyph.compose(panel.getGlyph(), glyph); new BitmapGlyphState(glyph).apply(panel.getGlyph()); panel.getGlyphComponent().glyphChanged(); return; } } } catch (IOException ioe) { ioe.printStackTrace(); } catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); } Toolkit.getDefaultToolkit().beep(); } }); } } public static final class ClearMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ClearMenuItem(final BitmapEditPanel panel) { super("Clear"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.getToolHandler().pushUndoState(null); BitmapFontGlyph glyph = panel.getGlyph(); glyph.setXY(0, 0); glyph.setGlyph(new byte[0][0]); glyph.setCharacterWidth(0); panel.getGlyphComponent().glyphChanged(); } }); } } public static final class TransformMenu extends JMenu { private static final long serialVersionUID = 1L; public TransformMenu(final GlyphComponent gc) { super("Transform"); for (BitmapGlyphTransform tx : BitmapGlyphTransform.TRANSFORMS) { if (tx == null) addSeparator(); else add(new TransformMenuItem(tx, gc)); } } } public static final class TransformMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public TransformMenuItem(final BitmapGlyphTransform tx,final GlyphComponent gc) { super(tx.name); setAccelerator(tx.keystroke); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tx.transform(gc.getGlyphFont(), gc.getGlyph()); gc.glyphChanged(); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapEditPanel.java000066400000000000000000000111651506470510200322340ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import com.kreative.bitsnpicas.BitmapFontGlyph; public class BitmapEditPanel extends GlyphEditPanel { private static final long serialVersionUID = 1L; private final GlyphComponent glyphComponent; private final BitmapToolPanel toolPanel; private final BitmapToolHandler toolHandler; public BitmapEditPanel(GlyphLocator locator, GlyphList gl) { super(locator, gl); this.glyphComponent = getGlyphComponent(); this.toolPanel = new BitmapToolPanel(); this.toolHandler = new BitmapToolHandler(toolPanel, glyphComponent); add(toolPanel, BorderLayout.LINE_START); glyphComponent.setFocusable(true); glyphComponent.addMouseListener(new MyMouseListener()); glyphComponent.addKeyListener(new MyKeyListener()); } public BitmapToolPanel getToolPanel() { return toolPanel; } public BitmapToolHandler getToolHandler() { return toolHandler; } public void setGlyph(GlyphLocator locator, Class glyphClass) { super.setGlyph(locator, glyphClass); this.toolHandler.clearHistory(); } private class MyMouseListener extends MouseAdapter { public void mousePressed(MouseEvent e) { glyphComponent.requestFocusInWindow(); } } private class MyKeyListener extends KeyAdapter { private boolean first = true; public void keyPressed(KeyEvent e) { if (!(e.isControlDown() || e.isMetaDown())) { switch (e.getKeyCode()) { case KeyEvent.VK_UP: translateGlyph(first, 0, -1); break; case KeyEvent.VK_DOWN: translateGlyph(first, 0, +1); break; case KeyEvent.VK_LEFT: translateGlyph(first, -1, 0); break; case KeyEvent.VK_RIGHT: translateGlyph(first, +1, 0); break; case KeyEvent.VK_OPEN_BRACKET: translateGlyphWidth(-1); break; case KeyEvent.VK_CLOSE_BRACKET: translateGlyphWidth(+1); break; case KeyEvent.VK_B: toolPanel.setSelectedTool(BitmapTool.PENCIL); break; case KeyEvent.VK_P: toolPanel.setSelectedTool(BitmapTool.PENCIL); break; case KeyEvent.VK_E: toolPanel.setSelectedTool(BitmapTool.ERASER); break; case KeyEvent.VK_I: toolPanel.setSelectedTool(BitmapTool.EYEDROPPER); break; case KeyEvent.VK_L: toolPanel.setSelectedTool(BitmapTool.LINE); break; case KeyEvent.VK_R: toolPanel.setSelectedTool(BitmapTool.RECTANGLE); break; case KeyEvent.VK_F: toolPanel.setSelectedTool(BitmapTool.FILLED_RECT); break; case KeyEvent.VK_N: toolPanel.setSelectedTool(BitmapTool.INVERT); break; case KeyEvent.VK_M: toolPanel.setSelectedTool(BitmapTool.MOVE); break; case KeyEvent.VK_V: toolPanel.setSelectedTool(BitmapTool.MOVE); break; case KeyEvent.VK_H: toolPanel.setSelectedTool(BitmapTool.GRABBER); break; case KeyEvent.VK_SPACE: toolPanel.setSelectedTool(BitmapTool.GRABBER); break; case KeyEvent.VK_D: toolPanel.setOpacity(255); break; case KeyEvent.VK_X: toolPanel.setOpacity(255 - toolPanel.getOpacity()); break; case KeyEvent.VK_BACK_QUOTE: toolPanel.setOpacity(0); break; case KeyEvent.VK_1: toolPanel.setOpacity(255 * 1 / 10); break; case KeyEvent.VK_2: toolPanel.setOpacity(255 * 2 / 10); break; case KeyEvent.VK_3: toolPanel.setOpacity(255 * 3 / 10); break; case KeyEvent.VK_4: toolPanel.setOpacity(255 * 4 / 10); break; case KeyEvent.VK_5: toolPanel.setOpacity(255 * 5 / 10); break; case KeyEvent.VK_6: toolPanel.setOpacity(255 * 6 / 10); break; case KeyEvent.VK_7: toolPanel.setOpacity(255 * 7 / 10); break; case KeyEvent.VK_8: toolPanel.setOpacity(255 * 8 / 10); break; case KeyEvent.VK_9: toolPanel.setOpacity(255 * 9 / 10); break; case KeyEvent.VK_0: toolPanel.setOpacity(255); break; case KeyEvent.VK_MINUS: translateOpacity(-1); break; case KeyEvent.VK_EQUALS: translateOpacity(+1); break; } } first = false; } public void keyReleased(KeyEvent e) { first = true; } } private void translateGlyph(boolean first, int tx, int ty) { if (first) toolHandler.pushUndoState(null); BitmapFontGlyph glyph = glyphComponent.getGlyph(); glyph.setXY(glyph.getX() + tx, glyph.getY() - ty); glyphComponent.glyphChanged(); } private void translateGlyphWidth(int t) { BitmapFontGlyph glyph = glyphComponent.getGlyph(); t += glyph.getCharacterWidth(); if (t < 0) t = 0; glyph.setCharacterWidth(t); glyphComponent.metricsChanged(); } private void translateOpacity(int t) { t += toolPanel.getOpacity(); if (t < 0) t = 0; if (t > 255) t = 255; toolPanel.setOpacity(t); } } BitmapGlyphListSelection.java000066400000000000000000000057711506470510200341030ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.awt.Color; import java.awt.Graphics2D; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class BitmapGlyphListSelection implements ClipboardOwner, Transferable { public static final DataFlavor flavor = new DataFlavor(BitmapGlyphState[].class, "Bitmap Glyph List"); private final BitmapGlyphState[] states; private final BufferedImage image; private final String string; public BitmapGlyphListSelection(Collection> locators) { StringBuffer textString = new StringBuffer(); List glyphs = new ArrayList(); List states = new ArrayList(); int totalGlyphWidth = 0, ascent = 0, descent = 0; for (GlyphLocator loc : locators) { if (loc.isCodePoint()) textString.append(Character.toChars(loc.getCodePoint())); else if (loc.isGlyphName()) textString.append(loc.getGlyphName()); BitmapFontGlyph glyph = loc.getGlyph(); if (glyph != null) { glyphs.add(glyph); states.add(new BitmapGlyphState(glyph)); totalGlyphWidth += glyph.getCharacterWidth(); } Font font = loc.getGlyphFont(); if (font != null) { if (font.getLineAscent() > ascent) ascent = font.getLineAscent(); if (font.getLineDescent() > descent) descent = font.getLineDescent(); } } this.states = states.toArray(new BitmapGlyphState[states.size()]); int w = totalGlyphWidth; if (w < 1) w = 1; int h = ascent + descent; if (h < 1) h = 1; this.image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); g.setColor(Color.black); double x = 0; for (BitmapFontGlyph glyph : glyphs) x += glyph.paint(g, x, ascent, 1); g.dispose(); this.string = textString.toString(); } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (BitmapGlyphListSelection.flavor.equals(flavor)) return states; else if (DataFlavor.imageFlavor.equals(flavor)) return image; else if (DataFlavor.stringFlavor.equals(flavor)) return string; else throw new UnsupportedFlavorException(flavor); } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{ BitmapGlyphListSelection.flavor, DataFlavor.imageFlavor, DataFlavor.stringFlavor }; } public boolean isDataFlavorSupported(DataFlavor flavor) { return ( BitmapGlyphListSelection.flavor.equals(flavor) || DataFlavor.imageFlavor.equals(flavor) || DataFlavor.stringFlavor.equals(flavor) ); } public void lostOwnership(Clipboard clipboard, Transferable contents) {} } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapGlyphState.java000066400000000000000000000017231506470510200324520ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.io.Serializable; import com.kreative.bitsnpicas.BitmapFontGlyph; public class BitmapGlyphState implements Serializable { private static final long serialVersionUID = 1L; private final int x; private final int y; private final byte[][] glyph; private final int advance; public BitmapGlyphState(BitmapFontGlyph glyph) { this.x = glyph.getX(); this.y = glyph.getY(); this.glyph = memcpy(glyph.getGlyph()); this.advance = glyph.getCharacterWidth(); } public void apply(BitmapFontGlyph glyph) { glyph.setXY(this.x, this.y); glyph.setGlyph(memcpy(this.glyph)); glyph.setCharacterWidth(this.advance); } private static byte[][] memcpy(byte[][] a) { byte[][] b = new byte[a.length][]; for (int i = 0; i < a.length; i++) b[i] = memcpy(a[i]); return b; } private static byte[] memcpy(byte[] a) { byte[] b = new byte[a.length]; for (int i = 0; i < a.length; i++) b[i] = a[i]; return b; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapGlyphTransform.java000066400000000000000000000075551506470510200333560ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.event.KeyEvent; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.transformer.BoldBitmapFontGlyphTransformer; public abstract class BitmapGlyphTransform { private static final int CTRL_SHIFT = CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK; public static final BitmapGlyphTransform[] TRANSFORMS = new BitmapGlyphTransform[] { new Bold ("Bold", CTRL_SHIFT, KeyEvent.VK_B), new Invert ("Invert", CTRL_SHIFT, KeyEvent.VK_N), new FlipHorizontal("Flip Horizontal", CTRL_SHIFT, KeyEvent.VK_H), new FlipVertical ("Flip Vertical", CTRL_SHIFT, KeyEvent.VK_J), null, new Nudge(-1, 0, "Nudge Left", CTRL_SHIFT, KeyEvent.VK_LEFT ), new Nudge(+1, 0, "Nudge Right", CTRL_SHIFT, KeyEvent.VK_RIGHT), new Nudge(0, -1, "Nudge Up", CTRL_SHIFT, KeyEvent.VK_UP ), new Nudge(0, +1, "Nudge Down", CTRL_SHIFT, KeyEvent.VK_DOWN ), }; public final String name; public final KeyStroke keystroke; public BitmapGlyphTransform(String name, int modifiers, int keyCode) { this.name = name; this.keystroke = KeyStroke.getKeyStroke(keyCode, modifiers); } public abstract void transform(Font font, BitmapFontGlyph glyph); public static final class Bold extends BitmapGlyphTransform { private final BoldBitmapFontGlyphTransformer tx; public Bold(String name, int keyCode, int modifiers) { super(name, keyCode, modifiers); this.tx = new BoldBitmapFontGlyphTransformer(true); } public void transform(Font font, BitmapFontGlyph glyph) { new BitmapGlyphState(tx.transformGlyph(glyph)).apply(glyph); } } public static final class Invert extends BitmapGlyphTransform { public Invert(String name, int keyCode, int modifiers) { super(name, keyCode, modifiers); } public void transform(Font font, BitmapFontGlyph glyph) { glyph.expand( 0, -font.getLineAscent(), glyph.getCharacterWidth(), font.getLineAscent() + font.getLineDescent() ); glyph.invertRect( 0, -font.getLineAscent(), glyph.getCharacterWidth(), font.getLineAscent() + font.getLineDescent() ); glyph.contract(); } } public static final class FlipHorizontal extends BitmapGlyphTransform { public FlipHorizontal(String name, int keyCode, int modifiers) { super(name, keyCode, modifiers); } public void transform(Font font, BitmapFontGlyph glyph) { for (byte[] row : glyph.getGlyph()) transform(row); int x = glyph.getCharacterWidth() - glyph.getGlyphWidth() - glyph.getGlyphOffset(); glyph.setXY(x, glyph.getGlyphAscent()); } private void transform(byte[] row) { for (int i = 0, j = row.length - 1; i < j; i++, j--) { byte tmp = row[i]; row[i] = row[j]; row[j] = tmp; } } } public static final class FlipVertical extends BitmapGlyphTransform { public FlipVertical(String name, int keyCode, int modifiers) { super(name, keyCode, modifiers); } public void transform(Font font, BitmapFontGlyph glyph) { transform(glyph.getGlyph()); int y = font.getLineAscent() - font.getLineDescent(); y += glyph.getGlyphHeight() - glyph.getGlyphAscent(); glyph.setXY(glyph.getGlyphOffset(), y); } private void transform(byte[][] rows) { for (int i = 0, j = rows.length - 1; i < j; i++, j--) { byte[] tmp = rows[i]; rows[i] = rows[j]; rows[j] = tmp; } } } public static final class Nudge extends BitmapGlyphTransform { private final int dx, dy; public Nudge(int dx, int dy, String name, int keyCode, int modifiers) { super(name, keyCode, modifiers); this.dx = dx; this.dy = dy; } public void transform(Font font, BitmapFontGlyph glyph) { int x = glyph.getX() + dx; int y = glyph.getY() - dy; glyph.setXY(x, y); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapListFrame.java000066400000000000000000000025471506470510200322610ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.io.File; import javax.swing.JFrame; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class BitmapListFrame extends JFrame { private static final long serialVersionUID = 1L; private final SaveManager sm; private final GlyphListPanel panel; private final BitmapListMenuBar mb; public BitmapListFrame(File fontFile, BitmapFontExporter format, BitmapFont font) { super(font.toString()); this.sm = new SaveManager(this, fontFile, format, font); this.panel = new GlyphListPanel(font, sm); this.mb = new BitmapListMenuBar(this, sm, font, panel.getGlyphList()); makeUI(); } public BitmapListFrame(SaveRoutine routine, BitmapFont font) { super(font.toString()); this.sm = new SaveManager(this, routine, font); this.panel = new GlyphListPanel(font, sm); this.mb = new BitmapListMenuBar(this, sm, font, panel.getGlyphList()); makeUI(); } public GlyphListPanel getPanel() { return panel; } private void makeUI() { setJMenuBar(mb); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(sm); panel.getGlyphList().requestFocusInWindow(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapListMenuBar.java000066400000000000000000000415701506470510200325570ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Color; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import javax.imageio.ImageIO; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.edit.exporter.BitmapExportFrame; import com.kreative.bitsnpicas.main.ViewFont; public class BitmapListMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public BitmapListMenuBar(final Frame frame, final SaveManager sm, final BitmapFont font, final GlyphList gl) { add(new FileMenu(frame, sm, font, gl)); add(new EditMenu(frame, gl)); add(new GlyphListMenuBar.ViewMenu(frame, gl)); add(new TransformMenu(gl)); } public static final class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Frame frame, final SaveManager sm, final BitmapFont font, final GlyphList gl) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(frame)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); add(new ExportMenuItem(font)); addSeparator(); add(new ImportMenuItem(frame, gl)); addSeparator(); add(new CommonMenuItems.FontInfoMenuItem(font, sm)); add(new PreviewMenuItem(font, gl)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static final class ExportMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ExportMenuItem(final BitmapFont font) { super("Export..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new BitmapExportFrame(font).setVisible(true); } }); } } public static final class ImportMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; private String lastDirectory = null; public ImportMenuItem(final Frame frame, final GlyphList gl) { super("Import Image..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List> locators = gl.getSelection(); if (locators.isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } FileDialog fd = new FileDialog(frame, "Import Image", FileDialog.LOAD); if (lastDirectory != null) fd.setDirectory(lastDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); if (ds == null || fs == null) return; File file = new File((lastDirectory = ds), fs); try { BufferedImage image = ImageIO.read(file); if (image != null) { for (GlyphLocator loc : locators) { BitmapFontGlyph glyph = new BitmapFontGlyph(); glyph.setToImage(0, -loc.getGlyphFont().getLineAscent(), image); glyph.setCharacterWidth(image.getWidth()); loc.setGlyph(glyph); } gl.glyphContentChanged(); } else { JOptionPane.showMessageDialog( null, "The selected file was not recognized as an image file.", "Import Image", JOptionPane.ERROR_MESSAGE ); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Import Image", JOptionPane.ERROR_MESSAGE ); } } }); } } public static final class PreviewMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PreviewMenuItem(final BitmapFont font, final GlyphList gl) { super("Preview"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { final ViewFont vf = new ViewFont(font); final GlyphListListener gll = new GlyphListListener() { public void selectionChanged(GlyphList gl, Font font) {} public void selectionOpened(GlyphList gl, Font font) {} public void metricsChanged(GlyphList gl, Font font) { vf.fontChanged(); } public void glyphsChanged(GlyphList gl, Font font) { vf.fontChanged(); } }; vf.setVisible(true); vf.addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent e) { gl.removeGlyphListListener(gll); } }); gl.addGlyphListListener(gll); } }); } } public static final class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(final Frame frame, final GlyphList gl) { super("Edit"); add(new CutMenuItem(gl)); add(new CopyMenuItem(gl)); add(new PasteMenuItem(gl, false)); add(new PasteMenuItem(gl, true)); add(new ClearMenuItem(gl)); addSeparator(); add(new GlyphListMenuBar.SelectAllMenuItem(gl)); add(new GlyphListMenuBar.SelectNoneMenuItem(gl)); add(new GlyphListMenuBar.SetSelectionMenuItem(frame, gl)); addSeparator(); add(new CreateMenuItem(frame, gl)); add(new MoveMenuItem(frame, gl, false)); add(new MoveMenuItem(frame, gl, true)); add(new GlyphListMenuBar.EditMenuItem(gl)); add(new GlyphListMenuBar.DeleteMenuItem(gl)); addSeparator(); add(new GenerateMenu(gl)); addSeparator(); add(new CommonMenuItems.FontMapMenuItem()); } } public static final class CutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CutMenuItem(final GlyphList gl) { super("Cut"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List> locators = gl.getSelection(); if (locators.isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } BitmapGlyphListSelection sel = new BitmapGlyphListSelection(locators); Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(sel, sel); gl.deleteSelection(); } }); } } public static final class CopyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CopyMenuItem(final GlyphList gl) { super("Copy"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List> locators = gl.getSelection(); if (locators.isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } BitmapGlyphListSelection sel = new BitmapGlyphListSelection(locators); Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(sel, sel); } }); } } public static final class PasteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PasteMenuItem(final GlyphList gl, final boolean into) { super(into ? "Paste Into" : "Paste"); setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_V, CommonMenuItems.SHORTCUT_KEY | (into ? KeyEvent.SHIFT_MASK : 0) )); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List> locators = gl.getSelection(); if (locators.isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } try { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(BitmapGlyphListSelection.flavor)) { BitmapGlyphState[] content = (BitmapGlyphState[])cb.getData(BitmapGlyphListSelection.flavor); if (content.length > 0) { for (int i = 0, n = locators.size(); i < n; i++) { BitmapFontGlyph glyph = new BitmapFontGlyph(); content[i % content.length].apply(glyph); if (into) glyph = BitmapFontGlyph.compose(locators.get(i).getGlyph(), glyph); locators.get(i).setGlyph(glyph); } if (locators.size() < content.length) { HashSet indices = new HashSet(); for (GlyphLocator loc : locators) indices.add(loc.getGlyphIndex()); GlyphLocator last = locators.get(locators.size() - 1); for (int i = locators.size(); i < content.length; i++) { last = last.getNext(); if (last == null) break; int index = last.getGlyphIndex(); if (index <= 0) break; indices.add(index); BitmapFontGlyph glyph = new BitmapFontGlyph(); content[i].apply(glyph); if (into) glyph = BitmapFontGlyph.compose(last.getGlyph(), glyph); last.setGlyph(glyph); } gl.setSelectedIndices(indices, true); } gl.glyphContentChanged(); return; } } else if (cb.isDataFlavorAvailable(DataFlavor.imageFlavor)) { Image content = (Image)cb.getData(DataFlavor.imageFlavor); BufferedImage image = SwingUtils.toBufferedImage(content); if (image != null) { for (GlyphLocator loc : locators) { BitmapFontGlyph glyph = new BitmapFontGlyph(); glyph.setToImage(0, -loc.getGlyphFont().getLineAscent(), image); glyph.setCharacterWidth(image.getWidth()); if (into) glyph = BitmapFontGlyph.compose(loc.getGlyph(), glyph); loc.setGlyph(glyph); } gl.glyphContentChanged(); return; } } else if (cb.isDataFlavorAvailable(DataFlavor.stringFlavor)) { String content = (String)cb.getData(DataFlavor.stringFlavor); if (content != null) { Font font = gl.getGlyphFont(); List glyphs = new ArrayList(); int stringHeight = font.getLineAscent() + font.getLineDescent(); int stringWidth = 0; int i = 0, n = content.length(); while (i < n) { int cp = content.codePointAt(i); i += Character.charCount(cp); BitmapFontGlyph g = font.getCharacter(cp); if (g == null) continue; glyphs.add(g); stringWidth += g.getCharacterWidth(); if (stringWidth >= 1024) { Toolkit.getDefaultToolkit().beep(); return; } } BufferedImage image = new BufferedImage(stringWidth, stringHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D gr = image.createGraphics(); gr.setColor(Color.black); double x = 0, a = font.getLineAscent(); for (BitmapFontGlyph g : glyphs) x += g.paint(gr, x, a, 1); gr.dispose(); for (GlyphLocator loc : locators) { BitmapFontGlyph glyph = new BitmapFontGlyph(); glyph.setToImage(0, -loc.getGlyphFont().getLineAscent(), image); glyph.setCharacterWidth(image.getWidth()); if (into) glyph = BitmapFontGlyph.compose(loc.getGlyph(), glyph); loc.setGlyph(glyph); } gl.glyphContentChanged(); return; } } } catch (IOException ioe) { ioe.printStackTrace(); } catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); } Toolkit.getDefaultToolkit().beep(); } }); } } public static final class ClearMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ClearMenuItem(final GlyphList gl) { super("Clear"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (gl.getSelection().isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } gl.deleteSelection(); } }); } } public static final class CreateMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CreateMenuItem(final Frame frame, final GlyphList gl) { super("Create Glyphs..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new CreateGlyphsDialog(frame, gl) { private static final long serialVersionUID = 1L; public BitmapFontGlyph createGlyph() { return new BitmapFontGlyph(); } }.setVisible(true); } }); } } public static final class MoveMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public MoveMenuItem(final Frame frame, final GlyphList gl, final boolean copy) { super(copy ? "Copy Glyphs..." : "Move Glyphs..."); setAccelerator(KeyStroke.getKeyStroke( copy ? KeyEvent.VK_C : KeyEvent.VK_X, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK )); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (gl.getSelection().isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } new MoveGlyphsDialog(frame, copy, gl) { private static final long serialVersionUID = 1L; public BitmapGlyphState serializeGlyph(BitmapFontGlyph g) { return new BitmapGlyphState(g); } public BitmapFontGlyph deserializeGlyph(BitmapGlyphState s) { BitmapFontGlyph g = new BitmapFontGlyph(); s.apply(g); return g; } }.setVisible(true); } }); } } public static final class GenerateMenu extends JMenu { private static final long serialVersionUID = 1L; public GenerateMenu(final GlyphList gl) { super("Generate"); add(new GenerateMenuItem(new UnifontHexGlyphGenerator(), gl)); add(new GenerateMenuItem(new TimestampGlyphGenerator(), gl)); add(new GenerateMenuItem(new SitelenPonaCartoucheGlyphGenerator(), gl)); } } public static final class GenerateMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public GenerateMenuItem(final GlyphGenerator gen, final GlyphList gl) { super(gen.getName()); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { switch (gen.generate(gl.getGlyphFont(), gl.getSelection())) { case NO_CHANGE: Toolkit.getDefaultToolkit().beep(); return; case CONTENT_CHANGED: gl.glyphContentChanged(); return; case REPERTOIRE_CHANGED: gl.glyphRepertoireChanged(); return; } } }); } } public static final class TransformMenu extends JMenu { private static final long serialVersionUID = 1L; public TransformMenu(final GlyphList gl) { super("Transform"); for (BitmapGlyphTransform tx : BitmapGlyphTransform.TRANSFORMS) { if (tx == null) addSeparator(); else add(new TransformMenuItem(tx, gl)); } } } public static final class TransformMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public TransformMenuItem(final BitmapGlyphTransform tx, final GlyphList gl) { super(tx.name); setAccelerator(tx.keystroke); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List> locators = gl.getSelection(); if (locators.isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } IdentityHashMap processed; processed = new IdentityHashMap(); for (GlyphLocator loc : locators) { Font font = loc.getGlyphFont(); BitmapFontGlyph glyph = loc.getGlyph(); if (glyph != null && !processed.containsKey(glyph)) { tx.transform(font, glyph); processed.put(glyph, glyph); } } gl.glyphContentChanged(); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapTool.java000066400000000000000000000014771506470510200313110ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Cursor; import java.awt.Image; public enum BitmapTool { PENCIL(Resources.PENCIL_TOOL, SwingUtils.CURSOR_CROSSHAIR), ERASER(Resources.ERASER_TOOL, SwingUtils.CURSOR_CROSSHAIR), EYEDROPPER(Resources.EYEDROPPER_TOOL, SwingUtils.CURSOR_CROSSHAIR), LINE(Resources.LINE_TOOL, SwingUtils.CURSOR_CROSSHAIR), RECTANGLE(Resources.RECTANGLE_TOOL, SwingUtils.CURSOR_CROSSHAIR), FILLED_RECT(Resources.FILLED_RECT_TOOL, SwingUtils.CURSOR_CROSSHAIR), INVERT(Resources.INVERT_TOOL, SwingUtils.CURSOR_CROSSHAIR), MOVE(Resources.MOVE_TOOL, SwingUtils.CURSOR_MOVE), GRABBER(Resources.GRABBER_TOOL, SwingUtils.CURSOR_HAND_OPEN); public final Image icon; public final Cursor cursor; private BitmapTool(Image icon, Cursor cursor) { this.icon = icon; this.cursor = cursor; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapToolHandler.java000066400000000000000000000144641506470510200326070ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Cursor; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import java.util.Stack; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class BitmapToolHandler implements GlyphComponentListener { private final BitmapToolPanel toolPanel; private final GlyphComponent glyphComponent; private final Stack undoStack; private final Stack redoStack; private BitmapTool inProgressTool; private byte inProgressOpacity; private BitmapGlyphState inProgressState; private int startX; private int startY; private int startGx; private int startGy; private double startTx; private double startTy; public BitmapToolHandler(BitmapToolPanel toolPanel, GlyphComponent glyphComponent) { this.toolPanel = toolPanel; this.glyphComponent = glyphComponent; this.undoStack = new Stack(); this.redoStack = new Stack(); glyphComponent.addGlyphComponentListener(this); } public void clearHistory() { undoStack.clear(); redoStack.clear(); } public boolean canUndo() { return (!undoStack.isEmpty()); } public boolean canRedo() { return (!redoStack.isEmpty()); } public void pushUndoState(BitmapGlyphState state) { if (state == null) { BitmapFontGlyph g = glyphComponent.getGlyph(); state = new BitmapGlyphState(g); } undoStack.push(state); redoStack.clear(); } public void undo() { if (!undoStack.isEmpty()) { BitmapFontGlyph g = glyphComponent.getGlyph(); redoStack.push(new BitmapGlyphState(g)); undoStack.pop().apply(g); glyphComponent.glyphChanged(); } } public void redo() { if (!redoStack.isEmpty()) { BitmapFontGlyph g = glyphComponent.getGlyph(); undoStack.push(new BitmapGlyphState(g)); redoStack.pop().apply(g); glyphComponent.glyphChanged(); } } public Cursor getCursor(MouseEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { return toolPanel.getSelectedTool().cursor; } public boolean mouseMoved(MouseEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { return false; } public boolean mousePressed(MouseEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { this.inProgressTool = toolPanel.getSelectedTool(); this.inProgressOpacity = (byte)toolPanel.getOpacity(); this.inProgressState = new BitmapGlyphState(glyph); this.startX = (int)Math.floor(p.getX()); this.startY = (int)Math.floor(p.getY()); return doTool(e, startX, startY, glyph, font, true, false); } public boolean mouseDragged(MouseEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { int x = (int)Math.floor(p.getX()); int y = (int)Math.floor(p.getY()); return doTool(e, x, y, glyph, font, false, false); } public boolean mouseReleased(MouseEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { int x = (int)Math.floor(p.getX()); int y = (int)Math.floor(p.getY()); return doTool(e, x, y, glyph, font, false, true); } private boolean doTool( MouseEvent e, int x, int y, BitmapFontGlyph glyph, Font font, boolean pressed, boolean released ) { int rx = Math.min(startX, x); int ry = Math.min(startY, y); int rw = Math.max(startX, x) - rx; int rh = Math.max(startY, y) - ry; switch (inProgressTool) { case PENCIL: if (pressed) { pushUndoState(inProgressState); byte existing = glyph.getPixel(x, y); if (inProgressOpacity == existing) inProgressOpacity = 0; } glyph.expand(rx, ry, rw + 1, rh + 1); glyph.drawLine(startX, startY, x, y, inProgressOpacity); startX = x; startY = y; if (released) glyph.contract(); return true; case ERASER: if (pressed) pushUndoState(inProgressState); glyph.expand(rx, ry, rw + 1, rh + 1); glyph.drawLine(startX, startY, x, y, (byte)0); startX = x; startY = y; if (released) glyph.contract(); return true; case EYEDROPPER: toolPanel.setOpacity(glyph.getPixel(x, y) & 0xFF); return false; case LINE: if (pressed) pushUndoState(inProgressState); inProgressState.apply(glyph); glyph.expand(rx, ry, rw + 1, rh + 1); glyph.drawLine(startX, startY, x, y, inProgressOpacity); if (released) glyph.contract(); return true; case RECTANGLE: if (pressed) pushUndoState(inProgressState); inProgressState.apply(glyph); glyph.expand(rx, ry, rw + 1, rh + 1); glyph.drawRect(rx, ry, rw, rh, inProgressOpacity); if (released) glyph.contract(); return true; case FILLED_RECT: if (pressed) pushUndoState(inProgressState); inProgressState.apply(glyph); glyph.expand(rx, ry, rw + 1, rh + 1); glyph.fillRect(rx, ry, rw + 1, rh + 1, inProgressOpacity); if (released) glyph.contract(); return true; case INVERT: if (pressed) pushUndoState(inProgressState); inProgressState.apply(glyph); glyph.expand(rx, ry, rw + 1, rh + 1); glyph.invertRect(rx, ry, rw + 1, rh + 1); if (released) glyph.contract(); return true; case MOVE: if (pressed) { pushUndoState(inProgressState); startGx = glyph.getX(); startGy = glyph.getY(); } else { glyph.setXY( startGx + (x - startX), startGy - (y - startY) ); } return true; case GRABBER: if (pressed) { glyphComponent.setCursor(SwingUtils.CURSOR_HAND_CLOSED); startX = e.getX(); startY = e.getY(); startTx = glyphComponent.getTranslateX(); startTy = glyphComponent.getTranslateY(); } else { glyphComponent.setTranslate( Math.round(startTx + e.getX() - startX), Math.round(startTy + e.getY() - startY) ); } if (released) { glyphComponent.setCursor(SwingUtils.CURSOR_HAND_OPEN); } return false; } return false; } public boolean mouseWheelMoved(MouseWheelEvent e, Point2D p, BitmapFontGlyph glyph, Font font) { int opacity = toolPanel.getOpacity() - e.getWheelRotation(); if (opacity < 0) opacity = 0; if (opacity > 255) opacity = 255; toolPanel.setOpacity(opacity); return false; } public void metricsChanged(BitmapFontGlyph glyph, Font font) {} public void glyphChanged(BitmapFontGlyph glyph, Font font) {} } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapToolList.java000066400000000000000000000024531506470510200321400ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Color; import java.awt.Component; import java.awt.SystemColor; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.border.Border; public class BitmapToolList extends JList { private static final long serialVersionUID = 1L; public BitmapToolList() { super(BitmapTool.values()); this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.setSelectedIndex(0); this.setFocusable(false); this.setCellRenderer(new ListCellRenderer() { public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) { BitmapTool tool = (BitmapTool)value; JLabel label = new JLabel(new ImageIcon(tool.icon)); Border ib = BorderFactory.createEmptyBorder(4, 6, 4, 6); Border ob = BorderFactory.createMatteBorder(((index == 0) ? 1 : 0), 1, 1, 1, Color.black); label.setBorder(BorderFactory.createCompoundBorder(ob, ib)); label.setBackground(sel ? SystemColor.textHighlight : SystemColor.text); label.setForeground(sel ? SystemColor.textHighlightText : SystemColor.textText); label.setOpaque(true); return label; } }); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/BitmapToolPanel.java000066400000000000000000000033521506470510200322630ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class BitmapToolPanel extends JPanel { private static final long serialVersionUID = 1L; private final BitmapToolList toolList; private final JLabel opacityLabel; private final JSlider opacitySlider; public BitmapToolPanel() { this.toolList = new BitmapToolList(); this.opacityLabel = new JLabel("255"); this.opacitySlider = new JSlider(JSlider.VERTICAL, 0, 255, 255); opacityLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT); opacityLabel.setHorizontalAlignment(JLabel.CENTER); opacityLabel.setHorizontalTextPosition(JLabel.CENTER); opacityLabel.setBorder(BorderFactory.createEmptyBorder(4, 0, 4, 0)); opacityLabel.setFont(opacityLabel.getFont().deriveFont(10f)); opacitySlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { opacityLabel.setText(Integer.toString(opacitySlider.getValue())); } }); JPanel p1 = new JPanel(new BorderLayout()); p1.add(opacityLabel, BorderLayout.PAGE_START); p1.add(opacitySlider, BorderLayout.CENTER); p1.setToolTipText("Opacity"); setLayout(new BorderLayout()); add(toolList, BorderLayout.PAGE_START); add(p1, BorderLayout.CENTER); } public BitmapTool getSelectedTool() { return (BitmapTool)toolList.getSelectedValue(); } public void setSelectedTool(BitmapTool tool) { toolList.setSelectedValue(tool, true); } public int getOpacity() { return opacitySlider.getValue(); } public void setOpacity(int opacity) { opacitySlider.setValue(opacity); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/CommonMenuItems.java000066400000000000000000000132161506470510200323100ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import java.io.IOException; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.geos.mover.GEOSMoverFrame; import com.kreative.bitsnpicas.mover.MoverFrame; import com.kreative.unicode.fontmap.FontMapController; public class CommonMenuItems { public static final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); public static final boolean IS_MAC_OS; static { boolean isMacOS; try { isMacOS = System.getProperty("os.name").toUpperCase().contains("MAC OS"); } catch (Exception e) { isMacOS = false; } IS_MAC_OS = isMacOS; } public static class NewMenu extends JMenu { private static final long serialVersionUID = 1L; public NewMenu() { super("New"); add(new NewBitmapFontMenuItem()); // add(new NewVectorFontMenuItem()); add(new NewFontSuitcaseMenuItem()); add(new NewGEOSFontMenuItem()); } } public static class NewBitmapFontMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewBitmapFontMenuItem() { super("New Bitmap Font"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.newBitmapFont(); } }); } } public static class NewVectorFontMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewVectorFontMenuItem() { super("New Vector Font"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.newVectorFont(); } }); } } public static class NewFontSuitcaseMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewFontSuitcaseMenuItem() { super("New Font Suitcase"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { MoverFrame.forNewFile().setVisible(true); } catch (IOException ioe) { ioe.printStackTrace(); } } }); } } public static class NewGEOSFontMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewGEOSFontMenuItem() { super("New GEOS Font"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { GEOSMoverFrame.forNewFile().setVisible(true); } }); } } public static class OpenMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenMenuItem() { super("Open..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.openFonts(); } }); } } public static class CloseMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CloseMenuItem(final Window window) { super("Close Window"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); } }); } } public static class SaveMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveMenuItem(final SaveInterface sm) { super("Save"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { sm.save(); } }); } } public static class SaveAsMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveAsMenuItem(final SaveInterface sm) { super("Save As..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { sm.saveAs(); } }); } } public static class FontInfoMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public FontInfoMenuItem(final Font font, final SaveManager sm) { super("Font Info"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new FontInfoFrame(font, sm).setVisible(true); } }); } } public static class ExitMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ExitMenuItem() { super("Exit"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) return; } } System.exit(0); } }); } } public static class FontMapMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public FontMapMenuItem() { super("Font Map"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontMapController.getInstance().getFrame().setVisible(true); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/CreateGlyphsDialog.java000066400000000000000000000213271506470510200327450ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public abstract class CreateGlyphsDialog extends JDialog { private static final long serialVersionUID = 1L; private final GlyphList glyphList; private JRadioButton byCodePointButton; private JRadioButton byIndexButton; private JCheckBox overwriteButton; private JTextArea specificationField; private JButton cancelButton; private JButton okButton; public CreateGlyphsDialog(Dialog parent, GlyphList gl) { super(parent, "Create Glyphs"); this.glyphList = gl; setModal(true); make(); } public CreateGlyphsDialog(Frame parent, GlyphList gl) { super(parent, "Create Glyphs"); this.glyphList = gl; setModal(true); make(); } public CreateGlyphsDialog(Window parent, GlyphList gl) { super(parent, "Create Glyphs"); this.glyphList = gl; setModal(true); make(); } private void make() { this.byCodePointButton = new JRadioButton("By Code Point"); this.byIndexButton = new JRadioButton("By Index"); this.overwriteButton = new JCheckBox("Overwrite existing glyphs"); this.specificationField = new JTextArea(); this.cancelButton = new JButton("Cancel"); this.okButton = new JButton("OK"); boolean isUnicode = isUnicodeRange(glyphList.getModel()); this.byCodePointButton.setSelected(isUnicode); this.byIndexButton.setSelected(!isUnicode); ButtonGroup bg1 = new ButtonGroup(); bg1.add(this.byCodePointButton); bg1.add(this.byIndexButton); JPanel bp1 = new JPanel(new GridLayout(1, 0, 8, 8)); bp1.add(this.byCodePointButton); bp1.add(this.byIndexButton); JPanel bp2 = new JPanel(new GridLayout(0, 1, 4, 4)); bp2.add(bp1); bp2.add(new JLabel("(Non-numeric values will be treated as glyph names.)")); bp2.add(this.overwriteButton); Dimension d = new Dimension(240, 120); this.specificationField.setMinimumSize(d); this.specificationField.setPreferredSize(d); this.specificationField.setLineWrap(true); this.specificationField.setWrapStyleWord(true); JScrollPane sp = new JScrollPane( this.specificationField, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); JPanel cp = new JPanel(new BorderLayout(8, 8)); cp.add(bp2, BorderLayout.PAGE_START); cp.add(sp, BorderLayout.CENTER); JPanel bp = new JPanel(new FlowLayout()); bp.add(this.cancelButton); bp.add(this.okButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(cp, BorderLayout.CENTER); mainPanel.add(bp, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), okButton); setResizable(false); pack(); setLocationRelativeTo(null); specificationField.requestFocusInWindow(); specificationField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_ENTER: okButton.doClick(); break; case KeyEvent.VK_ESCAPE: cancelButton.doClick(); break; case KeyEvent.VK_U: if (e.isControlDown() || e.isMetaDown()) { byCodePointButton.doClick(); } break; case KeyEvent.VK_I: if (e.isControlDown() || e.isMetaDown()) { byIndexButton.doClick(); } break; case KeyEvent.VK_O: if (e.isControlDown() || e.isMetaDown()) { overwriteButton.doClick(); } break; } } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { createGlyphs( specificationField.getText(), byIndexButton.isSelected(), overwriteButton.isSelected() ); dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } public abstract G createGlyph(); private static boolean isUnicodeRange(GlyphListModel model) { for (int lastCP = -1, i = 0, n = model.getCellCount(); i < n; i++) { if (model.isCodePoint(i)) { int cp = model.getCodePoint(i); if (lastCP < 0 || (lastCP + 1) == cp) { lastCP = cp; continue; } } return false; } return true; } private void createGlyphs(String s, boolean byIndex, boolean overwrite) { // Get the specified glyph identifiers before creating any glyphs. // If we create the glyphs at the same time the indices may change. Font font = glyphList.getGlyphFont(); GlyphListModel model = glyphList.getModel(); List> specifiedLocators = new ArrayList>(); TreeSet specifiedCodePoints = new TreeSet(); TreeSet specifiedGlyphNames = new TreeSet(); String[] parts = s.split("[,;]"); for (String part : parts) { try { int[] range = parseRange(part); if (byIndex) { int n = model.getCellCount(); for (int i = range[0]; i <= range[1]; i++) { if (i >= 0 && i < n) { specifiedLocators.add(new GlyphLocator(font, model, i)); } } } else { for (int cp = range[0]; cp <= range[1]; cp++) { specifiedCodePoints.add(cp); } } } catch (NumberFormatException nfe) { if ((part = part.trim()).length() > 0) { parseGlyphNames(part, specifiedGlyphNames); } } } // Put the glyphs at the destination glyph names before // setting the selection since the indices may change. for (GlyphLocator loc : specifiedLocators) { if (overwrite || loc.getGlyph() == null) loc.setGlyph(createGlyph()); } for (int cp : specifiedCodePoints) { if (overwrite || font.getCharacter(cp) == null) font.putCharacter(cp, createGlyph()); } for (String gn : specifiedGlyphNames) { if (overwrite || font.getNamedGlyph(gn) == null) font.putNamedGlyph(gn, createGlyph()); } glyphList.glyphRepertoireChanged(); // Calculate the selected indices now that the font is done changing. TreeSet selectedIndices = new TreeSet(); for (GlyphLocator loc : specifiedLocators) selectedIndices.add(loc.getGlyphIndex()); for (int cp : specifiedCodePoints) selectedIndices.add(model.indexOfCodePoint(cp)); for (String n : specifiedGlyphNames) selectedIndices.add(model.indexOfGlyphName(n)); glyphList.setSelectedIndices(selectedIndices, true); } private static int[] parseRange(String s) { String[] p = s.split("-+|:+|\\.\\.+", 2); if (p.length == 2) { int p0 = parseInt(p[0].trim()); int p1 = parseInt(p[1].trim()); int start = Math.min(p0, p1); int end = Math.max(p0, p1); return new int[]{ start, end }; } int i = parseInt(s.trim()); return new int[]{ i, i }; } private static int parseInt(String s) { if (s.startsWith("0x")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("0X")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("U+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("u+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("$")) return Integer.parseInt(s.substring(1), 16); if (s.startsWith("#")) return Integer.parseInt(s.substring(1), 10); return Integer.parseInt(s, 10); } private static final Pattern RANGE_PATTERN = Pattern.compile("\\{([0-9]+)(-+|:+|\\.\\.+)([0-9]+)\\}"); private static void parseGlyphNames(String s, Collection names) { Matcher m = RANGE_PATTERN.matcher(s); if (m.find()) { String s1 = m.group(1); String s3 = m.group(3); int v1 = Integer.parseInt(s1); int v3 = Integer.parseInt(s3); int length = Math.min(s1.length(), s3.length()); int start = Math.min(v1, v3); int end = Math.max(v1, v3); String prefix = s.substring(0, m.start()); String suffix = s.substring(m.end()); for (int vi = start; vi <= end; vi++) { String si = Integer.toString(vi); while (si.length() < length) si = "0" + si; parseGlyphNames(prefix + si + suffix, names); } } else { names.add(s); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/EraserTool.png000066400000000000000000000003361506470510200311520ustar00rootroot00000000000000PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqe<PLTE{FՁtRNSKFLIDATxڄI A?٪ԨJ"Op/fR,)6Cw`p2 Ptcbߩ;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/EyedropperTool.png000066400000000000000000000004041506470510200320430ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<IDATxb` WUUd0aBI1 gxX[?|xm yF"-C0XHL 5Ͼ 18y͸ Z36HҌnɚ K3J,Y d5e€xIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FilledRectTool.png000066400000000000000000000002341506470510200317430ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<>IDATxb?%B@, ?E@yy9ɚ;;;A0 `e&JR"FᜭIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontInfoFrame.java000066400000000000000000000034021506470510200317220ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; public class FontInfoFrame extends JFrame { private static final long serialVersionUID = 1L; private final Font font; private final FontInfoPanel panel; private final SaveManager sm; public FontInfoFrame(Font font, SaveManager sm) { super("Font Info"); this.font = font; this.panel = new FontInfoPanel(); this.panel.readFrom(this.font); this.sm = sm; JButton cancelButton = new JButton("Cancel"); JButton okButton = new JButton("OK"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(cancelButton); buttonPanel.add(okButton); JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.add(this.panel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); setContentPane(mainPanel); SwingUtils.setDefaultButton(getRootPane(), okButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontInfoFrame.this.dispose(); } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontInfoFrame.this.panel.writeTo(FontInfoFrame.this.font); FontInfoFrame.this.dispose(); FontInfoFrame.this.sm.setChanged(); } }); setSize(700, 500); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontInfoMetricsPanel.java000066400000000000000000000057471506470510200332740ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import com.kreative.bitsnpicas.Font; public class FontInfoMetricsPanel extends JPanel { private static final long serialVersionUID = 1L; private final SpinnerNumberModel emAscent; private final SpinnerNumberModel emDescent; private final SpinnerNumberModel lineAscent; private final SpinnerNumberModel lineDescent; private final SpinnerNumberModel lineGap; private final SpinnerNumberModel xHeight; private final SpinnerNumberModel capHeight; public FontInfoMetricsPanel() { JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); labelPanel.add(new JLabel("Em Ascent")); labelPanel.add(new JLabel("Em Descent")); labelPanel.add(new JLabel("Line Ascent")); labelPanel.add(new JLabel("Line Descent")); labelPanel.add(new JLabel("Line Gap")); labelPanel.add(new JLabel("X Height")); labelPanel.add(new JLabel("Cap Height")); JPanel spinnerPanel = new JPanel(new GridLayout(0, 1, 4, 4)); spinnerPanel.add(new JSpinner(emAscent = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(emDescent = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(lineAscent = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(lineDescent = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(lineGap = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(xHeight = new SpinnerNumberModel())); spinnerPanel.add(new JSpinner(capHeight = new SpinnerNumberModel())); Dimension d = new Dimension(80, spinnerPanel.getPreferredSize().height); spinnerPanel.setMinimumSize(d); spinnerPanel.setPreferredSize(d); JPanel mainPanel1 = new JPanel(new BorderLayout()); mainPanel1.add(spinnerPanel, BorderLayout.LINE_START); JPanel mainPanel2 = new JPanel(new BorderLayout(8, 8)); mainPanel2.add(labelPanel, BorderLayout.LINE_START); mainPanel2.add(mainPanel1, BorderLayout.CENTER); mainPanel2.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); setLayout(new BorderLayout()); add(mainPanel2, BorderLayout.PAGE_START); } public void readFrom(Font font) { emAscent.setValue(font.getEmAscent()); emDescent.setValue(font.getEmDescent()); lineAscent.setValue(font.getLineAscent()); lineDescent.setValue(font.getLineDescent()); lineGap.setValue(font.getLineGap()); xHeight.setValue(font.getXHeight()); capHeight.setValue(font.getCapHeight()); } public void writeTo(Font font) { font.setEmAscent(emAscent.getNumber().intValue()); font.setEmDescent(emDescent.getNumber().intValue()); font.setLineAscent(lineAscent.getNumber().intValue()); font.setLineDescent(lineDescent.getNumber().intValue()); font.setLineGap(lineGap.getNumber().intValue()); font.setXHeight(xHeight.getNumber().intValue()); font.setCapHeight(capHeight.getNumber().intValue()); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontInfoNamesPanel.java000066400000000000000000000143521506470510200327210ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.Scrollable; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public class FontInfoNamesPanel extends JPanel implements Scrollable { private static final long serialVersionUID = 1L; public static final Map NAME_TYPE_NAMES; static { Map ntn = new LinkedHashMap(); ntn.put(Font.NAME_FAMILY_AND_STYLE, "Font Family & Style Name"); ntn.put(Font.NAME_FAMILY, "Font Family Name"); ntn.put(Font.NAME_STYLE, "Font Style Name"); ntn.put(Font.NAME_POSTSCRIPT, "PostScript Name"); ntn.put(Font.NAME_WINDOWS_FAMILY, "Windows Family Name"); ntn.put(Font.NAME_WINDOWS_STYLE, "Windows Style Name"); ntn.put(Font.NAME_MACOS_FAMILY_AND_STYLE, "Mac OS Family & Style Name"); ntn.put(Font.NAME_WWS_FAMILY, "WWS Family Name"); ntn.put(Font.NAME_WWS_STYLE, "WWS Style Name"); ntn.put(Font.NAME_VERSION, "Version Number"); ntn.put(Font.NAME_UNIQUE_ID, "Unique ID"); ntn.put(Font.NAME_POSTSCRIPT_CID, "PostScript CID"); ntn.put(Font.NAME_COPYRIGHT, "Copyright Notice"); ntn.put(Font.NAME_TRADEMARK, "Trademark Notice"); ntn.put(Font.NAME_DESCRIPTION, "Description"); ntn.put(Font.NAME_MANUFACTURER, "Manufacturer"); ntn.put(Font.NAME_VENDOR_URL, "Vendor URL"); ntn.put(Font.NAME_DESIGNER, "Designer"); ntn.put(Font.NAME_DESIGNER_URL, "Designer URL"); ntn.put(Font.NAME_LICENSE_DESCRIPTION, "License Description"); ntn.put(Font.NAME_LICENSE_URL, "License URL"); ntn.put(Font.NAME_SAMPLE_TEXT, "Sample Text"); NAME_TYPE_NAMES = Collections.unmodifiableMap(ntn); } private final Map fields; public FontInfoNamesPanel() { JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); JPanel fieldPanel = new JPanel(new GridLayout(0, 1, 4, 4)); fields = new HashMap(); for (Map.Entry e : NAME_TYPE_NAMES.entrySet()) { JLabel label = new JLabel(e.getValue()); JTextField field = new JTextField(); labelPanel.add(label); fieldPanel.add(field); fields.put(e.getKey(), field); } JButton autoFillButton = new JButton("Auto Fill"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(autoFillButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(labelPanel, BorderLayout.LINE_START); mainPanel.add(fieldPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); setLayout(new BorderLayout()); add(mainPanel, BorderLayout.PAGE_START); autoFillButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { autoFillNames(); } }); } public void readFrom(Font font) { for (Map.Entry e : fields.entrySet()) { e.getValue().setText(font.getName(e.getKey())); } } public void writeTo(Font font) { for (Map.Entry e : fields.entrySet()) { String name = e.getValue().getText().trim(); if (name.length() == 0) font.removeName(e.getKey()); else font.setName(e.getKey(), name); } } public void autoFillNames() { BogusFont bogus = new BogusFont(); writeTo(bogus); bogus.autoFillNames(); readFrom(bogus); } public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public boolean getScrollableTracksViewportWidth() { return true; } public boolean getScrollableTracksViewportHeight() { return false; } public int getScrollableUnitIncrement(Rectangle vr, int or, int dir) { return fields.get(0).getPreferredSize().height + 4; } public int getScrollableBlockIncrement(Rectangle vr, int or, int dir) { int h = fields.get(0).getPreferredSize().height + 4; return (vr.height / h) * h; } private static class BogusFont extends Font { public int getEmAscent() { return 0; } public int getEmDescent() { return 0; } public int getLineAscent() { return 0; } public int getLineDescent() { return 0; } public int getXHeight() { return 0; } public int getCapHeight() { return 0; } public int getLineGap() { return 0; } public double getEmAscent2D() { return 0; } public double getEmDescent2D() { return 0; } public double getLineAscent2D() { return 0; } public double getLineDescent2D() { return 0; } public double getXHeight2D() { return 0; } public double getCapHeight2D() { return 0; } public double getLineGap2D() { return 0; } public void setEmAscent(int v) {} public void setEmDescent(int v) {} public void setLineAscent(int v) {} public void setLineDescent(int v) {} public void setXHeight(int v) {} public void setCapHeight(int v) {} public void setLineGap(int v) {} public void setEmAscent2D(double v) {} public void setEmDescent2D(double v) {} public void setLineAscent2D(double v) {} public void setLineDescent2D(double v) {} public void setXHeight2D(double v) {} public void setCapHeight2D(double v) {} public void setLineGap2D(double v) {} } private static class BogusGlyph extends FontGlyph { public int getGlyphOffset() { return 0; } public int getGlyphWidth() { return 0; } public int getGlyphHeight() { return 0; } public int getGlyphAscent() { return 0; } public int getGlyphDescent() { return 0; } public int getCharacterWidth() { return 0; } public double getGlyphOffset2D() { return 0; } public double getGlyphWidth2D() { return 0; } public double getGlyphHeight2D() { return 0; } public double getGlyphAscent2D() { return 0; } public double getGlyphDescent2D() { return 0; } public double getCharacterWidth2D() { return 0; } public void setCharacterWidth(int v) {} public void setCharacterWidth2D(double v) {} public double paint(Graphics g, double x, double y, double scale) { return 0; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontInfoPanel.java000066400000000000000000000024661506470510200317400ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import com.kreative.bitsnpicas.Font; public class FontInfoPanel extends JPanel { private static final long serialVersionUID = 1L; private final FontInfoNamesPanel namesPanel; private final FontInfoMetricsPanel metricsPanel; public FontInfoPanel() { JScrollPane namesPane = new JScrollPane( namesPanel = new FontInfoNamesPanel(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); JPanel namesPanel2 = new JPanel(new BorderLayout()); namesPanel2.add(namesPane, BorderLayout.CENTER); namesPanel2.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); SwingUtils.setOpaque(namesPanel2, false); JTabbedPane tabPane = new JTabbedPane(); tabPane.addTab("Names", namesPanel2); tabPane.addTab("Metrics", metricsPanel = new FontInfoMetricsPanel()); SwingUtils.setOpaque(metricsPanel, false); setLayout(new BorderLayout()); add(tabPane, BorderLayout.CENTER); } public void readFrom(Font font) { namesPanel.readFrom(font); metricsPanel.readFrom(font); } public void writeTo(Font font) { namesPanel.writeTo(font); metricsPanel.writeTo(font); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontListFrame.java000066400000000000000000000011131506470510200317370ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.io.File; import javax.swing.JFrame; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontExporter; public class FontListFrame extends JFrame { private static final long serialVersionUID = 1L; private final FontListPanel panel; public FontListFrame(File fontFile, FontExporter format, Font[] fonts) { this.panel = new FontListPanel(fontFile, format, fonts); setTitle("Open"); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/FontListPanel.java000066400000000000000000000037541506470510200317610ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontExporter; public class FontListPanel extends JPanel { private static final long serialVersionUID = 1L; private final File fontFile; private final FontExporter format; private final JList list; private final JLabel label; private final JButton openButton; public FontListPanel(File fontFile, FontExporter format, Font[] fonts) { this.fontFile = fontFile; this.format = format; this.list = new JList(fonts); this.label = new JLabel("This file contains multiple fonts. Please select one."); this.openButton = new JButton("Open"); JPanel buttons = new JPanel(new FlowLayout()); buttons.add(openButton); JPanel main = new JPanel(new BorderLayout(4, 4)); main.add(label, BorderLayout.PAGE_START); main.add(list, BorderLayout.CENTER); main.add(buttons, BorderLayout.PAGE_END); main.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); setLayout(new BorderLayout()); add(main, BorderLayout.CENTER); list.addMouseListener(new MyMouseListener()); openButton.addActionListener(new MyActionListener()); } private class MyMouseListener extends MouseAdapter { public void mouseClicked(MouseEvent e) { if (e.getClickCount() > 1) { Font font = (Font)list.getSelectedValue(); if (font != null) Main.openFont(fontFile, format, font); } } } private class MyActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { Font font = (Font)list.getSelectedValue(); if (font != null) Main.openFont(fontFile, format, font); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphComponent.java000066400000000000000000000473611506470510200322070ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Shape; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public class GlyphComponent extends JComponent { private static final long serialVersionUID = 1L; private static final int MARGIN_WIDTH = 60; private static final int MARGIN_HEIGHT = 24; private static final Color GRID_COLOR = new Color(0xFFCCCCCC); private static final Color CAP_HEIGHT_COLOR = new Color(0xFFFF9900); private static final Color X_HEIGHT_COLOR = new Color(0xFFFF9900); private static final Color LINE_GAP_COLOR = new Color(0xFFFFCC00); private static final Color LINE_ASCENT_COLOR = new Color(0xFFFF00CC); private static final Color LINE_DESCENT_COLOR = new Color(0xFF00CCFF); private static final Color EM_ASCENT_COLOR = Color.red; private static final Color EM_DESCENT_COLOR = Color.blue; private static final Color ADVANCE_COLOR = new Color(0xFF00CC00); private static final Color BOUNDS_COLOR = new Color(0xFF9900FF); private Font font; private G glyph; private double scale; private double tx; private double ty; private boolean fit; private boolean showGlyphBounds; private Dimension minimumSize; private Dimension preferredSize; private final List> listeners; public GlyphComponent(Font font, G glyph) { this.font = font; this.glyph = glyph; this.fit = true; this.showGlyphBounds = false; this.listeners = new ArrayList>(); MyMouseListener ml = new MyMouseListener(); this.addMouseListener(ml); this.addMouseMotionListener(ml); this.addMouseWheelListener(ml); MyComponentListener cl = new MyComponentListener(); this.addComponentListener(cl); } public Font getGlyphFont() { return this.font; } public G getGlyph() { return this.glyph; } public void setGlyph(Font font, G glyph) { this.font = font; this.glyph = glyph; metricsAndGlyphChanged(); } public double getScale() { return this.scale; } public void setScale(double scale) { if (this.scale != scale && scale > 0) { this.scale = scale; this.repaint(); } } public double getTranslateX() { return this.tx; } public double getTranslateY() { return this.ty; } public void setTranslate(double tx, double ty) { if (this.tx != tx || this.ty != ty) { this.tx = tx; this.ty = ty; this.repaint(); } } public void setBestScaleAndTranslate() { Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right; int h = getHeight() - insets.top - insets.bottom; int iw = w - MARGIN_WIDTH * 2; int ih = h - MARGIN_HEIGHT * 2; double fa = font.getEmAscent2D(); double fh = fa + font.getEmDescent2D(); double ns = (fh <= 0) ? (ih / 20.0) : (ih / fh / 2.0); if (ns <= 0) ns = 1; if (ns >= 1) ns = Math.floor(ns); double nx = Math.round((iw - glyph.getCharacterWidth2D() * ns) / 2); double ny = Math.round((ih - fh * ns) / 2 + fa * ns); if (this.scale != ns || this.tx != nx || this.ty != ny) { this.scale = ns; this.tx = nx; this.ty = ny; this.repaint(); } } public boolean getFit() { return this.fit; } public void setFit(boolean fit) { this.fit = fit; if (fit) setBestScaleAndTranslate(); } public boolean getShowGlyphBounds() { return this.showGlyphBounds; } public void setShowGlyphBounds(boolean showGlyphBounds) { this.showGlyphBounds = showGlyphBounds; repaint(); } public Dimension getMinimumSize() { if (minimumSize != null) { return minimumSize; } else { Insets i = getInsets(); int w = 20 + MARGIN_WIDTH * 2 + i.left + i.right; int h = 20 + MARGIN_HEIGHT * 2 + i.top + i.bottom; return new Dimension(w, h); } } public void setMinimumSize(Dimension d) { this.minimumSize = d; } public Dimension getPreferredSize() { if (preferredSize != null) { return preferredSize; } else { Insets i = getInsets(); int w = 400 + MARGIN_WIDTH * 2 + i.left + i.right; int h = 400 + MARGIN_HEIGHT * 2 + i.top + i.bottom; return new Dimension(w, h); } } public void setPreferredSize(Dimension d) { this.preferredSize = d; } public void addGlyphComponentListener(GlyphComponentListener l) { this.listeners.add(l); } public void removeGlyphComponentListener(GlyphComponentListener l) { this.listeners.remove(l); } public void metricsChanged() { for (GlyphComponentListener l : listeners) { l.metricsChanged(glyph, font); } repaint(); } public void glyphChanged() { for (GlyphComponentListener l : listeners) { l.glyphChanged(glyph, font); } repaint(); } public void metricsAndGlyphChanged() { for (GlyphComponentListener l : listeners) { l.metricsChanged(glyph, font); l.glyphChanged(glyph, font); } repaint(); } protected void paintComponent(Graphics g) { if (scale <= 0) setBestScaleAndTranslate(); Insets insets = getInsets(); int x = insets.left; int y = insets.top; int w = getWidth() - insets.left - insets.right; int h = getHeight() - insets.top - insets.bottom; int ix = x + MARGIN_WIDTH; int iy = y + MARGIN_HEIGHT; int iw = w - MARGIN_WIDTH * 2; int ih = h - MARGIN_HEIGHT * 2; int origin = ix + (int)Math.round(tx); int baseline = iy + (int)Math.round(ty); int emAscent = iy + (int)Math.round(ty - font.getEmAscent2D() * scale); int emDescent = iy + (int)Math.round(ty + font.getEmDescent2D() * scale); int lineAscent = iy + (int)Math.round(ty - font.getLineAscent2D() * scale); int lineDescent = iy + (int)Math.round(ty + font.getLineDescent2D() * scale); int lineGap = iy + (int)Math.round(ty + (font.getLineDescent2D() + font.getLineGap2D()) * scale); int xHeight = iy + (int)Math.round(ty - font.getXHeight2D() * scale); int capHeight = iy + (int)Math.round(ty - font.getCapHeight2D() * scale); int advance = ix + (int)Math.round(tx + glyph.getCharacterWidth2D() * scale); g.setColor(Color.black); g.fillRect(ix - 1, iy - 1, iw + 2, ih + 2); Shape saveClip = g.getClip(); g.clipRect(ix, iy, iw, ih); g.setColor(Color.white); g.fillRect(ix, iy, iw, ih); g.setColor(Color.black); glyph.paint(g, ix + tx, iy + ty, scale); if (scale >= 5) { g.setColor(GRID_COLOR); for (int i = 1; ty + i * scale <= ih; i++) { int ly = iy + (int)Math.round(ty + i * scale); g.drawLine(ix, ly, ix + iw, ly); } for (int i = 1; ty - i * scale >= 0; i++) { int ly = iy + (int)Math.round(ty - i * scale); g.drawLine(ix, ly, ix + iw, ly); } for (int i = 1; tx + i * scale <= iw; i++) { int lx = ix + (int)Math.round(tx + i * scale); g.drawLine(lx, iy, lx, iy + ih); } for (int i = 1; tx - i * scale >= 0; i++) { int lx = ix + (int)Math.round(tx - i * scale); g.drawLine(lx, iy, lx, iy + ih); } } g.setColor(Color.black); g.drawLine(ix, baseline, ix + iw, baseline); g.drawLine(origin, iy, origin, iy + ih); g.setColor(CAP_HEIGHT_COLOR); g.drawLine(ix, capHeight, ix + iw, capHeight); g.setColor(X_HEIGHT_COLOR); g.drawLine(ix, xHeight, ix + iw, xHeight); g.setColor(LINE_GAP_COLOR); g.drawLine(ix, lineGap, ix + iw, lineGap); g.setColor(LINE_ASCENT_COLOR); g.drawLine(ix, lineAscent, ix + iw, lineAscent); g.setColor(LINE_DESCENT_COLOR); g.drawLine(ix, lineDescent, ix + iw, lineDescent); g.setColor(EM_ASCENT_COLOR); g.drawLine(ix, emAscent, ix + iw, emAscent); g.setColor(EM_DESCENT_COLOR); g.drawLine(ix, emDescent, ix + iw, emDescent); g.setColor(ADVANCE_COLOR); g.drawLine(advance, iy, advance, iy + ih); if (showGlyphBounds) { g.setColor(BOUNDS_COLOR); int bx1 = ix + (int)Math.round(tx + glyph.getGlyphOffset2D() * scale); int by1 = iy + (int)Math.round(ty - glyph.getGlyphAscent2D() * scale); int bx2 = ix + (int)Math.round(tx + (glyph.getGlyphOffset2D() + glyph.getGlyphWidth2D()) * scale); int by2 = iy + (int)Math.round(ty + (-glyph.getGlyphAscent2D() + glyph.getGlyphHeight2D()) * scale); g.drawRect(bx1, by1, bx2 - bx1, by2 - by1); } g.setClip(saveClip); java.awt.Font saveFont = g.getFont(); g.setColor(Color.black); g.setFont(Resources.HEX_FONT); FontMetrics fm = g.getFontMetrics(); if (emAscent >= iy && emAscent < iy + ih) { String mas = toString(font.getEmAscent2D(), true) + " >"; g.drawString(mas, ix - fm.stringWidth(mas) - 1, emAscent + 4); } if (emDescent >= iy && emDescent < iy + ih) { String mds = toString(-font.getEmDescent2D(), true) + " >"; g.drawString(mds, ix - fm.stringWidth(mds) - 1, emDescent + 4); } if (xHeight >= iy && xHeight < iy + ih && xHeight != emAscent && xHeight != emDescent) { String xhs = toString(font.getXHeight2D(), false) + " >"; g.drawString(xhs, ix - fm.stringWidth(xhs) - 1, xHeight + 4); } if (lineAscent >= iy && lineAscent < iy + ih) { String las = "< " + toString(font.getLineAscent2D(), true); g.drawString(las, ix + iw + 2, lineAscent + 4); } if (lineDescent >= iy && lineDescent < iy + ih) { String lds = "< " + toString(-font.getLineDescent2D(), true); g.drawString(lds, ix + iw + 2, lineDescent + 4); } if (lineGap >= iy && lineGap < iy + ih && lineGap != lineAscent && lineGap != lineDescent) { String lgs = "< " + toString(font.getLineGap2D(), false); g.drawString(lgs, ix + iw + 2, lineGap + 4); } if (capHeight >= iy && capHeight < iy + ih && capHeight != lineAscent && capHeight != lineDescent && capHeight != lineGap) { String chs = "< " + toString(font.getCapHeight2D(), false); g.drawString(chs, ix + iw + 2, capHeight + 4); } if (advance >= ix && advance < ix + iw) { String aws = toString(glyph.getCharacterWidth2D(), false); g.drawString(aws, advance - fm.stringWidth(aws) / 2, iy - 11); g.drawString("~", advance - 4, iy); g.drawString("^", advance - 4, iy + ih + 7); g.drawString(aws, advance - fm.stringWidth(aws) / 2, iy + ih + 18); } g.setFont(saveFont); } private String toString(double d, boolean signed) { String s = (d == (int)d) ? Integer.toString((int)d) : Double.toString(d); return (d > 0 && signed) ? ("+" + s) : s; } private class MyComponentListener extends ComponentAdapter { public void componentResized(ComponentEvent e) { if (fit) setBestScaleAndTranslate(); } } private class MyMouseListener extends MouseAdapter { private MouseRegion inRegion = MouseRegion.NONE; private int baseX, baseY; private double baseValue; public void mouseWheelMoved(MouseWheelEvent e) { if (e.isControlDown()) { MouseRegion region = getRegion(e); Point2D p = (region == MouseRegion.INTERIOR) ? getInteriorPoint(e) : null; boolean changed = false; for (GlyphComponentListener l : listeners) { if (l.mouseWheelMoved(e, p, glyph, font)) { changed = true; } } if (changed) glyphChanged(); } else if (e.isAltDown()) { if (e.getWheelRotation() < 0) { scale *= 1.5; if (scale <= 0) scale = 1; if (scale >= 1) scale = Math.ceil(scale); repaint(); } if (e.getWheelRotation() > 0) { scale /= 1.5; if (scale <= 0) scale = 1; if (scale >= 1) scale = Math.floor(scale); repaint(); } } else if (e.isShiftDown()) { tx -= e.getWheelRotation(); repaint(); } else { ty -= e.getWheelRotation(); repaint(); } } public void mouseMoved(MouseEvent e) { if (inRegion == MouseRegion.NONE) { MouseRegion region = getRegion(e); Point2D p = (region == MouseRegion.INTERIOR) ? getInteriorPoint(e) : null; switch (region) { case EM_ASCENT: setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); setToolTipText("Em Ascent"); break; case EM_DESCENT: setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); setToolTipText("Em Descent"); break; case X_HEIGHT: setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); setToolTipText("X Height"); break; case LINE_ASCENT: setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); setToolTipText("Line Ascent"); break; case LINE_DESCENT: setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); setToolTipText("Line Descent"); break; case LINE_GAP: setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); setToolTipText("Line Gap"); break; case CAP_HEIGHT: setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); setToolTipText("Cap Height"); break; case ADVANCE_WIDTH: setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); setToolTipText("Advance Width"); break; case NONE: setCursor(null); setToolTipText(null); break; case INTERIOR: Cursor cursor = null; for (GlyphComponentListener l : listeners) { Cursor lc = l.getCursor(e, p, glyph, font); if (lc != null) cursor = lc; } setCursor(cursor); setToolTipText(null); break; } boolean changed = false; for (GlyphComponentListener l : listeners) { if (l.mouseMoved(e, p, glyph, font)) { changed = true; } } if (changed) glyphChanged(); } } public void mousePressed(MouseEvent e) { inRegion = getRegion(e); if (inRegion == MouseRegion.INTERIOR) { Point2D p = getInteriorPoint(e); boolean changed = false; for (GlyphComponentListener l : listeners) { if (l.mousePressed(e, p, glyph, font)) { changed = true; } } if (changed) glyphChanged(); } else if (inRegion != MouseRegion.NONE) { baseX = e.getX(); baseY = e.getY(); switch (inRegion) { case EM_ASCENT: baseValue = font.getEmAscent2D(); break; case EM_DESCENT: baseValue = font.getEmDescent2D(); break; case X_HEIGHT: baseValue = font.getXHeight2D(); break; case LINE_ASCENT: baseValue = font.getLineAscent2D(); break; case LINE_DESCENT: baseValue = font.getLineDescent2D(); break; case LINE_GAP: baseValue = font.getLineGap2D(); break; case CAP_HEIGHT: baseValue = font.getCapHeight2D(); break; case ADVANCE_WIDTH: baseValue = glyph.getCharacterWidth2D(); break; default: break; } } } public void mouseDragged(MouseEvent e) { if (inRegion == MouseRegion.INTERIOR) { Point2D p = getInteriorPoint(e); boolean changed = false; for (GlyphComponentListener l : listeners) { if (l.mouseDragged(e, p, glyph, font)) { changed = true; } } if (changed) glyphChanged(); } else if (inRegion != MouseRegion.NONE) { double valueX = Math.round(baseValue + (e.getX() - baseX) / scale); double valueY = Math.round(baseValue + (e.getY() - baseY) / scale); double valueY2 = Math.round(baseValue - (e.getY() - baseY) / scale); switch (inRegion) { case EM_ASCENT: font.setEmAscent2D((valueY2 > 0) ? valueY2 : 0); break; case EM_DESCENT: font.setEmDescent2D((valueY > 0) ? valueY : 0); break; case X_HEIGHT: font.setXHeight2D((valueY2 > 0) ? valueY2 : 0); break; case LINE_ASCENT: font.setLineAscent2D((valueY2 > 0) ? valueY2 : 0); break; case LINE_DESCENT: font.setLineDescent2D((valueY > 0) ? valueY : 0); break; case LINE_GAP: font.setLineGap2D((valueY > 0) ? valueY : 0); break; case CAP_HEIGHT: font.setCapHeight2D((valueY2 > 0) ? valueY2 : 0); break; case ADVANCE_WIDTH: glyph.setCharacterWidth2D((valueX > 0) ? valueX : 0); break; default: break; } metricsChanged(); } } public void mouseReleased(MouseEvent e) { if (inRegion == MouseRegion.INTERIOR) { Point2D p = getInteriorPoint(e); boolean changed = false; for (GlyphComponentListener l : listeners) { if (l.mouseReleased(e, p, glyph, font)) { changed = true; } } if (changed) glyphChanged(); } else if (inRegion != MouseRegion.NONE) { double valueX = Math.round(baseValue + (e.getX() - baseX) / scale); double valueY = Math.round(baseValue + (e.getY() - baseY) / scale); double valueY2 = Math.round(baseValue - (e.getY() - baseY) / scale); switch (inRegion) { case EM_ASCENT: font.setEmAscent2D((valueY2 > 0) ? valueY2 : 0); break; case EM_DESCENT: font.setEmDescent2D((valueY > 0) ? valueY : 0); break; case X_HEIGHT: font.setXHeight2D((valueY2 > 0) ? valueY2 : 0); break; case LINE_ASCENT: font.setLineAscent2D((valueY2 > 0) ? valueY2 : 0); break; case LINE_DESCENT: font.setLineDescent2D((valueY > 0) ? valueY : 0); break; case LINE_GAP: font.setLineGap2D((valueY > 0) ? valueY : 0); break; case CAP_HEIGHT: font.setCapHeight2D((valueY2 > 0) ? valueY2 : 0); break; case ADVANCE_WIDTH: glyph.setCharacterWidth2D((valueX > 0) ? valueX : 0); break; default: break; } metricsChanged(); } inRegion = MouseRegion.NONE; } private MouseRegion getRegion(MouseEvent e) { if (scale <= 0) setBestScaleAndTranslate(); Insets insets = getInsets(); int x = insets.left; int y = insets.top; int w = getWidth() - insets.left - insets.right; int h = getHeight() - insets.top - insets.bottom; int ix = x + MARGIN_WIDTH; int iy = y + MARGIN_HEIGHT; int iw = w - MARGIN_WIDTH * 2; int ih = h - MARGIN_HEIGHT * 2; if (e.getY() < iy || e.getY() >= iy + ih) { if (e.getX() >= ix && e.getX() < ix + iw) { int advance = ix + (int)Math.round(tx + glyph.getCharacterWidth2D() * scale); if (e.getX() > advance - 10 && e.getX() < advance + 10) { return MouseRegion.ADVANCE_WIDTH; } } } else if (e.getX() < ix) { if (e.getY() >= iy && e.getY() < iy + ih) { int emAscent = iy + (int)Math.round(ty - font.getEmAscent2D() * scale); int emDescent = iy + (int)Math.round(ty + font.getEmDescent2D() * scale); int exHeight = iy + (int)Math.round(ty - font.getXHeight2D() * scale); if (e.getY() > emAscent - 10 && e.getY() < emAscent + 10) { return MouseRegion.EM_ASCENT; } else if (e.getY() > emDescent - 10 && e.getY() < emDescent + 10) { return MouseRegion.EM_DESCENT; } else if (e.getY() > exHeight - 10 && e.getY() < exHeight + 10) { return MouseRegion.X_HEIGHT; } } } else if (e.getX() >= ix + iw) { if (e.getY() >= iy && e.getY() < iy + ih) { int lineAscent = iy + (int)Math.round(ty - font.getLineAscent2D() * scale); int lineDescent = iy + (int)Math.round(ty + font.getLineDescent2D() * scale); int lineGap = iy + (int)Math.round(ty + (font.getLineDescent2D() + font.getLineGap2D()) * scale); int capHeight = iy + (int)Math.round(ty - font.getCapHeight2D() * scale); if (e.getY() > lineAscent - 10 && e.getY() < lineAscent + 10) { return MouseRegion.LINE_ASCENT; } else if (e.getY() > lineDescent - 10 && e.getY() < lineDescent + 10) { return MouseRegion.LINE_DESCENT; } else if (e.getY() > lineGap - 10 && e.getY() < lineGap + 10) { return MouseRegion.LINE_GAP; } else if (e.getY() > capHeight - 10 && e.getY() < capHeight + 10) { return MouseRegion.CAP_HEIGHT; } } } else { return MouseRegion.INTERIOR; } return MouseRegion.NONE; } private Point2D getInteriorPoint(MouseEvent e) { if (scale <= 0) setBestScaleAndTranslate(); Insets insets = getInsets(); int ix = insets.left + MARGIN_WIDTH; int iy = insets.top + MARGIN_HEIGHT; int origin = ix + (int)Math.round(tx); int baseline = iy + (int)Math.round(ty); double px = (e.getX() - origin) / scale; double py = (e.getY() - baseline) / scale; return new Point2D.Double(px, py); } } private static enum MouseRegion { NONE, INTERIOR, EM_ASCENT, EM_DESCENT, X_HEIGHT, LINE_ASCENT, LINE_DESCENT, LINE_GAP, CAP_HEIGHT, ADVANCE_WIDTH; } } GlyphComponentListener.java000066400000000000000000000015641506470510200336310ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.awt.Cursor; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public interface GlyphComponentListener { public Cursor getCursor(MouseEvent e, Point2D p, G glyph, Font font); public boolean mouseMoved(MouseEvent e, Point2D p, G glyph, Font font); public boolean mousePressed(MouseEvent e, Point2D p, G glyph, Font font); public boolean mouseDragged(MouseEvent e, Point2D p, G glyph, Font font); public boolean mouseReleased(MouseEvent e, Point2D p, G glyph, Font font); public boolean mouseWheelMoved(MouseWheelEvent e, Point2D p, G glyph, Font font); public void metricsChanged(G glyph, Font font); public void glyphChanged(G glyph, Font font); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphEditFrame.java000066400000000000000000000054551506470510200321030ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public class GlyphEditFrame extends JFrame { private static final long serialVersionUID = 1L; private final GlyphEditPanel panel; private final GlyphEditMenuBar mb; public GlyphEditFrame(Class glyphClass, Font font, GlyphLocator locator, GlyphList gl, SaveManager sm) { this.panel = new GlyphEditPanel(locator, gl); this.mb = new GlyphEditMenuBar(this, sm, font, panel, glyphClass); setTitle(locator.toString()); setJMenuBar(mb); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); GlyphEditFrame.addActions(this, panel, glyphClass); panel.getGlyphComponent().requestFocusInWindow(); } public static void addActions(final JFrame frame, final GlyphEditPanel panel, final Class glyphClass) { InputMap im = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), "previousGlyph"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), "nextGlyph"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, KeyEvent.SHIFT_MASK), "previousDefinedGlyph"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, KeyEvent.SHIFT_MASK), "nextDefinedGlyph"); ActionMap am = frame.getRootPane().getActionMap(); am.put("previousGlyph", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getPrevious(), glyphClass); frame.setTitle(panel.getGlyphLocator().toString()); } }); am.put("nextGlyph", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getNext(), glyphClass); frame.setTitle(panel.getGlyphLocator().toString()); } }); am.put("previousDefinedGlyph", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getPreviousDefined(), null); frame.setTitle(panel.getGlyphLocator().toString()); } }); am.put("nextDefinedGlyph", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getNextDefined(), null); frame.setTitle(panel.getGlyphLocator().toString()); } }); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphEditMenuBar.java000066400000000000000000000154121506470510200323740ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public class GlyphEditMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public GlyphEditMenuBar( final Frame frame, final SaveManager sm, final Font font, final GlyphEditPanel panel, final Class glyphClass ) { add(new FileMenu(frame, sm, font)); add(new ViewMenu(frame, panel, glyphClass)); } public static final class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Frame frame, final SaveManager sm, final Font font) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(frame)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); addSeparator(); add(new CommonMenuItems.FontInfoMenuItem(font, sm)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static final class ViewMenu extends JMenu { private static final long serialVersionUID = 1L; public ViewMenu(final Frame frame, final GlyphEditPanel panel, final Class glyphClass) { super("View"); GlyphComponent gc = panel.getGlyphComponent(); FitToEmMenuItem fitToEm = new FitToEmMenuItem(gc); add(fitToEm); add(new ZoomOutMenuItem(gc, fitToEm)); add(new ZoomInMenuItem(gc, fitToEm)); addSeparator(); add(new ShowBoundingBoxMenuItem(gc)); addSeparator(); add(new PreviousGlyphMenuItem(frame, panel, glyphClass)); add(new NextGlyphMenuItem(frame, panel, glyphClass)); add(new PreviousDefinedGlyphMenuItem(frame, panel)); add(new NextDefinedGlyphMenuItem(frame, panel)); } } public static final class FitToEmMenuItem extends JCheckBoxMenuItem { private static final long serialVersionUID = 1L; public FitToEmMenuItem(final GlyphComponent gc) { super("Fit to Em"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, CommonMenuItems.SHORTCUT_KEY)); setSelected(gc.getFit()); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gc.setFit(true); setSelected(true); } }); } } public static final class ZoomInMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ZoomInMenuItem(final GlyphComponent gc, final FitToEmMenuItem fitToEm) { super("Zoom In"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gc.setFit(false); fitToEm.setSelected(false); double scale = gc.getScale() * 1.5; if (scale <= 0) scale = 1; if (scale >= 1) scale = Math.ceil(scale); gc.setScale(scale); } }); } } public static final class ZoomOutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ZoomOutMenuItem(final GlyphComponent gc, final FitToEmMenuItem fitToEm) { super("Zoom Out"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gc.setFit(false); fitToEm.setSelected(false); double scale = gc.getScale() / 1.5; if (scale <= 0) scale = 1; if (scale >= 1) scale = Math.floor(scale); gc.setScale(scale); } }); } } public static final class ShowBoundingBoxMenuItem extends JCheckBoxMenuItem { private static final long serialVersionUID = 1L; public ShowBoundingBoxMenuItem(final GlyphComponent gc) { super("Show Bounding Box"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, CommonMenuItems.SHORTCUT_KEY)); setSelected(gc.getShowGlyphBounds()); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gc.setShowGlyphBounds(isSelected()); } }); } } public static final class PreviousGlyphMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PreviousGlyphMenuItem(final Frame frame, final GlyphEditPanel panel, final Class glyphClass) { super("Previous Glyph"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getPrevious(), glyphClass); frame.setTitle(panel.getGlyphLocator().toString()); } }); } } public static final class NextGlyphMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NextGlyphMenuItem(final Frame frame, final GlyphEditPanel panel, final Class glyphClass) { super("Next Glyph"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getNext(), glyphClass); frame.setTitle(panel.getGlyphLocator().toString()); } }); } } public static final class PreviousDefinedGlyphMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PreviousDefinedGlyphMenuItem(final Frame frame, final GlyphEditPanel panel) { super("Previous Defined Glyph"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getPreviousDefined(), null); frame.setTitle(panel.getGlyphLocator().toString()); } }); } } public static final class NextDefinedGlyphMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NextDefinedGlyphMenuItem(final Frame frame, final GlyphEditPanel panel) { super("Next Defined Glyph"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.setGlyph(panel.getGlyphLocator().getNextDefined(), null); frame.setTitle(panel.getGlyphLocator().toString()); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphEditPanel.java000066400000000000000000000050021506470510200320740ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public class GlyphEditPanel extends JPanel { private static final long serialVersionUID = 1L; private final GlyphComponent glyphComponent; private final GlyphList glyphList; private GlyphLocator locator; public GlyphEditPanel(GlyphLocator locator, GlyphList gl) { this.glyphComponent = new GlyphComponent(locator.getGlyphFont(), locator.getGlyph()); this.glyphList = gl; this.locator = locator; setLayout(new BorderLayout()); add(glyphComponent, BorderLayout.CENTER); glyphComponent.addGlyphComponentListener(new GlyphComponentListener() { public void metricsChanged(G glyph, Font font) { if (glyphList != null) glyphList.metricsChanged(); } public void glyphChanged(G glyph, Font font) { if (glyphList != null) glyphList.glyphContentChanged(); } public Cursor getCursor(MouseEvent e, Point2D p, G glyph, Font font) { return null; } public boolean mouseMoved(MouseEvent e, Point2D p, G glyph, Font font) { return false; } public boolean mousePressed(MouseEvent e, Point2D p, G glyph, Font font) { return false; } public boolean mouseDragged(MouseEvent e, Point2D p, G glyph, Font font) { return false; } public boolean mouseReleased(MouseEvent e, Point2D p, G glyph, Font font) { return false; } public boolean mouseWheelMoved(MouseWheelEvent e, Point2D p, G glyph, Font font) { return false; } }); } public GlyphComponent getGlyphComponent() { return glyphComponent; } public Font getGlyphFont() { return glyphComponent.getGlyphFont(); } public G getGlyph() { return glyphComponent.getGlyph(); } public GlyphList getGlyphList() { return glyphList; } public GlyphLocator getGlyphLocator() { return locator; } public void setGlyph(GlyphLocator locator, Class glyphClass) { if (locator == null) return; Font font = locator.getGlyphFont(); G glyph = locator.getGlyph(); if (glyph == null) { if (glyphClass == null) return; try { glyph = glyphClass.newInstance(); locator.setGlyph(glyph); this.glyphList.glyphRepertoireChanged(); } catch (Exception ex) { return; } } this.glyphComponent.setGlyph(font, glyph); this.locator = locator; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphGenerator.java000066400000000000000000000006701506470510200321630ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.util.List; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public abstract class GlyphGenerator { public static enum Result { NO_CHANGE, CONTENT_CHANGED, REPERTOIRE_CHANGED } public abstract String getName(); public abstract Class getGlyphClass(); public abstract Result generate(Font font, List> locators); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphList.java000066400000000000000000000554441506470510200311610ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.SystemColor; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.InputEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.SortedSet; import javax.swing.JComponent; import javax.swing.Scrollable; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; import com.kreative.unicode.data.Block; import com.kreative.unicode.data.NameResolver; import com.kreative.unicode.fontmap.FontMapController; import com.kreative.unicode.fontmap.FontMapEntry; public class GlyphList extends JComponent implements Scrollable { private static final long serialVersionUID = 1L; private static final int LABEL_HEIGHT = 18; private static final Color SUBTABLE_BG = new Color(0xFFAA00); private static final Color SUBTABLE_SELBG = new Color(0xCC7700); private final FontMapController fontMap; private final Font font; private int cellSize; private int columnCount; private int rowCount; private boolean antiAlias; private boolean bufferedLabels; private boolean bufferedGlyphs; private Dimension preferredSize; private GlyphListModel model; private final GlyphListSelection selection; private final List> listeners; public GlyphList(Font font) { this.fontMap = FontMapController.getInstance(); this.font = font; this.cellSize = 36; this.columnCount = 16; this.rowCount = 8; this.antiAlias = CommonMenuItems.IS_MAC_OS; this.bufferedLabels = false; this.bufferedGlyphs = false; this.preferredSize = null; this.model = new GlyphListCodePointModel(new Block(0, 127, "Basic Latin")); this.selection = new GlyphListSelection(); this.listeners = new ArrayList>(); MyMouseListener ml = new MyMouseListener(); this.addMouseListener(ml); this.addMouseMotionListener(ml); MyKeyListener kl = new MyKeyListener(); this.addKeyListener(kl); this.setFocusable(true); MyComponentListener cl = new MyComponentListener(); this.addComponentListener(cl); } public Font getGlyphFont() { return this.font; } public int getCellSize() { return this.cellSize; } public void setCellSize(int cellSize) { if (this.cellSize != cellSize && cellSize >= 8) { this.cellSize = cellSize; this.revalidate(); this.repaint(); } } public int getColumnCount() { return this.columnCount; } public void setColumnCount(int columnCount) { if (this.columnCount != columnCount && columnCount > 0) { this.columnCount = columnCount; this.revalidate(); this.repaint(); } } public void setBestColumnCount() { Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right; int cc = w / cellSize; if (cc > 8) cc &=~ 7; if (this.columnCount != cc && cc > 0) { this.columnCount = cc; this.revalidate(); this.repaint(); } } public int getRowCount() { return this.rowCount; } public void setRowCount(int rowCount) { if (this.rowCount != rowCount && rowCount > 0) { this.rowCount = rowCount; this.revalidate(); this.repaint(); } } public boolean getAntiAlias() { return this.antiAlias; } public void setAntiAlias(boolean antiAlias) { this.antiAlias = antiAlias; this.repaint(); } public boolean getBufferedLabels() { return this.bufferedLabels; } public void setBufferedLabels(boolean bufferedLabels) { this.bufferedLabels = bufferedLabels; this.repaint(); } public boolean getBufferedGlyphs() { return this.bufferedGlyphs; } public void setBufferedGlyphs(boolean bufferedGlyphs) { this.bufferedGlyphs = bufferedGlyphs; this.repaint(); } public GlyphListModel getModel() { return this.model; } public void setModel(GlyphListModel model) { if (this.model != model && model != null) { this.model = model; this.model.tracksFont(); this.selection.clear(); for (GlyphListListener l : listeners) l.selectionChanged(this, font); this.revalidate(); this.repaint(); } } public void clearSelection() { selection.clear(); for (GlyphListListener l : listeners) l.selectionChanged(this, font); repaint(); } public void selectAll() { selection.clear(); selection.add(0, model.getCellCount() - 1); for (GlyphListListener l : listeners) l.selectionChanged(this, font); repaint(); } public SortedSet getSelectedIndices() { return selection.toSet(); } public void setSelectedIndices(Collection indices, boolean shouldScroll) { selection.clear(); int n = model.getCellCount(); for (Integer i : indices) { if (i != null && i >= 0 && i < n) { selection.add(i); } } if (shouldScroll) { Rectangle r = getSelectionRect(); if (r != null) scrollRectToVisible(r); } for (GlyphListListener l : listeners) l.selectionChanged(this, font); repaint(); } public List> getSelection() { List> locators = new ArrayList>(); for (int i : selection.toSet()) { GlyphLocator loc = new GlyphLocator(font, model, i); if (loc.isValid()) locators.add(loc); } return locators; } public void openSelection() { if (selection.isEmpty()) return; for (GlyphListListener l : listeners) l.selectionOpened(this, font); } public void deleteSelection() { if (selection.isEmpty()) return; for (GlyphLocator loc : getSelection()) loc.removeGlyph(); glyphRepertoireChanged(); } public Dimension getPreferredSize() { if (preferredSize != null) { return preferredSize; } else { int rows = (model.getCellCount() + columnCount - 1) / columnCount; int w = cellSize * columnCount + 1; int h = (cellSize + LABEL_HEIGHT) * rows + 1; Insets i = getInsets(); return new Dimension(w + i.left + i.right, h + i.top + i.bottom); } } public void setPreferredSize(Dimension d) { this.preferredSize = d; } public void addGlyphListListener(GlyphListListener l) { this.listeners.add(l); } public void removeGlyphListListener(GlyphListListener l) { this.listeners.remove(l); } public void metricsChanged() { for (GlyphListListener l : listeners) l.metricsChanged(this, font); repaint(); } public void glyphContentChanged() { for (GlyphListListener l : listeners) l.glyphsChanged(this, font); repaint(); } public void glyphRepertoireChanged() { if (model.tracksFont()) selection.clear(); for (GlyphListListener l : listeners) l.glyphsChanged(this, font); revalidate(); repaint(); } protected void paintComponent(Graphics g) { SortedSet sel = selection.toSet(); Rectangle vr = getVisibleRect(); Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right - 1; int bufw = (w / columnCount) + 1; BufferedImage lbuf = bufferedLabels ? new BufferedImage(bufw, LABEL_HEIGHT, BufferedImage.TYPE_INT_ARGB) : null; BufferedImage gbuf = bufferedGlyphs ? new BufferedImage(bufw, cellSize, BufferedImage.TYPE_INT_ARGB) : null; double fa = font.getEmAscent2D(); double fh = fa + font.getEmDescent2D(); double scale = (fh <= 0) ? ((cellSize - 3) / 10.0) : ((cellSize - 3) / fh); if (scale <= 0) scale = 1; if (scale >= 1) scale = Math.floor(scale); double ascent = Math.round(((cellSize - 3) - fh * scale) / 2 + fa * scale + 1); java.awt.Font markerFont = new java.awt.Font("Monospaced", 0, cellSize / 2); for (int i = 0, n = model.getCellCount(); i < n; i++) { int x1 = insets.left + w * (i % columnCount) / columnCount; int x2 = insets.left + w * ((i % columnCount) + 1) / columnCount; int y = insets.top + (cellSize + LABEL_HEIGHT) * (i / columnCount); if (vr.intersects(x1, y, x2 - x1 + 1, cellSize + LABEL_HEIGHT + 1)) { // Get glyph. If this index is undefined, skip this cell. String label; FontGlyph glyph; java.awt.Font labelFont; boolean labelAntiAlias; if (model.isCodePoint(i)) { int cp = model.getCodePoint(i); glyph = font.getCharacter(cp); label = getCharacterLabel(cp); if (label.length() < 4) { FontMapEntry e = fontMap.entryForCodePoint(cp); labelFont = (e != null) ? e.getFont() : g.getFont(); labelAntiAlias = antiAlias; } else { labelFont = (Resources.HEX_FONT != null) ? Resources.HEX_FONT : g.getFont(); labelAntiAlias = (Resources.HEX_FONT != null) ? false : antiAlias; } } else if (model.isGlyphName(i)) { label = model.getGlyphName(i); glyph = font.getNamedGlyph(label); labelFont = (Resources.PSNAME_FONT != null) ? Resources.PSNAME_FONT : g.getFont(); labelAntiAlias = (Resources.PSNAME_FONT != null) ? false : antiAlias; } else { Integer marker = model.getCodePoint(i); if (marker != null) { Color selbg, bg, fg; String ms; switch (marker.intValue()) { case GlyphListModelList.SEQUENCE_MARKER: selbg = Color.gray; bg = Color.lightGray; fg = Color.black; label = "Sequence"; ms = Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); break; case GlyphListModelList.SUBTABLE_MARKER: selbg = SUBTABLE_SELBG; bg = SUBTABLE_BG; fg = Color.black; label = "Subtable"; ms = Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); break; case GlyphListModelList.UNDEFINED_MARKER: selbg = Color.black; bg = Color.darkGray; fg = Color.white; label = "Undefined"; ms = Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); break; default: int ch0 = (marker.intValue() >>> 16); int ch1 = (marker.intValue() & 0xFFFF); if (ch0 < 0x20 || ch0 > 0xFFFD || ch1 < 0x20 || ch1 > 0xFFFD) continue; String cs0 = Integer.toHexString(0xFF0000 | ch0).substring(2).toUpperCase(); String cs1 = Integer.toHexString(0xFF0000 | ch1).substring(2).toUpperCase(); selbg = Color.gray; bg = Color.lightGray; fg = Color.black; label = cs0 + "." + cs1; ms = String.valueOf(new char[]{(char)ch0, (char)ch1}); break; } labelFont = (Resources.PSNAME_FONT != null) ? Resources.PSNAME_FONT : g.getFont(); labelAntiAlias = (Resources.PSNAME_FONT != null) ? false : antiAlias; paintCellBackground(g, bg, x1, x2, y); paintCellLabel(g, bg, fg, label, labelFont, labelAntiAlias, x1, x2, y, lbuf); paintCellMarker(g, (sel.contains(i) ? selbg : bg), fg, ms, markerFont, antiAlias, x1, x2, y, gbuf); } continue; } paintCellBackground(g, Color.gray, x1, x2, y); paintCellLabel(g, SystemColor.text, SystemColor.textText, label, labelFont, labelAntiAlias, x1, x2, y, lbuf); paintCellGlyph(g, glyph, sel.contains(i), x1, x2, y, gbuf, ascent, scale); } } } private void paintCellBackground(Graphics g, Color c, int x1, int x2, int y) { g.setColor(Color.black); g.fillRect(x1, y, x2 - x1 + 1, cellSize + LABEL_HEIGHT + 1); g.setColor(c); g.fillRect(x1 + 1, y + 1, x2 - x1 - 1, cellSize + LABEL_HEIGHT - 1); } private void paintCellLabel( Graphics g, Color bg, Color fg, String label, java.awt.Font labelFont, boolean labelAntiAlias, int x1, int x2, int y, BufferedImage lbuf ) { if (lbuf != null) { Graphics2D lg = lbuf.createGraphics(); lg.setColor(bg); lg.fillRect(0, 0, lbuf.getWidth(), lbuf.getHeight()); lg.setColor(fg); lg.setFont(labelFont); lg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); lg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); FontMetrics fm = lg.getFontMetrics(); int sw = fm.stringWidth(label); if (labelFont == Resources.PSNAME_FONT) sw--; int lx = ((x2 - x1 - 1) - sw) / 2; int ly = (LABEL_HEIGHT - fm.getHeight()) / 2 + fm.getAscent(); lg.drawString(label, lx, ly); lg.dispose(); g.drawImage( lbuf, x1 + 1, y + 1, x2, y + LABEL_HEIGHT, 0, 0, x2 - x1 - 1, LABEL_HEIGHT - 1, null ); } else { java.awt.Font oldFont = g.getFont(); java.awt.Shape oldClip = g.getClip(); g.setColor(bg); g.fillRect(x1 + 1, y + 1, x2 - x1 - 1, LABEL_HEIGHT - 1); g.clipRect(x1 + 1, y + 1, x2 - x1 - 1, LABEL_HEIGHT - 1); g.setColor(fg); g.setFont(labelFont); if (g instanceof Graphics2D) { ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } FontMetrics fm = g.getFontMetrics(); int sw = fm.stringWidth(label); if (labelFont == Resources.PSNAME_FONT) sw--; int lx = ((x2 - x1 - 1) - sw) / 2; int ly = (LABEL_HEIGHT - fm.getHeight()) / 2 + fm.getAscent(); g.drawString(label, x1 + 1 + lx, y + 1 + ly); g.setFont(oldFont); g.setClip(oldClip); } } private void paintCellGlyph( Graphics g, FontGlyph glyph, boolean sel, int x1, int x2, int y, BufferedImage gbuf, double ascent, double scale ) { if (glyph == null) { g.setColor(sel ? SystemColor.textHighlight : SystemColor.text); g.fillRect(x1 + 1, y + LABEL_HEIGHT + 1, x2 - x1 - 1, cellSize - 1); g.setColor(Color.gray); g.drawLine(x1 + 1, y + LABEL_HEIGHT + 1, x2 - 1, y + cellSize + LABEL_HEIGHT - 1); g.drawLine(x2 - 1, y + LABEL_HEIGHT + 1, x1 + 1, y + cellSize + LABEL_HEIGHT - 1); } else if (gbuf != null) { Graphics2D gg = gbuf.createGraphics(); gg.setColor(sel ? SystemColor.textHighlight : SystemColor.text); gg.fillRect(0, 0, gbuf.getWidth(), gbuf.getHeight()); gg.setColor(sel ? SystemColor.textHighlightText : SystemColor.textText); double gx = Math.round(((x2 - x1 - 2) - glyph.getCharacterWidth2D() * scale) / 2); glyph.paint(gg, gx, ascent, scale); gg.dispose(); g.drawImage( gbuf, x1 + 1, y + LABEL_HEIGHT + 1, x2, y + LABEL_HEIGHT + cellSize, 0, 0, x2 - x1 - 1, cellSize - 1, null ); } else { java.awt.Shape oldClip = g.getClip(); g.setColor(sel ? SystemColor.textHighlight : SystemColor.text); g.fillRect(x1 + 1, y + LABEL_HEIGHT + 1, x2 - x1 - 1, cellSize - 1); g.clipRect(x1 + 1, y + LABEL_HEIGHT + 1, x2 - x1 - 1, cellSize - 1); g.setColor(sel ? SystemColor.textHighlightText : SystemColor.textText); double gx = Math.round(((x2 - x1 - 2) - glyph.getCharacterWidth2D() * scale) / 2); glyph.paint(g, x1 + 1 + gx, y + LABEL_HEIGHT + 1 + ascent, scale); g.setClip(oldClip); } } private void paintCellMarker( Graphics g, Color bg, Color fg, String label, java.awt.Font labelFont, boolean labelAntiAlias, int x1, int x2, int y, BufferedImage gbuf ) { if (gbuf != null) { Graphics2D gg = gbuf.createGraphics(); gg.setColor(bg); gg.fillRect(0, 0, gbuf.getWidth(), gbuf.getHeight()); gg.setColor(fg); gg.setFont(labelFont); gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); gg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); FontMetrics fm = gg.getFontMetrics(); int gx = ((x2 - x1 - 1) - fm.stringWidth(label)) / 2; int gy = ((cellSize - 3) - fm.getHeight()) / 2 + fm.getAscent(); gg.drawString(label, gx, gy); g.drawImage( gbuf, x1 + 1, y + LABEL_HEIGHT + 1, x2, y + LABEL_HEIGHT + cellSize, 0, 0, x2 - x1 - 1, cellSize - 1, null ); } else { java.awt.Font oldFont = g.getFont(); java.awt.Shape oldClip = g.getClip(); g.setColor(bg); g.fillRect(x1 + 1, y + LABEL_HEIGHT + 1, x2 - x1 - 1, cellSize - 1); g.clipRect(x1 + 1, y + LABEL_HEIGHT + 1, x2 - x1 - 1, cellSize - 1); g.setColor(fg); g.setFont(labelFont); if (g instanceof Graphics2D) { ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, labelAntiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } FontMetrics fm = g.getFontMetrics(); int gx = ((x2 - x1 - 1) - fm.stringWidth(label)) / 2; int gy = ((cellSize - 3) - fm.getHeight()) / 2 + fm.getAscent(); g.drawString(label, x1 + 1 + gx, y + LABEL_HEIGHT + 1 + gy); g.setFont(oldFont); g.setClip(oldClip); } } public Dimension getPreferredScrollableViewportSize() { if (preferredSize != null) { return preferredSize; } else { int w = cellSize * columnCount + 1; int h = (cellSize + LABEL_HEIGHT) * rowCount + 1; Insets i = getInsets(); return new Dimension(w + i.left + i.right, h + i.top + i.bottom); } } public boolean getScrollableTracksViewportWidth() { return true; } public boolean getScrollableTracksViewportHeight() { return false; } public int getScrollableUnitIncrement(Rectangle vr, int or, int dir) { return cellSize + LABEL_HEIGHT; } public int getScrollableBlockIncrement(Rectangle vr, int or, int dir) { return (vr.height / (cellSize + LABEL_HEIGHT)) * (cellSize + LABEL_HEIGHT); } private String getCharacterLabel(int cp) { String c = NameResolver.instance(cp).getCategory(cp); if ("Zs Zl Zp Cc Cf Cs Cn".contains(c)) { String h = Integer.toHexString(cp).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } else { return String.valueOf(Character.toChars(cp)); } } private Rectangle getSelectionRect() { SortedSet sel = selection.toSet(); if (sel.isEmpty()) return null; Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right - 1; int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE; for (int i : sel) { int x1 = insets.left + w * (i % columnCount) / columnCount; int x2 = insets.left + w * ((i % columnCount) + 1) / columnCount; int y1 = insets.top + (cellSize + LABEL_HEIGHT) * (i / columnCount); int y2 = y1 + cellSize + LABEL_HEIGHT; if (x1 < minX) minX = x1; if (y1 < minY) minY = y1; if (x2 > maxX) maxX = x2; if (y2 > maxY) maxY = y2; } return new Rectangle(minX, minY, maxX-minX+1, maxY-minY+1); } private Rectangle getLastSelectionRect() { int i = selection.getLast(); if (i < 0) return null; Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right - 1; int x1 = insets.left + w * (i % columnCount) / columnCount; int x2 = insets.left + w * ((i % columnCount) + 1) / columnCount; int y1 = insets.top + (cellSize + LABEL_HEIGHT) * (i / columnCount); int y2 = y1 + cellSize + LABEL_HEIGHT; return new Rectangle(x1, y1, x2-x1+1, y2-y1+1); } private void startSelection(InputEvent e, int i) { if (e.isShiftDown()) { selection.extend(i); } else if (e.isControlDown() || e.isMetaDown()) { selection.add(i); } else { selection.clear(); selection.add(i); } Rectangle r = getLastSelectionRect(); if (r != null) scrollRectToVisible(r); for (GlyphListListener l : listeners) l.selectionChanged(GlyphList.this, font); repaint(); } private void continueSelection(InputEvent e, int i) { selection.extend(i); Rectangle r = getLastSelectionRect(); if (r != null) scrollRectToVisible(r); for (GlyphListListener l : listeners) l.selectionChanged(GlyphList.this, font); repaint(); } private class MyMouseListener extends MouseAdapter { public void mousePressed(MouseEvent e) { requestFocusInWindow(); int i = getClickedIndex(e); startSelection(e, i); } public void mouseDragged(MouseEvent e) { int i = getClickedIndex(e); continueSelection(e, i); } public void mouseReleased(MouseEvent e) { int i = getClickedIndex(e); continueSelection(e, i); } public void mouseClicked(MouseEvent e) { if (e.getClickCount() > 1) openSelection(); } private int getClickedIndex(MouseEvent e) { Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right; int x = (e.getX() - insets.left) * columnCount / w; if (x < 0) x = 0; if (x >= columnCount) x = columnCount - 1; int y = (e.getY() - insets.top) / (cellSize + LABEL_HEIGHT); int i = y * columnCount + x; if (i < 0) i = 0; if (i >= model.getCellCount()) i = model.getCellCount() - 1; return i; } } private class MyKeyListener extends KeyAdapter { public void keyPressed(KeyEvent e) { if ((e.isMetaDown() || e.isControlDown()) && e.isShiftDown()) return; switch (e.getKeyCode()) { case KeyEvent.VK_ESCAPE: case KeyEvent.VK_CLEAR: clearSelection(); break; case KeyEvent.VK_LEFT: if (!selection.isEmpty()) { int i = selection.getLast() - 1; if (i < 0) i = 0; if (i >= model.getCellCount()) i = model.getCellCount() - 1; startSelection(e, i); } break; case KeyEvent.VK_RIGHT: if (!selection.isEmpty()) { int i = selection.getLast() + 1; if (i < 0) i = 0; if (i >= model.getCellCount()) i = model.getCellCount() - 1; startSelection(e, i); } break; case KeyEvent.VK_UP: if (!selection.isEmpty()) { int i = selection.getLast() - columnCount; if (i < 0) i = 0; if (i >= model.getCellCount()) i = model.getCellCount() - 1; startSelection(e, i); } break; case KeyEvent.VK_DOWN: if (!selection.isEmpty()) { int i = selection.getLast() + columnCount; if (i < 0) i = 0; if (i >= model.getCellCount()) i = model.getCellCount() - 1; startSelection(e, i); } break; case KeyEvent.VK_HOME: startSelection(e, 0); break; case KeyEvent.VK_END: startSelection(e, model.getCellCount() - 1); break; case KeyEvent.VK_ENTER: openSelection(); break; case KeyEvent.VK_DELETE: deleteSelection(); break; case KeyEvent.VK_INSERT: setAntiAlias(!antiAlias); break; } } public void keyTyped(KeyEvent e) { if (e.isMetaDown() || e.isControlDown()) return; int cp = e.getKeyChar(); if ((cp >= 32 && cp < 127) || cp >= 160) { int i = model.indexOfCodePoint(cp); if (i >= 0) { selection.clear(); selection.add(i); Rectangle r = getLastSelectionRect(); if (r != null) scrollRectToVisible(r); for (GlyphListListener l : listeners) l.selectionChanged(GlyphList.this, font); repaint(); } } } } private class MyComponentListener extends ComponentAdapter { public void componentResized(ComponentEvent e) { setBestColumnCount(); } } } GlyphListCodePointModel.java000066400000000000000000000051341506470510200336570ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.util.List; import com.kreative.unicode.data.Block; public class GlyphListCodePointModel implements GlyphListModel { private final List codePoints; private final String name; private final String url; private final String iconGroup; public GlyphListCodePointModel(List codePoints, String name, String url, String iconGroup) { this.codePoints = codePoints; this.name = name; this.url = url; this.iconGroup = iconGroup; } public GlyphListCodePointModel(Block block) { this.codePoints = block; this.name = block.name; if (isPUABlock(block)) { this.url = null; this.iconGroup = "pua"; } else { String h = Integer.toHexString(block.firstCodePoint).toUpperCase(); while (h.length() < 4) h = "0" + h; this.url = "http://www.unicode.org/charts/PDF/U" + h + ".pdf"; this.iconGroup = "unicode"; } } private static boolean isPUABlock(Block block) { if (block.firstCodePoint >= 0xE000 && block.lastCodePoint <= 0xF8FF) { return (block.firstCodePoint != 0xE000 || block.lastCodePoint != 0xF8FF); } if (block.firstCodePoint >= 0xF0000 && block.lastCodePoint <= 0xFFFFF) { return (block.firstCodePoint != 0xF0000 || block.lastCodePoint != 0xFFFFF); } if (block.firstCodePoint >= 0x100000 && block.lastCodePoint <= 0x10FFFF) { return (block.firstCodePoint != 0x100000 || block.lastCodePoint != 0x10FFFF); } return false; } @Override public boolean isCodePoint(int index) { Integer cp = codePoints.get(index); return cp != null && Character.isValidCodePoint(cp); } @Override public Integer getCodePoint(int index) { return codePoints.get(index); } @Override public int indexOfCodePoint(Integer codePoint) { return codePoints.indexOf(codePoint); } @Override public boolean tracksFont() { return false; } @Override public int getCellCount() { return codePoints.size(); } @Override public boolean isGlyphName(int index) { return false; } @Override public String getGlyphName(int index) { return null; } @Override public int indexOfGlyphName(String name) { return -1; } @Override public String toString() { return name; } @Override public String getURL() { return url; } @Override public String getIconGroup() { return iconGroup; } @Override public boolean equals(Object o) { if (o instanceof GlyphListCodePointModel) { GlyphListCodePointModel that = (GlyphListCodePointModel)o; return this.codePoints.equals(that.codePoints) && this.name.equals(that.name); } return false; } @Override public int hashCode() { return this.codePoints.hashCode() ^ this.name.hashCode(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListDataPanel.java000066400000000000000000000034251506470510200327230ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; import com.kreative.unicode.data.NameResolver; public class GlyphListDataPanel extends JPanel implements GlyphListListener { private static final long serialVersionUID = 1L; private static final String T = " "; private final JLabel label; public GlyphListDataPanel(GlyphList gl) { this.label = new JLabel(" "); this.label.setFont(this.label.getFont().deriveFont(10f)); this.label.setBorder(BorderFactory.createEmptyBorder(2, 6, 2, 6)); setLayout(new BorderLayout()); add(this.label, BorderLayout.LINE_START); if (gl != null) gl.addGlyphListListener(this); } public void selectionChanged(GlyphList gl, Font font) { List> locators = gl.getSelection(); if (locators.isEmpty()) { label.setText(" "); } else if (locators.size() > 1) { label.setText(locators.size() + " glyphs selected"); } else if (locators.get(0).isCodePoint()) { int cp = locators.get(0).getCodePoint(); String h = Integer.toHexString(cp).toUpperCase(); while (h.length() < 4) h = "0" + h; NameResolver r = NameResolver.instance(cp); String c = r.getCategory(cp), n = r.getName(cp); label.setText("U+" + h + T + "#" + cp + T + c + T + n); } else if (locators.get(0).isGlyphName()) { label.setText(locators.get(0).getGlyphName()); } else { label.setText("1 glyph selected"); } } public void selectionOpened(GlyphList gl, Font font) {} public void metricsChanged(GlyphList gl, Font font) {} public void glyphsChanged(GlyphList gl, Font font) {} } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListFontModel.java000066400000000000000000000051211506470510200327540ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.Font; public class GlyphListFontModel implements GlyphListModel { private final Font font; private final boolean codePoints; private final boolean glyphNames; private final List ids; private final String name; public GlyphListFontModel(Font font, boolean codePoints, boolean glyphNames, String name) { this.font = font; this.codePoints = codePoints; this.glyphNames = glyphNames; this.ids = new ArrayList(); if (codePoints) { ids.addAll(font.characters(false).keySet()); } if (glyphNames) { int split = ids.size(); ids.addAll(font.namedGlyphs(false).keySet()); ids.remove(".notdef"); ids.add(split, ".notdef"); } this.name = name; } @Override public boolean tracksFont() { ids.clear(); if (codePoints) { ids.addAll(font.characters(false).keySet()); } if (glyphNames) { int split = ids.size(); ids.addAll(font.namedGlyphs(false).keySet()); ids.remove(".notdef"); ids.add(split, ".notdef"); } return true; } @Override public int getCellCount() { return ids.size(); } @Override public boolean isCodePoint(int index) { Object id = ids.get(index); if (!(id instanceof Integer)) return false; return Character.isValidCodePoint((Integer)id); } @Override public Integer getCodePoint(int index) { Object id = ids.get(index); if (!(id instanceof Integer)) return null; return (Integer)id; } @Override public int indexOfCodePoint(Integer codePoint) { return ids.indexOf(codePoint); } @Override public boolean isGlyphName(int index) { Object id = ids.get(index); if (!(id instanceof String)) return false; return ((String)id).length() > 0; } @Override public String getGlyphName(int index) { Object id = ids.get(index); if (!(id instanceof String)) return null; return (String)id; } @Override public int indexOfGlyphName(String name) { return ids.indexOf(name); } @Override public String toString() { return name; } @Override public String getURL() { return null; } @Override public String getIconGroup() { return "font"; } @Override public boolean equals(Object o) { if (o instanceof GlyphListFontModel) { GlyphListFontModel that = (GlyphListFontModel)o; return ( this.font == that.font && this.codePoints == that.codePoints && this.glyphNames == that.glyphNames && this.name.equals(that.name) ); } return false; } @Override public int hashCode() { return this.font.hashCode() ^ this.name.hashCode(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListFrame.java000066400000000000000000000024631506470510200321250ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.io.File; import javax.swing.JFrame; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontExporter; import com.kreative.bitsnpicas.FontGlyph; public class GlyphListFrame extends JFrame { private static final long serialVersionUID = 1L; private final SaveManager sm; private final GlyphListPanel panel; private final GlyphListMenuBar mb; public GlyphListFrame(File fontFile, FontExporter> format, Font font) { super(font.toString()); this.sm = new SaveManager(this, fontFile, format, font); this.panel = new GlyphListPanel(font, sm); this.mb = new GlyphListMenuBar(this, sm, font, panel.getGlyphList()); makeUI(); } public GlyphListFrame(SaveRoutine routine, Font font) { super(font.toString()); this.sm = new SaveManager(this, routine, font); this.panel = new GlyphListPanel(font, sm); this.mb = new GlyphListMenuBar(this, sm, font, panel.getGlyphList()); makeUI(); } public GlyphListPanel getPanel() { return panel; } private void makeUI() { setJMenuBar(mb); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(sm); panel.getGlyphList().requestFocusInWindow(); } } GlyphListGlyphNameModel.java000066400000000000000000000031531506470510200336560ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.util.List; public class GlyphListGlyphNameModel implements GlyphListModel { private final List glyphNames; private final String name; private final String url; private final String iconGroup; public GlyphListGlyphNameModel(List glyphNames, String name, String url, String iconGroup) { this.glyphNames = glyphNames; this.name = name; this.url = url; this.iconGroup = iconGroup; } @Override public boolean isGlyphName(int index) { String gn = glyphNames.get(index); return gn != null && gn.length() > 0; } @Override public String getGlyphName(int index) { return glyphNames.get(index); } @Override public int indexOfGlyphName(String name) { return glyphNames.indexOf(name); } @Override public boolean tracksFont() { return false; } @Override public int getCellCount() { return glyphNames.size(); } @Override public boolean isCodePoint(int index) { return false; } @Override public Integer getCodePoint(int index) { return null; } @Override public int indexOfCodePoint(Integer codePoint) { return -1; } @Override public String toString() { return name; } @Override public String getURL() { return url; } @Override public String getIconGroup() { return iconGroup; } @Override public boolean equals(Object o) { if (o instanceof GlyphListGlyphNameModel) { GlyphListGlyphNameModel that = (GlyphListGlyphNameModel)o; return this.glyphNames.equals(that.glyphNames) && this.name.equals(that.name); } return false; } @Override public int hashCode() { return this.glyphNames.hashCode() ^ this.name.hashCode(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListListener.java000066400000000000000000000006451506470510200326600ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public interface GlyphListListener { public void selectionChanged(GlyphList gl, Font font); public void selectionOpened(GlyphList gl, Font font); public void metricsChanged(GlyphList gl, Font font); public void glyphsChanged(GlyphList gl, Font font); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListMenuBar.java000066400000000000000000000235651506470510200324320ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Frame; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.KeyEvent; import javax.swing.ButtonGroup; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.Font; public class GlyphListMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public GlyphListMenuBar(final Frame frame, final SaveManager sm, final Font font, final GlyphList gl) { add(new FileMenu(frame, sm, font)); add(new EditMenu(frame, gl)); add(new ViewMenu(frame, gl)); } public static final class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Frame frame, final SaveManager sm, final Font font) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(frame)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); addSeparator(); add(new CommonMenuItems.FontInfoMenuItem(font, sm)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static final class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(final Frame frame, final GlyphList gl) { super("Edit"); add(new SelectAllMenuItem(gl)); add(new SelectNoneMenuItem(gl)); add(new SetSelectionMenuItem(frame, gl)); addSeparator(); add(new EditMenuItem(gl)); add(new DeleteMenuItem(gl)); addSeparator(); add(new CommonMenuItems.FontMapMenuItem()); } } public static final class SelectAllMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SelectAllMenuItem(final GlyphList gl) { super("Select All"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.selectAll(); } }); } } public static final class SelectNoneMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SelectNoneMenuItem(final GlyphList gl) { super("Select None"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.clearSelection(); } }); } } public static final class SetSelectionMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SetSelectionMenuItem(final Frame frame, final GlyphList gl) { super("Set Selection..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new SetSelectionDialog(frame, gl).setVisible(true); } }); } } public static final class EditMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public EditMenuItem(final GlyphList gl) { super("Edit Glyphs"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (gl.getSelection().isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } gl.openSelection(); } }); } } public static final class DeleteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public DeleteMenuItem(final GlyphList gl) { super("Delete Glyphs"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (gl.getSelection().isEmpty()) { Toolkit.getDefaultToolkit().beep(); return; } gl.deleteSelection(); } }); } } public static final class ViewMenu extends JMenu { private static final long serialVersionUID = 1L; public ViewMenu(final Frame frame, final GlyphList gl) { super("View"); add(new ZoomOutMenuItem(frame, gl)); add(new ZoomInMenuItem(frame, gl)); addSeparator(); ButtonGroup csg = new ButtonGroup(); add(new CellSizeMenuItem(csg, frame, gl, 12, KeyStroke.getKeyStroke(KeyEvent.VK_1, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 24, KeyStroke.getKeyStroke(KeyEvent.VK_2, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 36, KeyStroke.getKeyStroke(KeyEvent.VK_3, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 48, KeyStroke.getKeyStroke(KeyEvent.VK_4, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 72, KeyStroke.getKeyStroke(KeyEvent.VK_5, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 96, KeyStroke.getKeyStroke(KeyEvent.VK_6, CommonMenuItems.SHORTCUT_KEY))); add(new CellSizeMenuItem(csg, frame, gl, 128, KeyStroke.getKeyStroke(KeyEvent.VK_7, CommonMenuItems.SHORTCUT_KEY))); addSeparator(); ButtonGroup ccg = new ButtonGroup(); add(new ColumnCountMenuItem(ccg, frame, gl, 8, KeyStroke.getKeyStroke(KeyEvent.VK_8, CommonMenuItems.SHORTCUT_KEY))); add(new ColumnCountMenuItem(ccg, frame, gl, 16, KeyStroke.getKeyStroke(KeyEvent.VK_9, CommonMenuItems.SHORTCUT_KEY))); add(new ColumnCountMenuItem(ccg, frame, gl, 32, KeyStroke.getKeyStroke(KeyEvent.VK_0, CommonMenuItems.SHORTCUT_KEY))); addSeparator(); ButtonGroup rcg = new ButtonGroup(); add(new RowCountMenuItem(rcg, frame, gl, 4, KeyStroke.getKeyStroke(KeyEvent.VK_8, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK))); add(new RowCountMenuItem(rcg, frame, gl, 8, KeyStroke.getKeyStroke(KeyEvent.VK_9, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK))); add(new RowCountMenuItem(rcg, frame, gl, 16, KeyStroke.getKeyStroke(KeyEvent.VK_0, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK))); } } public static final class ZoomInMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ZoomInMenuItem(final Frame frame, final GlyphList gl) { super("Zoom In"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { switch (gl.getCellSize()) { case 12: gl.setCellSize(24); break; case 24: gl.setCellSize(36); break; case 36: gl.setCellSize(48); break; case 48: gl.setCellSize(72); break; case 72: gl.setCellSize(96); break; case 96: gl.setCellSize(128); break; } frame.pack(); } }); } } public static final class ZoomOutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ZoomOutMenuItem(final Frame frame, final GlyphList gl) { super("Zoom Out"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { switch (gl.getCellSize()) { case 24: gl.setCellSize(12); break; case 36: gl.setCellSize(24); break; case 48: gl.setCellSize(36); break; case 72: gl.setCellSize(48); break; case 96: gl.setCellSize(72); break; case 128: gl.setCellSize(96); break; } frame.pack(); } }); } } public static final class CellSizeMenuItem extends JRadioButtonMenuItem { private static final long serialVersionUID = 1L; public CellSizeMenuItem(final ButtonGroup group, final Frame frame, final GlyphList gl, final int cellSize, final KeyStroke ks) { super(cellSize + " Pixel Cell Size"); setAccelerator(ks); setSelected(gl.getCellSize() == cellSize); group.add(this); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.setCellSize(cellSize); setSelected(true); frame.pack(); } }); gl.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { setSelected(gl.getCellSize() == cellSize); } }); } } public static final class ColumnCountMenuItem extends JRadioButtonMenuItem { private static final long serialVersionUID = 1L; public ColumnCountMenuItem(final ButtonGroup group, final Frame frame, final GlyphList gl, final int columnCount, final KeyStroke ks) { super(columnCount + " Cell Wide Window"); setAccelerator(ks); setSelected(gl.getColumnCount() == columnCount); group.add(this); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.setColumnCount(columnCount); setSelected(true); frame.pack(); } }); gl.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { setSelected(gl.getColumnCount() == columnCount); } }); } } public static final class RowCountMenuItem extends JRadioButtonMenuItem { private static final long serialVersionUID = 1L; public RowCountMenuItem(final ButtonGroup group, final Frame frame, final GlyphList gl, final int rowCount, final KeyStroke ks) { super(rowCount + " Cell High Window"); setAccelerator(ks); setSelected(gl.getRowCount() == rowCount); group.add(this); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.setRowCount(rowCount); setSelected(true); frame.pack(); } }); gl.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { setSelected(gl.getRowCount() == rowCount); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListModel.java000066400000000000000000000010701506470510200321240ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; public interface GlyphListModel { public abstract boolean tracksFont(); public abstract int getCellCount(); public abstract boolean isCodePoint(int index); public abstract Integer getCodePoint(int index); public abstract int indexOfCodePoint(Integer codePoint); public abstract boolean isGlyphName(int index); public abstract String getGlyphName(int index); public abstract int indexOfGlyphName(String name); public abstract String toString(); public abstract String getURL(); public abstract String getIconGroup(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListModelList.java000066400000000000000000000216411506470510200327660ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Container; import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import javax.swing.JTree; import javax.swing.JViewport; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.edit.glmlicon.GLMLTreeCellRenderer; import com.kreative.unicode.data.Block; import com.kreative.unicode.data.BlockList; import com.kreative.unicode.data.Encoding; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.EncodingTable; import com.kreative.unicode.data.GlyphList; import com.kreative.unicode.data.GlyphLists; public class GlyphListModelList extends JTree { private static final long serialVersionUID = 1L; public static final int SEQUENCE_MARKER = 0xFFFF2B16; public static final int SUBTABLE_MARKER = 0xFFFF1EAD; public static final int UNDEFINED_MARKER = 0xFFFFBAD1; public GlyphListModelList(Font font) { super(new GlyphListModelRootNode(font)); setRootVisible(false); setShowsRootHandles(true); setLargeModel(true); getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); setCellRenderer(new GLMLTreeCellRenderer()); setVisibleRowCount(16); } public GlyphListModel getSelectedModel() { TreePath path = getSelectionPath(); if (path == null) return null; Object o = path.getLastPathComponent(); if (!(o instanceof GlyphListModelTreeNode)) return null; return ((GlyphListModelTreeNode)o).getModel(); } public String getSelectedModelName() { TreePath path = getSelectionPath(); if (path == null) return null; Object o = path.getLastPathComponent(); if (!(o instanceof GlyphListModelTreeNode)) return null; return ((GlyphListModelTreeNode)o).getModel().toString(); } public void setSelectedModel(GlyphListModel model, boolean shouldScroll) { Object root = getModel().getRoot(); if (!(root instanceof GlyphListModelTreeNode)) return; GlyphListModelTreeNode r = (GlyphListModelTreeNode)root; TreePath path = findGlyphListModel(model, r, new TreePath(r)); if (path != null) setSelectionPath(path, shouldScroll); } public void setSelectedModelName(String name, boolean shouldScroll) { Object root = getModel().getRoot(); if (!(root instanceof GlyphListModelTreeNode)) return; GlyphListModelTreeNode r = (GlyphListModelTreeNode)root; TreePath path = findGlyphListModelName(name, r, new TreePath(r)); if (path != null) setSelectionPath(path, shouldScroll); } private void setSelectionPath(TreePath path, boolean shouldScroll) { setSelectionPath(path); if (shouldScroll) { scrollPathToVisible(path); Container c = getParent(); while (c != null) { if (c instanceof JViewport) { JViewport port = (JViewport)c; Point pos = port.getViewPosition(); pos.x = 0; port.setViewPosition(pos); break; } c = c.getParent(); } } } private TreePath findGlyphListModel(GlyphListModel model, GlyphListModelTreeNode node, TreePath parent) { if (hasModel(model, node)) return parent; for (GlyphListModelTreeNode child : node.getChildren()) { TreePath path = findGlyphListModel(model, child, parent.pathByAddingChild(child)); if (path != null) return path; } return null; } private TreePath findGlyphListModelName(String name, GlyphListModelTreeNode node, TreePath parent) { if (hasModelName(name, node)) return parent; for (GlyphListModelTreeNode child : node.getChildren()) { TreePath path = findGlyphListModelName(name, child, parent.pathByAddingChild(child)); if (path != null) return path; } return null; } private static boolean hasModel(GlyphListModel model, GlyphListModelTreeNode node) { GlyphListModel other = node.getModel(); if (model == null) return (other == null); if (other == null) return (model == null); return model.equals(other); } private static boolean hasModelName(String name, GlyphListModelTreeNode node) { GlyphListModel other = node.getModel(); if (name == null) return (other == null); if (other == null) return (name == null); return name.equals(other.toString()); } private static class GlyphListModelRootNode extends GlyphListModelTreeNode { public GlyphListModelRootNode(Font font) { super(null, null); GlyphListModelTreeNode allGlyphs = new GlyphListModelTreeNode(this, new GlyphListFontModel(font, true, true, "All Glyphs in Font")); allGlyphs.children.add(new GlyphListModelTreeNode(this, new GlyphListFontModel(font, true, false, "All Code Points in Font"))); allGlyphs.children.add(new GlyphListModelTreeNode(this, new GlyphListFontModel(font, false, true, "All Named Glyphs in Font"))); children.add(allGlyphs); Iterator bi = BlockList.instance().iterator(); if (bi.hasNext()) { GlyphListModelTreeNode unicode = new GlyphListModelTreeNode(this, new GlyphListCodePointModel(bi.next())); while (bi.hasNext()) { unicode.children.add(new GlyphListModelTreeNode(this, new GlyphListCodePointModel(bi.next()))); } children.add(unicode); } for (GlyphList gl : GlyphLists.instance()) { children.add(new GlyphListModelTreeNode(this, new GlyphListCodePointModel(gl, gl.getName(), null, "glyphlist"))); } for (Encoding enc : EncodingList.instance().encodings()) { children.add(new GlyphListModelEncodingNode(this, enc)); } } } private static class GlyphListModelEncodingNode extends GlyphListModelTreeNode { public GlyphListModelEncodingNode(GlyphListModelTreeNode parent, Encoding encoding) { super(parent, fromEncodingTable(encoding, false, encoding.getName(), false)); for (int i = 0; i < 256; i++) { EncodingTable s = encoding.getSubtable(i); if (s != null) { String n = "Subtable " + Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); GlyphListCodePointModel m = fromEncodingTable(s, true, n, true); if (m != null) children.add(new GlyphListModelEncodingNode(this, s, m)); } } } private GlyphListModelEncodingNode(GlyphListModelTreeNode parent, EncodingTable table, GlyphListCodePointModel model) { super(parent, model); for (int i = 0; i < 256; i++) { EncodingTable s = table.getSubtable(i); if (s != null) { String n = model.toString() + " " + Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); GlyphListCodePointModel m = fromEncodingTable(s, true, n, true); if (m != null) children.add(new GlyphListModelEncodingNode(this, s, m)); } } } private static GlyphListCodePointModel fromEncodingTable(EncodingTable table, boolean nullOnEmpty, String name, boolean subtable) { Integer[] codePoints = new Integer[256]; for (int i = 0; i < 256; i++) { String s = table.getSequence(i); if (s != null && s.length() > 0) { if (s.codePointCount(0, s.length()) == 1) { codePoints[i] = s.codePointAt(0); } else if (s.length() == 2) { int ch0 = s.charAt(0) & 0xFFFF; int ch1 = s.charAt(1) & 0xFFFF; codePoints[i] = ( (ch0 < 0x20 || ch0 > 0xFFFD || ch1 < 0x20 || ch1 > 0xFFFD) ? SEQUENCE_MARKER : ((ch0 << 16) | ch1) ); } else { codePoints[i] = SEQUENCE_MARKER; } nullOnEmpty = false; } else if (table.getSubtable(i) != null) { codePoints[i] = SUBTABLE_MARKER; } else { codePoints[i] = UNDEFINED_MARKER; } } if (nullOnEmpty) return null; return new GlyphListCodePointModel( Arrays.asList(codePoints), name, null, (subtable ? "subtable" : "encoding") ); } } public static class GlyphListModelTreeNode implements TreeNode { protected final GlyphListModelTreeNode parent; protected final GlyphListModel model; protected final List children; public GlyphListModelTreeNode(GlyphListModelTreeNode parent, GlyphListModel model) { this.parent = parent; this.model = model; this.children = new ArrayList(); } public final GlyphListModelTreeNode getParent() { return parent; } public final GlyphListModel getModel() { return model; } public final List getChildren() { return children; } public final Enumeration children() { return new Enumeration() { private final Iterator iter = children.iterator(); public boolean hasMoreElements() { return iter.hasNext(); } public GlyphListModelTreeNode nextElement() { return iter.next(); } }; } public final boolean getAllowsChildren() { return !children.isEmpty(); } public final GlyphListModelTreeNode getChildAt(int index) { return children.get(index); } public final int getChildCount() { return children.size(); } public final int getIndex(TreeNode node) { return children.indexOf(node); } public final boolean isLeaf() { return children.isEmpty(); } public final String toString() { return (model != null) ? model.toString() : null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListPanel.java000066400000000000000000000111211506470510200321210ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.util.List; import java.util.SortedSet; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JViewport; import javax.swing.KeyStroke; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; import com.kreative.bitsnpicas.edit.GlyphListModelList.GlyphListModelTreeNode; public class GlyphListPanel extends JPanel { private static final long serialVersionUID = 1L; private final GlyphListModelList modelList; private final JScrollPane modelPane; private final GlyphListURLPanel urlPanel; private final GlyphList glyphList; private final JScrollPane glyphPane; private final GlyphListDataPanel dataPanel; public GlyphListPanel(Font font, final SaveManager sm) { modelList = new GlyphListModelList(font); modelPane = new JScrollPane(modelList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); urlPanel = new GlyphListURLPanel(modelList); glyphList = new GlyphList(font); glyphPane = new JScrollPane(glyphList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); dataPanel = new GlyphListDataPanel(glyphList); JPanel left = new JPanel(new BorderLayout()); left.add(setWidth(modelPane, 240), BorderLayout.CENTER); left.add(setWidth(urlPanel, 240), BorderLayout.PAGE_END); JPanel right = new JPanel(new BorderLayout()); right.add(glyphPane, BorderLayout.CENTER); right.add(dataPanel, BorderLayout.PAGE_END); JSplitPane main = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); main.setOneTouchExpandable(true); setLayout(new BorderLayout()); add(main, BorderLayout.CENTER); modelList.setSelectedModel(glyphList.getModel(), false); modelList.addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { glyphList.setModel(modelList.getSelectedModel()); } }); glyphList.addGlyphListListener(new GlyphListListener() { public void selectionChanged(GlyphList gl, Font font) {} public void selectionOpened(GlyphList gl, Font font) { List> selectedGlyphs = gl.getSelection(); if ( (selectedGlyphs.size() < 5) || (JOptionPane.showConfirmDialog( GlyphListPanel.this, "Are you sure you want to edit " + selectedGlyphs.size() + " glyphs?", "Edit Glyphs", JOptionPane.OK_CANCEL_OPTION ) == JOptionPane.OK_OPTION) ) { for (GlyphLocator loc : selectedGlyphs) { Main.openGlyph(font, loc, gl, sm); } } SortedSet selectedIndices = gl.getSelectedIndices(); if (selectedIndices.size() == 1) { int i = selectedIndices.first(); Integer cp = gl.getModel().getCodePoint(i); if (cp != null && cp.intValue() == GlyphListModelList.SUBTABLE_MARKER) { String name = "Subtable " + Integer.toHexString(0xFF00 | i).substring(2).toUpperCase(); TreePath path = modelList.getSelectionPath(); GlyphListModelTreeNode node = (GlyphListModelTreeNode)path.getLastPathComponent(); for (GlyphListModelTreeNode child : node.getChildren()) { if (name.equals(child.toString())) { path = path.pathByAddingChild(child); modelList.setSelectionPath(path); modelList.scrollPathToVisible(path); JViewport vp = modelPane.getViewport(); Point p = vp.getViewPosition(); p.x = 0; vp.setViewPosition(p); return; } } } } } public void metricsChanged(GlyphList gl, Font font) { sm.setChanged(); } public void glyphsChanged(GlyphList gl, Font font) { sm.setChanged(); } }); InputMap im = glyphPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); im.put(KeyStroke.getKeyStroke("UP"), "none"); im.put(KeyStroke.getKeyStroke("DOWN"), "none"); im.put(KeyStroke.getKeyStroke("LEFT"), "none"); im.put(KeyStroke.getKeyStroke("RIGHT"), "none"); } public GlyphListModelList getModelList() { return modelList; } public GlyphList getGlyphList() { return glyphList; } private static C setWidth(C c, int width) { Dimension d = c.getPreferredSize(); d.width = width; c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); return c; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListSelection.java000066400000000000000000000024061506470510200330150ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; public class GlyphListSelection { private final List ranges = new ArrayList(); public void clear() { ranges.clear(); } public void add(int i) { ranges.add(new int[]{i, i}); } public void add(int i, int j) { ranges.add(new int[]{i, j}); } public void extend(int i) { if (ranges.isEmpty()) ranges.add(new int[]{i, i}); else ranges.get(ranges.size() - 1)[1] = i; } public int getLast() { if (ranges.isEmpty()) return -1; else return ranges.get(ranges.size() - 1)[1]; } public boolean isEmpty() { return ranges.isEmpty(); } public boolean contains(int i) { boolean contains = false; for (int[] range : ranges) { int j = Math.min(range[0], range[1]); int k = Math.max(range[0], range[1]); if (i >= j && i <= k) contains = !contains; } return contains; } public SortedSet toSet() { SortedSet s = new TreeSet(); for (int[] range : ranges) { int j = Math.min(range[0], range[1]); int k = Math.max(range[0], range[1]); for (int i = j; i <= k; i++) { if (s.contains(i)) s.remove(i); else s.add(i); } } return s; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphListURLPanel.java000066400000000000000000000026251506470510200325150ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; public class GlyphListURLPanel extends JPanel implements TreeSelectionListener { private static final long serialVersionUID = 1L; private final JLabel label; public GlyphListURLPanel(GlyphListModelList modelList) { this.label = new JLabel(" "); this.label.setForeground(Color.blue); this.label.setFont(this.label.getFont().deriveFont(10f)); this.label.setBorder(BorderFactory.createEmptyBorder(2, 6, 2, 6)); setLayout(new BorderLayout()); add(this.label, BorderLayout.LINE_START); modelList.addTreeSelectionListener(this); this.label.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { String s = label.getText().trim(); if (s.length() > 0) BareBonesBrowserLaunch.openURL(s); } }); } public void valueChanged(TreeSelectionEvent e) { label.setText(" "); label.setToolTipText(null); GlyphListModel model = ((GlyphListModelList)e.getSource()).getSelectedModel(); if (model != null) { String url = model.getURL(); if (url != null) { label.setText(url); label.setToolTipText(url); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GlyphLocator.java000066400000000000000000000067341506470510200316470ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; import com.kreative.unicode.data.NameResolver; public class GlyphLocator { private final Font font; private final GlyphListModel model; private final int index; private final Integer codePoint; private final String glyphName; public GlyphLocator(Font font, GlyphListModel model, int index) { this.font = font; this.model = model; this.index = index; this.codePoint = model.isCodePoint(index) ? model.getCodePoint(index) : null; this.glyphName = model.isGlyphName(index) ? model.getGlyphName(index) : null; } public boolean isValid() { return codePoint != null || glyphName != null; } public G getGlyph() { if (codePoint != null) return font.getCharacter(codePoint); if (glyphName != null) return font.getNamedGlyph(glyphName); return null; } public G setGlyph(G g) { if (codePoint != null) return font.putCharacter(codePoint, g); if (glyphName != null) return font.putNamedGlyph(glyphName, g); return null; } public G removeGlyph() { if (codePoint != null) return font.removeCharacter(codePoint); if (glyphName != null) return font.removeNamedGlyph(glyphName); return null; } public Font getGlyphFont() { return font; } public GlyphListModel getGlyphListModel() { return model; } public int getGlyphIndex() { if (model.tracksFont()) { if (codePoint != null) return model.indexOfCodePoint(codePoint); if (glyphName != null) return model.indexOfGlyphName(glyphName); return -1; } return index; } public boolean isCodePoint() { return codePoint != null; } public Integer getCodePoint() { return codePoint; } public boolean isGlyphName() { return glyphName != null; } public String getGlyphName() { return glyphName; } public String toString() { if (codePoint != null) { String h = Integer.toHexString(codePoint).toUpperCase(); while (h.length() < 4) h = "0" + h; String n = NameResolver.instance(codePoint).getName(codePoint); return "U+" + h + " " + n + " from " + font.toString(); } if (glyphName != null) { return glyphName + " from " + font.toString(); } return "Undefined from " + font.toString(); } public GlyphLocator getPrevious() { int i = getGlyphIndex(); if (i >= 0) { int n = model.getCellCount(); for (int x = 0; x < n; x++) { if (i <= 0) i = n; i--; GlyphLocator loc = new GlyphLocator(font, model, i); if (loc.isValid()) return loc; } } return null; } public GlyphLocator getNext() { int i = getGlyphIndex(); if (i >= 0) { int n = model.getCellCount(); for (int x = 0; x < n; x++) { i++; if (i >= n) i = 0; GlyphLocator loc = new GlyphLocator(font, model, i); if (loc.isValid()) return loc; } } return null; } public GlyphLocator getPreviousDefined() { int i = getGlyphIndex(); if (i >= 0) { int n = model.getCellCount(); for (int x = 0; x < n; x++) { if (i <= 0) i = n; i--; GlyphLocator loc = new GlyphLocator(font, model, i); if (loc.getGlyph() != null) return loc; } } return null; } public GlyphLocator getNextDefined() { int i = getGlyphIndex(); if (i >= 0) { int n = model.getCellCount(); for (int x = 0; x < n; x++) { i++; if (i >= n) i = 0; GlyphLocator loc = new GlyphLocator(font, model, i); if (loc.getGlyph() != null) return loc; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/GrabberTool.png000066400000000000000000000004641506470510200312770ustar00rootroot00000000000000PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqe<0PLTEDDDwwwfff"""UUU333StRNS#]~IDATxD PکHm1 j, V((`n2 _-@ lGq,``S4oO?O!FNcu'(9BRcVf`3 'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/Hex.ttf000066400000000000000000000125501506470510200276310ustar00rootroot00000000000000  OS/2j(dcmapBg<glyfT  Dhead >6hhea )$hmtxTloca(Xmaxp=X namepost:\v_<Hl Hl 8  8 ,,V;dKBnP  8  XXdXX  9<>FUX^fux~ +<>@UX^aux~ @tPd(,t,  P \  | 8 | D D D D DdX d8,d888d dd, ,dd d8,  dddd,,,,  d,d8d  Xdd ddddddd  d,pddddddddd8  dd88dddddp,d,d 8,8  ddd8dddDd  d88ddd,,d,  d88ddd88Xd 8d ddddD,8  dd88ddd8,8,d 8,8  dd8d8dd,8 ,d  ddddd,ddddd|dddd  ddddd#'/37;?GKU Uddddd88d$dLd ddd$dddpd8ddd8d,8,d8dpppp,Xd ddpdX8p,pd,d  dd8X8,Xd  ,88dd88d8,8  d8ddd Xd dd ,8dd d 8,88 88 d,d8dXX  ddddd,d88,d dddddddddddddd  dd8X8,Xd  ,88dd88d8,8  d8ddd Xd dd ,8dd d 8,88 88 d,d8dXX  ddddd,d88,d  dddddJ*>DZV` ` 5 8C+F 0q    *    V `WHexRegularBitsNPicas: Hex: 2021HexVersion 1.0HexMade with Bits'n'Picas by Kreative Softwarehttp://www.kreativekorp.com/software/bitsnpicas/HexRegularBitsNPicas: Hex: 2021HexVersion 1.0HexMade with Bits'n'Picas by Kreative Softwarehttp://www.kreativekorp.com/software/bitsnpicas/HexRegularBitsNPicas: Hex: 2021HexVersion 1.0HexMade with Bits'n'Picas by Kreative Softwarehttp://www.kreativekorp.com/software/bitsnpicas/d,!#$%&'()8;ADEFGHIX[auni200Buni200Cuni200Dbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/InvertTool.png000066400000000000000000000002761506470510200312030ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<`IDATxb?%B@, ?E@yy9V X:;;i0A4c\B D1!M6a+ޱ32%)qs#@&! IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/LineTool.png000066400000000000000000000001201506470510200306070ustar00rootroot00000000000000PNG  IHDRaIDATxc`TxԠip BIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/Main.java000066400000000000000000000227171506470510200301230ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Toolkit; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.UIManager; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontExporter; import com.kreative.bitsnpicas.FontImporter; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.VectorFont; import com.kreative.bitsnpicas.VectorFontExporter; import com.kreative.bitsnpicas.VectorFontGlyph; import com.kreative.bitsnpicas.edit.importer.ImportFormat; import com.kreative.bitsnpicas.exporter.KbitxBitmapFontExporter; import com.kreative.bitsnpicas.exporter.KpcaxVectorFontExporter; public class Main { public static void main(String[] args) { try { System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Bits'n'Picas"); } catch (Exception e) {} try { System.setProperty("apple.laf.useScreenMenuBar", "true"); } catch (Exception e) {} try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) {} try { Method getModule = Class.class.getMethod("getModule"); Object javaDesktop = getModule.invoke(Toolkit.getDefaultToolkit().getClass()); Object allUnnamed = getModule.invoke(Main.class); Class module = Class.forName("java.lang.Module"); Method addOpens = module.getMethod("addOpens", String.class, module); addOpens.invoke(javaDesktop, "sun.awt.X11", allUnnamed); } catch (Exception e) {} try { Toolkit tk = Toolkit.getDefaultToolkit(); Field aacn = tk.getClass().getDeclaredField("awtAppClassName"); aacn.setAccessible(true); aacn.set(tk, "BitsNPicas"); } catch (Exception e) {} if (CommonMenuItems.IS_MAC_OS) { try { Class.forName("com.kreative.bitsnpicas.edit.mac.MacDummyWindow").newInstance(); } catch (Exception e) { e.printStackTrace(); } } if (args.length == 0) { newBitmapFont(); } else { for (String arg : args) { openFonts(new File(arg)); } } if (CommonMenuItems.IS_MAC_OS) { try { Class.forName("com.kreative.bitsnpicas.edit.mac.MyApplicationListener").newInstance(); } catch (Exception e) { e.printStackTrace(); } } } public static JFrame newBitmapFont() { BitmapFont bfont = new BitmapFont(14, 2, 14, 2, 0, 0, 0); bfont.autoFillNames(); return openFont(null, new KbitxBitmapFontExporter(), bfont); } public static JFrame newVectorFont() { VectorFont vfont = new VectorFont(800, 200, 800, 200, 0, 0, 0); vfont.autoFillNames(); return openFont(null, new KpcaxVectorFontExporter(), vfont); } private static String lastOpenDirectory = null; public static JFrame openFonts() { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Open", FileDialog.LOAD); if (lastOpenDirectory != null) fd.setDirectory(lastOpenDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; File file = new File((lastOpenDirectory = ds), fs); return openFonts(file); } public static JFrame openFonts(File file) { try { ImportFormat format = ImportFormat.forFile(file); if (format != null) { if (format.macResFork) file = MacUtility.getResourceFork(file); FontImporter importer = format.createImporter(); if (importer != null) { Font[] fonts = importer.importFont(file); if (fonts != null && fonts.length > 0) { return openFonts(file, format.createExporter(), fonts); } } JFrame f = format.createOptionFrame(file); if (f != null) { f.setVisible(true); return f; } JOptionPane.showMessageDialog( null, "The selected file did not contain any fonts.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } else { JOptionPane.showMessageDialog( null, "The selected file was not recognized as a font file readable by Bits'n'Picas.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } public static JFrame openFonts(File fontFile, FontExporter format, Font[] fonts) { if (fonts.length > 1) { JFrame f = new FontListFrame(fontFile, format, fonts); f.setVisible(true); return f; } else if (fonts.length > 0) { return openFont(fontFile, format, fonts[0]); } else { JOptionPane.showMessageDialog( null, "The selected file did not contain any fonts.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } public static JFrame openFont(File fontFile, FontExporter format, Font font) { if (font instanceof BitmapFont) { BitmapFontExporter bformat = (BitmapFontExporter)format; BitmapFont bfont = (BitmapFont)font; JFrame f = new BitmapListFrame(fontFile, bformat, bfont); f.setVisible(true); return f; } else if (font instanceof VectorFont) { VectorFontExporter vformat = (VectorFontExporter)format; VectorFont vfont = (VectorFont)font; JFrame f = new GlyphListFrame(fontFile, vformat, vfont); f.setVisible(true); return f; } else { JOptionPane.showMessageDialog( null, "The selected font was not recognized by the Bits'n'Picas editor.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } public static JFrame openFont(SaveRoutine routine, Font font) { if (font instanceof BitmapFont) { BitmapFont bfont = (BitmapFont)font; JFrame f = new BitmapListFrame(routine, bfont); f.setVisible(true); return f; } else if (font instanceof VectorFont) { VectorFont vfont = (VectorFont)font; JFrame f = new GlyphListFrame(routine, vfont); f.setVisible(true); return f; } else { JOptionPane.showMessageDialog( null, "The selected font was not recognized by the Bits'n'Picas editor.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } public static JFrame openGlyph(Font font, GlyphLocator loc, GlyphList gl, SaveManager sm) { if (font instanceof BitmapFont) { BitmapFont bfont = (BitmapFont)font; @SuppressWarnings("unchecked") GlyphLocator bloc = (GlyphLocator)loc; @SuppressWarnings("unchecked") GlyphList bgl = (GlyphList)gl; if (bloc.getGlyph() == null) { bloc.setGlyph(new BitmapFontGlyph()); bgl.glyphRepertoireChanged(); } JFrame f = new BitmapEditFrame(bfont, bloc, bgl, sm); f.setVisible(true); return f; } else if (font instanceof VectorFont) { VectorFont vfont = (VectorFont)font; @SuppressWarnings("unchecked") GlyphLocator vloc = (GlyphLocator)loc; @SuppressWarnings("unchecked") GlyphList vgl = (GlyphList)gl; if (vloc.getGlyph() == null) { vloc.setGlyph(new VectorFontGlyph()); vgl.glyphRepertoireChanged(); } JFrame f = new GlyphEditFrame(VectorFontGlyph.class, vfont, vloc, vgl, sm); f.setVisible(true); return f; } else { JOptionPane.showMessageDialog( null, "The selected font was not recognized by the Bits'n'Picas editor.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } public static String getSaveSuffix(Font font) { if (font instanceof BitmapFont) return ".kbitx"; if (font instanceof VectorFont) return ".kpcax"; return null; } private static String lastSaveDirectory = null; public static File getSaveFile(String suffix) { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Save", FileDialog.SAVE); if (lastSaveDirectory != null) fd.setDirectory(lastSaveDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; if (!fs.toLowerCase().endsWith(suffix.toLowerCase())) fs += suffix; return new File((lastSaveDirectory = ds), fs); } public static FontExporter getSaveFormat(Font font) { if (font instanceof BitmapFont) return new KbitxBitmapFontExporter(); if (font instanceof VectorFont) return new KpcaxVectorFontExporter(); return null; } public static boolean saveFont(File fontFile, FontExporter format, Font font) { if (font instanceof BitmapFont) { BitmapFontExporter bformat = (BitmapFontExporter)format; BitmapFont bfont = (BitmapFont)font; bfont.contractGlyphs(); try { bformat.exportFontToFile(bfont, fontFile); return true; } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); return false; } } else if (font instanceof VectorFont) { VectorFontExporter vformat = (VectorFontExporter)format; VectorFont vfont = (VectorFont)font; try { vformat.exportFontToFile(vfont, fontFile); return true; } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); return false; } } else { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); return false; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/MoveGlyphsDialog.java000066400000000000000000000364131506470510200324520ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import java.util.TreeSet; import java.util.regex.PatternSyntaxException; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontGlyph; public abstract class MoveGlyphsDialog extends JDialog { private static final long serialVersionUID = 1L; private final boolean copy; private final GlyphList glyphList; private JRadioButton byCodePointButton; private JRadioButton byIndexButton; private JTextField offsetField; private JButton cancelButton; private JButton okButton; public MoveGlyphsDialog(Dialog parent, boolean copy, GlyphList gl) { super(parent, copy ? "Copy Glyphs" : "Move Glyphs"); this.copy = copy; this.glyphList = gl; setModal(true); make(); } public MoveGlyphsDialog(Frame parent, boolean copy, GlyphList gl) { super(parent, copy ? "Copy Glyphs" : "Move Glyphs"); this.copy = copy; this.glyphList = gl; setModal(true); make(); } public MoveGlyphsDialog(Window parent, boolean copy, GlyphList gl) { super(parent, copy ? "Copy Glyphs" : "Move Glyphs"); this.copy = copy; this.glyphList = gl; setModal(true); make(); } private void make() { // The order in which we do things here is very important! // If we get it wrong we can completely screw it up. // Get the locators for the selected glyphs. // Must be done before calling tracksFont() // in case that changes the model's glyph list. final List> locators = glyphList.getSelection(); // Disable moving by index if the model tracks // the font because what does that even mean? final GlyphListModel model = glyphList.getModel(); Boolean byIndex = ( model.tracksFont() ? (copy ? Boolean.FALSE : null) : Boolean.valueOf(!isUnicodeRange(model)) ); this.byCodePointButton = new JRadioButton("By Code Point"); this.byIndexButton = new JRadioButton("By Index"); this.offsetField = new JTextField("+0"); this.cancelButton = new JButton("Cancel"); this.okButton = new JButton("OK"); if (byIndex == null) { this.byCodePointButton.setSelected(true); this.byIndexButton.setSelected(false); this.byIndexButton.setEnabled(false); } else { this.byCodePointButton.setSelected(!byIndex); this.byIndexButton.setSelected(byIndex); } ButtonGroup bg1 = new ButtonGroup(); bg1.add(this.byCodePointButton); bg1.add(this.byIndexButton); JPanel bp1 = new JPanel(new GridLayout(1, 0, 8, 8)); bp1.add(this.byCodePointButton); bp1.add(this.byIndexButton); JPanel bp2 = new JPanel(new GridLayout(0, 1, 4, 4)); bp2.add(bp1); bp2.add(new JLabel("(Non-numeric values will be treated as glyph names.)")); JPanel cp = new JPanel(new BorderLayout(8, 8)); cp.add(bp2, BorderLayout.PAGE_START); cp.add(this.offsetField, BorderLayout.CENTER); JPanel bp = new JPanel(new FlowLayout()); bp.add(this.cancelButton); bp.add(this.okButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(cp, BorderLayout.CENTER); mainPanel.add(bp, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), okButton); setResizable(false); pack(); setLocationRelativeTo(null); offsetField.requestFocusInWindow(); offsetField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_ENTER: okButton.doClick(); break; case KeyEvent.VK_ESCAPE: cancelButton.doClick(); break; case KeyEvent.VK_U: if (e.isControlDown() || e.isMetaDown()) { byCodePointButton.doClick(); } break; case KeyEvent.VK_I: if (e.isControlDown() || e.isMetaDown()) { byIndexButton.doClick(); } break; } } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String offsetString = offsetField.getText().trim(); boolean byIndex = byIndexButton.isSelected(); try { boolean relative; int offset; if (offsetString.startsWith("+")) { relative = true; offset = +parseInt(offsetString.substring(1)); } else if (offsetString.startsWith("-")) { relative = true; offset = -parseInt(offsetString.substring(1)); } else if (offsetString.startsWith("@")) { relative = false; offset = parseInt(offsetString.substring(1)); } else { relative = false; offset = parseInt(offsetString); } // Create a copy of the selected glyphs. List states = serializeGlyphs(locators); // If this is a move operation, remove the // selected glyphs from their current location. // This also calls tracksFont() again afterwards. if (!copy) glyphList.deleteSelection(); // Put the glyphs back in the destination location. if (byIndex) moveByIndex(locators, states, relative, offset); else moveByCodePoint(locators, states, relative, offset); } catch (NumberFormatException nfe) { if (offsetString.length() > 0) { List states = serializeGlyphs(locators); if (!copy) glyphList.deleteSelection(); moveByGlyphName(locators, states, offsetString); } else { Toolkit.getDefaultToolkit().beep(); } } dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } public abstract S serializeGlyph(G g); public abstract G deserializeGlyph(S s); private static boolean isUnicodeRange(GlyphListModel model) { for (int lastCP = -1, i = 0, n = model.getCellCount(); i < n; i++) { if (model.isCodePoint(i)) { int cp = model.getCodePoint(i); if (lastCP < 0 || (lastCP + 1) == cp) { lastCP = cp; continue; } } return false; } return true; } private static int parseInt(String s) { if (s.startsWith("0x")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("0X")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("U+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("u+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("$")) return Integer.parseInt(s.substring(1), 16); if (s.startsWith("#")) return Integer.parseInt(s.substring(1), 10); return Integer.parseInt(s, 10); } private List serializeGlyphs(List> locators) { // Create a copy of the selected glyphs. List states = new ArrayList(); for (GlyphLocator loc : locators) { G glyph = loc.getGlyph(); if (glyph == null) states.add(null); else states.add(serializeGlyph(glyph)); } return states; } private void moveByIndex(List> locators, List states, boolean relative, int offset) { Font font = glyphList.getGlyphFont(); TreeSet selectedIndices = new TreeSet(); GlyphListModel model = glyphList.getModel(); int gn = model.getCellCount(); for (int i = 0, n = locators.size(); i < n; i++) { int gi = locators.get(i).getGlyphIndex(); if (gi < 0) continue; if (relative) gi += offset; else gi = offset + i; if (gi < 0 || gi >= gn) continue; selectedIndices.add(gi); S state = states.get(i); if (state == null) continue; new GlyphLocator(font, model, gi).setGlyph(deserializeGlyph(state)); } glyphList.glyphRepertoireChanged(); glyphList.setSelectedIndices(selectedIndices, true); } private void moveByCodePoint(List> locators, List states, boolean relative, int offset) { // Put the glyphs at the destination code points before // setting the selection since the indices may change. Font font = glyphList.getGlyphFont(); TreeSet selectedCodePoints = new TreeSet(); List> selectedLocators = new ArrayList>(); for (int i = 0, n = locators.size(); i < n; i++) { int cp; if (relative) { GlyphLocator loc = locators.get(i); if (loc.isCodePoint()) { cp = loc.getCodePoint() + offset; } else { selectedLocators.add(loc); S state = states.get(i); if (state == null) continue; loc.setGlyph(deserializeGlyph(state)); continue; } } else { cp = offset + i; } if (Character.isValidCodePoint(cp)) { selectedCodePoints.add(cp); S state = states.get(i); if (state == null) continue; font.putCharacter(cp, deserializeGlyph(state)); } } glyphList.glyphRepertoireChanged(); // Calculate the selected indices now that the font is done changing. GlyphListModel model = glyphList.getModel(); TreeSet selectedIndices = new TreeSet(); for (int cp : selectedCodePoints) selectedIndices.add(model.indexOfCodePoint(cp)); for (GlyphLocator loc : selectedLocators) selectedIndices.add(loc.getGlyphIndex()); glyphList.setSelectedIndices(selectedIndices, true); } private void moveByGlyphName(List> locators, List states, String baseName) { // Put the glyphs at the destination glyph names before // setting the selection since the indices may change. Font font = glyphList.getGlyphFont(); TreeSet selectedGlyphNames = new TreeSet(); GlyphListModel model = glyphList.getModel(); int gn = model.getCellCount(); for (int i = 0, n = locators.size(); i < n; i++) { String glyphName = formatGlyphName(baseName, i, n, locators.get(i), gn); if (glyphName.length() == 0) continue; selectedGlyphNames.add(glyphName); S state = states.get(i); if (state == null) continue; font.putNamedGlyph(glyphName, deserializeGlyph(state)); } glyphList.glyphRepertoireChanged(); // Calculate the selected indices now that the font is done changing. TreeSet selectedIndices = new TreeSet(); for (String n : selectedGlyphNames) selectedIndices.add(model.indexOfGlyphName(n)); glyphList.setSelectedIndices(selectedIndices, true); } private String formatGlyphName(String baseName, int li, int lim, GlyphLocator loc, int gim) { int gi = loc.getGlyphIndex(); StringBuffer name = new StringBuffer(); char[] chars = baseName.toCharArray(); int ci = 0, cn = chars.length; while (ci < cn) { char ch = chars[ci++]; if (ch == '%' && ci < cn) { StringBuffer vws = new StringBuffer(); int vw = 0; char vc = chars[ci++]; int vd = Character.digit(vc, 10); while (vd >= 0 && ci < cn) { vws.append(vc); vw = vw * 10 + vd; vc = chars[ci++]; vd = Character.digit(vc, 10); } switch (vc) { case '%': // literal % name.append('%'); break; case 'u': case 'U': // Unicode code point, decimal if (loc.isCodePoint()) { String s = Integer.toString(loc.getCodePoint()); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'x': case 'X': // Unicode code point, hexadecimal if (loc.isCodePoint()) { String s = Integer.toHexString(loc.getCodePoint()); if (vc == 'x') s = s.toLowerCase(); if (vc == 'X') s = s.toUpperCase(); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 's': case 'S': // glyph name { String s; if (loc.isCodePoint()) { int cp = loc.getCodePoint(); s = Integer.toHexString(cp).toUpperCase(); while (s.length() < 4) s = "0" + s; if (cp < 0x10000) s = "uni" + s; else s = "u" + s; } else if (loc.isGlyphName()) { s = loc.getGlyphName(); } else { s = ""; } if (ci < cn && chars[ci] == '/') { ci++; StringBuffer pb = new StringBuffer(); while (ci < cn) { char pc = chars[ci++]; if (pc == '/') break; if (pc == '\\' && ci < cn) { pc = chars[ci++]; if (pc != '/') pb.append('\\'); } pb.append(pc); } StringBuffer rb = new StringBuffer(); while (ci < cn) { char rc = chars[ci++]; if (rc == '/') break; if (rc == '\\' && ci < cn) { rc = chars[ci++]; if (rc != '/') rb.append('\\'); } rb.append(rc); } try { s = s.replaceAll(pb.toString(), rb.toString()); } catch (PatternSyntaxException e) { s = s.replace(pb.toString(), rb.toString()); } } name.append(s); } break; case 'd': case 'D': // glyph index, decimal if (gi >= 0) { String s = Integer.toString(gi); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'o': case 'O': // glyph index, octal if (gi >= 0) { String s = Integer.toString(gi, 8); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'h': case 'H': // glyph index, hexadecimal if (gi >= 0) { String s = Integer.toHexString(gi); if (vc == 'h') s = s.toLowerCase(); if (vc == 'H') s = s.toUpperCase(); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'i': // selection index, zero based if (li >= 0) { String s = Integer.toString(li); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'j': // selection index, one based if (li >= 0) { String s = Integer.toString(li + 1); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'n': // number of glyphs in selection if (lim >= 0) { String s = Integer.toString(lim); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'I': // glyph index, zero based if (gi >= 0) { String s = Integer.toString(gi); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'J': // glyph index, one based if (gi >= 0) { String s = Integer.toString(gi + 1); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; case 'N': // number of glyphs in glyph list if (gim >= 0) { String s = Integer.toString(gim); for (int x = s.length(); x < vw; x++) name.append('0'); name.append(s); } break; default: // invalid specifier name.append('%'); name.append(vws); name.append(vc); break; } } else { name.append(ch); } } return name.toString().trim(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/MoveTool.png000066400000000000000000000003241506470510200306340ustar00rootroot00000000000000PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqe<PLTEFFFppp%%%w[tRNSSJIDATxڌK f?J[?<e)%NVsd<Xto ~*H+o]pg'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/PencilTool.png000066400000000000000000000003531506470510200311420ustar00rootroot00000000000000PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqe<PLTEnuL$|Rb9hu tRNS,MIDATxdI0MLRU XfTC@P;\ؕwpl_Xo[[FZm$IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/PsName.ttf000066400000000000000000000232641506470510200302740ustar00rootroot00000000000000  OS/2zZ(dcmap4?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`auni007Fbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/RectangleTool.png000066400000000000000000000001271506470510200316330ustar00rootroot00000000000000PNG  IHDRaIDATxc`6?n0jān/qZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/Resources.java000066400000000000000000000023761506470510200312100ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Font; import java.awt.Image; import java.awt.Toolkit; public class Resources { public static final Image ERASER_TOOL = getImage("EraserTool.png"); public static final Image EYEDROPPER_TOOL = getImage("EyedropperTool.png"); public static final Image FILLED_RECT_TOOL = getImage("FilledRectTool.png"); public static final Image GRABBER_TOOL = getImage("GrabberTool.png"); public static final Image INVERT_TOOL = getImage("InvertTool.png"); public static final Image LINE_TOOL = getImage("LineTool.png"); public static final Image MOVE_TOOL = getImage("MoveTool.png"); public static final Image PENCIL_TOOL = getImage("PencilTool.png"); public static final Image RECTANGLE_TOOL = getImage("RectangleTool.png"); public static final Font HEX_FONT = getFont("Hex.ttf", 10f); public static final Font PSNAME_FONT = getFont("PsName.ttf", 10f); private static Image getImage(String name) { return Toolkit.getDefaultToolkit().createImage(Resources.class.getResource(name)); } private static Font getFont(String name, float size) { try { return Font.createFont( Font.TRUETYPE_FONT, Resources.class.getResourceAsStream(name) ).deriveFont(size); } catch (Exception e) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SaveChangesDialog.java000066400000000000000000000054101506470510200325350ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; public class SaveChangesDialog extends JDialog { private static final long serialVersionUID = 1L; public static enum Action { SAVE, CANCEL, DONT_SAVE } private JLabel label; private JButton dontSaveButton; private JButton cancelButton; private JButton saveButton; private Action action; public SaveChangesDialog(Dialog parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Frame parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Window parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } private void make(String name) { label = new JLabel("Save changes to \u201C" + name + "\u201D before closing?"); dontSaveButton = new JButton("Don\u2019t Save"); cancelButton = new JButton("Cancel"); saveButton = new JButton("Save"); JPanel leftButtonPanel = new JPanel(new FlowLayout()); leftButtonPanel.add(dontSaveButton); JPanel rightButtonPanel = new JPanel(new FlowLayout()); rightButtonPanel.add(cancelButton); rightButtonPanel.add(saveButton); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.add(leftButtonPanel, BorderLayout.WEST); buttonPanel.add(rightButtonPanel, BorderLayout.EAST); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(label, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDontSaveButton(getRootPane(), dontSaveButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), saveButton); setResizable(false); pack(); setLocationRelativeTo(null); saveButton.requestFocusInWindow(); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.SAVE; dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.CANCEL; dispose(); } }); dontSaveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.DONT_SAVE; dispose(); } }); } public Action showDialog() { action = Action.CANCEL; setVisible(true); return action; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SaveInterface.java000066400000000000000000000002271506470510200317460ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; public interface SaveInterface { public void setChanged(); public boolean save(); public boolean saveAs(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SaveManager.java000066400000000000000000000050761506470510200314270ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import javax.swing.JFrame; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.FontExporter; public class SaveManager extends WindowAdapter implements SaveInterface { private JFrame frame; private File file; private FontExporter format; private SaveRoutine routine; private Font font; private boolean changed; public SaveManager(JFrame frame, File file, FontExporter format, Font font) { this.frame = frame; this.file = file; this.format = format; this.routine = null; this.font = font; this.changed = false; updateWindow(); } public SaveManager(JFrame frame, SaveRoutine routine, Font font) { this.frame = frame; this.file = null; this.format = null; this.routine = routine; this.font = font; this.changed = false; updateWindow(); } public void setChanged() { this.changed = true; updateWindow(); } public boolean save() { if (routine == null) { if (file == null || format == null) return saveAs(); boolean succeeded = Main.saveFont(file, format, font); if (succeeded) changed = false; updateWindow(); return succeeded; } else { boolean succeeded = routine.save(font); if (succeeded) changed = false; updateWindow(); return succeeded; } } public boolean saveAs() { FontExporter newFormat = Main.getSaveFormat(font); if (newFormat == null) return false; String newSuffix = Main.getSaveSuffix(font); if (newSuffix == null) return false; File newFile = Main.getSaveFile(newSuffix); if (newFile == null) return false; file = newFile; format = newFormat; boolean succeeded = Main.saveFont(file, format, font); if (succeeded) changed = false; updateWindow(); return succeeded; } public void windowClosing(WindowEvent e) { Window w = e.getWindow(); if (!changed || (file == null && font.isEmpty())) w.dispose(); else switch (new SaveChangesDialog(w, font.toString()).showDialog()) { case SAVE: if (save()) w.dispose(); break; case DONT_SAVE: w.dispose(); break; case CANCEL: break; } } private void updateWindow() { String title = font.toString(); if (file != null) title += " from " + file.getName(); if (CommonMenuItems.IS_MAC_OS) { frame.getRootPane().putClientProperty("Window.documentFile", file); frame.getRootPane().putClientProperty("Window.documentModified", changed); frame.setTitle(title); } else { if (changed) title += " \u2022"; frame.setTitle(title); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SaveRoutine.java000066400000000000000000000002221506470510200314660ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import com.kreative.bitsnpicas.Font; public interface SaveRoutine { public boolean save(Font font); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SetSelectionDialog.java000066400000000000000000000220171506470510200327510ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class SetSelectionDialog extends JDialog { private static final long serialVersionUID = 1L; private final GlyphList gl; private JRadioButton byCodePointButton; private JRadioButton byIndexButton; private JTextArea selectionField; private JButton cancelButton; private JButton okButton; public SetSelectionDialog(Dialog parent, GlyphList gl) { super(parent, "Set Selection"); setModal(true); this.gl = gl; make(); } public SetSelectionDialog(Frame parent, GlyphList gl) { super(parent, "Set Selection"); setModal(true); this.gl = gl; make(); } public SetSelectionDialog(Window parent, GlyphList gl) { super(parent, "Set Selection"); setModal(true); this.gl = gl; make(); } private void make() { this.byCodePointButton = new JRadioButton("By Code Point"); this.byIndexButton = new JRadioButton("By Index"); this.selectionField = new JTextArea(); this.cancelButton = new JButton("Cancel"); this.okButton = new JButton("OK"); boolean isUnicode = isUnicodeRange(gl.getModel()); this.byCodePointButton.setSelected(isUnicode); this.byIndexButton.setSelected(!isUnicode); ButtonGroup bg1 = new ButtonGroup(); bg1.add(this.byCodePointButton); bg1.add(this.byIndexButton); JPanel bp1 = new JPanel(new GridLayout(1, 0, 8, 8)); bp1.add(this.byCodePointButton); bp1.add(this.byIndexButton); JPanel bp2 = new JPanel(new GridLayout(0, 1, 4, 4)); bp2.add(bp1); bp2.add(new JLabel("(Non-numeric values will be treated as glyph names.)")); Dimension d = new Dimension(240, 120); this.selectionField.setMinimumSize(d); this.selectionField.setPreferredSize(d); this.selectionField.setLineWrap(true); this.selectionField.setWrapStyleWord(true); this.selectionField.setText(selectionToString(gl.getSelection(), !isUnicode)); JScrollPane sp = new JScrollPane( this.selectionField, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); JPanel cp = new JPanel(new BorderLayout(8, 8)); cp.add(bp2, BorderLayout.PAGE_START); cp.add(sp, BorderLayout.CENTER); JPanel bp = new JPanel(new FlowLayout()); bp.add(this.cancelButton); bp.add(this.okButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(cp, BorderLayout.CENTER); mainPanel.add(bp, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), okButton); setResizable(false); pack(); setLocationRelativeTo(null); selectionField.requestFocusInWindow(); byCodePointButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectionField.setText(selectionToString(gl.getSelection(), false)); } }); byIndexButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectionField.setText(selectionToString(gl.getSelection(), true)); } }); selectionField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_ENTER: okButton.doClick(); break; case KeyEvent.VK_ESCAPE: cancelButton.doClick(); break; case KeyEvent.VK_U: if (e.isControlDown() || e.isMetaDown()) { byCodePointButton.doClick(); } break; case KeyEvent.VK_I: if (e.isControlDown() || e.isMetaDown()) { byIndexButton.doClick(); } break; } } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { gl.setSelectedIndices(stringToIndices( selectionField.getText(), gl.getModel(), byIndexButton.isSelected() ), true); dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } private static boolean isUnicodeRange(GlyphListModel model) { for (int lastCP = -1, i = 0, n = model.getCellCount(); i < n; i++) { if (model.isCodePoint(i)) { int cp = model.getCodePoint(i); if (lastCP < 0 || (lastCP + 1) == cp) { lastCP = cp; continue; } } return false; } return true; } private static String selectionToString(Collection> locators, boolean byIndex) { List intValues = new ArrayList(); List stringValues = new ArrayList(); for (GlyphLocator loc : locators) { if (byIndex) intValues.add(loc.getGlyphIndex()); else if (loc.isCodePoint()) intValues.add(loc.getCodePoint()); else if (loc.isGlyphName()) stringValues.add(loc.getGlyphName()); } Collections.sort(intValues); Collections.sort(stringValues); StringBuffer sb = new StringBuffer(); List runs = new ArrayList(); for (int i : intValues) { if (runs.isEmpty()) { runs.add(new int[]{i, i}); } else if (i == runs.get(runs.size() - 1)[1] + 1) { runs.get(runs.size() - 1)[1] = i; } else { runs.add(new int[]{i, i}); } } for (int[] run : runs) { if (sb.length() > 0) { sb.append(", "); } if (byIndex) { sb.append(run[0]); } else { sb.append("U+"); String h = Integer.toHexString(run[0]).toUpperCase(); for (int i = h.length(); i < 4; i++) sb.append("0"); sb.append(h); } if (run[0] != run[1]) { sb.append("-"); if (byIndex) { sb.append(run[1]); } else { sb.append("U+"); String h = Integer.toHexString(run[1]).toUpperCase(); for (int i = h.length(); i < 4; i++) sb.append("0"); sb.append(h); } } } for (String s : stringValues) { if (sb.length() > 0) sb.append(", "); sb.append(s); } return sb.toString(); } private static Collection stringToIndices(String s, GlyphListModel model, boolean byIndex) { TreeSet indices = new TreeSet(); String[] parts = s.split("[,;]"); for (String part : parts) { try { int[] range = parseRange(part); if (byIndex) { int n = model.getCellCount(); for (int i = range[0]; i <= range[1]; i++) { if (i >= 0 && i < n) indices.add(i); } } else { for (int cp = range[0]; cp <= range[1]; cp++) { int i = model.indexOfCodePoint(cp); if (i >= 0) indices.add(i); } } } catch (NumberFormatException nfe) { if ((part = part.trim()).length() > 0) { TreeSet names = new TreeSet(); parseGlyphNames(part, names); for (String name : names) { int i = model.indexOfGlyphName(name); if (i >= 0) indices.add(i); } } } } return indices; } private static int[] parseRange(String s) { String[] p = s.split("-+|:+|\\.\\.+", 2); if (p.length == 2) { int p0 = parseInt(p[0].trim()); int p1 = parseInt(p[1].trim()); int start = Math.min(p0, p1); int end = Math.max(p0, p1); return new int[]{ start, end }; } int i = parseInt(s.trim()); return new int[]{ i, i }; } private static int parseInt(String s) { if (s.startsWith("0x")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("0X")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("U+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("u+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("$")) return Integer.parseInt(s.substring(1), 16); if (s.startsWith("#")) return Integer.parseInt(s.substring(1), 10); return Integer.parseInt(s, 10); } private static final Pattern RANGE_PATTERN = Pattern.compile("\\{([0-9]+)(-+|:+|\\.\\.+)([0-9]+)\\}"); private static void parseGlyphNames(String s, Collection names) { Matcher m = RANGE_PATTERN.matcher(s); if (m.find()) { String s1 = m.group(1); String s3 = m.group(3); int v1 = Integer.parseInt(s1); int v3 = Integer.parseInt(s3); int length = Math.min(s1.length(), s3.length()); int start = Math.min(v1, v3); int end = Math.max(v1, v3); String prefix = s.substring(0, m.start()); String suffix = s.substring(m.end()); for (int vi = start; vi <= end; vi++) { String si = Integer.toString(vi); while (si.length() < length) si = "0" + si; parseGlyphNames(prefix + si + suffix, names); } } else { names.add(s); } } } SitelenPonaCartoucheGlyphGenerator.java000066400000000000000000000037451506470510200361120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.util.List; import java.util.Map; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.PuaaCache; import com.kreative.unicode.ttflib.PuaaTable; public class SitelenPonaCartoucheGlyphGenerator extends GlyphGenerator { private static final PuaaTable extras = PuaaCache.getPuaaTable("extras.ucd"); private static final Map psNames = extras.getPropertyMap("PostScript_Name"); private static final String getGlyphName(GlyphLocator loc) { String name = loc.getGlyphName(); if (name != null) return name; int cp = loc.getCodePoint(); name = psNames.get(cp); if (name != null) return name; name = Integer.toHexString(cp).toUpperCase(); if (cp >= 0x10000) return "u" + name; if (cp >= 0x1000) return "uni" + name; if (cp >= 0x100) return "uni0" + name; if (cp >= 0x10) return "uni00" + name; if (cp >= 0x0) return "uni000" + name; throw new IllegalArgumentException(name); } public String getName() { return "Sitelen Pona Cartouche Glyph"; } public Class getGlyphClass() { return BitmapFontGlyph.class; } public Result generate(Font font, List> locators) { if (locators.isEmpty()) return Result.NO_CHANGE; int a = -font.getLineAscent(); int d = font.getLineDescent()-1; for (GlyphLocator loc : locators) { BitmapFontGlyph g = loc.getGlyph(); if (g != null) { int w = g.getCharacterWidth(); BitmapFontGlyph extn = BitmapFontGlyph.compose(g); extn.expand(0, d, w, 1); extn.fillRect(0, d, w, 1, (byte)-1); BitmapFontGlyph cart = BitmapFontGlyph.compose(extn); cart.expand(0, a, w, 1); cart.fillRect(0, a, w, 1, (byte)-1); String name = getGlyphName(loc); font.putNamedGlyph(name + ".cartouche", cart); font.putNamedGlyph(name + ".extension", extn); } } return Result.REPERTOIRE_CHANGED; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/SwingUtils.java000066400000000000000000000144611506470510200313440ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.KeyStroke; public class SwingUtils { public static void setOpaque(JPanel p, boolean opaque) { p.setOpaque(opaque); for (int i = 0, n = p.getComponentCount(); i < n; i++) { Component c = p.getComponent(i); if (c instanceof JPanel) setOpaque((JPanel)c, opaque); } } public static void setDefaultButton(final JRootPane rp, final JButton b) { rp.setDefaultButton(b); } public static void setCancelButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); rp.getActionMap().put("cancel", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } public static void setDontSaveButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "dontSave"); rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, rp.getToolkit().getMenuShortcutKeyMask()), "dontSave"); rp.getActionMap().put("dontSave", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } public static BufferedImage toBufferedImage(Image image) { if (image == null) return null; // Prepare Toolkit tk = Toolkit.getDefaultToolkit(); boolean prepared = false; for (int attempts = 0; attempts < 10; attempts++) { prepared = tk.prepareImage(image, -1, -1, null); if (prepared) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } if (!prepared) return null; // Get Size int w = -1, h = -1; for (int attempts = 0; attempts < 10; attempts++) { w = image.getWidth(null); h = image.getHeight(null); if (w > 0 && h > 0) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } if (w < 1 || h < 1) return null; // Render BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); boolean drawn = false; for (int attempts = 0; attempts < 10; attempts++) { drawn = g.drawImage(image, 0, 0, null); if (drawn) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } g.dispose(); if (!drawn) return null; // Return return bi; } private static final int K = 0xFF000000; private static final int W = 0xFFFFFFFF; public static final Cursor CURSOR_CROSSHAIR = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); public static final Cursor CURSOR_MOVE = makeCursor( 17, 17, new int[] { 0,0,0,0,0,0,0,0,W,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,W,K,W,0,0,0,0,0,0,0, 0,0,0,0,0,0,W,K,K,K,W,0,0,0,0,0,0, 0,0,0,0,0,W,K,K,K,K,K,W,0,0,0,0,0, 0,0,0,0,W,W,W,W,K,W,W,W,W,0,0,0,0, 0,0,0,W,W,0,0,W,K,W,0,0,W,W,0,0,0, 0,0,W,K,W,0,0,W,K,W,0,0,W,K,W,0,0, 0,W,K,K,W,W,W,W,K,W,W,W,W,K,K,W,0, W,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,W, 0,W,K,K,W,W,W,W,K,W,W,W,W,K,K,W,0, 0,0,W,K,W,0,0,W,K,W,0,0,W,K,W,0,0, 0,0,0,W,W,0,0,W,K,W,0,0,W,W,0,0,0, 0,0,0,0,W,W,W,W,K,W,W,W,W,0,0,0,0, 0,0,0,0,0,W,K,K,K,K,K,W,0,0,0,0,0, 0,0,0,0,0,0,W,K,K,K,W,0,0,0,0,0,0, 0,0,0,0,0,0,0,W,K,W,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,W,0,0,0,0,0,0,0,0, }, 8, 8, "Move" ); public static final Cursor CURSOR_HAND_OPEN = makeCursor( 16, 16, new int[] { 0,0,0,0,0,0,0,K,K,0,0,0,0,0,0,0, 0,0,0,K,K,0,K,W,W,K,K,K,0,0,0,0, 0,0,K,W,W,K,K,W,W,K,W,W,K,0,0,0, 0,0,K,W,W,K,K,W,W,K,W,W,K,0,K,0, 0,0,0,K,W,W,K,W,W,K,W,W,K,K,W,K, 0,0,0,K,W,W,K,W,W,K,W,W,K,W,W,K, 0,K,K,0,K,W,W,W,W,W,W,W,K,W,W,K, K,W,W,K,K,W,W,W,W,W,W,W,W,W,W,K, K,W,W,W,K,W,W,W,W,W,W,W,W,W,K,0, 0,K,W,W,W,W,W,W,W,W,W,W,W,W,K,0, 0,0,K,W,W,W,W,W,W,W,W,W,W,W,K,0, 0,0,K,W,W,W,W,W,W,W,W,W,W,K,0,0, 0,0,0,K,W,W,W,W,W,W,W,W,W,K,0,0, 0,0,0,0,K,W,W,W,W,W,W,W,K,0,0,0, 0,0,0,0,0,K,W,W,W,W,W,W,K,0,0,0, 0,0,0,0,0,K,W,W,W,W,W,W,K,0,0,0, }, 6, 6, "Hand" ); public static final Cursor CURSOR_HAND_CLOSED = makeCursor( 16, 16, new int[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,K,K,0,K,K,0,K,K,0,0,0,0, 0,0,0,K,W,W,K,W,W,K,W,W,K,K,0,0, 0,0,0,K,W,W,W,W,W,W,W,W,K,W,K,0, 0,0,0,0,K,W,W,W,W,W,W,W,W,W,K,0, 0,0,0,K,K,W,W,W,W,W,W,W,W,W,K,0, 0,0,K,W,W,W,W,W,W,W,W,W,W,W,K,0, 0,0,K,W,W,W,W,W,W,W,W,W,W,W,K,0, 0,0,K,W,W,W,W,W,W,W,W,W,W,K,0,0, 0,0,0,K,W,W,W,W,W,W,W,W,W,K,0,0, 0,0,0,0,K,W,W,W,W,W,W,W,K,0,0,0, 0,0,0,0,0,K,W,W,W,W,W,W,K,0,0,0, 0,0,0,0,0,K,W,W,W,W,W,W,K,0,0,0, }, 6, 6, "HandClosed" ); public static Cursor makeCursor(int width, int height, int[] rgb, int hotx, int hoty, String name) { try { Toolkit tk = Toolkit.getDefaultToolkit(); Dimension d = tk.getBestCursorSize(width, height); if (d.width <= 0 || d.height <= 0) { System.err.println("Notice: System does not support custom cursors. Returning generic cursor."); return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); } if (d.width < width || d.height < height) { d = tk.getBestCursorSize(width*2, height*2); if (d.width < width || d.height < height) { System.err.println("Notice: Tool requested a cursor larger than possible on this system. Returning generic cursor."); return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); } } BufferedImage img2 = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB); img2.setRGB(0, 0, width, height, rgb, 0, width); return tk.createCustomCursor(img2, new Point(hotx, hoty), name); } catch (Exception e) { e.printStackTrace(); return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); } } } TimestampGlyphGenerator.java000066400000000000000000000043731506470510200337740ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.util.GregorianCalendar; import java.util.List; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class TimestampGlyphGenerator extends GlyphGenerator { public String getName() { return "Timestamp Glyph"; } public Class getGlyphClass() { return BitmapFontGlyph.class; } public Result generate(Font font, List> locators) { if (locators.isEmpty()) return Result.NO_CHANGE; BitmapFontGlyph[] glyphs = getTimestampGlyphs(font, new GregorianCalendar()); if (glyphs == null) return Result.NO_CHANGE; for (GlyphLocator loc : locators) { loc.setGlyph(BitmapFontGlyph.compose(glyphs)); } return Result.CONTENT_CHANGED; } public static BitmapFontGlyph[] getTimestampGlyphs(Font font, GregorianCalendar cal) { int y = cal.get(GregorianCalendar.YEAR); int m = cal.get(GregorianCalendar.MONTH) + 1; int d = cal.get(GregorianCalendar.DAY_OF_MONTH); BitmapFontGlyph[] namedGlyphs = { font.getNamedGlyph("timestamp.ch" + ((y / 1000) % 10)), font.getNamedGlyph("timestamp.cl" + ((y / 100) % 10)), font.getNamedGlyph("timestamp.yh" + ((y / 10) % 10)), font.getNamedGlyph("timestamp.yl" + ((y / 1) % 10)), font.getNamedGlyph("timestamp.mh" + ((m / 10) % 10)), font.getNamedGlyph("timestamp.ml" + ((m / 1) % 10)), font.getNamedGlyph("timestamp.dh" + ((d / 10) % 10)), font.getNamedGlyph("timestamp.dl" + ((d / 1) % 10)), font.getNamedGlyph("timestamp"), }; for (BitmapFontGlyph g : namedGlyphs) { if (g != null) return namedGlyphs; } BitmapFontGlyph[] mappedGlyphs = { font.getCharacter(0x10FF40 + ((y / 1000) % 10)), font.getCharacter(0x10FF50 + ((y / 100) % 10)), font.getCharacter(0x10FF60 + ((y / 10) % 10)), font.getCharacter(0x10FF70 + ((y / 1) % 10)), font.getCharacter(0x10FF80 + ((m / 10) % 10)), font.getCharacter(0x10FF90 + ((m / 1) % 10)), font.getCharacter(0x10FFA0 + ((d / 10) % 10)), font.getCharacter(0x10FFB0 + ((d / 1) % 10)), font.getCharacter(0x10FFC0) }; for (BitmapFontGlyph g : mappedGlyphs) { if (g != null) return mappedGlyphs; } return null; } } UnifontHexGlyphGenerator.java000066400000000000000000000061401506470510200341120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/editpackage com.kreative.bitsnpicas.edit; import java.util.List; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class UnifontHexGlyphGenerator extends GlyphGenerator { public String getName() { return "Unifont Hex Glyph"; } public Class getGlyphClass() { return BitmapFontGlyph.class; } public Result generate(Font font, List> locators) { if (locators.isEmpty()) return Result.NO_CHANGE; for (GlyphLocator loc : locators) { if (loc.isCodePoint()) { loc.setGlyph(createGlyph(loc.getCodePoint())); } } return Result.CONTENT_CHANGED; } public static BitmapFontGlyph createGlyph(int cp) { int offset = (cp < 0x10000) ? 1 : 0; return new BitmapFontGlyph(createGlyphData(cp), offset, 16, 13); } public static byte[][] createGlyphData(int cp) { int width = (cp < 0x10000) ? 14 : 16; byte[][] g = new byte[14][width]; for (int y = 0; y < 14; y++) { for (int x = 0; x < width; x++) { g[y][x] = -1; } } if (cp < 0x10000) { copy(g, 2, 1, digits[(cp >> 12) & 0x0F]); copy(g, 8, 1, digits[(cp >> 8) & 0x0F]); copy(g, 2, 8, digits[(cp >> 4) & 0x0F]); copy(g, 8, 8, digits[(cp >> 0) & 0x0F]); } else { copy(g, 1, 1, digits[(cp >> 20) & 0x0F]); copy(g, 6, 1, digits[(cp >> 16) & 0x0F]); copy(g, 11, 1, digits[(cp >> 12) & 0x0F]); copy(g, 1, 8, digits[(cp >> 8) & 0x0F]); copy(g, 6, 8, digits[(cp >> 4) & 0x0F]); copy(g, 11, 8, digits[(cp >> 0) & 0x0F]); } return g; } private static void copy(byte[][] dst, int x, int y, byte[][] src) { for (byte[] row : src) { for (byte col : row) { dst[y][x] = col; x++; } x -= row.length; y++; } } private static final byte[][][] digits = { {{-1, 0, 0, -1}, {0, -1, -1, 0}, {0, -1, -1, 0}, {0, -1, -1, 0}, {-1, 0, 0, -1}}, {{-1, -1, 0, -1}, {-1, 0, 0, -1}, {-1, -1, 0, -1}, {-1, -1, 0, -1}, {-1, 0, 0, 0}}, {{0, 0, 0, 0}, {-1, -1, -1, 0}, {0, 0, 0, 0}, {0, -1, -1, -1}, {0, 0, 0, 0}}, {{0, 0, 0, -1}, {-1, -1, -1, 0}, {-1, 0, 0, 0}, {-1, -1, -1, 0}, {0, 0, 0, -1}}, {{0, -1, -1, 0}, {0, -1, -1, 0}, {0, 0, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0}}, {{0, 0, 0, 0}, {0, -1, -1, -1}, {0, 0, 0, 0}, {-1, -1, -1, 0}, {0, 0, 0, 0}}, {{-1, 0, 0, -1}, {0, -1, -1, -1}, {0, 0, 0, -1}, {0, -1, -1, 0}, {-1, 0, 0, -1}}, {{0, 0, 0, 0}, {-1, -1, -1, 0}, {-1, -1, 0, -1}, {-1, 0, -1, -1}, {-1, 0, -1, -1}}, {{-1, 0, 0, -1}, {0, -1, -1, 0}, {-1, 0, 0, -1}, {0, -1, -1, 0}, {-1, 0, 0, -1}}, {{-1, 0, 0, -1}, {0, -1, -1, 0}, {-1, 0, 0, 0}, {-1, -1, -1, 0}, {-1, 0, 0, -1}}, {{0, 0, 0, 0}, {0, -1, -1, 0}, {0, 0, 0, 0}, {0, -1, -1, 0}, {0, -1, -1, 0}}, {{0, 0, 0, -1}, {0, -1, -1, 0}, {0, 0, 0, -1}, {0, -1, -1, 0}, {0, 0, 0, -1}}, {{-1, 0, 0, 0}, {0, -1, -1, -1}, {0, -1, -1, -1}, {0, -1, -1, -1}, {-1, 0, 0, 0}}, {{0, 0, 0, -1}, {0, -1, -1, 0}, {0, -1, -1, 0}, {0, -1, -1, 0}, {0, 0, 0, -1}}, {{0, 0, 0, 0}, {0, -1, -1, -1}, {0, 0, 0, -1}, {0, -1, -1, -1}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, -1, -1, -1}, {0, 0, 0, -1}, {0, -1, -1, -1}, {0, -1, -1, -1}}, }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporter/000077500000000000000000000000001506470510200302335ustar00rootroot00000000000000BitmapExportAmigaPanel.java000066400000000000000000000036601506470510200353610ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportAmigaPanel extends JPanel { private static final long serialVersionUID = 1L; private final JComboBox amigaEncoding; private final JComboBox amigaProportional; public BitmapExportAmigaPanel() { this.amigaEncoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); this.amigaProportional = new JComboBox(new String[]{"Auto", "No (Monospaced)", "Yes (Proportional)"}); amigaEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(amigaEncoding); JPanel amigaLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); amigaLabelPanel.add(new JLabel("Encoding")); amigaLabelPanel.add(new JLabel("Proportional")); JPanel amigaControlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); amigaControlPanel.add(amigaEncoding); amigaControlPanel.add(amigaProportional); JPanel amigaInnerPanel = new JPanel(new BorderLayout(8, 8)); amigaInnerPanel.add(amigaLabelPanel, BorderLayout.LINE_START); amigaInnerPanel.add(amigaControlPanel, BorderLayout.CENTER); JPanel amigaOuterPanel = new JPanel(new BorderLayout()); amigaOuterPanel.add(amigaInnerPanel, BorderLayout.LINE_START); this.setLayout(new BorderLayout()); this.add(amigaOuterPanel, BorderLayout.PAGE_START); } public GlyphList getSelectedEncoding() { return (GlyphList)(amigaEncoding.getSelectedItem()); } public void setSelectedEncoding(GlyphList enc) { amigaEncoding.setSelectedItem(enc); } public Boolean getAmigaProportional() { switch (amigaProportional.getSelectedIndex()) { default: return null; case 1: return false; case 2: return true; } } } BitmapExportColorPanel.java000066400000000000000000000033711506470510200354200ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; public class BitmapExportColorPanel extends JPanel { private static final long serialVersionUID = 1L; private final SpinnerNumberModel pngColorRed; private final SpinnerNumberModel pngColorGreen; private final SpinnerNumberModel pngColorBlue; public BitmapExportColorPanel() { this.pngColorRed = new SpinnerNumberModel(0, 0, 255, 1); this.pngColorGreen = new SpinnerNumberModel(0, 0, 255, 1); this.pngColorBlue = new SpinnerNumberModel(0, 0, 255, 1); JPanel pngColorLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); pngColorLabelPanel.add(new JLabel("Red")); pngColorLabelPanel.add(new JLabel("Green")); pngColorLabelPanel.add(new JLabel("Blue")); JPanel pngColorSpinnerPanel = new JPanel(new GridLayout(0, 1, 4, 4)); pngColorSpinnerPanel.add(new JSpinner(pngColorRed)); pngColorSpinnerPanel.add(new JSpinner(pngColorGreen)); pngColorSpinnerPanel.add(new JSpinner(pngColorBlue)); JPanel pngColorInnerPanel = new JPanel(new BorderLayout(8, 8)); pngColorInnerPanel.add(pngColorLabelPanel, BorderLayout.LINE_START); pngColorInnerPanel.add(pngColorSpinnerPanel, BorderLayout.CENTER); JPanel pngColorOuterPanel = new JPanel(new BorderLayout()); pngColorOuterPanel.add(pngColorInnerPanel, BorderLayout.LINE_START); this.setLayout(new BorderLayout()); this.add(pngColorOuterPanel, BorderLayout.PAGE_START); } public int getSelectedColor() { return ( (pngColorRed.getNumber().intValue() << 16) | (pngColorGreen.getNumber().intValue() << 8) | (pngColorBlue.getNumber().intValue() << 0) ); } } BitmapExportEncodingPanel.java000066400000000000000000000022721506470510200360670ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportEncodingPanel extends JPanel { private static final long serialVersionUID = 1L; private final JComboBox generalEncoding; public BitmapExportEncodingPanel() { this.generalEncoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); generalEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(generalEncoding); JPanel encodingInnerPanel = new JPanel(new BorderLayout(8, 8)); encodingInnerPanel.add(new JLabel("Encoding"), BorderLayout.LINE_START); encodingInnerPanel.add(generalEncoding, BorderLayout.CENTER); this.setLayout(new BorderLayout()); this.add(encodingInnerPanel, BorderLayout.PAGE_START); } public GlyphList getSelectedEncoding() { return (GlyphList)(generalEncoding.getSelectedItem()); } public void setSelectedEncoding(GlyphList enc) { generalEncoding.setSelectedItem(enc); } } BitmapExportFONTXPanel.java000066400000000000000000000054061506470510200352410ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.nio.charset.Charset; import javax.swing.ButtonGroup; import javax.swing.JComboBox; import javax.swing.JPanel; import javax.swing.JRadioButton; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportFONTXPanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton singleByte; private final JRadioButton doubleByte; private final JComboBox singleByteEncoding; private final JComboBox doubleByteEncoding; public BitmapExportFONTXPanel() { this.singleByte = new JRadioButton("Single-Byte Encoding:"); this.doubleByte = new JRadioButton("Double-Byte Encoding:"); this.singleByteEncoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); this.doubleByteEncoding = new JComboBox(Charset.availableCharsets().keySet().toArray()); singleByte.setSelected(true); doubleByte.setSelected(false); ButtonGroup bg = new ButtonGroup(); bg.add(singleByte); bg.add(doubleByte); JPanel bp = new JPanel(new GridLayout(0, 1, 4, 4)); bp.add(singleByte); bp.add(doubleByte); singleByteEncoding.setEditable(false); doubleByteEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(singleByteEncoding); new GLMLListCellRenderer("encoding").apply(doubleByteEncoding); singleByteEncoding.setSelectedItem(EncodingList.instance().getGlyphList("CP437")); doubleByteEncoding.setSelectedItem(Charset.forName("CP943").displayName()); JPanel ep = new JPanel(new GridLayout(0, 1, 4, 4)); ep.add(singleByteEncoding); ep.add(doubleByteEncoding); JPanel encodingInnerPanel = new JPanel(new BorderLayout(8, 8)); encodingInnerPanel.add(bp, BorderLayout.LINE_START); encodingInnerPanel.add(ep, BorderLayout.CENTER); this.setLayout(new BorderLayout()); this.add(encodingInnerPanel, BorderLayout.PAGE_START); singleByteEncoding.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { singleByte.setSelected(true); } }); doubleByteEncoding.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { doubleByte.setSelected(true); } }); } public boolean getSelectedSingleByte() { return singleByte.isSelected(); } public boolean getSelectedDoubleByte() { return doubleByte.isSelected(); } public GlyphList getSelectedSingleByteEncoding() { return (GlyphList)(singleByteEncoding.getSelectedItem()); } public String getSelectedDoubleByteEncoding() { return (String)(doubleByteEncoding.getSelectedItem()); } } BitmapExportFormat.java000066400000000000000000000177721506470510200346240ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.Dimension; import java.io.File; import java.io.IOException; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.exporter.*; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public enum BitmapExportFormat { KBITS("Kbits (Kreative Bits'n'Picas 1.x)", ".kbits", "v1") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new KbitsBitmapFontExporter(); } }, TTF("TTF (TrueType)", ".ttf", "ttf") { public BitmapFontExporter createExporter(BitmapExportOptions o) { Dimension d = o.getPixelDimension(); boolean exWinMtx = o.getExtendWinMetrics(); return new TTFBitmapFontExporter(d.width, d.height, exWinMtx); } }, OTB("OTB (OpenType Bitmap)", ".otb", "otb") { public BitmapFontExporter createExporter(BitmapExportOptions o) { boolean exWinMtx = o.getExtendWinMetrics(); return new OTBBitmapFontExporter(exWinMtx); } }, BDF("BDF (Bitmap Distribution Format)", ".bdf", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new BDFBitmapFontExporter(); } }, PSF("PSF (PC Screen Font) (Uncompressed)", ".psf", "psf") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new PSFBitmapFontExporter( o.getPSFVersion(), o.getPSFLowEncoding(), o.getPSFHighEncoding(), o.getPSFUseLowEncoding(), o.getPSFUseHighEncoding(), o.getPSFUseAllGlyphs(), o.getPSFUnicodeTable(), false ); } }, PSFGZ("PSF (PC Screen Font) (Gzip Compressed)", ".psf.gz", "psf") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new PSFBitmapFontExporter( o.getPSFVersion(), o.getPSFLowEncoding(), o.getPSFHighEncoding(), o.getPSFUseLowEncoding(), o.getPSFUseHighEncoding(), o.getPSFUseAllGlyphs(), o.getPSFUnicodeTable(), true ); } }, SUIT("Mac OS Classic Font Suitcase (Resource Fork)", ".suit", "mac", "MacRoman", true) { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new NFNTBitmapFontExporter.ResourceFile( o.getIDGenerator(), o.getPointSizeGenerator(), o.getSelectedEncoding() ); } public void postProcess(File file) throws IOException { MacUtility.setTypeAndCreator(file, "FFIL", "DMOV"); } }, DFONT("Mac OS Classic Font Suitcase (Data Fork)", ".dfont", "mac", "MacRoman", false) { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new NFNTBitmapFontExporter.ResourceFile( o.getIDGenerator(), o.getPointSizeGenerator(), o.getSelectedEncoding() ); } }, NFNT("Mac OS Classic Font Resource in Data Fork", ".nfnt", "encoding", "MacRoman") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new NFNTBitmapFontExporter.FlatFile(o.getSelectedEncoding()); } }, SFONT("PNG (SDL SFont)", ".png", "color") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new SFontBitmapFontExporter(o.getSelectedColor()); } }, RFONT("PNG (Kreative RFont)", ".png", "color") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new RFontBitmapFontExporter(o.getSelectedColor()); } }, HEX("Hex (GNU Unifont)", ".hex", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new HexBitmapFontExporter(); } }, CVT("GEOS Font in Convert Wrapper", ".cvt", "geos") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new GEOSBitmapFontExporter( o.getIDGenerator(), o.getPointSizeGenerator(), o.getGEOSMega(), o.getGEOSKerning(), o.getGEOSUTF8() ); } }, FZX("FZX (ZX Spectrum)", ".fzx", "encoding", "FZX PUA") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new FZXBitmapFontExporter(o.getSelectedEncoding()); } }, U8M("U8/M (UTF-8 for Microcomputers)", ".u8m", "u8m", "U8/M PETSCII") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new U8MBitmapFontExporter(o.getLoadAddress(), o.getSelectedEncoding()); } }, AMIGA("Amiga Font File and Directory", ".font", "amiga", "ISO-8859-1") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new AmigaBitmapFontExporter.ContentsFile(o.getAmigaProportional(), o.getSelectedEncoding()); } }, FNT3("FNT (Windows 3.x)", ".fnt", "encoding", "CP1252") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new FNTBitmapFontExporter(3, o.getSelectedEncoding()); } }, FNT2("FNT (Windows 2.x)", ".fnt", "encoding", "CP1252") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new FNTBitmapFontExporter(2, o.getSelectedEncoding()); } }, FONTX("FONTX (DOS/V)", ".fnt", "fontx") { public BitmapFontExporter createExporter(BitmapExportOptions o) { if (o.getFONTXDoubleByte()) { String en = o.getFONTXDoubleByteEncoding(); if (en == null || en.length() == 0) en = "CP943"; return new FONTXBitmapFontExporter(en); } else { GlyphList et = o.getSelectedEncoding(); if (et == null) et = EncodingList.instance().getGlyphList("CP437"); return new FONTXBitmapFontExporter(et); } } }, MGTK("MGTK (Apple II MouseGraphics ToolKit)", ".fnt", "encoding", "MouseDesk") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new MGTKBitmapFontExporter(o.getSelectedEncoding()); } }, RB12("RB12 (Rockbox 2.3 or above)", ".fnt", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new RockboxBitmapFontExporter(RockboxBitmapFontExporter.RB12); } }, RB11("RB11 (Rockbox 2.2 or below and iPodLinux)", ".fnt", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new RockboxBitmapFontExporter(RockboxBitmapFontExporter.RB11); } }, CYBIKO("Cybiko", ".fnt", "encoding", "Cybiko") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new CybikoBitmapFontExporter(o.getSelectedEncoding()); } }, PLAYDATE("Playdate", ".fnt", "playdate") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new PlaydateBitmapFontExporter(o.getPlaydateSeparate()); } }, HRCG("HRCG (Apple II Hi-Res Character Generator)", ".set", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new HRCGBitmapFontExporter(); } }, HMZK("HMZK (Mi Band 2)", ".hmzk", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new HMZKBitmapFontExporter(); } }, // **** Add new formats above this line. **** SBF("SBF (Sabriel Font)", ".sbf", "encoding", "Kreative SuperLatin") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new SBFBitmapFontExporter(o.getSelectedEncoding()); } }, TOS("TOS Character Set", ".ft", "none") { public BitmapFontExporter createExporter(BitmapExportOptions o) { return new TOSBitmapFontExporter(); } }; public final String name; public final String suffix; public final String cardName; public final String defaultEncodingName; public final boolean macResFork; private BitmapExportFormat(String name, String suffix, String cardName) { this.name = name; this.suffix = suffix; this.cardName = cardName; this.defaultEncodingName = null; this.macResFork = false; } private BitmapExportFormat(String name, String suffix, String cardName, String defaultEncodingName) { this.name = name; this.suffix = suffix; this.cardName = cardName; this.defaultEncodingName = defaultEncodingName; this.macResFork = false; } private BitmapExportFormat(String name, String suffix, String cardName, String defaultEncodingName, boolean macResFork) { this.name = name; this.suffix = suffix; this.cardName = cardName; this.defaultEncodingName = defaultEncodingName; this.macResFork = macResFork; } public abstract BitmapFontExporter createExporter(BitmapExportOptions o); public void postProcess(File file) throws IOException {} public String toString() { return this.name; } } BitmapExportFrame.java000066400000000000000000000007601506470510200344130ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import javax.swing.JFrame; import com.kreative.bitsnpicas.BitmapFont; public class BitmapExportFrame extends JFrame { private static final long serialVersionUID = 1L; private final BitmapExportPanel panel; public BitmapExportFrame(BitmapFont font) { this.panel = new BitmapExportPanel(font); setTitle("Export"); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } BitmapExportGEOSPanel.java000066400000000000000000000111521506470510200350730ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; public class BitmapExportGEOSPanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton geosFontIdAuto; private final JRadioButton geosFontIdManual; private final SpinnerNumberModel geosFontId; private final JRadioButton geosFontSizeAutoAny; private final JRadioButton geosFontSizeAutoStandard; private final JRadioButton geosFontSizeManual; private final SpinnerNumberModel geosFontSize; private final JRadioButton geosFontSizeMega; private final JCheckBox geosKerning; private final JCheckBox geosUTF8; public BitmapExportGEOSPanel() { this.geosFontIdAuto = new JRadioButton("Auto"); this.geosFontIdManual = new JRadioButton("Manual:"); this.geosFontId = new SpinnerNumberModel(512, 0, 0x3FF, 1); this.geosFontSizeAutoAny = new JRadioButton("Auto (Unrestricted)"); this.geosFontSizeAutoStandard = new JRadioButton("Auto (Standard Sizes)"); this.geosFontSizeManual = new JRadioButton("Manual:"); this.geosFontSize = new SpinnerNumberModel(12, 1, 63, 1); this.geosFontSizeMega = new JRadioButton("MEGA"); this.geosKerning = new JCheckBox("Add kerning tables (EXPERIMENTAL)"); this.geosUTF8 = new JCheckBox("Add UTF-8 tables (EXPERIMENTAL)"); geosFontIdAuto.setSelected(true); geosFontSizeAutoAny.setSelected(true); ButtonGroup geosFontIdGroup = new ButtonGroup(); geosFontIdGroup.add(geosFontIdAuto); geosFontIdGroup.add(geosFontIdManual); ButtonGroup geosFontSizeGroup = new ButtonGroup(); geosFontSizeGroup.add(geosFontSizeAutoAny); geosFontSizeGroup.add(geosFontSizeAutoStandard); geosFontSizeGroup.add(geosFontSizeManual); geosFontSizeGroup.add(geosFontSizeMega); JPanel geosFontIdManualPanel = new JPanel(new BorderLayout(8, 8)); geosFontIdManualPanel.add(geosFontIdManual, BorderLayout.LINE_START); geosFontIdManualPanel.add(new JSpinner(geosFontId), BorderLayout.CENTER); JPanel geosFontSizeManualPanel = new JPanel(new BorderLayout(8, 8)); geosFontSizeManualPanel.add(geosFontSizeManual, BorderLayout.LINE_START); geosFontSizeManualPanel.add(new JSpinner(geosFontSize), BorderLayout.CENTER); JPanel geosLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); geosLabelPanel.add(new JLabel("GEOS Font ID")); geosLabelPanel.add(new JLabel(" ")); geosLabelPanel.add(new JLabel("GEOS Font Size")); geosLabelPanel.add(new JLabel(" ")); geosLabelPanel.add(new JLabel(" ")); geosLabelPanel.add(new JLabel(" ")); geosLabelPanel.add(new JLabel("CX16 Extensions")); geosLabelPanel.add(new JLabel(" ")); JPanel geosControlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); geosControlPanel.add(geosFontIdAuto); geosControlPanel.add(geosFontIdManualPanel); geosControlPanel.add(geosFontSizeAutoAny); geosControlPanel.add(geosFontSizeAutoStandard); geosControlPanel.add(geosFontSizeManualPanel); geosControlPanel.add(geosFontSizeMega); geosControlPanel.add(geosKerning); geosControlPanel.add(geosUTF8); JPanel geosInnerPanel = new JPanel(new BorderLayout(8, 8)); geosInnerPanel.add(geosLabelPanel, BorderLayout.LINE_START); geosInnerPanel.add(geosControlPanel, BorderLayout.CENTER); JPanel geosOuterPanel = new JPanel(new BorderLayout()); geosOuterPanel.add(geosInnerPanel, BorderLayout.LINE_START); this.setLayout(new BorderLayout()); this.add(geosOuterPanel, BorderLayout.PAGE_START); } public IDGenerator getIDGenerator() { if (geosFontIdManual.isSelected()) { int id = geosFontId.getNumber().intValue(); return new IDGenerator.Sequential(id, 128, 1024); } else { return new IDGenerator.HashCode(128, 1024); } } public PointSizeGenerator getPointSizeGenerator() { if (geosFontSizeMega.isSelected()) { return new PointSizeGenerator.Fixed(48); } else if (geosFontSizeManual.isSelected()) { int size = geosFontSize.getNumber().intValue(); return new PointSizeGenerator.Fixed(size); } else if (geosFontSizeAutoStandard.isSelected()) { return new PointSizeGenerator.Standard(9, 10, 12, 14, 18, 24, 36, 48, 60); } else { return new PointSizeGenerator.Automatic(6, 63); } } public boolean getGEOSMega() { return geosFontSizeMega.isSelected(); } public boolean getGEOSKerning() { return geosKerning.isSelected(); } public boolean getGEOSUTF8() { return geosUTF8.isSelected(); } } BitmapExportLabelPanel.java000066400000000000000000000006631506470510200353620ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import javax.swing.JLabel; import javax.swing.JPanel; public class BitmapExportLabelPanel extends JPanel { private static final long serialVersionUID = 1L; public BitmapExportLabelPanel(String text) { super(new BorderLayout()); JLabel label = new JLabel(text); label.setHorizontalAlignment(JLabel.CENTER); add(label, BorderLayout.CENTER); } } BitmapExportMacPanel.java000066400000000000000000000104521506470510200350400ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportMacPanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton macFontIdAuto; private final JRadioButton macFontIdManual; private final SpinnerNumberModel macFontId; private final JRadioButton macFontSizeAutoAny; private final JRadioButton macFontSizeAutoStandard; private final JRadioButton macFontSizeManual; private final SpinnerNumberModel macFontSize; private final JComboBox macEncoding; public BitmapExportMacPanel() { this.macFontIdAuto = new JRadioButton("Auto"); this.macFontIdManual = new JRadioButton("Manual:"); this.macFontId = new SpinnerNumberModel(128, 128, 32767, 1); this.macFontSizeAutoAny = new JRadioButton("Auto (Unrestricted)"); this.macFontSizeAutoStandard = new JRadioButton("Auto (Standard Sizes)"); this.macFontSizeManual = new JRadioButton("Manual:"); this.macFontSize = new SpinnerNumberModel(12, 1, 127, 1); this.macEncoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); macFontIdAuto.setSelected(true); macFontSizeAutoAny.setSelected(true); macEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(macEncoding); ButtonGroup macFontIdGroup = new ButtonGroup(); macFontIdGroup.add(macFontIdAuto); macFontIdGroup.add(macFontIdManual); ButtonGroup macFontSizeGroup = new ButtonGroup(); macFontSizeGroup.add(macFontSizeAutoAny); macFontSizeGroup.add(macFontSizeAutoStandard); macFontSizeGroup.add(macFontSizeManual); JPanel macFontIdManualPanel = new JPanel(new BorderLayout(8, 8)); macFontIdManualPanel.add(macFontIdManual, BorderLayout.LINE_START); macFontIdManualPanel.add(new JSpinner(macFontId), BorderLayout.CENTER); JPanel macFontSizeManualPanel = new JPanel(new BorderLayout(8, 8)); macFontSizeManualPanel.add(macFontSizeManual, BorderLayout.LINE_START); macFontSizeManualPanel.add(new JSpinner(macFontSize), BorderLayout.CENTER); JPanel macLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); macLabelPanel.add(new JLabel("Macintosh Font ID")); macLabelPanel.add(new JLabel(" ")); macLabelPanel.add(new JLabel("Macintosh Font Size")); macLabelPanel.add(new JLabel(" ")); macLabelPanel.add(new JLabel(" ")); macLabelPanel.add(new JLabel("Encoding")); JPanel macControlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); macControlPanel.add(macFontIdAuto); macControlPanel.add(macFontIdManualPanel); macControlPanel.add(macFontSizeAutoAny); macControlPanel.add(macFontSizeAutoStandard); macControlPanel.add(macFontSizeManualPanel); macControlPanel.add(macEncoding); JPanel macInnerPanel = new JPanel(new BorderLayout(8, 8)); macInnerPanel.add(macLabelPanel, BorderLayout.LINE_START); macInnerPanel.add(macControlPanel, BorderLayout.CENTER); JPanel macOuterPanel = new JPanel(new BorderLayout()); macOuterPanel.add(macInnerPanel, BorderLayout.LINE_START); this.setLayout(new BorderLayout()); this.add(macOuterPanel, BorderLayout.PAGE_START); } public GlyphList getSelectedEncoding() { return (GlyphList)(macEncoding.getSelectedItem()); } public void setSelectedEncoding(GlyphList enc) { macEncoding.setSelectedItem(enc); } public IDGenerator getIDGenerator() { if (macFontIdManual.isSelected()) { int id = macFontId.getNumber().intValue(); return new IDGenerator.Sequential(id, 128, 32768); } else { return new IDGenerator.HashCode(128, 32768); } } public PointSizeGenerator getPointSizeGenerator() { if (macFontSizeManual.isSelected()) { int size = macFontSize.getNumber().intValue(); return new PointSizeGenerator.Fixed(size); } else if (macFontSizeAutoStandard.isSelected()) { return new PointSizeGenerator.Standard(9, 10, 12, 14, 18, 24, 36, 48, 72); } else { return new PointSizeGenerator.Automatic(4, 127); } } } BitmapExportOTBPanel.java000066400000000000000000000024211506470510200347610ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; public class BitmapExportOTBPanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton winMetricsLineHeight; private final JRadioButton winMetricsYminYmax; public BitmapExportOTBPanel() { this.winMetricsLineHeight = new JRadioButton("typoAscent/typoDescent
(Force line height. More compatible.)"); this.winMetricsYminYmax = new JRadioButton("yMin/yMax
(Prevent clipping. More conformant.)"); JPanel winMetricsPanel = new JPanel(new GridLayout(0, 1, 4, 4)); winMetricsPanel.add(new JLabel("Set winAscent/winDescent to:")); winMetricsPanel.add(winMetricsLineHeight); winMetricsPanel.add(winMetricsYminYmax); winMetricsLineHeight.setSelected(true); winMetricsYminYmax.setSelected(false); ButtonGroup bg = new ButtonGroup(); bg.add(winMetricsLineHeight); bg.add(winMetricsYminYmax); this.setLayout(new BorderLayout()); this.add(winMetricsPanel, BorderLayout.PAGE_START); } public boolean getExtendWinMetrics() { return winMetricsYminYmax.isSelected(); } } BitmapExportOptions.java000066400000000000000000000020361506470510200350120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.Dimension; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.unicode.data.GlyphList; public interface BitmapExportOptions { public Dimension getPixelDimension(); public boolean getExtendWinMetrics(); public int getSelectedColor(); public Integer getLoadAddress(); public GlyphList getSelectedEncoding(); public IDGenerator getIDGenerator(); public PointSizeGenerator getPointSizeGenerator(); public Boolean getAmigaProportional(); public boolean getGEOSMega(); public boolean getGEOSKerning(); public boolean getGEOSUTF8(); public boolean getFONTXDoubleByte(); public String getFONTXDoubleByteEncoding(); public int getPSFVersion(); public GlyphList getPSFLowEncoding(); public GlyphList getPSFHighEncoding(); public boolean getPSFUseLowEncoding(); public boolean getPSFUseHighEncoding(); public boolean getPSFUseAllGlyphs(); public boolean getPSFUnicodeTable(); public boolean getPlaydateSeparate(); } BitmapExportPSFPanel.java000066400000000000000000000113541506470510200347720ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportPSFPanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton version1; private final JRadioButton version2; private final JComboBox lowEncoding; private final JComboBox highEncoding; private final JCheckBox useLowEncoding; private final JCheckBox useHighEncoding; private final JCheckBox useAllGlyphs; private final JCheckBox unicodeTable; public BitmapExportPSFPanel() { this.version1 = new JRadioButton("PSF1"); this.version2 = new JRadioButton("PSF2"); this.version1.setSelected(false); this.version2.setSelected(true); ButtonGroup vbg = new ButtonGroup(); vbg.add(version1); vbg.add(version2); JPanel vp1 = new JPanel(new GridLayout(1, 0, 8, 8)); vp1.add(version1); vp1.add(version2); JPanel vp2 = new JPanel(new BorderLayout()); vp2.add(vp1, BorderLayout.LINE_START); ArrayList lea = new ArrayList(); lea.add("U+0000 - U+00FF"); lea.addAll(EncodingList.instance().glyphLists()); this.lowEncoding = new JComboBox(lea.toArray()); this.lowEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(lowEncoding); ArrayList hea = new ArrayList(); hea.add("U+0100 - U+01FF"); hea.addAll(EncodingList.instance().glyphLists()); this.highEncoding = new JComboBox(hea.toArray()); this.highEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(highEncoding); this.useLowEncoding = new JCheckBox("Include $000-$0FF"); this.useHighEncoding = new JCheckBox("Include $100-$1FF"); this.useAllGlyphs = new JCheckBox("Include all characters"); this.unicodeTable = new JCheckBox("Add Unicode mapping table"); this.useLowEncoding.setSelected(true); this.useHighEncoding.setSelected(false); this.useAllGlyphs.setSelected(true); this.unicodeTable.setSelected(true); JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); labelPanel.add(new JLabel("Version")); labelPanel.add(useLowEncoding); labelPanel.add(useHighEncoding); JPanel popupPanel = new JPanel(new GridLayout(0, 1, 4, 4)); popupPanel.add(vp2); popupPanel.add(lowEncoding); popupPanel.add(highEncoding); JPanel upperPanel = new JPanel(new BorderLayout(8, 8)); upperPanel.add(labelPanel, BorderLayout.LINE_START); upperPanel.add(popupPanel, BorderLayout.CENTER); JPanel lowerPanel = new JPanel(new GridLayout(0, 1, 4, 4)); lowerPanel.add(useAllGlyphs); lowerPanel.add(unicodeTable); lowerPanel.add(new JLabel()); JPanel mainPanel = new JPanel(new GridLayout(0, 1, 4, 4)); mainPanel.add(upperPanel); mainPanel.add(lowerPanel); this.setLayout(new BorderLayout()); this.add(mainPanel, BorderLayout.PAGE_START); version1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { useLowEncoding.setSelected(true); useLowEncoding.setEnabled(false); useAllGlyphs.setSelected(false); useAllGlyphs.setEnabled(false); } }); version2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { useLowEncoding.setSelected(true); useLowEncoding.setEnabled(true); useAllGlyphs.setSelected(true); useAllGlyphs.setEnabled(true); } }); lowEncoding.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { useLowEncoding.setSelected(true); } }); highEncoding.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { useHighEncoding.setSelected(true); } }); } public int getVersion() { return version1.isSelected() ? 1 : 2; } public GlyphList getLowEncoding() { if (lowEncoding.getSelectedIndex() <= 0) return null; return (GlyphList)lowEncoding.getSelectedItem(); } public GlyphList getHighEncoding() { if (highEncoding.getSelectedIndex() <= 0) return null; return (GlyphList)highEncoding.getSelectedItem(); } public boolean getUseLowEncoding() { return useLowEncoding.isSelected(); } public boolean getUseHighEncoding() { return useHighEncoding.isSelected(); } public boolean getUseAllGlyphs() { return useAllGlyphs.isSelected(); } public boolean getUnicodeTable() { return unicodeTable.isSelected(); } } BitmapExportPanel.java000066400000000000000000000204101506470510200344120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.File; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JPanel; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.bitsnpicas.edit.Main; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportPanel extends JPanel implements BitmapExportOptions { private static final long serialVersionUID = 1L; private final BitmapFont font; private final JComboBox format; private final BitmapExportTTFPanel ttfPanel; private final BitmapExportOTBPanel otbPanel; private final BitmapExportGEOSPanel geosPanel; private final BitmapExportMacPanel macPanel; private final BitmapExportAmigaPanel amigaPanel; private final BitmapExportEncodingPanel encodingPanel; private final BitmapExportFONTXPanel fontxPanel; private final BitmapExportU8MPanel u8mPanel; private final BitmapExportColorPanel colorPanel; private final BitmapExportPSFPanel psfPanel; private final BitmapExportPlaydatePanel playdatePanel; private final JButton exportButton; public BitmapExportPanel(BitmapFont font) { this.font = font; this.format = new JComboBox(BitmapExportFormat.values()); this.ttfPanel = new BitmapExportTTFPanel(); this.otbPanel = new BitmapExportOTBPanel(); this.geosPanel = new BitmapExportGEOSPanel(); this.macPanel = new BitmapExportMacPanel(); this.amigaPanel = new BitmapExportAmigaPanel(); this.encodingPanel = new BitmapExportEncodingPanel(); this.fontxPanel = new BitmapExportFONTXPanel(); this.u8mPanel = new BitmapExportU8MPanel(); this.colorPanel = new BitmapExportColorPanel(); this.psfPanel = new BitmapExportPSFPanel(); this.playdatePanel = new BitmapExportPlaydatePanel(); this.exportButton = new JButton("Export"); JPanel nonePanel = new BitmapExportLabelPanel("This format has no options."); JPanel v1Panel = new BitmapExportLabelPanel( "
Version 1.x only supports basic metrics, names,
" + "and mapped characters. Other features, such
" + "as named glyphs and kerning pairs, will be lost.
" ); final CardLayout formatOptionsLayout = new CardLayout(); final JPanel formatOptionsPanel = new JPanel(formatOptionsLayout); formatOptionsPanel.add(ttfPanel, "ttf"); formatOptionsPanel.add(otbPanel, "otb"); formatOptionsPanel.add(geosPanel, "geos"); formatOptionsPanel.add(macPanel, "mac"); formatOptionsPanel.add(amigaPanel, "amiga"); formatOptionsPanel.add(encodingPanel, "encoding"); formatOptionsPanel.add(fontxPanel, "fontx"); formatOptionsPanel.add(u8mPanel, "u8m"); formatOptionsPanel.add(colorPanel, "color"); formatOptionsPanel.add(psfPanel, "psf"); formatOptionsPanel.add(playdatePanel, "playdate"); formatOptionsPanel.add(v1Panel, "v1"); formatOptionsPanel.add(nonePanel, "none"); format.setEditable(false); format.setMaximumRowCount(BitmapExportFormat.values().length); format.setSelectedItem(BitmapExportFormat.TTF); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(exportButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(format, BorderLayout.PAGE_START); mainPanel.add(formatOptionsPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); setLayout(new BorderLayout()); add(mainPanel, BorderLayout.CENTER); format.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); formatOptionsLayout.show(formatOptionsPanel, f.cardName); GlyphList enc = ( (f.defaultEncodingName == null) ? null : EncodingList.instance().getGlyphList(f.defaultEncodingName) ); macPanel.setSelectedEncoding(enc); amigaPanel.setSelectedEncoding(enc); encodingPanel.setSelectedEncoding(enc); u8mPanel.setSelectedEncoding(enc); Window c = getMyContainingWindow(); if (c != null) c.pack(); } }); exportButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); if (f == null) return; BitmapFontExporter exporter = f.createExporter(BitmapExportPanel.this); if (exporter == null) return; File file = Main.getSaveFile(f.suffix); if (file == null) return; if (f.macResFork) { try { file.createNewFile(); } catch (IOException ioe) {} file = new File(file, "..namedfork"); file = new File(file, "rsrc"); } if (Main.saveFont(file, exporter, BitmapExportPanel.this.font)) { if (f.macResFork) file = file.getParentFile().getParentFile(); try { f.postProcess(file); } catch (IOException ioe) {} Window c = getMyContainingWindow(); if (c != null) c.dispose(); } } }); } private Window getMyContainingWindow() { Component c = getParent(); while (c != null) { if (c instanceof Window) { return ((Window)c); } else { c = c.getParent(); } } return null; } @Override public Dimension getPixelDimension() { return ttfPanel.getPixelDimension(); } @Override public boolean getExtendWinMetrics() { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); if (f.cardName.equals("otb")) return otbPanel.getExtendWinMetrics(); return ttfPanel.getExtendWinMetrics(); } @Override public int getSelectedColor() { return colorPanel.getSelectedColor(); } @Override public Integer getLoadAddress() { return u8mPanel.getLoadAddress(); } @Override public GlyphList getSelectedEncoding() { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); if (f.cardName.equals("mac")) return macPanel.getSelectedEncoding(); if (f.cardName.equals("amiga")) return amigaPanel.getSelectedEncoding(); if (f.cardName.equals("u8m")) return u8mPanel.getSelectedEncoding(); if (f.cardName.equals("fontx")) return fontxPanel.getSelectedSingleByteEncoding(); return encodingPanel.getSelectedEncoding(); } @Override public IDGenerator getIDGenerator() { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); if (f.cardName.equals("geos")) return geosPanel.getIDGenerator(); return macPanel.getIDGenerator(); } @Override public PointSizeGenerator getPointSizeGenerator() { BitmapExportFormat f = (BitmapExportFormat)format.getSelectedItem(); if (f.cardName.equals("geos")) return geosPanel.getPointSizeGenerator(); return macPanel.getPointSizeGenerator(); } @Override public Boolean getAmigaProportional() { return amigaPanel.getAmigaProportional(); } @Override public boolean getGEOSMega() { return geosPanel.getGEOSMega(); } @Override public boolean getGEOSKerning() { return geosPanel.getGEOSKerning(); } @Override public boolean getGEOSUTF8() { return geosPanel.getGEOSUTF8(); } @Override public boolean getFONTXDoubleByte() { return fontxPanel.getSelectedDoubleByte(); } @Override public String getFONTXDoubleByteEncoding() { return fontxPanel.getSelectedDoubleByteEncoding(); } @Override public int getPSFVersion() { return psfPanel.getVersion(); } @Override public GlyphList getPSFLowEncoding() { return psfPanel.getLowEncoding(); } @Override public GlyphList getPSFHighEncoding() { return psfPanel.getHighEncoding(); } @Override public boolean getPSFUseLowEncoding() { return psfPanel.getUseLowEncoding(); } @Override public boolean getPSFUseHighEncoding() { return psfPanel.getUseHighEncoding(); } @Override public boolean getPSFUseAllGlyphs() { return psfPanel.getUseAllGlyphs(); } @Override public boolean getPSFUnicodeTable() { return psfPanel.getUnicodeTable(); } @Override public boolean getPlaydateSeparate() { return playdatePanel.getSeparate(); } } BitmapExportPlaydatePanel.java000066400000000000000000000016451506470510200361070ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JPanel; import javax.swing.JRadioButton; public class BitmapExportPlaydatePanel extends JPanel { private static final long serialVersionUID = 1L; private final JRadioButton allInOne; private final JRadioButton separate; public BitmapExportPlaydatePanel() { this.allInOne = new JRadioButton("All-in-one (fnt)"); this.separate = new JRadioButton("Separate (fnt+png)"); this.allInOne.setSelected(true); this.separate.setSelected(false); ButtonGroup bg = new ButtonGroup(); bg.add(allInOne); bg.add(separate); JPanel bp = new JPanel(new GridLayout(0, 1, 4, 4)); bp.add(allInOne); bp.add(separate); this.setLayout(new BorderLayout()); this.add(bp, BorderLayout.PAGE_START); } public boolean getSeparate() { return separate.isSelected(); } } BitmapExportTTFPanel.java000066400000000000000000000055761506470510200350100ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; public class BitmapExportTTFPanel extends JPanel { private static final long serialVersionUID = 1L; private final SpinnerNumberModel pixelWidth; private final SpinnerNumberModel pixelHeight; private final JRadioButton winMetricsLineHeight; private final JRadioButton winMetricsYminYmax; public BitmapExportTTFPanel() { this.pixelWidth = new SpinnerNumberModel(100, 1, 1000, 1); this.pixelHeight = new SpinnerNumberModel(100, 1, 1000, 1); this.winMetricsLineHeight = new JRadioButton("typoAscent/typoDescent
(Force line height. More compatible.)"); this.winMetricsYminYmax = new JRadioButton("yMin/yMax
(Prevent clipping. More conformant.)"); JPanel pixelLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); pixelLabelPanel.add(new JLabel("Pixel Width")); pixelLabelPanel.add(new JLabel("Pixel Height")); JPanel pixelSpinnerPanel = new JPanel(new GridLayout(0, 1, 4, 4)); pixelSpinnerPanel.add(new JSpinner(pixelWidth)); pixelSpinnerPanel.add(new JSpinner(pixelHeight)); JPanel pixelUnitPanel = new JPanel(new GridLayout(0, 1, 4, 4)); pixelUnitPanel.add(new JLabel("em units")); pixelUnitPanel.add(new JLabel("em units")); JPanel pixelInnerPanel1 = new JPanel(new BorderLayout(8, 8)); pixelInnerPanel1.add(pixelLabelPanel, BorderLayout.LINE_START); pixelInnerPanel1.add(pixelSpinnerPanel, BorderLayout.CENTER); JPanel pixelInnerPanel2 = new JPanel(new BorderLayout(8, 8)); pixelInnerPanel2.add(pixelInnerPanel1, BorderLayout.LINE_START); pixelInnerPanel2.add(pixelUnitPanel, BorderLayout.CENTER); JPanel pixelOuterPanel = new JPanel(new BorderLayout()); pixelOuterPanel.add(pixelInnerPanel2, BorderLayout.LINE_START); JPanel winMetricsPanel = new JPanel(new GridLayout(0, 1, 4, 4)); winMetricsPanel.add(new JLabel("Set winAscent/winDescent to:")); winMetricsPanel.add(winMetricsLineHeight); winMetricsPanel.add(winMetricsYminYmax); winMetricsLineHeight.setSelected(true); winMetricsYminYmax.setSelected(false); ButtonGroup bg = new ButtonGroup(); bg.add(winMetricsLineHeight); bg.add(winMetricsYminYmax); JPanel outerPanel = new JPanel(new BorderLayout(8, 8)); outerPanel.add(pixelOuterPanel, BorderLayout.PAGE_START); outerPanel.add(winMetricsPanel, BorderLayout.CENTER); this.setLayout(new BorderLayout()); this.add(outerPanel, BorderLayout.PAGE_START); } public Dimension getPixelDimension() { return new Dimension( pixelWidth.getNumber().intValue(), pixelHeight.getNumber().intValue() ); } public boolean getExtendWinMetrics() { return winMetricsYminYmax.isSelected(); } } BitmapExportU8MPanel.java000066400000000000000000000050011506470510200347430ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/exporterpackage com.kreative.bitsnpicas.edit.exporter; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapExportU8MPanel extends JPanel { private static final long serialVersionUID = 1L; private final JComboBox u8mEncoding; private final JCheckBox u8mHasLoadAddress; private final JTextField u8mLoadAddress; public BitmapExportU8MPanel() { this.u8mEncoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); this.u8mHasLoadAddress = new JCheckBox("Load Address:"); this.u8mLoadAddress = new JTextField("$A000"); u8mEncoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(u8mEncoding); u8mLoadAddress.setEnabled(false); JPanel u8mLabelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); u8mLabelPanel.add(u8mHasLoadAddress); u8mLabelPanel.add(new JLabel("Native Encoding:")); JPanel u8mLoadAddressPanel = new JPanel(new BorderLayout()); u8mLoadAddressPanel.add(u8mLoadAddress, BorderLayout.LINE_START); JPanel u8mControlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); u8mControlPanel.add(u8mLoadAddressPanel); u8mControlPanel.add(u8mEncoding); JPanel u8mInnerPanel = new JPanel(new BorderLayout(8, 8)); u8mInnerPanel.add(u8mLabelPanel, BorderLayout.LINE_START); u8mInnerPanel.add(u8mControlPanel, BorderLayout.CENTER); this.setLayout(new BorderLayout()); this.add(u8mInnerPanel, BorderLayout.PAGE_START); u8mHasLoadAddress.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { u8mLoadAddress.setEnabled(u8mHasLoadAddress.isSelected()); } }); } public Integer getLoadAddress() { if (u8mHasLoadAddress.isSelected()) { String s = u8mLoadAddress.getText(); try { if (s.startsWith("0X") || s.startsWith("0x")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("$")) return Integer.parseInt(s.substring(1), 16); return Integer.parseInt(s); } catch (NumberFormatException e) {} } return null; } public GlyphList getSelectedEncoding() { return (GlyphList)(u8mEncoding.getSelectedItem()); } public void setSelectedEncoding(GlyphList enc) { u8mEncoding.setSelectedItem(enc); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/000077500000000000000000000000001506470510200301675ustar00rootroot00000000000000GLMLListCellRenderer.java000066400000000000000000000035471506470510200346420ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmliconpackage com.kreative.bitsnpicas.edit.glmlicon; import java.awt.Component; import java.awt.Dimension; import java.awt.Image; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.ImageIcon; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JList; import com.kreative.unicode.data.Encoding; import com.kreative.unicode.data.GlyphList; public class GLMLListCellRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = 1L; private final String group; public GLMLListCellRenderer() { this.group = null; } public GLMLListCellRenderer(String group) { this.group = group; } public void apply(JComboBox c) { Dimension d1 = c.getPreferredSize(); c.setRenderer(this); Dimension d2 = c.getPreferredSize(); int width = Math.max(d1.width, d2.width); int height = Math.max(d1.height, d2.height); c.setPreferredSize(new Dimension(width, height)); } public Component getListCellRendererComponent( JList list, Object value, int index, boolean sel, boolean focus ) { Component c = super.getListCellRendererComponent(list, value, index, sel, focus); if (c instanceof JLabel) { JLabel label = (JLabel)c; label.setBorder(BorderFactory.createEmptyBorder(4, 8, 4, 8)); label.setIcon(new ImageIcon(getImageForListCell(value))); } return c; } private Image getImageForListCell(Object value) { if (value instanceof GlyphList) { String group = (this.group != null) ? this.group : "glyphlist"; String name = ((GlyphList)value).getName(); return GLMLResources.getImage(group, name); } if (value instanceof Encoding) { String group = (this.group != null) ? this.group : "encoding"; String name = ((Encoding)value).getName(); return GLMLResources.getImage(group, name); } return GLMLResources.getImage(this.group, value.toString()); } } GLMLResources.java000066400000000000000000000050721506470510200334050ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmliconpackage com.kreative.bitsnpicas.edit.glmlicon; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import javax.imageio.ImageIO; public class GLMLResources { public static Image getImage(String group, String name) { if (group != null && name != null) { if (group.equals("subtable")) { try { int v = Integer.parseInt(name.substring(name.length() - 2), 16); if (subtableImages[v] != null) return subtableImages[v]; } catch (NumberFormatException nfe) {} } Map submap = mappedImages.get(group); if (submap != null) { Image image = submap.get(name); if (image != null) return image; } } return getImage("unknown.png"); } private static final Map imageResources = new HashMap(); private static Image getImage(String name) { Image image = imageResources.get(name); if (image != null) return image; URL res = GLMLResources.class.getResource(name); if (res == null) return null; image = Toolkit.getDefaultToolkit().createImage(res); if (image == null) return null; imageResources.put(name, image); return image; } private static final Map> mappedImages = new HashMap>(); static { Scanner index = new Scanner(GLMLResources.class.getResourceAsStream("index.txt")); while (index.hasNextLine()) { String[] line = index.nextLine().trim().split("\\s+", 3); if (line.length != 3) continue; Image image = getImage(line[0]); if (image == null) continue; Map submap = mappedImages.get(line[1]); if (submap == null) mappedImages.put(line[1], (submap = new HashMap())); submap.put(line[2], image); } index.close(); } private static final BufferedImage[] subtableImages = new BufferedImage[256]; static { try { BufferedImage ss = ImageIO.read(GLMLResources.class.getResource("subtable.png")); int cw = ss.getWidth() / 32; int ch = ss.getHeight(); int[] rgb = new int[cw * ch]; for (int v0 = 0; v0 < 16; v0++) { for (int v1 = 0; v1 < 16; v1++) { BufferedImage ci = new BufferedImage(cw*2, ch, BufferedImage.TYPE_INT_ARGB); ss.getRGB((v0*2) * cw, 0, cw, ch, rgb, 0, cw); ci.setRGB(0, 0, cw, ch, rgb, 0, cw); ss.getRGB((v1*2+1) * cw, 0, cw, ch, rgb, 0, cw); ci.setRGB(cw, 0, cw, ch, rgb, 0, cw); subtableImages[(v0 << 4) | v1] = ci; } } } catch (IOException e) { e.printStackTrace(); } } } GLMLTreeCellRenderer.java000066400000000000000000000031771506470510200346250ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmliconpackage com.kreative.bitsnpicas.edit.glmlicon; import java.awt.Component; import java.awt.Dimension; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JTree; import javax.swing.JViewport; import javax.swing.tree.DefaultTreeCellRenderer; import com.kreative.bitsnpicas.edit.GlyphListModel; import com.kreative.bitsnpicas.edit.GlyphListModelList.GlyphListModelTreeNode; public class GLMLTreeCellRenderer extends DefaultTreeCellRenderer { private static final long serialVersionUID = 1L; public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean exp, boolean leaf, int row, boolean focus ) { Component c = super.getTreeCellRendererComponent(tree, value, sel, exp, leaf, row, false); if (c instanceof JLabel) { JLabel label = (JLabel)c; Dimension d = label.getPreferredSize(); int tw = getViewportWidth(tree); if (d.width < tw) d.width = tw; if (d.height < 24) d.height = 24; label.setPreferredSize(d); label.setIcon(new ImageIcon(getImageForTreeCell(value))); } return c; } private static int getViewportWidth(Component c) { while (c != null) { if (c instanceof JViewport) { return c.getWidth(); } c = c.getParent(); } return -1; } private static Image getImageForTreeCell(Object value) { if (value instanceof GlyphListModelTreeNode) { GlyphListModel model = ((GlyphListModelTreeNode)value).getModel(); if (model != null) { String group = model.getIconGroup(); String name = value.toString(); return GLMLResources.getImage(group, name); } } return GLMLResources.getImage(null, null); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/allcodes.png000066400000000000000000000004241506470510200324630ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS ÛȟW}D{1NhL&d0oskϛH. Db:@`ዟ^XZ9xq!܁s_#  0<9yyB2QW/+ͮmPd?k^xC~]pIBu [ )2az`iIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/atari8.png000066400000000000000000000002511506470510200320630ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<;IDATxbVS@h`@3X 0:@0r#@GvHJIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/atarist.png000066400000000000000000000004441506470510200323460ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڴ= ˖ isxݻx4DTvO Gqx LnBzr ^A]aG8gteYc,;K 6G!uF1T: }'}Z5Ykg9R`7<Jb;c̝ Sb&!A~a ;~_IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/big5.png000066400000000000000000000011611506470510200315220ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڜSKAfw'5&&]**$JA@Pz 'R_!?J{t]FҢar2`UzBK6x< zǁ-/E2iX ݺ zzHb~ :vwsHzQ(rp6H SSq/*ae%RL~AY혝}FG_55>ޅ:OaP5DeP՗ fq.`@~ p_pF7(VҌL| 9yr Hqn0RcIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure080.png000066400000000000000000000006621506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<DIDATxbL3Y@h`@3lzQzЕf b|b-0FjYҴe8ɶdP՗PbL=ƠgP 7]a³`ob߾bagQlpqa ^`]/>3\< ,6mΛ`Äyw`xr-Cl70d3Hf XpE_f?g2a9A:`gQ .`p> v1| iF'7А3yAHAFY!܁AFaV.u8 X/`6'7CZC:&\Kis75M <eTDi'vނK, t-< M}K0 ꢖ1<̮ 6ؒ>_N6^pWcHkrgXun++@ - @[@ 2duӚ q1 %O6=,@j1 mRŹ nZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure150.png000066400000000000000000000003761506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-bXnΰ0V‰S,N 8۪+A0`N&\68 9jK一`,!+ъIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure1b0.png000066400000000000000000000005161506470510200323230ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz\ɝ />cP՗bQFu`6dK5?gx3og̀M-N[,KN60`" 3.}Hn`#+`!hz4^: @ wkpWê ML Ad(yd@mr\@Qn0[H&+qGIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure1d0.png000066400000000000000000000004671506470510200323320ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ|3BU})8ɝ ߿![Ăn4H8/CZÉ/: I0 a^~f0wWc303/q [F!H8(Ad(y"Pd@mr\@Qn0SsIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure200.png000066400000000000000000000005461506470510200322450ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӼuak`b "k/3p3Xt >u L3 ty fas  '7 rť޾L'vڬf˨3K1l_t| w ate  pAӎax#1lѳV`7 @ɓXX&P PYs IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure270.png000066400000000000000000000007441506470510200322540ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<vIDATxbL3Y@h`@3lzQzӖ?Ù.}ps$<*##EL&4o_t' FJ  l,`6H $R P 'JG- |e/X $RAN;n22Xyi0v,i/%p|Mf3W5So3,R?Ò ߿bQf2 aAlؾ}ÊC ~c`bb~< ^ANxa5ϯ~b0uQ+dX N@3UcX3k  Ja  0a,m (΍ט{)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure290.png000066400000000000000000000005041506470510200322500ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-s3 ~Π/ ,pbM:ÓorR]ض,acrȀb/ƀ_~ae D^f3fض,Ó;o1`]=+a+@@&iX, P)pW#*)#074(ʍ)PJ{EIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure2c0.png000066400000000000000000000004551506470510200323270ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖҌ,Lٛg3!KRddqUȚ&l # mQl⌱b+8 EX 0Dr;MR'Ű}?Q3Z3W:L qE fLIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure2d0.png000066400000000000000000000004621506470510200323260ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-N1:βdQ&l#E[b/ Ryp3\ /leU k.}B+N6'r )s{uA: (IX&')ʍ!U<> IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure300.png000066400000000000000000000005441506470510200322440ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6߿bؿ2}m2ܾ aX U/ o_|fX;80X 'mY@98/`3]aIw{DK炘2b `,B yg3FE(6dTF)N@^;;pbBNdp6`jZ[- IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure340.png000066400000000000000000000005731506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzЕf ]- .E>`xr--$ˠoÆ YuN ,̠/hPGZ_~g􀶪K g X0~ɜ@ap eQ& [F_2toL(܁D>z98P^X;8C.@@.B   \ \0eoX~0%ObZ `iT@qn0XZ1KIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure360.png000066400000000000000000000005141506470510200322470ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz1K=+sĦ&mCV˄MyKmY'w4[ \< jhCo_|fX;8l8/C~ 3P`xAX M 6 ͠XβH= g'(y3| &IX&P M9bZ|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure380.png000066400000000000000000000005041506470510200322500ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6L,[8[ kj 6,K<.3Ĕ:o0Cj  U}Im΂5 Xp н1h%ObZ `iDQn0x=WIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure3b0.png000066400000000000000000000005371506470510200323300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-Àk/3cXu.'"LfV&-: ;,Ո3 ^q`fbpX V A'E8'Y-MNJ(7VʠXIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure400.png000066400000000000000000000005531506470510200322450ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf //>!egH-`W1&|\:AZ!ׇX`u2{n'qvq `v]2 X o_~2p1Ė90̮߅ӛX ]lP6fc.ɝy w.5 Jp1U})> 7̄<j.mRŹ M۸IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure430.png000066400000000000000000000006461506470510200322530ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<8IDATxbL3Y@h`@3lz ""u`6L]3uajpg /`[ >`Hkr# j}ˠg@ i p`+ KÆ(F@ɓXX&'%R q3b)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure470.png000066400000000000000000000005351506470510200322540ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖgw/?c(,Æb ".vI[l!q^0 20 ]dCL=iHkrİlR`mY'w280Kb5 W@y3y_ 8P`Q+x]Jdp6`7NF.rIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure490.png000066400000000000000000000005141506470510200322530ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-1N;ΰV9}#}-SU >n_|g̠gS ŰmY0mᮆW3V8y8ꢗ]``c.] @WA `@FEbf0Ó;o&m{Xy' Oq IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure580.png000066400000000000000000000004261506470510200322550ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf "k}V2aS0h X Ku . f ]0!8 ipWc)sN;U .@adIs:`` 7t@ɓXM(ʍi/ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure5a0.png000066400000000000000000000005441506470510200323270ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf bg'wb#eg]N;5L t-:/w/?&mӎ: z ]0x30CL=Ox#FyYu{0n_| r 5_8yTp3U})a ^;o*f,K0iMntdg@\:%ObZ `iT@qn03UGkIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure5c0.png000066400000000000000000000004771506470510200323360ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf b/0Fjٴv1;ou >ɘ2j ߾Qfβ$΀]@.ض,X+ pj l!Oz >ypsb5ӎ38bǬ]HCHҼJdp6`hFIʇIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure5e0.png000066400000000000000000000005571506470510200323370ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-bX9OeX;8ûFŖtz e !.8/&h(&`p6k#lotZ8f| h>4Aag Pt"2`ANSa,m (΍|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure650.png000066400000000000000000000005241506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-.E߿btC,m2}:tm ςixc=k0[U_AXL  lFܾ )]e&7yK/>cQc.Ò@3(6R8x3J| y  V &(P$ IFU>&ɐEIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure680.png000066400000000000000000000004341506470510200322550ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6/>cqptu0Ab6`(a3 > 1l 4-dP/#l11P(6# @QcOٛtD{<j.mr`a49p A IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure6d0.png000066400000000000000000000004321506470510200323270ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-`p8 cyxfbx3iwLz />xN#8c΂߾{1H,eTFI,@V w,mFAEgQİ`fia ^0DE Aj0Ó;oQعXd1c1 wh< />g2Af8: 6dpKB[+"* @ɓXX&'(ʍmBg0NIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure770.png000066400000000000000000000004511506470510200322540ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-]`ya" m` ~c``b%dX5Hs ^=f&N .8v +3~'r 3fxz-֤a,m (΍EIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure780.png000066400000000000000000000005551506470510200322620ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ ^~UtcP2aa k4 C;o1:`y`bw.>ê AA@x xr ÆrІ׈vc.x\`,xm\;5p@ 8l(PeT7&N@9&0Jj1 mrb`~`L.?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure800.png000066400000000000000000000004631506470510200322510ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-bXpIvɝ`$W1igY_~1E/#݀KG0< q/g@\̪Ű8l.}CZBɝ79AN QlLZ:%ObZ `iHQn0?19\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure830.png000066400000000000000000000005341506470510200322530ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- >/>cؿ /|a¥ 'wbxz-WNK[!q^8c0/E "̰}YAC/> ^~faCQ3A;'aQ^Y85ti%x^)q5'Y-M*87WYXIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csure890.png000066400000000000000000000005431506470510200322610ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-Ģ- E{r-C ߿Bc"dH  p;oia ^$cɨ-: 6z ~|3X:Cp%< 8ڽ1< 9y ½K一`aDeڜGIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csureaa0.png000066400000000000000000000004251506470510200324010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ[>:lj( z@YX+1W:2LٛVYh 6H $RC #ᅈB;@6[h$,Tt20dװ@N4R >ojwuIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csureb00.png000066400000000000000000000005651506470510200323260ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-_~1,:9yuT7YZ] lȶEg.}eT%޽0h ;ohڿ2 u!^ Oӎ3ܾAHAFYdp"`r-aK|z-W1 P ;odj5aH.`BNdp/69.(7Z[]CAIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csureb40.png000066400000000000000000000004511506470510200323240ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf |3 1d,lyr-] B ^dHmtcQPDŽˀ.3x3ii_%xl d2Qaβ$N6'|bFc,(ˈ<M# I,@V w,mF 0DIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csureb60.png000066400000000000000000000004041506470510200323240ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6^f(_@a,U7@FE6䅵ӎ|^F/O0aT՗cNv 12a` w.>#.38 )s P܃4 .XQXbf0$0D @ɓXX&P OG8tIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurebe0.png000066400000000000000000000005331506470510200324060ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2ׁL0AYX5ݿ.l16~anr ?Â} F}Y?0nӏoƐ\Do_|fXԱ!ΕO %X 0v381K"VVM>/i@0pS GV@f#P){dT*!3Y lG3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurebf0.png000066400000000000000000000003331506470510200324050ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<mIDATxbL3Y@h`@3lzQzӖ9yVSae2Bl#ڀQ/ @°y=)cKۤs#@;$pyIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurec00.png000066400000000000000000000004751506470510200323270ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-Ģ- : ^|] }?bJӎ⌉3R%x&7/>cU3 xQ0È6`c ߿-:K|'u08˒xMӸ4br$ {qE C<yaIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurec30.png000066400000000000000000000004751506470510200323320ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-.}|a,K X;8XW/B н1 ̿}N/` sX гVz[+9γ.f'-@! uPl[xx/'. ,½K一`˞?GŧotIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurec70.png000066400000000000000000000006021506470510200323260ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӜ< L˨3x3Y+`l d~~r-ì]`N0 c./ |/N;O wu Xu`C,"  r> {[ 8_ 7]/A3fؿ Vy&bMZY 2 <g2xÁXqYV@oi(y ]KE 28IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csured40.png000066400000000000000000000003731506470510200323310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf k~r-/ -kgxr A01P(6ɝn_| $`6.0ڪ/5T1χ4'Y-MNP $?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csured80.png000066400000000000000000000004051506470510200323310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6L,ڂr-ilj7g(_ dTEz @?#l^q@qE e D{<j.mrb`4E,RIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csuredb0.png000066400000000000000000000007161506470510200324100ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<`IDATxbL3Y@h`@3lzQzЕf "k~ O?04XwC-6l0e?N켅nQ /g€Ÿ3@ZIޕp?22gHåc<{+0b \z/g0:0 q1pp6 ;]`a`p cX7|M{ƫ * ,L F jR N g%l 5`:&X|vNVw 87D1XAX KaZ =bP2M*87jjH7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurede0.png000066400000000000000000000003421506470510200324060ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<tIDATxbL3Y@h`@3lzQzЕf ]-d,|t@!l1eoa4kaϿxJdp69HQn0~$IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csuredf0.png000066400000000000000000000011331506470510200324060ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2ס ]f0Cz;X|s (jMoNXŰei;m"[fV&<9 o}ɥ[Qԣ0~ C3]}!0 61D1~!.9{Rܰ'$P՗dN0a(`/.  +`7Nrg lَ L,ڂ§8H6ן[=`c P$a1Ra,mF^Oe[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf16e.png000066400000000000000000000003261506470510200323340ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<hIDATxbL3Y@h`@3lzQzЕf kq -SaesQ`Hq  O`;1 .W<$@s(P0Blř po#lIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf1b0.png000066400000000000000000000005401506470510200323210ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖg8dT1Բ`as OakfK X aX+ވAU_ wXIvAH1XA8 βd'/y3Y+o,l0a|>VėlT $&7]Aw 4 !0!'ObZ `iT@qn0 E&U`IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf1c4.png000066400000000000000000000006271506470510200323340ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<)IDATxbL3Y@h`@3lzĢ-`:Eѭ7 ]l& Hs]2[$Rl (C33K|3H 2@1Gf~1i*`[60as궅tA˩ }w6X $G g o_|zIƫ`1 Vz Θad4\# ._} uG0aaC@&( a7@@@ )FVa,m (΍qjD8zIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf1c8.png000066400000000000000000000004171506470510200323350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-L,DP8@j 2=ʐa b R }>p@jp` ׌@brLQ4'Y-<aiP ,;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf200.png000066400000000000000000000004321506470510200322400ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ9y){0Բ  @!\uӏdtB0\Yd+I o ? @HaRbHv"F`fO  P 7?{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf268.png000066400000000000000000000004161506470510200322600ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf b//>c#eeN;6$8˒AZ:y!^ut޾ .K]i }> %ObZx:mr@Qn0/IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf270.png000066400000000000000000000005731506470510200322550ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzӖ|Sɥ[Q4rxQԢo}bfP74l+CR \3:0@VMl÷?5a,e `ΛUO s V@` ^~&+LB 1e`ofXW0\7铊d 핈 %(^98L +@P (@DJYB&n@6"0d`sM*87l IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf280.png000066400000000000000000000005511506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf Ҽe%]PĐ2[ Oeβ©j``5_ kc}9/ v'Z^ieh\ `1l>`p ҅uA /`s.'wޒ3 w/?3 ́x-: Q dTJw: \S @qn0"EYԙ'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf283.png000066400000000000000000000006011506470510200322510ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6o_|FAɝ`0 ؿ2CGZ_~1G/g8X| %l8y:p6^n_|Ơ/f˨ , kK @x(f^-U,$΋sw5p@{bMUI ]eYu{d8:`A~~˜2aJdp6`ӎ_\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf28a.png000066400000000000000000000004421506470510200323320ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf "k޶,^2aSmY@! ڀY[U}) t0y|a A:XY9ݷ kcβb%N6@M< 3qji@ң<j.mrE w1l2IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf8a0.png000066400000000000000000000005551506470510200323350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-!߿bض,Xge`c._{`65$pr-xY ODŠo{\_2M*87a>QIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/csurf8d0.png000066400000000000000000000005671506470510200323430ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzЕf "k>Ó;oKG0L,°Z&to_|Va@ZÀ%]Egؿ2X36X,mH_ achZ5<0\%χAU_ . 6(@_ ^~3Fo_@ 8 @߀[ " O'{} @ieap`,9 IkrÙ1 mRŹ hZ⣌IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/cybiko.png000066400000000000000000000010501506470510200321510ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڌSJQ=#SiRQDdrE A{m)D-tVFĈ("KôuQKg gͼ;s I{4:P%qƯc(S#j'N(хO+QsIO DK廂ιܬF5"C!bSfk; j3+0ĚürZ \P C3 #T9 ds2ML]qӥ5{Ԋ:_\ęUXuz:CS뫺ȝ@81~o5ZzvXYQ&/7>?ZiS۳mљRjK =cv٦FPT&?`3瞶צX} JXV.Ɛ;=-Y8]lΨ U,=abGK3v`@"U|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/gb.png000066400000000000000000000006701506470510200312700ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<JIDATxڤSKN0}e)]g @7h$$#pH*v( h;Rb̳Mp l`!N7 'p6?ޱ$MDuDpwz(i[T(&Nc5?Fpb}tuLЁI@= e㪝wB݀z6A>xuN,0Zc&q`|[Z.ZMR)Pwȓ&&H>Ӂf{yDzY bo+ŗ)b7V/w%sVu`ܱo} |Lї!t v%IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/ibm.png000066400000000000000000000007001506470510200314410ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<RIDATxJ@ɥ5͒zb+jqeΝa|"n\HUh#4I,xr33rxz@Lg" Hh`ym=?<]-kl7񹉝6*9m R&DvΆvfm8k똢/ /A_J]ApOTv:! |A,䱶6$xp|ƆJ_aa~ GG)I0X\tc.[ sL;xxxA:'@ VV0 {{Y.!I: ;r" b bтSDsrv{ $ӅLoñ-,C lF44H(/JL#a8V w3SS<^ʧ{:v }}48Hv[ .Z,ߑ,7cn)pO*nJ(AoosT+XDmr*R?/ɫiZSA~ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/iso.png000066400000000000000000000014651506470510200314750ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxlS[Ha=3;3뮻f&yiqK% z街I (HQ$  )M4mfgg/d ?9! pLΗ.lr&̀BHE(N#;e"K uC!Ji1{3L^#σi({+ 0QvbI~p)g!z?:*$sc EG RS #:U2RdnBp Hv= ކz/%,6] J%r[5xrJuu2PEi\yPWb{ (U 6 Dࣈ 3Dg7ECDAYJūi'V9cod~hy',O21̝ltyb^H;,P}'HFQs~<ȜQesޣ)0mtRYw1 RE9\;xH<\vzv6,GHA"$TZÜ5=/ܱ ` |2Gx~GF^~,p7&Lu@R8pw0̷lB%kk Atm Jq2ys/?{ ZX+@q]ʶmwi+7EAsDFIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/jis.png000066400000000000000000000004561506470510200314670ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb@iIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/ks.png000066400000000000000000000005461506470510200313170ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbCr O `zQEgBiadM 7SPlَ9P,5@ܸ]P_/S3H !TTX6npA64NH@^h8{, e)i} IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/macos.png000066400000000000000000000002461506470510200320010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<8IDATxbLK;S3 L4 PF f@ P = 8‡IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/petscii.png000066400000000000000000000003211506470510200323310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<cIDATxbg``h` 40 @`b0^VS,]Fe4, >Ң, rT(ۨߔ 0`w0L(`0(PlIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfaiha.png000066400000000000000000000006301506470510200321240ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<*IDATxbL3Y@h`@3lz[oV (2ׁia+ރŦMa>_~1_{  .(jT v Ū 9y.}f\C'wb7a[ADp _ pw@/m#A^S 0a_A.iUg A:  Y!@aHkrN(nL0'Q B9Áud'w21\:ן Y`bf0_T0x5߾ @㻗N]߾dضz fH />=X,pJ2 (LLdepv0@]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfewell.png000066400000000000000000000005321506470510200323330ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbSA|3îP3?O ,u`6L13v ) pjYp9-Ҁ>@E3:`&x3Y ga|! #‰E[0İ„Ma~B61 iY$8/BU})A`ӌOB@a2XwC|4'(+@jaDAVggsO6ËIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pflatin.png000066400000000000000000000006341506470510200323350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<.IDATxbL3Y@h`@3lzQzЕf ]- 6/>c8.ӏ|MSY'eU}) ,4o[x=,2$πa ^F }cu8&@o_|fX;8W1å Kx ak߿a[o_~1KA\A0'[ 4` @.:f?f cipz `a!"3 ' 4\2fdp6`iQ5IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfnisk.png000066400000000000000000000005521506470510200321710ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2ׁL0A\g1d,liT6wWc3PÄπKG0Y+00ܾ k/5?dx3 O,4` e 3%xA\2ǖ90̮E8'w-, Km'X qH_bp~qLٛFtRfBNdg&& 28;`RFi(IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfophid.png000066400000000000000000000006151506470510200323300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2ׁL0Ab5eAxr-i޽и4.ֳV`-s`anHWgz}%xNŰCZ\ e[u!.@8cśN}905e8 tAp%ndXXlΐ 69 4Ld Tj@ `Y) 5'(+ aDAVgg:2IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfponaa.png000066400000000000000000000004611506470510200323220ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ ^uLeee7<5ldN]p=8?yÔiꘐ9 E0 1 u:J8 D H>m ς1PDO^82MNP ~-; y9IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfponab.png000066400000000000000000000006311506470510200323220ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<+IDATxbL3Y@h`@3lzĢ-`:Eѭ7 ]l& Hs]2[$Rl (C33K|3H 2@1G 'w3h3Ė;p ga%CDXlߚK ܼ &*b׋G0[+ 6H `&x a8"  к*_ 8@bDyAIG dĈ’|(aB ~aE!x4b@9Z `iT@qn0zme'LIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfponac.png000066400000000000000000000005671506470510200323330ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzЕf bӼkMsNa#ef×?jwR0ܿ.b$4O!ޅavnw/>3|xafNF7:`,I>-3YK20132XȃňrAH!Ǜ! m$m)0_<|0m&9{a,WR0 r#@w]>F-IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfponad.png000066400000000000000000000006441506470510200323300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<6IDATxbL3Y@h`@3lzQzЕf ]-ӑ!эAX̿ti޾ ;2gY$Hyaۢ 1e S1toL`'X R@Et`82W185߀n_x3uǔ:5bD/>oȉ^ K0mag^U% A `N' ⃼0~Ӏ;@gYj`AN_;8ftӀ2I&X t<j.mRŹ (py\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pfteng.png000066400000000000000000000006421506470510200321620ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<4IDATxbL3Y@h`@3lz\&yCLÒ`] .u`6Lf}b-ljYk40 vtbg8yn_|;0߽`a/>cx3CH#&mafc 0ˠgOek~rM QAeQ _$?A@AU_ w/`} Yh=g0wSo@XkH33&6v@jaS(΍eN\eIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pftones.png000066400000000000000000000005151506470510200323540ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf Ҝ<Z& Q2nAcس"x_p75D7`+ ϰkh# O1cxk/ *͏7Yx2,VL8d-hʠ#Ԣ~( MCI69)`Eo.IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pua6ants.png000066400000000000000000000003741506470510200324420ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӜ< Ei [@!t8cĢ-(>ģ&¶gQR$,h Ja Sa,mr#@o#IIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pua7seg.png000066400000000000000000000004731506470510200322540ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖyNn h2UdHipP˄n:H[!"$C, ߽ 29tt@!pȯj(6gpr-:`p( Ўaײ c5Pb)Dv. 3sUeغ v,aS΂Hs#@ZYMIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pua8ants.png000066400000000000000000000003541506470510200324420ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<~IDATxbL3Y@h`@3lzQzӖӜ< Ei [@!`A3Fo[xU>ޘh н.O}/uDPĖ"H-M*87,(K1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaabepf.png000066400000000000000000000005571506470510200324670ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- 6Oeض,û`g0&lkgP՗dи4l7g p05D`tiI aX ́a vW՗"  , gp1D(uy(/B `7`:8˒aIAp4}> iF(y ]Kۤs#@=?\krdIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaabpfa.png000066400000000000000000000005761506470510200324640ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ/;o21Q.xr Ģ-pρΗdP5d%lC~ 2&9y`{[`gϪ`ưm9Nv@9=k'( KCٯiM"@o2xbKDr#@ #S]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaarpfa.png000066400000000000000000000005271506470510200325000ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf Ҝ< FWDȶ){PhtDgpb-KGnHcGZw2H+ ȱgK# {LlN}Ò xr a B 7$Я؀/W11vwl)_ ;A\e-j ^~&:- 'OP 9 %e `iT@qn0yO|{^zIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaath.png000066400000000000000000000005071506470510200321610ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- 䉝t$"P13C w50k/3ܾ! k9ɝ e-sKma#ͪR``5_ 'gL0FieaNkûrgpMd38P$ IF!>DIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puabetty.png000066400000000000000000000006671506470510200325430ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IIDATxbL3Y@h`@3lzQzӖ kgQfex3;g1/ZtO|_ >q/>gm j *R 2 'w+`C ́ɝ`oȨX a&t,KA^yr-π7`y ,8U}IKxÁk`xAZ \W@1Hr:f."]3l[ta³`6(@A^0ۗ` 9l`ANSL6`;tutrIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puabiblo.png000066400000000000000000000006661506470510200325020ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<HIDATxbL3Y@h`@3lzQzӖ?Ù.}p <*##E,&4o_tO FJ !9V`qA _?g 6 _`h/ 6H $R P\` 9γw40s`u2,k0 X4 /tfcx| ,CV'+! 82\;` ; b8 3(+FQ)>Ϡ)ǰ&$_XtK6`m X1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puabitsa.png000066400000000000000000000005301506470510200325030ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-6߿btC,m2}aX acгVU%%xI37@e&7m 2<4n_| , `]%7A1g  7 ڿ2÷/?ʉ0 ` Ɣi$>(<jyIFWeIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puablock.png000066400000000000000000000004041506470510200324730ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz[o46u`6L"M-6w! ifB0!Lje%@QIG7z3[Z.Ci ,ȱ\IbW,P 6Pq?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaboxex.png000066400000000000000000000005331506470510200325310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2סӜ< ){P,bOtjA0abӸk+f1 *'g0y<8\M?[ aLKE `Ơe&˰my@HO?/>G,L I 7]m(yR6JTmcPԂř -LCee9IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puac1pic.png000066400000000000000000000004321506470510200324010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2סҜ< ̎,eiELS1,?L0  |?Ah iP "! \2 nN0Ȇ`!& I`b/)#{9j)LLdepv0@F -IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puac64os.png000066400000000000000000000006471506470510200323500ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<9IDATxbL3Y@h`@3lz\ Xu=+sD K0ɝ 4Z&tA@8 / >`X" 3 0~XCp%b+ 9m(wjÓo64'X < 6v Csl0n/8`9חa+j( ef]2AI( k,6b(@64h=kxX'(5.D Xd?bKۤs#@4 X8IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puacamp.png000066400000000000000000000004771506470510200323330ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf bӼkMsNa#eb ,?ptuÛ1G_8430200Y+`1bp=#{%N~0$F0/~]D @ O?b\J mxc0ƕ1 mrE D˂IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puacardo.png000066400000000000000000000005521506470510200324750ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖgӎ3`(_`{ + tv / =<^iz g:xT @b 6`[G޸6tIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puachesa.png000066400000000000000000000006031506470510200324650ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-ē;oN;g cAuAU_ OI+ 3KggxCp%FtX88<@2-\ @K 9y ]Kۤs#@o>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puachesb.png000066400000000000000000000006671506470510200325000ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IIDATxbL3Y@h`@3lzQzЕf ]- .}Æ"/=kyU})q&ty $ļ`P$0X0k~ /ӻo ˁ\A߿dd;0Ȩ3(5a x {݋ q`_:A(r N/4liβ{ B@Y ly760@o_xw)N,NfFs0dG#F:)b>L1nj@E, Ra,m (΍ISIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puachess.png000066400000000000000000000006561506470510200325170ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<@IDATxbL3Y@h`@3lzQzӖ/1p1Ko_|a Owނ: >`eQFq }pr- \{;(l8cwd@. Vr*'7;0 >tȟ߾{^fVF @DpI|bMp8DO`\g PȠَ Aa' ߠ7A[@ jۢ/>3<Z&l6{p3aA欝vlȀ3Ȩ380\:+ eޘs75=`8}AU_! @6+$ , W՗ 8091X.H@ i/`Xu tN60dۥc^acQf&@<4ѳw1x]$ 4d(^1( , L b`BN0`t :3Y-M*87}\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puacmbsb.png000066400000000000000000000005261506470510200324740ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖM󉝷%xy4/6,l,| &l}AU_ ߽;X '÷/? ^s6;wrѽC|p`ekH2t8yy zaq`'(\9y"0P4:٠1 mRŹ ]i,-IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puacpicb.png000066400000000000000000000006641506470510200324710ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<FIDATxbL3Y@h`@3lzQzӖ8df a\Â.ph߿d_~A Voace}XLU_AE_ u,2d+8<{݋piW1CvCA^< EOax  p x t򒮃 ߀rÄ&dIp m @\ X. 4(*a›@_N4rr bKۤs#@k}6AIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puacvrep.png000066400000000000000000000005171506470510200325250ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ8df a\ÄKgXe pk0,:!-p񰁱S4X҈M3z bu 1#OH`/0K6Rt+`j߽pÒtʄMݷ`ۄy^x Q @8cXL=Eg3`IAO$ U}ImX aAoP \pY) ^V,ȶ5%PM#.!Q qgdANI 82M*876vbTIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puadivin.png000066400000000000000000000006141506470510200325150ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf kqV 62@V˂Ϧ; -"tgC^7òC @Dۃ LٛP@N7e=⫝̸^߲/ < Y^]l!fVf33ș xcXy!4ך ,>.@H7RjNi 0xv ix ) ;ltױ @qn0[^IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puadomex.png000066400000000000000000000003721506470510200325210ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ$ R @ Kղa4YX]Äϩ61>@!`'K]0 R) r)8|IX&'(ʍ` +FXtIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaenana.png000066400000000000000000000006511506470510200324670ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<;IDATxbL3Y@h`@3lzQzӖ?Ù.}p <*##E,&4o_ta#맟<`5d3L3':'7ρXNTE a ́AU_Nkrê0?%x\M 0 |PhÀAPT!! W,<`(AQ YuKi/`4xEP0P<#5a,m (΍jȐ'"IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaencjk.png000066400000000000000000000007401506470510200324760ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<rIDATxbL3Y@h`@3lzQzӖ?Ù.}p <*##E,&4o_tO FJ !9V`qA _?g 6 _`hp~a.0$A(l9]r30}HH nj o_|a}9Ѐ ߿+ `˰eP [!q0 Nn6b5Ga0-sz3+(aPC7&w(y R( `f]x{7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaffxb.png000066400000000000000000000004071506470510200323310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- 69γj7 C-^e( `D & [!;8m.6Plx4` 2x]ϟؒ2 6l.(7 3Z9HIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaflags.png000066400000000000000000000003441506470510200325000ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<vIDATxbL3Y@h`@3lzQzЕf ]- D, 7 m[x^tE`<@l:Jdp69.(7P~IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaftmtx.png000066400000000000000000000003341506470510200325450ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<nIDATxbL3Y@h`@3lzQzӖljYل k+pF (o"\J) ']Rb`$Z^ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puagcomp.png000066400000000000000000000004661506470510200325160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖҼmY 7YIb0_xp3mΒo<+pg!q^sw5GnXX[rTd!icX `&(" Ė`6'C~NgB9yJDj1 mRŹ @#pcIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puagfigs.png000066400000000000000000000004021506470510200324760ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz}tu0mu`6dXSblll|s:6K+ i> & { !cKHX %OP #&!#07$(΍AՖ]fIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puagmail.png000066400000000000000000000005211506470510200324720ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖҼmY 7YIb薰T,8/åbjiT%|ieaŤ02a3Λp߿bx3N/a5 A셇p>QX1\@0gY1<x l(с-8x8 61aJZ `iT@qn0zKF`BIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puagstsa.png000066400000000000000000000005071506470510200325260ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf bӼkMsNa#ebPl .1r߿ " J 8콫/1}<4÷?,<Ա߿ .b?7sUn@H F f{!(Â8/ >1 A䉞" p&e `i/P N"OIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puahanaf.png000066400000000000000000000005451506470510200324640ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӼ0-ױjd,E]HsV'8/\{۶,d&fN60M`5d/4!Հ/n{&fFVf&&F v1Ç7_ " &#@o|Oo%~ !DJ,69 JaX%e `iT@qn0QV{\eIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puahex.png000066400000000000000000000003571506470510200321740ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӜ< Ei [Ălp&l W H,l',؂KDy_D(yk;Z`iP 'QIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puahwfwa.png000066400000000000000000000007331506470510200325220ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<mIDATxbL3Y@h`@3lz\ Oe5u`6LY3J1|jp J:`q] ,L c}/?Dy]y`ꢊa Npx5HFF{H) 1X3X{k\ v^N3<AXkA `ܻϿ`.h ,7-3!'O0CAXkRF`nOAfb87pGKbIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaihate.png000066400000000000000000000006251506470510200325000ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<'IDATxbL3Y@h`@3lz\fba 0[H+.u`6LY3gY2y A(rjYpMFEa4~i޽Oiea`]꘰ FLA.}AlHOeQ H(/|'7ayg ӳV  D %]~ׁHhpWcڶ8bx(y"0N6&7pjܾ,{ W#07 31P XXf<IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puajgnsm.png000066400000000000000000000006471506470510200325300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<9IDATxbL3Y@h`@3lzN߿bfzЕf)i~G1 XضʉG(jQ .{0.O_0Jâ̩\0kbC՜4/Ӈ7]cxvCx ?~ LLX_WnƠe&5pY J闏?0xAYWx@@Bl+/pF/. 28Qt@Qvh4?N5OAJIoZ(y'^n,bKۤs#@n^lh~IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakabuf.png000066400000000000000000000004371506470510200324770ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӼ0-ױjd,E]HiX q60s*HL4 a% T߽5I70+\pz9(@~& |%,@gZ CX@qn04@IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakakto.png000066400000000000000000000006221506470510200325140ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<$IDATxbL3Y@h`@3lz_~1ܾpW=+s 7Y;oNgU})ft,ܵmYfp  6j@Z]fؿ2ögDБt8cfa ^.`3agӎͷ/>gtO Vf ħw'*8 $.,,pbM -LyE@̖Q& 0W0 %OSX&P :|cJIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakanaa.png000066400000000000000000000006651506470510200324650ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<GIDATxbL3Y@h`@3lzQzЕf k>|{ ^FQ˄˖ӎ1p>`3f:ly ,@>;0n@> ^B>h aX/K251265~,[?r` ,OM0rrC}kn6@ հC.00wSc}8ğ} 8qۢp%]ޱpWǛP {F]/& DXCbE gRp,m (΍ŘuE-zIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakanab.png000066400000000000000000000005601506470510200324600ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]->o_|f^pr-'w߀ e 6E[.} $g "L}>`ɝ K0K2XwAZrꬺ] < B@R@Was>h8'1.Đ\ n$ pdwIGn_|P>#>`p4`۴P=&=+/1<<4Jx_gÉw`` t+; a@O_ ?>@g01PP paXuw _{0v'&n/&2zaRe >!.7&mfx 8-|a 6IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakkf7.png000066400000000000000000000006251506470510200322500ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<'IDATxbL3Y@h`@3lzg 2 ^ B eHkr?+s 7N;P13 exr-CHljY f0^?0!spb-Y`WXaI0@!@E7|p%Jl03L`M0RŹ qtSIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakkf8.png000066400000000000000000000005721506470510200322520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzӖ_ v^F 2*jYpٲv1sw5.6k0Y+ @8 iض,C~/ 0P՗b0wScH_[ t@! 7gun_xuar4/pwU}Io$AQ# ƂW1gpgYANe)s{ I,@V̍)L FkWJoIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakkff0.png000066400000000000000000000005431506470510200324060ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf "k޿2Ò ߿c$M- 6T.}Бep&le}mbdTax!̟U ,F ,^;?,F gltEK@bD{`2ʐt{RVl:!~ L[6<ѓ2. 6`cX{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakkff1.png000066400000000000000000000005571506470510200324140ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz쉝[o2ׁpi^uG6Y- 6w4ǔ90]L iβdac5ȀWȨ3ܾ 2 @&\N;`RZ4>av.F7DRo fu  ߽S . 2L, _$H@iiiu(y"0!06zR0IFt ]ܡZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakmkwi.png000066400000000000000000000010611506470510200325230ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖn1 _?`d gdHkrƂlݷMβd`aef`faLosABN5(d; ̈LN61@l IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puakodo.png000066400000000000000000000003621506470510200323400ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- D,M*BB|@ׄG _A aȀB0 `P,1!'ObZx:mr€`1('W>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pualatxa.png000066400000000000000000000005601506470510200325150ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- /w`Qo_x , e#n_|g 7 g,){r73T F1 g P՗bx3åp}Th!2"@`?Pl \; `P X][VNv{} {! #LɓXX&P v~UuIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pualatxb.png000066400000000000000000000004431506470510200325160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]-bXpIyݷ ߿dгVc][@,؊aV.\ "Sf6ұ/N;g8c 8&M (){hLɓXX&F9IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/pualaund.png000066400000000000000000000006251506470510200325110ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<'IDATxbL3Y@h`@3lzQzЕf ~a^^Aj@jaA1^M_,Qh 5 ƘJMɰ Ct=FX{`0112( 3x. (ÒaS`p} dA^}(Ȩ0)捧@H1+9qzv߿4(`̂ |aZ `iT@qn0YmOe<IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamahj.png000066400000000000000000000004661506470510200323300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӼ}?=j4uQetD]HiX q60s-6=;,;6 Q&#X 2( AadS01PzGt@߸N@Q;('lьar(΍~MIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamatha.png000066400000000000000000000003521506470510200324750ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<|IDATxbL3Y@h`@3lzQzЕf bӼ}?CO qdL  `'_H pU]a@,Mo&I,@V w,m)ʍ%@U 7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puameter.png000066400000000000000000000005041506470510200325160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- ĥ8yTn_|. ]] z nkHkrkFC,axr- Y`ZFE;L9n' ql ҚAllu0gl.Dy 6a I,@V w,mFyOht,IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamgame.png000066400000000000000000000004301506470510200324660ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ{ 6^ ee H|d @7 tɌ `x 42&ـ2V|`"d;!Wt1b(RKaSL6`,GIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamod.png000066400000000000000000000005141506470510200321620ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖ\ox5 s1%%ڎ=kyA1Y+fH 2`A0220xJ1\:pglir g`ؾ,6 FO?] {C32Ɂ߄`aAN)PR0IF#H.CIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamodex.png000066400000000000000000000007141506470510200325210ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<^IDATxbL3Y@h`cMbS!Jӣ[o2ׁL0Ab5eA(] * !Ơf Šc)rí x' ok ʺ`_(dۥYX0!sVlk`c 1H N|`k>{Ez!Ó' ?`g00)2hº'8@aAb 9xaۢ ^~ 6H $Rxc0}= 1d5aJ^q` SZ(I(LLdepv0 /(IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamouse.png000066400000000000000000000003771506470510200325420ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf "kp>^2aS0a7D =2 $10!L!LF8.CXE(}hiQ %OdM()c,m (΍P4zTIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamucy.png000066400000000000000000000005441506470510200323630ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf 4o[taV.Bt>Z`BP՗dN>6@!`&xb-@ÆW5d3w/?f#/}6 B `AO2OЀ'wbq"ȹ߿ hӻoQ^~aβmȯ3n_|SpG#(yRjH6`#b.IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamufia.png000066400000000000000000000005731506470510200325110ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzЕf ]-bX9o_|f8/É޽/ ɠg8]ts& Y@lŰvqv:xr-m΂@W~aP'Ҁ_12x Ol 5pUI_A _ kΖ˧57\=+N6.v0;߿P0aE|Z `iHQn0&!buIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamufib.png000066400000000000000000000004741506470510200325120ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf k~3fZ&\,:`Πgpr-i8ykiIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamufic.png000066400000000000000000000005711506470510200325110ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxbL3Y@h`@3lzQzӖyۢ`[ n 2*( eA7g`+ΘAH z pyd6j h !^<ݷ ߿ێ&|y ,K bU4/lХc_~1v@%ـ;o]' Ym9eXuE( N6&78P.%OlI9 6`Z<IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamufid.png000066400000000000000000000004671506470510200325160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf k~3fZ&\,:`Πg[a%q3N6!jxDȿ O,6,%x)s!@`o/0eo'7;ieG0~/':0wSCZFRp,mF8eIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puamusic.png000066400000000000000000000004751506470510200325310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖɝ ]tdTee H/ 01PXI(]!΋.ض,i3[ nj Oa}|x^q o_|!ÀN]q`ado@ Ȋa N6w/>6g^o YV R ^q X.޾d(^} $ H oN( C28%zeX;8~(lҚn w1l[x Ka2* K#q 6`l?NfIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puanishi.png000066400000000000000000000006241506470510200325170ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<&IDATxbL3Y@h`@3lz\ >`agpWCu`6dOeX_`be4'y 0 9U*f'ʀw/!%xVA Hsp;Òpx!q^\߿d0wSd 4P|+6dT 5Ҍ ps ` Oef߿$Ag ́)`4',A@Ѡy]-0s 2Ź 7hFS`IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puanumfm.png000066400000000000000000000006431506470510200325300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<5IDATxbL3Y@h`@3lzQzӖ3{o3\: ~Mٛt2~Q!$NJ_ k0 _/Yu8y,0 `B9[Z>&v@-7LFEexr aHl%x޾f{  r:x3ya@% &Ϊ ~bXؾluFFF͠<քP0!.`+)cKE ~u3?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaornda.png000066400000000000000000000006021506470510200325040ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf b/0Fjٴ,/>2"p6OUpr-@g ۶,,o_| K5zA@P;of#huWճV`βs ς&im^ nj z}dT%P@!{%h2)u *':9%e 6`[$5OIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puap8num.png000066400000000000000000000003461506470510200324550ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<xIDATxbL3Y@h`@3lzQzӖ9yVSaee L1!@!dos{6|P0B^0 Dr#@"@gIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapatts.png000066400000000000000000000003451506470510200325400ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<wIDATxbL3Y@h`@3lzQzЕf 48G\FV ,GڂOٛ7>Dii)zaxS. (΍k IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapcdex.png000066400000000000000000000004261506470510200325100ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzӖӼ}?=j4uQetD]HiX q60r&ȉG\ӸN5nI6Y3.`i&DJ,ƕpJJ([R0IFZ3K IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapcdsm.png000066400000000000000000000006561506470510200325200ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<@IDATxbL3Y@h`@3lz%x1t=+sD />gؿ28Z&\n{r-eX 9g z _>`X!Ll> c.Xs*w/6[ Y ?0n'~ ΖG  $ yyIAVf<;'+,P( 3vAH Kc ~c5oBA}z-C]ǃ5X03KG£ M+Bu%J/0g5)cKۤs#@y&IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapenaa.png000066400000000000000000000006431506470510200324720ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<5IDATxbL3Y@h`@3lzQzӖ3{o3\: ~Mٛt2~Q!$NJ_ k0 _/Yu8y,0 `B9[Z>&v@-7LFEexr aHl%x޾f{  r:x3ya@% &Ϊ ~bXؾluFFF͠<քP0!.`+)cKE ~u3?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapenab.png000066400000000000000000000006461506470510200324760ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<8IDATxbL3Y@h`@3lzQzӖ3{o3\: ~Mٛt2~Q!$NJ_ k@64W:2)5O,B gYo_|fx3Pq-dF7 w2| '~l|Nv ci.bq  ,̠/Šg_&Ϊ R| + , ##g1 ͓ y0 `K."̠g ,PDO@ 0IFȖP}FIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapico8.png000066400000000000000000000005661506470510200324340ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`cMbS!Jӣ[o2ׁL0Ab5eBqŰsyAr 5Xofv1+;3r8.}p&f1?fB`I2e oeŠ 5 /}:^$i@N/n;@lHR |p*H $R7" mX<j)LLdepv0nl sIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puapicta.png000066400000000000000000000006111506470510200325010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lz'w2Ȩ=+sĦlݷ >@CV˄}/>cx 4@H[Xհ |"F_~2H+ ]g 8&Fz o_|fEQK  w b/ P0`F\ 0 .$΃$g`]Q!q^i*3,>HA 'PDl, z X2 2,m (΍s7DJTiIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puarylk.png000066400000000000000000000004051506470510200323630ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- d,MCS*i8vBض` b,  &Xtذx'!BLt (labFV7ң3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puasafe.png000066400000000000000000000007521506470510200323250ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<|IDATxbL3Y@h`@3lz?4[o2ׁp5?aj6@Π%΀M-6w4Ow+ff%V?07=n+/,!'= +FR *" Zf | ){@ + 0@ PDOX&' (ʍS;GIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puaslca.png000066400000000000000000000005301506470510200323230ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf 1yZ&\_<_RdӀU ܃{ 2s=pC`6C5?i @0$պ09(1\?L30vC Nj5p !'",b@L?eoZx L,876T dIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puastdvr.png000066400000000000000000000006671506470510200325560ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IIDATxbL3Y@h`@3lzA߿bxCW:0 &_ ^f8\ɝ IDbLXmjUAZAFYaIiJ`3` 2* `k/.{ȐPĠe* .} 2KbhiH6 >LB 1e |8c\ fk98@\3H  '(}z-:VXS y8-:gF7^`AADbᮆ3zi,m (΍d\|EwIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puatally.png000066400000000000000000000004151506470510200325300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxbL3Y@h`@3lzQzЕf ]- d,MC 3kw2|C-!46ag"VijiDi }cDT`!r$ IFԢ?~IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puatecha.png000066400000000000000000000006301506470510200324660ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<*IDATxbL3Y@h`@3lzQzЕf ]- 6OeH_Ӏ){pHW1F D 'y$r6 βk}8A!X'(oZ `iT@qn0 je=ABIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puavexil.png000066400000000000000000000003421506470510200325310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<tIDATxbL3Y@h`@3lzQzЕf ]-<(MSa7]@b/ ,HvaJRX&F5HIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puavoyn.png000066400000000000000000000006471506470510200324050ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<9IDATxbL3Y@h`cMbS!Jӣ[o2סMT;o1{AFYAZ >`H_0h ؐk/3l_t,7n/%]}P13n;28 xr ة h#'NvI]2`] 7& fieT^q(`L30&s3AX>dP5dX;8<@!8 9γ4D]C>ʄrDSL0@qfb +3@2Us7zqIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/puavsymb.png000066400000000000000000000010121506470510200325350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤSKKBa=\aO"E3,!E$ jY6Qh?m6Uta(Qд*oLPF7sV K2 h}kCn\C@""pvD8=i1>mB:#U2v}0fף \ ^a M'/@sQȭ+/sL>] |i4*H!"})@IF#߭'io + oIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/riscos.png000066400000000000000000000010141506470510200321730ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڔRMKQ=/0KB4 ۹6-Un\% բOm" ܈(0!̈$R FuDZqfa9w{8xA+0 8W1\.R)@@]`fT}'5!R} 4T9*=ݽ AEۺb~-]G歪#&,>h44PLC60Ɓ)ʝqodxndRe2)л>D;l&]V!aKXR$QAثx.Zdn_ !H.& (}1DeI=dOck~-oDfPɇhb ͭ+wI"u&0Xk891)bM[WezB*muUŝ6'T_wC-)g\'#㴽U5$5eyq#t^rY LFF]KK)hq&b"5mV`q`o@fdxBWG<'،O/O7RfYtӵ.o#ϧ'-<gMnIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/subtable.png000066400000000000000000000022601506470510200324760ustar00rootroot00000000000000PNG  IHDRӡIgAMA7tEXtSoftwareAdobe ImageReadyqe<BIDATx1LTA 6X`}Pz&VZ Bw*Xh Њ 4RH+H:wBnv]zDԠ~_꟠V81X7ܽ/KYJ(*a.$#\"?ӟwD+>։jS6jYy1j>k+{6]ov{ܫ9J1پp?5]y>s~Ig;W]+*6x/CZ&m6v?O?  [v㥻cZ4&EKX&&Z*c0,_VkL(.8'$Lc1DA0jn[ g 緡1qLǘ,XXY~'t#x0>p4"ʤ0) N ιpt &e4rdp4)61 3x0 qDc!i14. Bp-c?I. ܂1 7Hw` iWk݁2Rj\6LO,8X;^3"a ge6l#<[tnS~+[ن,1?LG4>^g1 N*>2 SG$Dc9!]d֎v!},, V~LY5X}c)xuؙܻon#eV߫D܍qc6Ɔ 8\h,0n:1^c*&4ƂssQ5&W3ec* ]v8?kL.8lL=g@gaiy"V0رo\H4&0H1&WY 'eɃ. k,*X7PŶ,0.I`me v6,>0 do?ic56dd b2d&aSTJRY. o~YRRY~CV EE%*+HtaIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/ti994a.png000066400000000000000000000003461506470510200317230ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<xIDATxbt򵞁<4?Rp,,ލ?e+~/^$|5{y o0\dmsiIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/tis.png000066400000000000000000000004171506470510200314760ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxblQg``h` 4EV.tE!"ACZ,?}"ϠnhDΟc`bl\ܙdi~N~ #^xXdeG7$3J:xb#di~JVl``$33=A ` 4P!IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000000.png000066400000000000000000000004731506470510200316050ustar00rootroot00000000000000PNG  IHDRaIDATx^1EPU =XF M(T^"*ЉJ3$a7$'{ ?=¿琦)>=Δe$Nj>Ȳ K@4P$I"8 0 c?~ /0 AQڶ}DQ;0p]wӸh˲`bIKW@UU0MsSMx>kv "8kGʲx|ܙu~7|;tt@IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000080.png000066400000000000000000000006131506470510200316110ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS;n@}p"CpN\q DOc׮h@= 'vv~7 Fhoe3vh"UUAӴN6Ak(`O t۫UU!,y̱v4u3,<+<}` ˲(IjHiraE @c"0 e3|qp]w=]שyr$I:EQev8py[H,<ٶBߟ'1S,?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000100.png000066400000000000000000000006331506470510200316040ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<-IDATxڤ=n@`j BO$ SAݹuzD DAG `9 $S4!o5Ʋ,ʲ~<vjkkN'EA"ReiY50Y`m$$5M3Z`! Cn7ض <<ϛ`&Wx<(v)qvEE\.B`l299>en4~,7>bqXIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000180.png000066400000000000000000000006171506470510200316160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<!IDATxڜ1P  $zOJ<!В@z0 RPYh+ .K&ddyhmd!ʲ$I,>yN Qɶm$.wy|>y(kW ]\ׅifzb>p8(Ez3h0 ,fC~pTUe>cZ.tx+! C6D]>f/a~o,:HӔ- ml^#"Nr`Z3MUU Kho,MnoL|-TzI\>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000250.png000066400000000000000000000004161506470510200316110ustar00rootroot00000000000000PNG  IHDRaIDATx^ 0_l,ƁF`X,&};&.wi ~\v F!]C۶*9 v`5xoEfG>?^ݻFay\.Z뺎|z(Q@ǘfe meY:E{v ]3/A@EV+O4 iҝIYLkuQ%E8_ڶ>b$$ yiF=˲h>8oQ@40MYy}N4L'Ĵ@O8IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000600.png000066400000000000000000000004411506470510200316060ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0E =GA"ֶ^ ' @EA`g,5uw}0dLӄ,H你koB480 08˲zFUUƥ`=(ܢ\ yF'oĽ:lxIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000700.png000066400000000000000000000004451506470510200316130ustar00rootroot00000000000000PNG  IHDRaIDATx^ @1Xb6XM&A| h d|jEns<`v`aWvOͫkIp5 FeT_e I`$I " +m,(Bqw1W:!TUih۶틟p!ciip]<R4ME>udYEYeYPUaiAa}JNO۩aOpIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000750.png000066400000000000000000000005101506470510200316110ustar00rootroot00000000000000PNG  IHDRaIDATx^P<`a`d2lF#>ED]\]?8=x)‡\~(.F.EQsW!aXWq AH+4mߐ$ +w,ˢΊ<ϡ( w<σam,<py߂,pߗC\.n7A̮`{4MCiVCAuhi"4WC,ː$ CE UU1oPP5ʲ$ s5N'sanIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000780.png000066400000000000000000000004201506470510200316140ustar00rootroot00000000000000PNG  IHDRaIDATx^1E@E' Z PP(4zV2T &733S0Z̞§na]neAQqcgYt]ufiO@۶0Mr˲4 AG EH۶Q5,[8UiIbEQZ@Y<yc]We(-NO} |O#/IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0007c0.png000066400000000000000000000004011506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^͓!0ˉp@RAxR;HAOC 0ge+!l}ɟ_*^ !=1wW,ڶůރF)seƼ=,CI&8I_@ʓ,IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000840.png000066400000000000000000000003541506470510200316170ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0sdr(lN^#dElL=p[S*+Z{yI)!|rw3LXkq6ٍ 5TUiֵs.Sc ڶEau`&p4eqP<(JGEQlBw]/}Ck8^p)_w5y|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000860.png000066400000000000000000000005361506470510200316230ustar00rootroot00000000000000PNG  IHDRa%IDATx^@A,m`akagm) D+BHR٥(]XوDbи?80Νo;3A_?ݬ%A`,a6$I(l6x</5oqcZAUU(`&xGQ?v8C]4 Iy]q:a,dY㱏eY0 QUU_W4:A@dȡ&ݎ(vm{b$`|>#s<ގ〢(i:,k81~4W.ägO)/ 'D:X?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000870.png000066400000000000000000000004341506470510200316210ustar00rootroot00000000000000PNG  IHDRaIDATx^= 0Sw$C ؊vb'ة3B0u`0GB/Oӽ~/ʲķ,;.u]qxw1]<Ǻ; 旀(mBO X80]P.PSqx-myF$,KHaBQhUU:2RU۶ib o[XIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0008a0.png000066400000000000000000000004251506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@u=WpKrKP)$zKHBDUT"~fb̮/y/c=?vO_<*4{, Jb@Yg MSLt,0 1DGnqömEq-A˲iLӄa<q4. }P52 ѻCeB_Y$ <PЫ ೭.$)ߨ{8g?jIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000900.png000066400000000000000000000004751506470510200316200ustar00rootroot00000000000000PNG  IHDRaIDATx^=0F]"عAAq "\B KDa{く EQgϐiW!{Ow9 ڶi2mcY@$eYIX#w4 qo8@$80>~t:$I0#384M, MlHizGQ!!UUEkei݁m7Cn{A|>t/MӠ(ue0{8P iB$b@)`a>ʲdRA۶, i¶mdY.{qQy%gHgmҗ G4|QA4.:#0꺆pD&xԳ{y IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000b00.png000066400000000000000000000005471506470510200316710ustar00rootroot00000000000000PNG  IHDRa.IDATx^@y Bi !XQ ʆ7@Ic(vPHMO`a{9Qn7a۶8]0(8N$ }l6Ȳ ]4MA`,򧂪X,>m4~$ Ge<! (j'>LXJG A*qn/nQ%4p=߈~O:]`aIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000b80.png000066400000000000000000000005241506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^1@VbB$&"`'VB ?!B ZmsF/9ݷ{ EQ_?=-p\],˂#}l6A, 2#ɷQ' s5MCM+A@Ǩ>@۶0q-vDQMy$a; XפO)$IH&ZV$?iJ&pQt:eYt] !wum,Kw်jXxwV"R1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000c00.png000066400000000000000000000005271506470510200316700ustar00rootroot00000000000000PNG  IHDRaIDATx^DP1(4iBS)JH4 Ⱥ+YNYg㸷?x7ſ!MSVdvxVUUXe͛,ˈx1EQyj0@$\W3`Gj 0 CLa p8м뺗&\꺆:C{n7XNeųʲ84 }my#"LӴLDkNOEQmOoDI@uDڶS~wKVxhiIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000c80.png000066400000000000000000000004521506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^?D@ŝ@BZQ8JՖ BDPj\@"VrfegmfxK}bar3:{h{u՚=hI<4MGmDQq`Y,K"C<4v;QeAuHYq"CxUU0iPqcY}=#xJ|TUu1 mۘP<Ap)|=eRCyϟIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000d00.png000066400000000000000000000004501506470510200316640ustar00rootroot00000000000000PNG  IHDRaIDATx^ͪEP]k ͤ 2;TJ2;D )39ڵmZ}ZϷkAY>rYyw} yF, m޷_ TUE EaǛSA]p]iam Ma ˲}qeYB4]E0II+kQ˲[]e(/m#IL8y˲ O/>bm9{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000d80.png000066400000000000000000000004671506470510200317040ustar00rootroot00000000000000PNG  IHDRaIDATx^F@^BWxN [k4JA!(tD!x$:;6ڬINdr/;3 0oMz63 Àߊ>5u]8eA$~e$I90DUUY8,eYDmi>y8}ӣiFWY9m[EQ x(0mitEQ<#hEpEow~~eIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000e00.png000066400000000000000000000004541506470510200316710ustar00rootroot00000000000000PNG  IHDRaIDATx^1@EU4yo`d4M,0 ĶmIp{owcD@n2qIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000e80.png000066400000000000000000000005201506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^@-@v*A-e!"|߇(u{Quthi!~w UGiIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u000f00.png000066400000000000000000000003661506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^A =Xжe7h!sAmwnCktf2jz~|CA !}cbk>rAu%)%۶AQ9,=* u!XkRu]L,47?RJm[4ay4qOLӄ|2@k|23zte!IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001000.png000066400000000000000000000004751506470510200316100ustar00rootroot00000000000000PNG  IHDRaIDATx^@}$4_@,` [}1p &IA }eAa]w810 Ä/M³~ M"0MLӄ(umb i{X( Z PX]4+$aY#|¶~_<2y<G@}WI2˲=x<ϴHּnpee۶D9DQD8, àJpF/wf]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0010a0.png000066400000000000000000000005541506470510200316670ustar00rootroot00000000000000PNG  IHDRa3IDATx^1`%F~!ZsNj?HǦFq~C*nxwD9~ ,vog EQ௰ގp8`Xmkxq\.EQ+8Fֆa@$ib<~ |ߧ\%9E|<ZÂvK9*U$ɰ sa:ґ'TUnjP1۫|OSh@eIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001400.png000066400000000000000000000004231506470510200316050ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 @E[mZ[[('[`)1 ? ,%&> f̲cY)bOa4Mɖe}uP<'gYUUa$yPMӼ{ʻC@UU,8a6ՇeYh(0MڶHӔ,iv۶Qk]Wq%|׾ExL6P(0 , m 4MJ|lF `\( F^K@:8NX,2LB\Wo~Gvt: `݊p@Ӵg%]?w4>*IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0016a0.png000066400000000000000000000003571506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^͓A =B6^Dk*ڴ p:EPDi3?y<c>6*fO\0uX8f Ѐ,ڶ-1u]2$@)\ , *xQ$@J k-֘pEiRD&Rs@>HW:n { PIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001700.png000066400000000000000000000004731506470510200316150ustar00rootroot00000000000000PNG  IHDRaIDATx^1E@@+  *V'Q؁ h6,A%RkIHHƍܗ/9?_f&3EQ_߅=5[Ax= u]9 uMᘽ$ q0!d&$I/<}<M`Yt]e ׂri?;UUAmEQ`YE0 pI`&lގ,0ʲDEȲ"(hZA M;'|}%fE8RIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001720.png000066400000000000000000000004641506470510200316170ustar00rootroot00000000000000PNG  IHDRaIDATx^1FPF-BIұ Xf ؁FDcVPRk<8M/cY+ 2qBTRUqap] QAE ۶VN22Tǩ( :A$$ a̡<(UU!۶eYPeYܡ h}2M4?ȲL<1 \/Ե+7q=:YJIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001780.png000066400000000000000000000004451506470510200316240ustar00rootroot00000000000000PNG  IHDRaIDATx^ݓ E`ōhsMjyop&ye1)F%,1˭uStAƏgw~$;Z0mu4EUU!{QA4TUq`y8^m""q>9L]ס( $I,4 a:eYA,˖-EQ7u e $7?8*uLd;|׾8 `.۾!IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001800.png000066400000000000000000000004401506470510200316100ustar00rootroot00000000000000PNG  IHDRaIDATx^ E`]M-*ٌL.A.܆2[ ";uy뭯ga2.5i.ʲĿ"ow#m zu]QU)iq Q8o| mcYJȲ a( ȲL u]CQky8t]˲66MD8bu~D;U{iWIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0018b0.png000066400000000000000000000004161506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^= 0Fso"V,=6Z,x+tVABdY60?{Պ;iWVvֹ:dv‡%MBc2~t:{ =xQ=)c m, H}i󣣔< Rbc m"!^C]0m*늦i, eIŀ2Z On-IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001980.png000066400000000000000000000005121506470510200316210ustar00rootroot00000000000000PNG  IHDRaIDATx^@E_Hamc%Bm" Xm J"6XؤI?FPβ!d=x˛3EQ_?xv~ZzŻ3 꺆y0{˲PUkv00 , M@4ʲ\G\.2w]~OddYp8 E!$I$$EϻȲL@Em?irEAymq 4q(Zi<YQp]w e&7Զ _ʳIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0019e0.png000066400000000000000000000004041506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0EsYNTaMN;O`t ]lƅqB^!Bǫ,gOa6,Bu0 , uEq4M1 ֐RR iB$PJm[ymump8@A$Ihݹ<\4M˦+4Me]]Q#n2MwEQB7C#FLIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001a20.png000066400000000000000000000004721506470510200316700ustar00rootroot00000000000000PNG  IHDRaIDATx^E@Ž'yD4$W :($JR$ *RKD%8f7u/IQ4}ejej^g%I!(:ɀi 2uŶm$ m2D@H_UxI,cgu]4-eYy,!Ct]۶*ǁeY-qC4 À0 A4>dy!"t](`湪W~GLt.] v_a܅IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001ab0.png000066400000000000000000000004701506470510200317460ustar00rootroot00000000000000PNG  IHDRaIDATx^K0E]#WX.\.EHg:~t/6 ׆@ATF*Q$g/G(c&yƶmL0 24E]P> <σiFMӠ:,eYp]}ߣ˚Ѐb6@g~S]hPU|ZeɴЀ, Fn"4pkBu]1 ӔqEhж-0dEaZh@!Oqv S] )wa"ݩIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001b00.png000066400000000000000000000004721506470510200316670ustar00rootroot00000000000000PNG  IHDRaIDATx^E@F>B:* JB WDD"#/ $]Z{ON|' EQǗGg_Wt]$A$@$xm`6?Ȳ ]4 DQD(au] A8²,, a*y&k: x<_8q\4M>O}uIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001bc0.png000066400000000000000000000004011506470510200317420ustar00rootroot00000000000000PNG  IHDRaIDATx^͓! @F'[<`&O ^$xn V EQ`q]a>0#Wrv(˒{w:bYdY(mی8q]yӢ(B4f&t]'Ic0 Xa8}O4iiAp,W(6>!mۮPp6(ow~~cIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001c00.png000066400000000000000000000005421506470510200316660ustar00rootroot00000000000000PNG  IHDRa)IDATx^P uѺ?fr"ج]P,Š11X bXxޛہ%2>AWuC*q?4z} ^1L,dYq0M~Xu!"%x]> h <~jyVETU۶QEe6 ht|ba08N %IR[VUa|>5 0 $Ip8 IN'aخp( sPXjn(]q<EvΟ2PZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001c50.png000066400000000000000000000005561506470510200317000ustar00rootroot00000000000000PNG  IHDRa5IDATx^=PM]؄$mZRYebc!h#Y@R V H!6ZyE43;ޏ(?̿ V$h+Ix4q:k/ 0MXVNPeYGib>t:*Hd*k]ױ\.8AeeA4f3_,z6yb۶Of> nu/I7Q5 (Оg㩪f̉D,yv;p8;9rau]yY'>~g S+1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001c80.png000066400000000000000000000004251506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@sQiMco"@5V%H۝ }K̛/f!2~4{Ȳ Wq䞦INmC$q,F\uaY0<)?AUU|f(CZkPUQqe/ ihvOu]Ce À0 l6@ # Ci, Ev<EQ`]WZ'bչ_WE7ۗm4kdoĽ^~kIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001d00.png000066400000000000000000000005471506470510200316740ustar00rootroot00000000000000PNG  IHDRa.IDATx^APqଉ&5L,ҁ-Ɖxx%\EQ_??}j{v :I`X}\Wһnnl60ϡ: 0^XE/9eYEQ@U-ť 4Ѷ*d$Z,Kh]1y+}Obu}U;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u001dc0.png000066400000000000000000000005561506470510200317570ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڜRKD@-f -$sWqsNNB$vvDVg;K^R_x7y5M]YFY,KTa6ƾ4C 꺆$I*E$IZ9?eYض-m4Eq6"\( <¼6׾axQmA 0˲cqA>r>\.U<m$ Ne$pq^!2a`A`Z1 GhIEQ@$&{ )ʲ(L@Te|OEQ]י)qOEpݐkip]w|3۶^aY6 kmXǣ,˦fA0{gxwFgMhIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002000.png000066400000000000000000000003061506470510200316020ustar00rootroot00000000000000PNG  IHDRaIDATx^퓱 C! Dـh.QQ` &A\BR}I夓,*BnKSS՘=fZ9Gk ZkPJZ0 @0s R"Rs}{;>畵5IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002070.png000066400000000000000000000003371506470510200316150ustar00rootroot00000000000000PNG  IHDRaIDATx^哱 ExSxA 4(7@P ~bG.rDŽ|K`ǫbxg-W1癢=UZk}i( ,9r! =E{4 ڶR@W9u]?U{ ۔uIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0020a0.png000066400000000000000000000005211506470510200316620ustar00rootroot00000000000000PNG  IHDRaIDATx^=P݊ H']. Al,tA,,S4he {pfF̘˽~a>w$ ^Y (a]4M!0#(lSw^}|;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002150.png000066400000000000000000000007221506470510200316120ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<dIDATxڤSN@=- ;lH(+u u.oQ\wpˆG]HRBT(It%  &N9s [FNUUA EP9 m"xTI?Y*0 < KkCW`K$Ft:ETU.P(7s#bMdpea<0X8PZa4\?q 0a6dYF,nFH׷7K*wV%IQTJ!yj‚_EsZ a j"L&<dy6iEiKHKO3oGI_ sH4M~iY1~tN{AoOm-9^YIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002300.png000066400000000000000000000004201506470510200316020ustar00rootroot00000000000000PNG  IHDRaIDATx^1 @ET֞D;Z6"ֶ^b#? lцΞ=Kfdg&f(@TRUIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002460.png000066400000000000000000000005311506470510200316140ustar00rootroot00000000000000PNG  IHDRa IDATx^P}CY%TvUƤ  yK j/B8s/k80g>F ||4͎¿Cm 4i3Ք 5 UUin7uf(^,˼IuHįEa=eY|bcXi˲. [}0 =ou]qe4|zEm{p߱\.q>!xjz&(>g$I05 =G~l`Qy'OnL+|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002500.png000066400000000000000000000003221506470510200316050ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<dIDATxb```dzF(lc9sDaZ$`dk#:\ lD(PӀgL}0Y-řJ; {OBIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002580.png000066400000000000000000000003061506470510200316170ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<XIDATxb```dzF(lc9sDaZ$`dk#:& 00W 0gϞ%ZZ33v S@~CAVIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0025a0.png000066400000000000000000000004101506470510200316640ustar00rootroot00000000000000PNG  IHDRaIDATx^Y 0Ь@=9/ Sℂ(k_Rm wWcϡtMЮ=qlY\U"Zs%r,PV"J`\%4Maxm媪:LD۶acID ]׉[84Er}Y,3Z|>S(.$~kºc>0 ~m4Ȳaҳiek5(<#MS\W, ,˗hAp%I"ݢ*EщZV;UU( lnG.r6Fw\Nye>y좙F͆3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002c60.png000066400000000000000000000004461506470510200317000ustar00rootroot00000000000000PNG  IHDRaIDATx^?D@ŧp אP*@'B#qgЩ4.@( ۝섈zKoC!M?pV4\!`e8<!ڶEe$ A2(TUDQqQ]" ض}`&EYD/4q Ày4 <#c$IY!9|E_[Q ]׭njow~зoBG]uIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002c80.png000066400000000000000000000004721506470510200317010ustar00rootroot00000000000000PNG  IHDRaIDATx^ͪEPIb+1ܷ@1$@.@ Ȉsٱm:x+][(z|YEQැ{-8bY]Ω s4 ]/%i`ƚyis* ɖe8uR@ @UU}.㠪*dYeaGAY4m74aBE}$AEe k0 P<ϯ Xi Iz4MW7Ӷk}oԽ ۖdpIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002d00.png000066400000000000000000000005031506470510200316650ustar00rootroot00000000000000PNG  IHDRa IDATx^DPHF<#(H6:!P y)'Qf*-]6+]'眯A|| vo54#ڶ]C@u`}x C8eE{~(u @Ӵ9eeY.slۆy񬗀*|߇뺸\.C@4( uLӄaK=H\IMvx7( 8da I,BUU<(V/?i"˲֬S>sMpA)MIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002d30.png000066400000000000000000000002721506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^͓ DGp g nF6N2hDh,C_B9eݮ\=0K: 0Z֙)R Z\ཇR0򜺚 8B9u5CA i{7O/} sMIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002d80.png000066400000000000000000000005011506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^DP)$DE8>y}DeS@軮N8Be۩j)_k/?Ya^QIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u002de0.png000066400000000000000000000005301506470510200317520ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤ;0DIKPNqA (BZᓑV^^y~1|6&uI$ +5u@ {Xug11>ZS4M4Moa(8.8Hm,A0 XlA,B$ MV!B>,[ͥdݪ:0iNu}yi*a,ѶJЍd0c۶Ѳ,u]u]iXi^u)[S 4McCSe^`"B2,˻ȧHƩq!a=W{Oha%`UDIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003000.png000066400000000000000000000003401506470510200316010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<rIDATxb```dzF(lc9sDaZ$Xm;|0B###f4d e?\6Kp"ű0jyQL 0}g&f(@tlgIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003040.png000066400000000000000000000005451506470510200316140ustar00rootroot00000000000000PNG  IHDRa,IDATx^@E}?;Jv*7\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003100.png000066400000000000000000000003731506470510200316100ustar00rootroot00000000000000PNG  IHDRaIDATx^ Yal3XSXKKw ZY[&S_$!%pp f}b<޽NMӄ,ˬ[^@QBXUeYEF4e81ϳpB\)&{>i)%8&B۶&cPJ0q$`]Wt]4MS~w Iy OIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003130.png000066400000000000000000000004301506470510200316050ustar00rootroot00000000000000PNG  IHDRaIDATx^OD0{ 7 .$6%n`cOÊݛa2Bљ_%4kעm[|5X}a, ;$4MY!Iʲdǟq#sYmts`4Vu]4.,˂먪ꔹ$I:"zHދmۇP54M8<cS4Mmo p%p)Ud|\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003190.png000066400000000000000000000004261506470510200316200ustar00rootroot00000000000000PNG  IHDRaIDATx^͓ @EghggOةV Vb7 qIlraa0~4]s.ΊdWwaE$yPUu4M,`$IBYj @eYPyCuiz N6M 8A@]1%yqö}ie^ (`Y}ϙM@۶]͵qiǙkC|׾dJ+IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0031a0.png000066400000000000000000000003771506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^; 0s !7,鵴L;oB+-qu1(&ׁ+ [ԿEUU6{Ӹ]NeYFyFRB)uq爢4ĦqA)5 pm[$IbcEQ,~.u]e4E;7sa}_a4x_w^On;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0031c0.png000066400000000000000000000003151506470510200316670ustar00rootroot00000000000000PNG  IHDRaIDATx^; 9WM8-=55DDlc0]LBbfl>sFp B0|iAJ J1FH)!x[=8研Zز+Z1b+RVC liS{ Q[}IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0031f0.png000066400000000000000000000003331506470510200316720ustar00rootroot00000000000000PNG  IHDRaIDATx^Փ- F(cT0*,g M$.l6Yh}&3S@!Wcy7Z]D0#RX׵]t]!(RS0 p!X>9,K9ġ}̩8i^F4[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003200.png000066400000000000000000000006301506470510200316050ustar00rootroot00000000000000PNG  IHDRa_IDATx^P־bT6 lDXH $"UT?wK3sgKD3`_sV7xp8u]vgnx>dR;{<|vѭZ 㑆 @x<$I8,"Jnc2ömJ%> b^FHt:3m6d2> c\"JtpH Y10 p>Q.iib4M X,l6n)/ \.Vh4#.- 1DzjE}\~j"^-V 0cğrH;=<_IAIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u003300.png000066400000000000000000000004631506470510200316120ustar00rootroot00000000000000PNG  IHDRaIDATx^ϊFP] pjvVX-Q +Y7si1㩷~yt1 ü}YdS(U'agTU> 6q]=,Y,qoKyqDUUt,iiȡ UUH\eBq~rY@_#s(mzONWFxZ8XIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a000.png000066400000000000000000000004711506470510200316640ustar00rootroot00000000000000PNG  IHDRaIDATx^F@=נF<J_PkQ'hҩ$* dw$w;3qO&g6ꯢiV$i<ϻ֮m[*DQ$I>Lӄ(8ϓ0q (Im'beAD0,KyUUQUa2L4M0 $uYQ&̀ m]WXEn1q( ۶-&`GȲ q)ջ} z<~;CtFijIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a490.png000066400000000000000000000003761506470510200317050ustar00rootroot00000000000000PNG  IHDRaIDATx^= 0Fs7!S*] g {{A MBp#`H23yE~! x{JIu= q( }[=NAUUs$I z)%ʲDEb]Wq vyc6\,˂4Mi۶[oA4! CdYiڎSmNOFO-wO[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a4d0.png000066400000000000000000000004171506470510200317540ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0Es4^@H.VR[KKK k[Vban\ .!<2!i\=M: CEWR4m[] YT%,4M{6(i u5RE`Aq 1|m a6꺆8XeF`rwh p{ow~aף~kIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a500.png000066400000000000000000000004211506470510200316640ustar00rootroot00000000000000PNG  IHDRaIDATx^D@1IhUr N{O QUJ"81$.cM]?( *De $S'=,ܔfN$C84m p u >lۆi˲*0QAQy m,::[uuk1 LS@4HTr])?{pzꗐIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a640.png000066400000000000000000000004451506470510200316770ustar00rootroot00000000000000PNG  IHDRaIDATx^= @-WK!l۔6 lB{-E%3AHXBb|003vav%InABl<+Ju 0ETUhۖ"2(4M1ϳh]@lƾa"@Qo0#_m33v S@pWIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a720.png000066400000000000000000000005451506470510200316770ustar00rootroot00000000000000PNG  IHDRa,IDATx^1@=AXو6WNc )bg#"". "U4;$q>x̼?faI`SL<_EjOP%sAO#4iZ7 TU}xnp]Ƽ~/'0W ώEY-HIqsxG:xf$x(~O RXIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a840.png000066400000000000000000000004151506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^ @7 |1(h2یo`,&fDF۹rq?|0~i1/pV^}#v%0 {$`t]m}_"˲sȶm Q<@4pM C²,Lk[ж-8&<ϻ.LQji9}GX( ʲD$JU(j AFKIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a880.png000066400000000000000000000005151506470510200317030ustar00rootroot00000000000000PNG  IHDRaIDATx^@ĵQN(R6V> Vv"2u>m@=SrwEQo?=}xWj},U(z%傮V3Ou]CE ^Q,0 q0 ,i 8bAeIO_Jqy$IZ0 )ɮk, 8NȲd۶L!su]i~`Yڶ%x0 ;Nò,Y1 0DsA`G$IuyʲT;F )%,C۶R0 88Bk4MA)k{4)'_F= 0 LIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a900.png000066400000000000000000000004271506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^ 0EAPp lm,GTRZ 88KaA $I"a`G= 毀0 Ya,Ȳ Q!IkA4(eq躎89Eq]ib]W6߶M\P%cUUq&,wea<i 3w}u]s.,4 mCUU̹:mi89 ^?}?#Xw;IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a930.png000066400000000000000000000004021506470510200316720ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0s+ow&d \\\[<⢄gB!Ii} y/GBz k=|:oy۱?s 0ϳ{uEhUU,K0ư;$1K qC))_A][t]g׀(miԮBEkS@eXla0n?<Ɉ5̀+IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a960.png000066400000000000000000000004271506470510200317040ustar00rootroot00000000000000PNG  IHDRaIDATx^͓ DP=DUv(v씅da (ec?slD毿{_gq0e|iwSw(gEnW@uiBua0y |0MXmh l6(i.FwsI(ͺsfΙ93EQ_?Z33Wu jr;FyC4LSE0*5t]$I\.$`&,MӰ, eYb>l6kF iX@EVi9ědYv0q>QUU Pe.YYra2 Mv(myÁ8FÀ-1!+ǻK@SJ$I]%Q u]?Ͼ7rdzIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00a9e0.png000066400000000000000000000005131506470510200317570ustar00rootroot00000000000000PNG  IHDRaIDATx^@E6?N,lXiJF?Fƻ;ea1&^xw10 ƛ&~M" U`hQq>quNX((: mAq>hgEهmۮp) 6WY3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00ab00.png000066400000000000000000000005031506470510200317420ustar00rootroot00000000000000PNG  IHDRa IDATx^E@=xhT*! "TjD$߀ .0o… 3Ç`zƍ0qDz~ 8pÆ @IIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00db80.png000066400000000000000000000005161506470510200317610ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb```dzF(lc9sCAzz:؛7o֭[f380aUDD>|` >dgذaA/]PPPf4N8x@ ??L2% `HHH &tx+|}}I7Ζ$PLYH7… `z!ـx4Mg&f(@lC[sa tIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00dc00.png000066400000000000000000000004611506470510200317510ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb```dzF(lc1`(9s&ٳgLLLl& 6  1ccc8B 6l ߀ o@||<ÁB###q.g{B`!fdcu7oNf(@PsކIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00e000.png000066400000000000000000000005641506470510200316730ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS 0 u?pl 1#ll8 mVIV6DD>)e'q2#1O]]H4 MDYQHN8oy<͋`m[$Iߔc^ÓUU%1j7Ӂq‰Ddt@IG;4M sp _ms!%eyzdHe4k=B4N-&_]ggrҾz0pωɺIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00f900.png000066400000000000000000000004301506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^Փ 0p!vqw9\}7AQPtQR u?K>80ah=l~g!>[ey, <<ϻS뺰m4A$nu u]UUݝiEQ sȲ,`ڶ=84=8FE|axhò,ERKD SkX~03]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00fb00.png000066400000000000000000000003721506470510200317530ustar00rootroot00000000000000PNG  IHDRaIDATx^哽 0\f CG# A1t JkG0 Iy뼋@Yw@?贳,۶kiD034ZΩ\~|;GvjzIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00fb50.png000066400000000000000000000005431506470510200317600ustar00rootroot00000000000000PNG  IHDRa*IDATx^=PF% Xen@H#H%SX nA bkE+0("o7ɁޟwPr}I{$ ڶ+D~f^y+Ȳ qju]򷂁.(S4 N}DQx0 ~,˸^4 ۍ0p\Pv%W˲ Iəjb۶\.8EEQ^A@<4g))@HӔ=ݎ>Dʯt]G>s?~o`f&OCIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00fe00.png000066400000000000000000000007271506470510200317620ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<iIDATxڤSNP= ;Y%k(36k`xl i iÙKK RCpL3sLO/E\mZḮ,.z[650wuH7n)%lF^jBHZ OX.'!47 '2=Syh6Uo )m`YjeY^8 |RtHYt٥ƹEݿB+_vIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00fe10.png000066400000000000000000000002441506470510200317550ustar00rootroot00000000000000PNG  IHDRakIDATx^c```db^ AR1q̙Z ffflk3O__TTl't0j- 8)S)`{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u00fe20.png000066400000000000000000000004401506470510200317540ustar00rootroot00000000000000PNG  IHDRaIDATx^Q E@mȣX5ܝYGʃB1^#wr96v !@J9g+Ykm٘9H) ZkBX/ b vAkfcW.]Dc$2 { 9NIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010080.png000066400000000000000000000004411506470510200316110ustar00rootroot00000000000000PNG  IHDRaIDATx^D@IJ"(5 :NH1^Ki1E2MYr+}߃sC5Rk-BXclJmq>['J)8,KNZxy)t;\ qYEocIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010190.png000066400000000000000000000005101506470510200316100ustar00rootroot00000000000000PNG  IHDRaIDATx^1@EMͼƚxI}(>}.uMӠm[i EQ0fSAUUem*gYA8}# CX4$ ǖK 0 $I8r (<0 U\ y4 u]CUU&Pi8,p]m\ ~b8n7u~\w""IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010280.png000066400000000000000000000003501506470510200316120ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 =C[dr/xLY+H6'!kO u1v{?&=SIgGLD#!<ϤScж-BdEQcss~(ZcH)um#3EAPJc%3EA.X뺒IP+R^ye{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0102a0.png000066400000000000000000000004021506470510200316610ustar00rootroot00000000000000PNG  IHDRaIDATx^ 03O#fTb KlG8qWلxZnWmTvS,ː=:p]W]!c$Iι>0P5Az 8H[B.*yn(P*qb& V0 }]7O8bK S{ =guFEIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0102e0.png000066400000000000000000000004551506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^=D@ @TU+; '9;H$zDMlvz/|$p]n?ki|{|:dY$I`ElۆaPȲ,_ eAyHŽ sLӴa Ya0#u4LAdi<9A}A I4"0mےwuMa |'k4.b(*t]Gǘ癊=` ~ 8)sZ{, IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010300.png000066400000000000000000000004231506470510200316040ustar00rootroot00000000000000PNG  IHDRaIDATx^= 0s?le!G+b..] ɼ03Ĭy5>I48+UM!vW(uO 8y~"歠:(]E@X 2$A4mbY}0 $ 0 ضa;,4M4M* i0MReY8+`q]<9n͡}>l5.ÐϪPSF~'8\+#K9IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010400.png000066400000000000000000000004631506470510200316110ustar00rootroot00000000000000PNG  IHDRaIDATx^10;K Xx!(Xw(zAb)nl]f&_ > |7˲Wa.0ĺ(4$I( q UUiiWu]$ q\4<ϩ'k~y7em[MPʲf1 EQGEn~ǫ" '},1 <_y/lۆ P$a{ 쉢Wޯ(@4 Øע(V.vaai 2Yev|>/yPUKbж|,˖Y8NKOuXE$sx<`&,Z2DODr@u4M;Np[\&ORU@=/pD5!0IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010530.png000066400000000000000000000005341506470510200316140ustar00rootroot00000000000000PNG  IHDRa#IDATx^1@ULl<֦I*lRXxAH!vv6i-J,w?|98qod>EQ"'C4<u*#qdY@EMӰpˀD{I'$a, "<0 EAeqȲ n[kr̂dQҍe&?tݐe+:2EۥIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010570.png000066400000000000000000000004621506470510200316200ustar00rootroot00000000000000PNG  IHDRaIDATx^;0݉;wNl Nl{; NN2L{ yq_{j4+M]ؓSn˲:}81p+, }ZfYv'\ ʲm۴^5$IiXו!\ t]GE,o(BV. CEi 2ui˃ ePU_ qDpO*Z$ض aͭNOA_ןBz4M(eYu]8`GI)Ѷ-}4M87 f0 2pΩpW]"n^0f4IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010780.png000066400000000000000000000003511506470510200316200ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 0s/=C%1 ^! 5Cp-Cƀ׈҂XE } !0>Mz$8b#ow~nSaʎIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010840.png000066400000000000000000000004221506470510200316140ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0Ey !^BmYm-^3XzRegcB<^ƟUmqV4*"ua0#qqU7M$IX~{<8?`r}Ӕ'h#SJu R(l:!jGAssd5^GBHc̵`4 Wy#xLLIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010900.png000066400000000000000000000004721506470510200316160ustar00rootroot00000000000000PNG  IHDRaIDATx^E@=VA'4$ōZD:BU QhET" ͽKN2sf7gawAjOOcTUw!{OOy*hq0Mu]( u_ i(,#sqLsI`]eYzr4v`gA`Y<ò,ҍKi϶m8IKi8Aa ",;n\ ڶW!"(;s)8u]1E9 n?q;Cniv LIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010920.png000066400000000000000000000004621506470510200316170ustar00rootroot00000000000000PNG  IHDRaIDATx^D@@# ^B)QgD<R %3,vKN2sΙoqs 3CqTUo!;$I4M4{n7㦵Q!IAǫ|dWʲC]Hdlg7p/ʹFIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0109a0.png000066400000000000000000000004601506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^FPƭn21w`6܀+ )ĀRl@ r^W穧szίs(~^?=lgѶ-=v4M>lۆaP(i;aMӐ$T1<#y$ISVr]] |,!2,˂iu}}5`8(eB]`8^-I0k PUp8q,$IF;,Z&vGEp;4MH6  q!dYi^˂1A,mz EQup(h(|>k22 xE눢Y! C\. HKK`pssB|||pԩvvv`,%%v #h2. #ŀ+W?<0`@qRShIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010a80.png000066400000000000000000000004541506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@Jk@rQTb $J(BEll]vK^o?0 Ɵ&gwY4MoE;;eY,T,x89 W(m0M$I,PD(*lۆyEu]221MS8 E,Ze> 0 8]םLӤ}{ t]+QHm0 vO};]?+IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010ac0.png000066400000000000000000000004741506470510200317530ustar00rootroot00000000000000PNG  IHDRaIDATx^=@H3S1B!\iGeA@Q, ޯi 2=۶q`44MTUEos 2 $"$I°8Kuu](4 8ea r]}cy @vʑ>i6$=%|}8T() V_IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010b00.png000066400000000000000000000003631506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 0DCQċXإb 66^qBq]WXv``2By6\ou]c6Z)`YPJQ(Be.yv}Q =`Gt]mQUcM y~ R"co9RHI@iWۧ| 2L}7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010b40.png000066400000000000000000000003711506470510200316710ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 0Du<^ G+KbGi,*u& 6K\B/GaYWض eYlEUU{Xi< c{PJR c qD${pʲ EQxHEZG]סk4Mm9}}ߟiy>\n?{rc}AIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010b60.png000066400000000000000000000004711506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^ϊFPNdEX܎keXY+v66Q8Sdo4o=uwas%|W߃:{/w<#88eI|4;KUUK-`]W(MӰ, u]a}d̲,}߉0#DQqdIilۆ`6]Mӄ,ćax8OI*e!I( À,PB۶4]xwNjK];IIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010b80.png000066400000000000000000000004551506470510200317000ustar00rootroot00000000000000PNG  IHDRaIDATx^1DPEb, (Ub ɨDh5vhEԲ*yܼ oqs8S|~E]׸mNp% βo ?.'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010c00.png000066400000000000000000000003441506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^ q7tf`;:Fa&p[*𿃋&/+^B^0n|o, rg/RZ@`&4M9Y@a=(e vf1ǁqk/jgm N1` Nm[DP+R|Y IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010c80.png000066400000000000000000000003721506470510200316770ustar00rootroot00000000000000PNG  IHDRaIDATx^A =FɅ7h O,B`tVVFDf|_qX`Eu}_3A飯 mۢ( J]hIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010f00.png000066400000000000000000000004101506470510200316630ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0D# "V^@!xdJcilddApݍ@2By<-vwUmpUJ<aO&S,aN.GQ۶1:u My0hf3y.s]9BeY²,PJ HA}iqdo&:$I8?(cYp)0^= !IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u010f30.png000066400000000000000000000003341506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^͓ Dkhف O!(1]v)'=B/%۰kcħ9`Y(;!d}Q9g4MY_ k-sB+ض /`"*gWG~fv=ps~SfA/G[@m[HDLÐ,˂( 2\E<A`w6`gQ( LӄeYg_5𑪪Ȳm}sʲE<ϰmeY5/Bt4 Ag͟ PTU0 ma]A$hv̽7{t ,ː$ x E 9XeYiv pƞ*axĀ]}ߟ)?^QZ,swIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0110d0.png000066400000000000000000000004141506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^ 0;DJװ[t$3Rk'l;=0*<|"!.YCx>ipApFRTU􌂾.z.n/=a?{WuaU;l]ױln1( @ 2Ȳ 4i.& )8뺏,0 ۶MW~\zX,4yV(H~*7]AT*<ϻDQ|]nr~GD$ $x`Ya<i(?}>i(,Ka!t]_{4M쒀yEQPvI@RU$AuUQ~/Nۣ*.IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011180.png000066400000000000000000000004741506470510200316210ustar00rootroot00000000000000PNG  IHDRaIDATx^?E@E"h$$@!J؆De Z Q(Q8OO}uJL˥IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0111e0.png000066400000000000000000000005431506470510200316730ustar00rootroot00000000000000PNG  IHDRa*IDATx^@ Y URYe6ڈ 6lB.]o`V" v?;. 0wAzw'I}۶:=a~ev44 4MC}p8@Qn7gijzMeOAPU,8z_- XEu]0 Nuݢm'"$ 'S >_UVR)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011200.png000066400000000000000000000004701506470510200316060ustar00rootroot00000000000000PNG  IHDRaIDATx^E@Ft UPB; ZJUHD!3ܻr?9g|sf2qcڇw;ij) cmm099 $I뺎eYm۬XQu4MCeҺ0 <#MSqXMUUjѲ,=c041TUeKJ( I0OEY1RYta8 Q]^n?q;&xNuIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011280.png000066400000000000000000000004761506470510200316240ustar00rootroot00000000000000PNG  IHDRaIDATx^DPDZF+:脒^@"R+%:J$ZFJ8Lv2X$'s&^ ]Wߋ,GM cuq0 ]oa$#8u},kY0 ERZwuE(l[(i03ڶE$ylEQ@40 UU9 f4Mccy$ m#MSdY [a]_tT;|׾0q~T1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0112b0.png000066400000000000000000000005421506470510200316700ustar00rootroot00000000000000PNG  IHDRa)IDATx^1`U-Ah/8撸788k&'srh) ? WJ 0 Ugջ>iwSvu'.Kkt:|>دqyAit]wβ [., 7Mz! CjVUlF( aNr$\.ޫVyba@4DQ$YQy(.Bv8q,ˮ,mۤ>ڶ}8뺤w<1M0eYi,\ $#Y8iGo>C-Zv?Y4!IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011380.png000066400000000000000000000004361506470510200316210ustar00rootroot00000000000000PNG  IHDRaIDATxœM DP=~ vVg_P ;I"whSoS}N(*|#s<}]בiAeYPU0ĺ!2LMHUYeDQq0 ;n](¶mx4$ E0ض&I( ˲~8Nc:um}OIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011400.png000066400000000000000000000004431506470510200316100ustar00rootroot00000000000000PNG  IHDRaIDATx^=D@V(uP8VKpFD"PlZz7ɗ qRY*4it]J~ ڶeYk$Iic8a EAcb]!"A,˴ AYp]0mqyeW=(B]PUu<ϔI4M(`q* ;a,Hc CdYLn?#]~cIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011480.png000066400000000000000000000003541506470510200316210ustar00rootroot00000000000000PNG  IHDRaIDATx^1 E&rjŞZ Ɔ  f7ذX_^(!^ g|i7S an# `4Mҏ J)Zsu03lvHV+B1vXy 2yN;m{u\ 1"1&ۋw$OA}7A)r l IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011580.png000066400000000000000000000005111506470510200316150ustar00rootroot00000000000000PNG  IHDRaIDATx^?FP%xzn򔔲zlZѬ &)U`{l{qǧ~uϧ9PE}| 2K7eY⯐ޝqQUA]כ:T l , IDQ4M© MSp,( $I0 Lӄ( ]׽dY/}9gY X{g"\ykP.80 c΅a8CBhf^?Ohm À(NpS~O<2^>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011600.png000066400000000000000000000004701506470510200316120ustar00rootroot00000000000000PNG  IHDRaIDATx^=@3cS悁@PATLLL ֜<ϑ$ɱH\uGvvO?;?qypIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011680.png000066400000000000000000000005561506470510200316270ustar00rootroot00000000000000PNG  IHDRa5IDATx^@M@H!ZB>O$Mg>m[躎bAyQErVmN'ʗ%fB44^ TU{OkaU< $Ij!2 ˲>.,K\n3Sz D=<þ7@>VUIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0116d0.png000066400000000000000000000003401506470510200316720ustar00rootroot00000000000000PNG  IHDRaIDATxݓ1 Dנ$Cik,h Tvshbvf)܍aI&?"F_:v?giB ,˂i9c RlVJ֖ڶs.g5q}Ƙ뺢:g y_Nny>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011700.png000066400000000000000000000005421506470510200316130ustar00rootroot00000000000000PNG  IHDRa)IDATx^@mղNBB+ABI]o 9F0qg,v[rS-@_u,P5N$9laxi( 7 DQlYV7 ct 4i=fdYzj0wL&JSh瑦)$Iz `bSG t]l9^q(o[, /lDuA@kQQvX.UU/}0eZOy@ ?"EIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011800.png000066400000000000000000000005001506470510200316060ustar00rootroot00000000000000PNG  IHDRaIDATx^1@mEr K[1 hg'Y켅`/`ci`!6!EN`4م5~`W 3 0_?!g-!{8HIm[*YL:\ץ1 e!mz}:u p>1  ,t4 mv4Mگ EMӀeYt]8|B\.e0 !IN'dY- |%s8 ָpgͻ,߭a[[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0118a0.png000066400000000000000000000003331506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^c```db^ AR1q̙Z Auu@o K yOIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0119a0.png000066400000000000000000000004271506470510200317000ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@Π BVmR踈 (TzQJ6462VOdLfc6~4ϞwYm QmCuO= 2 @Q׀]a,Kt]EQ`YqD$W,0@UU0q<ķn&$IBUU4iR},CTi(ycgƺh昹xwdģIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011a00.png000066400000000000000000000003011506470510200316560ustar00rootroot00000000000000PNG  IHDRaIDATx^! EW0@`ߝ6YSj3aac1.fg7c ̊g Z+sRBcc)%(sj)/ox&Gg\osroLNIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011a50.png000066400000000000000000000004311506470510200316670ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0=M< (: nN^MJVZby/A =5\t]֐'+4}JM #c(YQ%$(۶iea(]+ǁip]mۢ{vA]ט^E4 ˲$i=σ30 q,Iz$۶'S;gq(+IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011ab0.png000066400000000000000000000004201506470510200317420ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0Ds F x[Yhac)j!n"kցBy}?fEY+{}ߋZ`624Mm+j%@u4 <6`8$Ie|߇uqcY) @]Qt `, a<0 wN4!">4 7BRS~g *{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011ac0.png000066400000000000000000000005421506470510200317500ustar00rootroot00000000000000PNG  IHDRa)IDATx^@EHU 1bF>i-BCV% "E9lq0rg(4HC]:dY>~Y]8N]W@۶nX,i\\ÜAcϛ=ZJ qY!IRr J ~áQM887r m%S I RZ2dwr=2C ?WhIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011b60.png000066400000000000000000000003311506470510200316700ustar00rootroot00000000000000PNG  IHDRaIDATxڥ }{΂ ]VqPl+ץ=hc/Q !>Z-B]k'`۶˳[J) `8(8R yi :9˲<{gWR~!ZZ1|/+,S:w<IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011bc0.png000066400000000000000000000003611506470510200317500ustar00rootroot00000000000000PNG  IHDRaIDATxM 0s ǥ$ ϐУ,q%;x@kBuf`f!0Nz=30 T[ਾ+tiO}=IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011c00.png000066400000000000000000000004711506470510200316700ustar00rootroot00000000000000PNG  IHDRaIDATx^E@P? %54Z}᭮nUp!R Zk1GE7hYPJ=[HE͗m\r΋O}}-NvIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011d60.png000066400000000000000000000003671506470510200317030ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0Ds^nea52E  Lɫ{Mw]BupmaqTU(朣ikMaΧ4Mht΀eYy,C]HAl03&e8M}ېRB "ci6)?=*IDGIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011db0.png000066400000000000000000000003441506470510200317520ustar00rootroot00000000000000PNG  IHDRaIDATxڥ= :Hr &\b{O:hrve-֌ Wc=^ѥ'1VpWc68p]}10@eYhRJQ* F1Q`z=/BՂi0xO&bex77`,@9nX N' h ]+ ߯0hC(ujE)Et:܅#0 ۭ64sjr>FqtO^C}" MġCL-pnX,sr@e#^/&VxqdsY&'T0a<I!9 !va6rART <3QukohVIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011fb0.png000066400000000000000000000003631506470510200317550ustar00rootroot00000000000000PNG  IHDRaIDATx^Փ 0C@26B& 5) XMKغxw O/wV?_BwP~0 bq;ڶ:=Q,! kϟ*=PJ$ q k-8PJkE;.b^, 4E4S4M`Ya;r~7r;?Uk~ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u011fc0.png000066400000000000000000000005141506470510200317540ustar00rootroot00000000000000PNG  IHDRaIDATx^@}C_6oFE P+" IWF, g8ޏ㏞kg j]$xDE|\`&4Mvf8鄾93E!ɲ,8qa! ~GQ, H @UUut]y$I(`Yt< ,[fH }ضM|8:ni_\m,~&-ZQ~}wbpJ40"IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u012000.png000066400000000000000000000004251506470510200316050ustar00rootroot00000000000000PNG  IHDRaIDATx^ E@= a#Y`B Wνf WS[BH.~,{8ж-4M( 84 m4MEeY I\E[:u=u 0خ*8h=σ }eY2沠iXQ13cNq]eTU7I` _0M,c{盔A)?JrNIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u012400.png000066400000000000000000000003541506470510200316120ustar00rootroot00000000000000PNG  IHDRaIDATx^͓1 0Es'`" yVbx  =ߍ6*UBy}?ʻ]WAp ca_ I`Y8(1EQ*q !(u]_ 8HY9mE|횦PJ1:{_<Ʃr@¾`~xIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u012480.png000066400000000000000000000004511506470510200316200ustar00rootroot00000000000000PNG  IHDRaIDATx^F@=7 )%-#Q(v^5kaso~ujMsΌ +`ͧq-i_a7SH8ǑK!I@4x,PUmJ/HAE0ME!IezZ0 9ʲľu4Em}u]:A X @ImBE&e894M4 uJ/H,K!O ?Ͼ7bnW"IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u012f90.png000066400000000000000000000002751506470510200317070ustar00rootroot00000000000000PNG  IHDRaIDATx^퓱 E9,8CX ػĤ2DH ]=ՓB~;xH{; rB7 @k 9(B SAKJ R'xC`R 1cPJ ܁֮˫wyIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u013000.png000066400000000000000000000005351506470510200316100ustar00rootroot00000000000000PNG  IHDRa$IDATx^@}!6o 6)Lv$ULvV1iRQ A-dA6?9~ ?>],|>fyl[AaHӴ_[z  kH o,ˢiDB}<iw]Ȳ,yt]tB}f@VE(w>(*<۶q\`O4h bX`\8DQ}@g#Iy(1AuÀɣ<}Orl<[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u013430.png000066400000000000000000000006261506470510200316200ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<(IDATxڤSN@<=^Շo&pjOBC .5 PmCLvffv9)s㠌( $wQaln6\~ݥÁ;կ=%IUUwY^f1v:m<>I'EQ{t]hq#ITU0 8tfu)$hYmt`&;{o5?W~rLGo^IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u014400.png000066400000000000000000000005411506470510200316120ustar00rootroot00000000000000PNG  IHDRa(IDATx^O`ѩg!Ha b^D :FSŃzvgv73qy|}A 3hUk\vWޖJP~ M桠kX`dlF/4l_Mӄ3h vp]Պ#,Kq- $.Ae?㑟Ny~Nlx5^|> <xQq8>"z=WS$I44M10o=~۶YR%dYb_x8ĤwsvIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u016100.png000066400000000000000000000004621506470510200316130ustar00rootroot00000000000000PNG  IHDRaIDATxڥϪEPƽ ))Ix)ehl̔ &߽{q㫯^k[EQޏeY⬶+,yǜ8?E$9CQm确!I ÀeAu p `Yq8{ iE!1m[,iWIӔ< 2pa=MzM뺾q| ӥqSC@UIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u016800.png000066400000000000000000000004551506470510200316240ustar00rootroot00000000000000PNG  IHDRaIDATx^DPxZ#zB""oQHtzPig6rkחLLLr8,.M8 ~*eS(86&BuX0iLӤC#s:9aH=C<E "q UU)[iض hmP6y$!IiJ p~ж-dYt0)x>,)4Mq;OB]o8aIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u016a40.png000066400000000000000000000004261506470510200316770ustar00rootroot00000000000000PNG  IHDRaIDATx^1 03xwo 8eS=x'77qPڴ 6P|dH!>Ξ«~/ڶqQUar&=xEM`6TUEe>4 4MyY1$Q )<@PȤy:fa26]$wp\HPuibG+#Igݟi ",˂iP{, ]亮1,p8DeM`M u6^VX,݀t n(66Mt%dYyaP%v];^d2x< i C ض38FEa5:l6)L7MS,IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u016d80.png000066400000000000000000000006061506470510200317060ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤSEP+$jNѬ?|oPZ(BĬ OI&w̹3sMF-eJĮxT@+󀢨{д $. 6{Ymv-:CexUk]A۶$WUq4zv4A4ض EQ gY&_@$`0 zg躾<yCREQ< L 4MC$qQ%9˲rXu\hE]ס, nǁui==N?>ekAYIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u016ea0.png000066400000000000000000000004561506470510200317630ustar00rootroot00000000000000PNG  IHDRaIDATxڥ?EP-CmPi6TYK4,A$:KPXQHT :w\/33$3EQ?Ɨ&_o (UiIm[@eimq IseY0Ms]ׅaO=IDATx^MPBAkrD(B["E+-h!&Z?@t+IQ˹{d1iˁ8Hr`^cX`>C4NFx\A^jf8ϰ, ӉM&HY,f\׭oG,KLSF#躎 ZKlۦ[Ȳ0k-U zPU~< 'I"Z3/W;KuyIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u018b00.png000066400000000000000000000004441506470510200316760ustar00rootroot00000000000000PNG  IHDRaIDATx^ @-FEiEAE0@M-웈/`93[\XWa~a/GMߓaH1:L@$t]Siu9 ۶)8(eEQ,OkBxA4ml תB4w <ϡiL8uA)a, 4!q`6,˂8m@PU$q@e.i3:a`'3]KȲ,P׵8P%ڶ(Ip+늾yy^7?ž{jwIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01aff0.png000066400000000000000000000002711506470510200320370ustar00rootroot00000000000000PNG  IHDRaIDATx^ U'.Vbe'H9xC8NruEJ S`@Ι*y{RT D#:Z+*1h p~OàD(IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01b000.png000066400000000000000000000003761506470510200316720ustar00rootroot00000000000000PNG  IHDRaIDATx^ 0q;!.8ۤԳD[?81nŸewwlYݝ=:>XY9eq & @EHJ)aOeY0M뻮sWb]WAy I4MCcǡ seI7^mn2W0SP׾Z'IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01b100.png000066400000000000000000000004361506470510200316700ustar00rootroot00000000000000PNG  IHDRaIDATx^D@Ք^ $Du:: (PP($ή-.NrBy}?=uw_=$I;4ݎ.c,qk@p]뺆,`t ,K <Y2(:l0EQ2!<68 0`Y֢6ж-- I 8i vO}7>D񆞖IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01b130.png000066400000000000000000000005271506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^P}DBBPRQwPҥR0=.%IsoΕ(O#Oo's+,˱mI Ùh)$IPa'Z,"{TU5\W01nY|eYp]nlI{0 `64Mrżm Y:#,SUUE 4MqL}:>f L|9pEAx|'ꧼ}oXr CIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01b170.png000066400000000000000000000003701506470510200316740ustar00rootroot00000000000000PNG  IHDRaIDATx^!0Fkk1%A`I\- ߀! vرpl}3 !z,0^1WgʺpaG @k$IPm1/i8 yF躎FVPUFV;,R*VP% cCicϣkPK=, ڶ8yQ%|7}u9R4k$~ %!h (v9}Y{@u81M-Ƣ(y;,L:AM`"Y1Y 0@W{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01cec0.png000066400000000000000000000004051506470510200320340ustar00rootroot00000000000000PNG  IHDRaIDATxڭ 0E"B>EંNvۤT-6j/\/y!BnᗟiJ~U(Z9U. CAc}_PU$Y,P:0 LӴJʲDQ&geR]=T0M깢ܮWow~4ڶIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d000.png000066400000000000000000000006011506470510200316630ustar00rootroot00000000000000PNG  IHDRaHIDATx^ϪP]'EB> B;_o 3ЍDZ6"L ]93g~3qm܊, VlmT4~G8 `AuYv(fYVȊ<rn8Nd2A@U;)My+|G'x-%Z-F#DQD00q:lK$4M$IB~QWeY1 . lۆ}v:cl6-K4Mzv Nt Rw&v]a|>S)`}/I_vIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d100.png000066400000000000000000000005041506470510200316660ustar00rootroot00000000000000PNG  IHDRa IDATx^1@Edc$x bdͼ"((̘fÇ_]Blao&~+eYߵ q\Os~sjIIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d200.png000066400000000000000000000005261506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^1@-XXXG-$wi CQ`@R+A,n|73}0 EQgw'Ie]FC۶S0 9n,aX%{A4GVu]6n䫂UU!WA$>BQ˅EQ.,tELUxeY^m $J|?ϾXZZxڏeIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d2c0.png000066400000000000000000000005431506470510200317550ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS[ 0{@H@u$$ `o^z# 7& 3KKDTH*nebbM-Bu]SUU=vlYqy'I"c "J)m/N{: ˲y܏+s4MItyی㘺i3uui4},lfBҳ7z3M b QΠdWL"_BSxIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d2e0.png000066400000000000000000000004621506470510200317570ustar00rootroot00000000000000PNG  IHDRaIDATx^=@=f"x1T0@dR1^ޮɀ*fy|~p,qU{T4+ s(heRe{iEiR-Iaq,| a#`Yhme˲*wuey>v5MC8)+mCH^U5(mpa٫ _DeUgIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d300.png000066400000000000000000000002551506470510200316730ustar00rootroot00000000000000PNG  IHDRatIDATx^ Esq=/ {p6OF~x ~} *a+GD\ Ys.- QSJ.-V-X |Lk<~H o4 NIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d360.png000066400000000000000000000002621506470510200316770ustar00rootroot00000000000000PNG  IHDRayIDATx^ %ddBN^)1 y$ě rZck0; v{/N1.NX9'NXR8$NZ9,NXx87}OeqIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d400.png000066400000000000000000000005241506470510200316730ustar00rootroot00000000000000PNG  IHDRaIDATx^@}()RZ",,m,EK_@I{ (E0Qn8h.ޝ?0;312 ü}4;K՟roEzg$qvHtZ^h( "z  zBu?GTUY1 ʲpxu$IBl6t beimp:y,˂4MZ[Q~sD 맀mn (xNo,C44V?^nl0ϪZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01d800.png000066400000000000000000000004251506470510200316770ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@(NTj )&шNuѣYY/yL2C!K(}QxT5 4ML ,ke܀,ˠiyfrn@UU0 ; ,C B4M*ڶEu0MS y(:<R{־q>t oGmi]U8"Iqޡ S~gya8tjvsIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01df00.png000066400000000000000000000005311506470510200317530ustar00rootroot00000000000000PNG  IHDRa IDATx^@},>)IjK++RZ4 (L/=Xs]fbwa{Sg?uv,C8(Wf:(, mc6vS|(tLma&xXVp,#Mq@$I I˲h&NDQ$4A~'OqI8q<I*X,!].RvzMϪ\5 ÀyHU~}O]6Z諸IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e000.png000066400000000000000000000004321506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^1D@QtZBv喎nD$ADo663Cf_3o'aa<^yYg]W4M#ދmۆHD(۶!88'80 yhiu]DQ˲, G]EVU%mQ8r[/D)G) GReY ,CU՛P+Hi֫5NcL₥`@Q-0 ti^oS&v Z \G)};ė(L(JtmPu-G!r x.> +>B{,Y3~S? 0^K?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e100.png000066400000000000000000000004221506470510200316660ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0Dsk ;k,= x/`YxADg7YfE:0)~B!xh{(oQ5TŲCY8J痀8a6 4 R)s Xib6Q}mۊ=)`Y~^Y!sv 0 <ϓjJi)yeY"äÐO1 ">ξẮ04M a@uEkx_w?Nk4BڧIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e290.png000066400000000000000000000004221506470510200317000ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0EsK#DlVxQ ;uay0!atмo4 ]iYa]Wy0.ǁmضM(a"MS}y12JA,Ku$IPt]ԴihV($ڹ:h(9'ܾXe]S~gy /3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e2c0.png000066400000000000000000000004251506470510200317550ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0s78" .NB\s)Atqro4HmA{y!$r{~evW6EQ8˲w'1ks(mCQC0 PUi#3Ɛ ,yHaRD,K+rqxmTж-4M4M<Q,uQUȦi6+R0 9I躎 6+RY//ĵ| IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e4d0.png000066400000000000000000000007211506470510200317570ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<cIDATxb```dzF(lc9sDaZdv2ϟstǂ2T21xA\\o  iXY3fOMLS?y] \.Bw ^|>zjSR0_RDܼ?~X 왳z ,vw2 $ d] ;o0 [2\r۷` |Xp+sXk2D T ACCAN^E"bH- PځL ݮ/}IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e5d0.png000066400000000000000000000005211506470510200317560ustar00rootroot00000000000000PNG  IHDRaIDATxڥ1@6jk!DUHc C,<ΔN"T6ZG,H"񇁝YaӯK#_?o9֊xzr!{ڶ^X}}3*PJ+?Gր~y[IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01e7e0.png000066400000000000000000000005651506470510200317710ustar00rootroot00000000000000PNG  IHDRaa 3Li*$II`5躎8I?Mx8$c ,BT&2&=Sœm$c 0Mi" CmK0;˲ sjWNOB]7w.IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01ec70.png000066400000000000000000000003661506470510200317660ustar00rootroot00000000000000PNG  IHDRaIDATx^; 0ERg`iSA܁MjkA:@́Kͩ{6;ml݃.8T0 <Ϙ ZkumI,52DQP @YG 0R Bq4My|߇1\$ 8Ri )|W!]j4*8?e}|‹A|JIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01ed00.png000066400000000000000000000004211506470510200317500ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0sO+^Cйqz 8GDMТ-ZKV8(Bp}yF0MUU"]aY(BX%omC4Ƙ:3X )$8/>O}X~ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01ee00.png000066400000000000000000000004271506470510200317570ustar00rootroot00000000000000PNG  IHDRaIDATx^1 0sqtIs(Epp\ xĿMcilS4!ǫgzOڶUړ@,K5:PJQUK(KiKNEj$$HT˲ ˲Ç$`i aa=`6A u$AQ+8ypm4MX%6]_ƺ1㡷s>7u~~QI4{IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f000.png000066400000000000000000000004171506470510200316720ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤSA ,}w&m'it4δPd-f'x 9"߭Xk/-&^1QkzH)Av)cc_zC1F9*kr䠫"hx ]΀פEǗ? s`IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f030.png000066400000000000000000000003671506470510200317010ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڴ E[u#p3qةRQ6%? `H)yf+=ђxoML3^M@f-ynJpE-Kbz9Nyvɴ-z M3Df5+'{NԲTn@'$)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f0a0.png000066400000000000000000000003761506470510200317570ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxRQ Fz]z&DRȲ}6ƛo0ƘN1I)"> Xax#7c91JZk%kM[~)?|^PcJ1'>՞,?/ VaX>4IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f100.png000066400000000000000000000006031506470510200316700ustar00rootroot00000000000000PNG  IHDRaJIDATx^1P3}>KK 5Y UZE]r rjKwO(A p߹^8 3ػ/_VPIu\ק. VU]EdR7ɲ Iz4!s=LӤMzt:Ȳ<0`v3@UUaHrMȋ4)4qv;75MeS,ˢ6}'Nf.<#u]mfp8vk,lhU +1>>g:6SAyYUIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f200.png000066400000000000000000000005331506470510200316730ustar00rootroot00000000000000PNG  IHDRa"IDATx^@} ڪHy`!bTilR3؈MAsx]e(_= yc/AYt:u] ]׉fa"IN'm8A IuQ*0NjE`&O$Al68ϰmqc8FbɄ^`YuAr 4 .Oi0 n7&`^c6aTU}, JEQl6zVrK:xTUEPh4. 0v} S;8G+IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f600.png000066400000000000000000000005561506470510200317040ustar00rootroot00000000000000PNG  IHDRa5IDATx^͋@GQٓ@L CIt%B CtUE}gi]f߼ ˛Oӷ_Y.(xh4Mn7 eaZX#p8`0@UU۶t~dYb<ikzv EQp[rp8d$  (zb<Fxytib>,fVl6 H.n*m)u]q YE3$d2y]:AcU}St:! CAuh[ kpfaIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f650.png000066400000000000000000000005051506470510200317030ustar00rootroot00000000000000PNG  IHDRa IDATx^1@E =\AFsQF:)(  ]{qXVYM7EQǗMiZj7: UU=`!.kt]i:+8E]0 `qCȲI@4aYY\EQ1 CyN r(m8n(~id>4MeYf.`zeTq'I,Xն-y~%6O}Ojs;b˰IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f680.png000066400000000000000000000005721506470510200317120ustar00rootroot00000000000000PNG  IHDRaAIDATx^ϊPݴ|D۹PD&| BB ]EP|딠M>@7so436? 0o}Zݜ8HqHEQ0Nq^~0\.9 `0~$\.۶1IihBUUN{Y}aH!~S|@^jnn1q:,p@<AjBDC_r*}e鮚aXiu]l6{@xm!RkXl*O2)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f700.png000066400000000000000000000005771506470510200317100ustar00rootroot00000000000000PNG  IHDRaFIDATx^P!p*sitiIhmuN89E8 AK$ZCyNj'r~aCWnoE8>2\.KOn }hbfn9Ȳ,4MDQVQ!TUw^+x`0l6C^$IXKDaVx~ba+ ɿx<]H`rHtZ* <~?MSkx7MS |߇au]C$A,MTUE4EQYqtMt:ж-lۦjqzfEQ@8v ˲ꄗriv8Ð֓$yQEw]Ya浇R@ }_eYb'OyA,ΟSXQHrcIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f800.png000066400000000000000000000002711506470510200317000ustar00rootroot00000000000000PNG  IHDRaIDATx^c```db^ AR1q̙Z 7o104YJJ꿊 VCpmfȐOkIePԌ@˗700@۷oGQb'e 0etCY]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01f900.png000066400000000000000000000005521506470510200317030ustar00rootroot00000000000000PNG  IHDRa1IDATx^ˋP0ƝIܴTj㢍An t=Lsp<=^ ˛Ow{0['꺆m0 ..ˇ.`ݢ(ct]iz} n$y@|g) @Ye}f3>`0PaQ'IBuvr:04UU\F|@EkF3w:{Wq^&EQhۋł(bZaѷh`-rD4Zz(2L&:6g=Z-:f*r1IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01fa00.png000066400000000000000000000004441506470510200317530ustar00rootroot00000000000000PNG  IHDRaIDATx^= 0ţx[`ce 6Vv)K Zx dAaw/<^"?M^_Ym"7}nMc*&i۶!$AeXeaǡ(Hby0QAEH8iVjq*dYy뚶@d&,ˢuQa 0 # -LDAFuy>s<]?/9oi)IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01fa70.png000066400000000000000000000004241506470510200317600ustar00rootroot00000000000000PNG  IHDRaIDATx^ 0E Qn\PLiQLE끁d9B"Ix %{1B{w\i 07wJ4 EA$m,,K^;,qE,k ,eY|q{ y# CD03TH#ʢi6ńP@x4aXl) aE ΰ~7w~):&IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u01fb00.png000066400000000000000000000004201506470510200317460ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڬR +>A`.1S5}!r#jڋDDJ6э!#1-6S{Zk!tlCB@~;}SJShcٜ 2`c ][VHS@?2HW&{]c/>9u s7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u020000.png000066400000000000000000000003431506470510200316030ustar00rootroot00000000000000PNG  IHDRaIDATx^= F^.`X,S79A`c߮iB.7%qOg|{Ĵm !80J)u(N`4Mje݋ G9Xk=cPJ, `G4MawVyKvOp;_vVxIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u02a700.png000066400000000000000000000005771506470510200317040ustar00rootroot00000000000000PNG  IHDRaFIDATx^Kk@5ayDAj 9 "K$ K¿)-mm6ogq7ɿ{\.Wmò,V+ʩW@p8ijfpB fT*`0@$f\.C4Ȳ EQ:unFnǶm+JlGKn#Ni`zNV#HRn7w(s àR<"#~ 8F#|>nK"KBxL<jL&r2/,&{ pY,t:2 fjEZ}`MFrrDu( 4(6bYJL%@LP(;8,Á~e2DO9ut:^2~|?g\޳IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u02b820.png000066400000000000000000000005211506470510200316750ustar00rootroot00000000000000PNG  IHDRaIDATx^@}O[@ڄ4 ,NAw,YhcO"9bEb́޹e(2qWab`tm?]S@e4 u]v*p<:nCԶm<. :8AY \vpXGrA, (dMQeiI4M}0 E˲PUiqx0N)=$eY6i`AE$a<;+o?7wz~iIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u02ceb0.png000066400000000000000000000004331506470510200320350ustar00rootroot00000000000000PNG  IHDRaIDATx^! 01h6If1A4Lbl{'Ɏ|cc=^?k^}R%~e{㈾߲O F|ݑ eA4HeQf6HEQ s(a(s0e%]`u]Ami- yQ*<M(q(iJ@DUU ) io9XUsIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u02ebf0.png000066400000000000000000000005751506470510200320470ustar00rootroot00000000000000PNG  IHDRaDIDATxڥM@A m]}B,-r*."DA+!v\\n%Q y|p}};tv;{oi""V4M1)@QlfIZzZ^``2@EXB$IHot 0nIu<ϣ\.ö|~TUt: l6T*h4g-!!inV r$I(J"WfpD{wIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u02f800.png000066400000000000000000000004261506470510200317030ustar00rootroot00000000000000PNG  IHDRaIDATx^?D@T 8{(赢^DRv}]/y}o~dfc0w"s|ii#1it]*eEQp ! cK])SmۮS@0M2MӸ$ ,BeQA$#TUǡuY+yHtN<0 #lFexG8t캮{_wKIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u030000.png000066400000000000000000000005401506470510200316030ustar00rootroot00000000000000PNG  IHDRa'IDATx^ϊP}TڸBWDh)dB| %pi"7 MӁs8bk;wcb෪rztB۶wAx7xEۿsv"ZIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u031350.png000066400000000000000000000006231506470510200316160ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<%IDATxڤSMO@}ԋPN__?&^C1؂7u X_2ٯ3og`"wv:CWy2Wᘁ\1 " 9YӴz )^}Ii>zj,0MW!l Ӡ4MJ\b3\eLp}{x^B(1{Ig`F-˪˱yc-j%XL {l_7ϲ ]6./u+! R.@'o Wg2o!Y![IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0323b0.png000066400000000000000000000005471506470510200317010ustar00rootroot00000000000000PNG  IHDRa.IDATxڥͪP}^#_EHQ ⦞A\h!ڮ+s. u? g8gw| qm(~(_Q௚|˲PUկx,Y$I<q$IHEA]1qa.K?DAbb`6yd@%F#N',K{VIӴG HavEQlpt:t=`^Qvn+/t<( {ǪqۍeYYm` UUs<#j^RIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0e0000.png000066400000000000000000000003531506470510200316670ustar00rootroot00000000000000PNG  IHDRaIDATx^͓ EHf~W&'\qd4qCnFmIorXM_^mq7ٓ7Lԁa`uuc /EQ "'i]}lu J)ʲDH<nCBKYHZq˥'(~}'Չ\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0e0100.png000066400000000000000000000007421506470510200316720ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<tIDATxڤSj@=T-&KK] OV*HiqUcc@$cΌFHۀ sss TdWƀWx,. o36DQy8$$AR~gFhRd^)"Tl[˂^TDZ`6<0j ۶:!xL΂m)g el0 fCaiv eFjnc!U^0F(-oܟ}4r zz."E?ODPh`Y֑Qfu:1缼PmQ&1Uj_< u=Kxe˷q&IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/u0f0000.png000066400000000000000000000004311506470510200316650ustar00rootroot00000000000000PNG  IHDRaIDATx^9 @6i K+]+o vB^O`&Y7 3 )MS5>r/`8!<úiy mUi E6.|)@u?IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane01.png000066400000000000000000000005421506470510200323230ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS 0ܴDxbO~7A""-WKI>&ٝz/*o,KmkLN8(yYq iRQDJmB8Lx >,Uz3WU6gPmXO08ڜumL~^G`W$IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane05.png000066400000000000000000000005411506470510200323260ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS 0 M7"ы7}w&H/(xֵc@6//i^JDT*o.[,)˲m38I0˲4M468iJyk(<:m[R\ih۶l)WV;s0!EY/KnaKRzde",lKƾT9R}$'Ɠ' @Jq1`"М]qIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane06.png000066400000000000000000000005471506470510200323350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS 0 M7O*"Ew컼M/(x)յc@im^^ҼHDT*.LJ,)ڶfp$1aeihwfOӔP$QyUp4 YQຮj߶MW R~ˆ !$q_ɜ62qT0d̸gX*0 S>S@gHmO0m`gb%TIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane07.png000066400000000000000000000005401506470510200323270ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS= 0EMF8K5){ QYvl>dYFqD뚊 0 )o_oBʄꕝ IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane13.png000066400000000000000000000005531506470510200323300ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS10 t( B C,tC6&b)F*D-Erw*Ğ{^0s0bNIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/uplane16.png000066400000000000000000000005461506470510200323350ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڤS10 t( Bw|(  !`QQK//_/z.ಹH)!ISIM@Q:Ea4M0 }&{ǐ)A@q亮m[{ |se{4B*yQ l8йpϦ1Ѳ,sf܎y3LFRnp&FN,K:VeTR}[$+'om`+t۞oIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/us.png000066400000000000000000000007351506470510200313310ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<oIDATxbdȨg``h` 40 @`)A0#9ˠ" 6i 6qǗ eeH $5X4Ԥ#}`){s ÿ?f8p3Vf4X?xp 5 ܜp71E5r42?gSa8A^J,;^G@x9xlPh7mB @B5c->|ɡT Q > ` o"#)3%2 P+edc "8J$!35P 3IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/windows.png000066400000000000000000000002541506470510200323700ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<>IDATxbZe>di& @Y}O/@P m f`}IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/glmlicon/zx8x.png000066400000000000000000000002661506470510200316220ustar00rootroot00000000000000PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<HIDATxb```dzF(l@!H$@q,Q꤃3g0CSbÀ `XpW]_IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importer/000077500000000000000000000000001506470510200302245ustar00rootroot00000000000000BinaryBitmapFontImporterFrame.java000066400000000000000000000011141506470510200367120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.io.File; import java.io.IOException; import javax.swing.JFrame; public class BinaryBitmapFontImporterFrame extends JFrame { private static final long serialVersionUID = 1L; private final BinaryBitmapFontImporterPanel panel; public BinaryBitmapFontImporterFrame(File fontFile) throws IOException { this.panel = new BinaryBitmapFontImporterPanel(fontFile); setTitle("Create From Binary File"); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } BinaryBitmapFontImporterPanel.java000066400000000000000000000344541506470510200367340ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTable; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.importer.BinaryBitmapFontImporter; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class BinaryBitmapFontImporterPanel extends JPanel { private static final long serialVersionUID = 1L; private final File file; private final byte[] data; private final BinaryBitmapFontImporter importer; private List previewImages; private final RawImportEncodingList eList = new RawImportEncodingList(); private final EncodingTableModel eTableModel = new EncodingTableModel(); private final JTable eTable = new JTable(eTableModel); private final NameDatabase ndb = NameDatabase.instance(); public BinaryBitmapFontImporterPanel(File file) throws IOException { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); in.close(); this.file = file; this.data = out.toByteArray(); this.importer = new BinaryBitmapFontImporter(); makeUI(); updatePreview(); } private void makeUI() { final SpinnerNumberModel offset = new SpinnerNumberModel(importer.offset, 0, data.length, 1); final SpinnerNumberModel bytesPerChar = new SpinnerNumberModel(importer.bytesPerChar, 0, data.length, 1); final SpinnerNumberModel bytesPerRow = new SpinnerNumberModel(importer.bytesPerRow, 0, data.length, 1); final SpinnerNumberModel cellWidth = new SpinnerNumberModel(importer.cellWidth, 1, data.length, 1); final SpinnerNumberModel cellHeight = new SpinnerNumberModel(importer.cellHeight, 1, data.length, 1); final SpinnerNumberModel ascent = new SpinnerNumberModel(importer.ascent, -data.length, data.length, 1); final SpinnerNumberModel bitsPerPixel = new SpinnerNumberModel(importer.bitsPerPixel, 1, 8, 1); final JCheckBox invert = new JCheckBox("Invert"); invert.setSelected(importer.invert); final JCheckBox rightAlign = new JCheckBox("Right-Align"); rightAlign.setSelected(importer.rightAlign); final JCheckBox flipBits = new JCheckBox("Reverse Bits"); flipBits.setSelected(importer.flipBits); final JCheckBox flipBytes = new JCheckBox("Reverse Bytes"); flipBytes.setSelected(importer.flipBytes); final SpinnerNumberModel cellCount = new SpinnerNumberModel(importer.cellCount, 1, data.length, 1); final JPanel offsetPanel = borderLayout(0, 0, jSpinner(offset), BorderLayout.LINE_START); final JPanel bytesPerCharPanel = borderLayout(0, 0, jSpinner(bytesPerChar), BorderLayout.LINE_START); final JPanel bytesPerRowPanel = borderLayout(0, 0, jSpinner(bytesPerRow), BorderLayout.LINE_START); final JPanel cellWidthPanel = borderLayout(0, 0, jSpinner(cellWidth), BorderLayout.LINE_START); final JPanel cellHeightPanel = borderLayout(0, 0, jSpinner(cellHeight), BorderLayout.LINE_START); final JPanel ascentPanel = borderLayout(0, 0, jSpinner(ascent), BorderLayout.LINE_START); final JPanel bitsPerPixelPanel = borderLayout(0, 0, jSpinner(bitsPerPixel), BorderLayout.LINE_START); final JPanel cellCountPanel = borderLayout(0, 0, jSpinner(cellCount), BorderLayout.LINE_START); final JPanel labelPanel = gridLayout(0, 1, 4, 4, new JLabel("Offset:"), new JLabel("Bytes Per Char.:"), new JLabel("Bytes Per Row:"), new JLabel("Char. Width:"), new JLabel("Char. Height:"), new JLabel("Ascent:"), new JLabel("Bits Per Pixel:"), new JLabel("Bit Format:"), new JLabel(" "), new JLabel(" "), new JLabel(" "), new JLabel("Characters:") ); final JPanel ctrlPanel = gridLayout(0, 1, 4, 4, offsetPanel, bytesPerCharPanel, bytesPerRowPanel, cellWidthPanel, cellHeightPanel, ascentPanel, bitsPerPixelPanel, rightAlign, flipBytes, flipBits, invert, cellCountPanel ); final JPanel settingsPanel = borderLayout(8, 8, labelPanel, BorderLayout.LINE_START, ctrlPanel, BorderLayout.CENTER); final JPanel leftPanel = borderLayout(0, 0, settingsPanel, BorderLayout.PAGE_START); eTable.setDefaultRenderer(BufferedImage.class, new GlyphCellRenderer()); setColumnWidth(eTable.getColumnModel().getColumn(1), 80); setColumnWidth(eTable.getColumnModel().getColumn(2), 80); final JScrollPane eScrollPane = new JScrollPane(eTable); final JPanel eListPanel = borderLayout(8, 8, new JLabel("Encoding:"), BorderLayout.LINE_START, eList, BorderLayout.CENTER); final JPanel eTablePanel = borderLayout(4, 4, eListPanel, BorderLayout.PAGE_START, eScrollPane, BorderLayout.CENTER); final JButton openButton = new JButton("Create"); final JPanel buttonPanel = flowLayout(openButton); final JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(leftPanel, BorderLayout.LINE_START); mainPanel.add(eTablePanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); offset.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.offset = offset.getNumber().intValue(); updatePreview(); } }); bytesPerChar.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.bytesPerChar = bytesPerChar.getNumber().intValue(); updatePreview(); } }); bytesPerRow.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.bytesPerRow = bytesPerRow.getNumber().intValue(); updatePreview(); } }); cellWidth.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.cellWidth = cellWidth.getNumber().intValue(); updatePreview(); } }); cellHeight.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.cellHeight = cellHeight.getNumber().intValue(); updatePreview(); } }); ascent.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.ascent = ascent.getNumber().intValue(); updatePreview(); } }); bitsPerPixel.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.bitsPerPixel = bitsPerPixel.getNumber().intValue(); updatePreview(); } }); invert.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importer.invert = invert.isSelected(); updatePreview(); } }); rightAlign.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importer.rightAlign = rightAlign.isSelected(); updatePreview(); } }); flipBits.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importer.flipBits = flipBits.isSelected(); updatePreview(); } }); flipBytes.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importer.flipBytes = flipBytes.isSelected(); updatePreview(); } }); cellCount.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.cellCount = cellCount.getNumber().intValue(); updatePreview(); } }); eList.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { eList.applySelectedEncoding(importer.encoding); eTableModel.fireTableRowsUpdated(0, importer.encoding.size()); } }); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.openFonts(file, null, importer.importFont(data)); } }); } private void updatePreview() { previewImages = importer.preview(data); List selectedEncoding = eList.getSelectedEncoding(); if (importer.encoding == null) importer.encoding = new ArrayList(); for (int es = importer.encoding.size(), ps = previewImages.size(); es < ps; es++) { importer.encoding.add( (selectedEncoding != null && es < selectedEncoding.size()) ? selectedEncoding.get(es) : -1 ); } for (int ps = previewImages.size(), es = importer.encoding.size(); ps < es; es--) { importer.encoding.remove(ps); } eTableModel.fireTableDataChanged(); eTable.setRowHeight(Math.max(16, importer.cellHeight + 4)); setColumnWidth(eTable.getColumnModel().getColumn(0), Math.max(20, importer.cellWidth + 8)); } private class EncodingTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; public Class getColumnClass(int col) { switch (col) { case 0: return BufferedImage.class; case 1: return String.class; case 2: return String.class; case 3: return String.class; default: return Object.class; } } public int getColumnCount() { return 4; } public String getColumnName(int col) { switch (col) { case 0: return "Glyph"; case 1: return "Code Point"; case 2: return "Character"; case 3: return "Character Name"; default: return null; } } public int getRowCount() { if (importer.encoding == null) return 0; return importer.encoding.size(); } public Object getValueAt(int row, int col) { switch (col) { case 0: if (previewImages == null) return null; if (row < previewImages.size()) return previewImages.get(row); return null; case 1: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; String h = Integer.toHexString(e.intValue()).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } return null; case 2: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; return String.valueOf(Character.toChars(e.intValue())); } return null; case 3: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; return NameResolver.instance(e).getName(e); } return null; default: return null; } } public boolean isCellEditable(int row, int col) { return (col == 1 || col == 2 || col == 3); } public void setValueAt(Object val, int row, int col) { switch (col) { case 1: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else try { int e = Integer.parseInt(val.toString(), 16); importer.encoding.set(row, e); eList.setSelectedIndex(0); } catch (NumberFormatException e) { // ignored } } return; case 2: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else { int e = val.toString().codePointAt(0); importer.encoding.set(row, e); eList.setSelectedIndex(0); } } return; case 3: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else { NameDatabase.NameEntry ne = ndb.find(val.toString()); if (ne == null) importer.encoding.set(row, -1); else importer.encoding.set(row, ne.codePoint); eList.setSelectedIndex(0); } } return; } fireTableRowsUpdated(row, row); } } private class GlyphCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; public Component getTableCellRendererComponent(JTable t, Object v, boolean sel, boolean focus, int row, int col) { Component c = super.getTableCellRendererComponent(t, v, sel, focus, row, col); if (c instanceof JLabel && v instanceof BufferedImage) { final JLabel label = (JLabel)c; final BufferedImage bi = (BufferedImage)v; label.setText(null); label.setIcon(new ImageIcon(bi)); } return c; } } private static JPanel borderLayout(int dx, int dy, Component comp, String cons) { JPanel p = new JPanel(new BorderLayout(dx, dy)); p.add(comp, cons); return p; } private static JPanel borderLayout(int dx, int dy, Component comp1, String cons1, Component comp2, String cons2) { JPanel p = new JPanel(new BorderLayout(dx, dy)); p.add(comp1, cons1); p.add(comp2, cons2); return p; } private static JPanel flowLayout(Component... comps) { JPanel p = new JPanel(new FlowLayout()); for (Component c : comps) p.add(c); return p; } private static JPanel gridLayout(int rows, int cols, int dx, int dy, Component... comps) { JPanel p = new JPanel(new GridLayout(rows, cols, dx, dy)); for (Component c : comps) p.add(c); return p; } private static JSpinner jSpinner(SpinnerNumberModel m) { JSpinner s = new JSpinner(m); Dimension d = s.getPreferredSize(); d.width = 80; s.setMinimumSize(d); s.setPreferredSize(d); s.setMaximumSize(d); return s; } private static void setColumnWidth(TableColumn col, int width) { col.setMinWidth(width); col.setWidth(width); col.setMaxWidth(width); } } DualEncodingSelectionFrame.java000066400000000000000000000011671506470510200361720ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.io.File; import javax.swing.JFrame; public class DualEncodingSelectionFrame extends JFrame { private static final long serialVersionUID = 1L; private final DualEncodingSelectionPanel panel; public DualEncodingSelectionFrame(String sben, String dben, File file, DualEncodingSelectionImporter importer) { this.panel = new DualEncodingSelectionPanel(sben, dben, file, importer); setTitle("Open " + file.getName()); setContentPane(panel); setResizable(false); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } DualEncodingSelectionImporter.java000066400000000000000000000004041506470510200367320ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import com.kreative.bitsnpicas.FontImporter; import com.kreative.unicode.data.GlyphList; public interface DualEncodingSelectionImporter { public FontImporter createImporter(GlyphList sbenc, String dbenc); } DualEncodingSelectionPanel.java000066400000000000000000000063421506470510200361770ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class DualEncodingSelectionPanel extends JPanel { private static final long serialVersionUID = 1L; public DualEncodingSelectionPanel(final String sben, final String dben, final File file, final DualEncodingSelectionImporter importer) { final JComboBox sbe = new JComboBox(EncodingList.instance().glyphLists().toArray()); sbe.setEditable(false); new GLMLListCellRenderer("encoding").apply(sbe); sbe.setSelectedItem(EncodingList.instance().getGlyphList(sben)); final JComboBox dbe = new JComboBox(Charset.availableCharsets().keySet().toArray()); dbe.setEditable(false); new GLMLListCellRenderer("encoding").apply(dbe); dbe.setSelectedItem(dben); final JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); labelPanel.add(new JLabel("Single-Byte Encoding:")); labelPanel.add(new JLabel("Double-Byte Encoding:")); final JPanel controlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); controlPanel.add(sbe); controlPanel.add(dbe); final JPanel formPanel = new JPanel(new BorderLayout(8, 8)); formPanel.add(labelPanel, BorderLayout.LINE_START); formPanel.add(controlPanel, BorderLayout.CENTER); final JPanel contentPanel = new JPanel(new BorderLayout(12, 12)); contentPanel.add(new JLabel("Select an encoding for " + file.getName() + "."), BorderLayout.PAGE_START); contentPanel.add(formPanel, BorderLayout.CENTER); final JButton openButton = new JButton("Open"); final JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(openButton); final JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(contentPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { GlyphList sbenc = (GlyphList)(sbe.getSelectedItem()); String dbenc = (String)(dbe.getSelectedItem()); Font[] fonts = importer.createImporter(sbenc, dbenc).importFont(file); if (fonts != null && fonts.length > 0) { Main.openFonts(file, null, fonts); } else { JOptionPane.showMessageDialog( null, "The selected file did not contain any fonts.", "Open", JOptionPane.ERROR_MESSAGE ); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); } } }); } } EncodingSelectionFrame.java000066400000000000000000000011401506470510200353530ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.io.File; import javax.swing.JFrame; public class EncodingSelectionFrame extends JFrame { private static final long serialVersionUID = 1L; private final EncodingSelectionPanel panel; public EncodingSelectionFrame(String encodingName, File file, EncodingSelectionImporter importer) { this.panel = new EncodingSelectionPanel(encodingName, file, importer); setTitle("Open " + file.getName()); setContentPane(panel); setResizable(false); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } EncodingSelectionImporter.java000066400000000000000000000003651506470510200361320ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import com.kreative.bitsnpicas.FontImporter; import com.kreative.unicode.data.GlyphList; public interface EncodingSelectionImporter { public FontImporter createImporter(GlyphList encoding); } EncodingSelectionPanel.java000066400000000000000000000056671506470510200354020ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.edit.BitmapListFrame; import com.kreative.bitsnpicas.edit.GlyphListFrame; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class EncodingSelectionPanel extends JPanel { private static final long serialVersionUID = 1L; public EncodingSelectionPanel(final String encodingName, final File file, final EncodingSelectionImporter importer) { final JComboBox encoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); encoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(encoding); encoding.setSelectedItem(EncodingList.instance().getGlyphList(encodingName)); final JPanel encodingPanel = new JPanel(new BorderLayout(12, 12)); encodingPanel.add(new JLabel("Select an encoding for " + file.getName() + "."), BorderLayout.PAGE_START); encodingPanel.add(encoding, BorderLayout.CENTER); final JButton openButton = new JButton("Open"); final JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(openButton); final JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(encodingPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { GlyphList enc = (GlyphList)(encoding.getSelectedItem()); Font[] fonts = importer.createImporter(enc).importFont(file); if (fonts != null && fonts.length > 0) { JFrame frame = Main.openFonts(file, null, fonts); if (frame instanceof GlyphListFrame) { ((GlyphListFrame)frame).getPanel().getModelList().setSelectedModelName(enc.getName(), true); } else if (frame instanceof BitmapListFrame) { ((BitmapListFrame)frame).getPanel().getModelList().setSelectedModelName(enc.getName(), true); } } else { JOptionPane.showMessageDialog( null, "The selected file did not contain any fonts.", "Open", JOptionPane.ERROR_MESSAGE ); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); } } }); } } ImageBitmapFontImporterFrame.java000066400000000000000000000011021506470510200365050ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.io.File; import java.io.IOException; import javax.swing.JFrame; public class ImageBitmapFontImporterFrame extends JFrame { private static final long serialVersionUID = 1L; private final ImageBitmapFontImporterPanel panel; public ImageBitmapFontImporterFrame(File fontFile) throws IOException { this.panel = new ImageBitmapFontImporterPanel(fontFile); setTitle("Create From Image"); setContentPane(panel); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } ImageBitmapFontImporterPanel.java000066400000000000000000000370611506470510200365270ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTable; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import com.kreative.bitsnpicas.WindingOrder; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.importer.ImageBitmapFontImporter; import com.kreative.bitsnpicas.importer.ImageBitmapFontImporter.PreviewResult; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class ImageBitmapFontImporterPanel extends JPanel { private static final long serialVersionUID = 1L; private final File file; private final BufferedImage image; private final ImageBitmapFontImporter importer; private BufferedImage previewImage = null; private Point[] previewPoints = null; private final JLabel previewLabel = new JLabel(); private final RawImportEncodingList eList = new RawImportEncodingList(); private final EncodingTableModel eTableModel = new EncodingTableModel(); private final JTable eTable = new JTable(eTableModel); private final NameDatabase ndb = NameDatabase.instance(); public ImageBitmapFontImporterPanel(File file) throws IOException { this.file = file; this.image = ImageIO.read(file); this.importer = new ImageBitmapFontImporter(); makeUI(); updatePreview(); } private void makeUI() { final JComboBox matte = new JComboBox(new String[]{"White", "Black"}); matte.setEditable(false); final SpinnerNumberModel startX = new SpinnerNumberModel(importer.startX, 0, image.getWidth(), 1); final SpinnerNumberModel startY = new SpinnerNumberModel(importer.startY, 0, image.getHeight(), 1); final SpinnerNumberModel cellWidth = new SpinnerNumberModel(importer.cellWidth, 1, image.getWidth(), 1); final SpinnerNumberModel cellHeight = new SpinnerNumberModel(importer.cellHeight, 1, image.getHeight(), 1); final SpinnerNumberModel ascent = new SpinnerNumberModel(importer.ascent, -image.getHeight(), image.getHeight(), 1); final SpinnerNumberModel deltaX = new SpinnerNumberModel(importer.deltaX, 0, image.getWidth(), 1); final SpinnerNumberModel deltaY = new SpinnerNumberModel(importer.deltaY, 0, image.getHeight(), 1); final SpinnerNumberModel columnCount = new SpinnerNumberModel(importer.columnCount, 0, image.getWidth(), 1); final SpinnerNumberModel rowCount = new SpinnerNumberModel(importer.rowCount, 0, image.getHeight(), 1); final JComboBox order = new JComboBox(WindingOrder.values()); order.setEditable(false); final JCheckBox invert = new JCheckBox("Invert"); invert.setSelected(importer.invert); final SpinnerNumberModel threshold = new SpinnerNumberModel(importer.threshold, 0, 255, 1); final JPanel startPanel = borderLayout(0, 0, boxLayout(BoxLayout.LINE_AXIS, jSpinner(startX), new JLabel(" , "), jSpinner(startY)), BorderLayout.LINE_START); final JPanel cellWidthPanel = borderLayout(0, 0, jSpinner(cellWidth), BorderLayout.LINE_START); final JPanel cellHeightPanel = borderLayout(0, 0, jSpinner(cellHeight), BorderLayout.LINE_START); final JPanel ascentPanel = borderLayout(0, 0, jSpinner(ascent), BorderLayout.LINE_START); final JPanel deltaPanel = borderLayout(0, 0, boxLayout(BoxLayout.LINE_AXIS, jSpinner(deltaX), new JLabel(" , "), jSpinner(deltaY)), BorderLayout.LINE_START); final JPanel columnCountPanel = borderLayout(0, 0, jSpinner(columnCount), BorderLayout.LINE_START); final JPanel rowCountPanel = borderLayout(0, 0, jSpinner(rowCount), BorderLayout.LINE_START); final JPanel thresholdPanel = borderLayout(0, 0, boxLayout(BoxLayout.LINE_AXIS, jSpinner(threshold), new JLabel(" "), invert), BorderLayout.LINE_START); final JPanel labelPanel = gridLayout(0, 1, 4, 4, new JLabel("Matte:"), new JLabel("Offset:"), new JLabel("Char. Width:"), new JLabel("Char. Height:"), new JLabel("Ascent:"), new JLabel("Spacing:"), new JLabel("Columns:"), new JLabel("Rows:"), new JLabel("Order:"), new JLabel("Threshold:") ); final JPanel ctrlPanel = gridLayout(0, 1, 4, 4, matte, startPanel, cellWidthPanel, cellHeightPanel, ascentPanel, deltaPanel, columnCountPanel, rowCountPanel, order, thresholdPanel ); final JPanel settingsPanel = borderLayout(8, 8, labelPanel, BorderLayout.LINE_START, ctrlPanel, BorderLayout.CENTER); final JScrollPane previewPane = new JScrollPane(previewLabel); previewPane.setPreferredSize(new Dimension(300, 200)); previewLabel.setHorizontalAlignment(JLabel.CENTER); previewLabel.setVerticalAlignment(JLabel.CENTER); final JPanel leftPanel = borderLayout(12, 12, settingsPanel, BorderLayout.PAGE_START, previewPane, BorderLayout.CENTER); eTable.setDefaultRenderer(Point.class, new GlyphCellRenderer()); setColumnWidth(eTable.getColumnModel().getColumn(1), 80); setColumnWidth(eTable.getColumnModel().getColumn(2), 80); final JScrollPane eScrollPane = new JScrollPane(eTable); final JPanel eListPanel = borderLayout(8, 8, new JLabel("Encoding:"), BorderLayout.LINE_START, eList, BorderLayout.CENTER); final JPanel eTablePanel = borderLayout(4, 4, eListPanel, BorderLayout.PAGE_START, eScrollPane, BorderLayout.CENTER); final JButton openButton = new JButton("Create"); final JPanel buttonPanel = flowLayout(openButton); final JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(leftPanel, BorderLayout.LINE_START); mainPanel.add(eTablePanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); matte.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { importer.matte = matte.getSelectedIndex() - 1; updatePreview(); } }); startX.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.startX = startX.getNumber().intValue(); updatePreview(); } }); startY.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.startY = startY.getNumber().intValue(); updatePreview(); } }); cellWidth.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.cellWidth = cellWidth.getNumber().intValue(); updatePreview(); } }); cellHeight.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.cellHeight = cellHeight.getNumber().intValue(); updatePreview(); } }); ascent.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.ascent = ascent.getNumber().intValue(); updatePreview(); } }); deltaX.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.deltaX = deltaX.getNumber().intValue(); updatePreview(); } }); deltaY.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.deltaY = deltaY.getNumber().intValue(); updatePreview(); } }); columnCount.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.columnCount = columnCount.getNumber().intValue(); updatePreview(); } }); rowCount.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.rowCount = rowCount.getNumber().intValue(); updatePreview(); } }); order.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { importer.order = (WindingOrder)order.getSelectedItem(); updatePreview(); } }); invert.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importer.invert = invert.isSelected(); updatePreview(); } }); threshold.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { importer.threshold = threshold.getNumber().intValue(); updatePreview(); } }); eList.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { eList.applySelectedEncoding(importer.encoding); eTableModel.fireTableRowsUpdated(0, importer.encoding.size()); } }); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.openFont(file, null, importer.importFont(image)); } }); } private void updatePreview() { PreviewResult pr = importer.preview(image); previewImage = pr.preview; previewPoints = pr.points; previewLabel.setIcon(new ImageIcon(pr.preview)); List selectedEncoding = eList.getSelectedEncoding(); if (importer.encoding == null) importer.encoding = new ArrayList(); for (int es = importer.encoding.size(), ps = pr.points.length; es < ps; es++) { importer.encoding.add( (selectedEncoding != null && es < selectedEncoding.size()) ? selectedEncoding.get(es) : -1 ); } for (int ps = pr.points.length, es = importer.encoding.size(); ps < es; es--) { importer.encoding.remove(ps); } eTableModel.fireTableDataChanged(); eTable.setRowHeight(Math.max(16, importer.cellHeight + 4)); setColumnWidth(eTable.getColumnModel().getColumn(0), Math.max(20, importer.cellWidth + 8)); } private class EncodingTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; public Class getColumnClass(int col) { switch (col) { case 0: return Point.class; case 1: return String.class; case 2: return String.class; case 3: return String.class; default: return Object.class; } } public int getColumnCount() { return 4; } public String getColumnName(int col) { switch (col) { case 0: return "Glyph"; case 1: return "Code Point"; case 2: return "Character"; case 3: return "Character Name"; default: return null; } } public int getRowCount() { if (importer.encoding == null) return 0; return importer.encoding.size(); } public Object getValueAt(int row, int col) { switch (col) { case 0: if (previewPoints == null) return null; if (row < previewPoints.length) return previewPoints[row]; return null; case 1: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; String h = Integer.toHexString(e.intValue()).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } return null; case 2: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; return String.valueOf(Character.toChars(e.intValue())); } return null; case 3: if (importer.encoding == null) return null; if (row < importer.encoding.size()) { Integer e = importer.encoding.get(row); if (e == null || e.intValue() < 0) return null; return NameResolver.instance(e).getName(e); } return null; default: return null; } } public boolean isCellEditable(int row, int col) { return (col == 1 || col == 2 || col == 3); } public void setValueAt(Object val, int row, int col) { switch (col) { case 1: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else try { int e = Integer.parseInt(val.toString(), 16); importer.encoding.set(row, e); eList.setSelectedIndex(0); } catch (NumberFormatException e) { // ignored } } return; case 2: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else { int e = val.toString().codePointAt(0); importer.encoding.set(row, e); eList.setSelectedIndex(0); } } return; case 3: if (importer.encoding == null) return; if (row < importer.encoding.size()) { if (val == null || val.toString().length() == 0) { importer.encoding.set(row, -1); eList.setSelectedIndex(0); } else { NameDatabase.NameEntry ne = ndb.find(val.toString()); if (ne == null) importer.encoding.set(row, -1); else importer.encoding.set(row, ne.codePoint); eList.setSelectedIndex(0); } } return; } fireTableRowsUpdated(row, row); } } private class GlyphCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; public Component getTableCellRendererComponent(JTable t, Object v, boolean sel, boolean focus, int row, int col) { Component c = super.getTableCellRendererComponent(t, v, sel, focus, row, col); if (c instanceof JLabel && v instanceof Point) { final JLabel label = (JLabel)c; final Point p = (Point)v; label.setText(null); label.setIcon(new Icon() { public int getIconHeight() { return importer.cellHeight; } public int getIconWidth() { return importer.cellWidth; } public void paintIcon(Component c, Graphics g, int x, int y) { g.drawImage( previewImage, x, y, x + importer.cellWidth, y + importer.cellHeight, p.x, p.y, p.x + importer.cellWidth, p.y + importer.cellHeight, null ); } }); } return c; } } private static JPanel borderLayout(int dx, int dy, Component comp, String cons) { JPanel p = new JPanel(new BorderLayout(dx, dy)); p.add(comp, cons); return p; } private static JPanel borderLayout(int dx, int dy, Component comp1, String cons1, Component comp2, String cons2) { JPanel p = new JPanel(new BorderLayout(dx, dy)); p.add(comp1, cons1); p.add(comp2, cons2); return p; } private static JPanel boxLayout(int axis, Component... comps) { JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, axis)); for (Component c : comps) p.add(c); return p; } private static JPanel flowLayout(Component... comps) { JPanel p = new JPanel(new FlowLayout()); for (Component c : comps) p.add(c); return p; } private static JPanel gridLayout(int rows, int cols, int dx, int dy, Component... comps) { JPanel p = new JPanel(new GridLayout(rows, cols, dx, dy)); for (Component c : comps) p.add(c); return p; } private static JSpinner jSpinner(SpinnerNumberModel m) { JSpinner s = new JSpinner(m); Dimension d = s.getPreferredSize(); d.width = 80; s.setMinimumSize(d); s.setPreferredSize(d); s.setMaximumSize(d); return s; } private static void setColumnWidth(TableColumn col, int width) { col.setMinWidth(width); col.setWidth(width); col.setMaxWidth(width); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importer/ImportFormat.java000066400000000000000000000257231506470510200335230ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit.importer; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import javax.swing.JFrame; import com.kreative.bitsnpicas.FileProxy; import com.kreative.bitsnpicas.FontExporter; import com.kreative.bitsnpicas.FontImporter; import com.kreative.bitsnpicas.exporter.KbitxBitmapFontExporter; import com.kreative.bitsnpicas.exporter.KpcaxVectorFontExporter; import com.kreative.bitsnpicas.geos.mover.GEOSMoverFrame; import com.kreative.bitsnpicas.importer.*; import com.kreative.bitsnpicas.mover.MoverFrame; import com.kreative.unicode.data.GlyphList; public enum ImportFormat { KBITX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kbitx"); } public FontImporter createImporter() { return new KbitxBitmapFontImporter(); } public FontExporter createExporter() { return new KbitxBitmapFontExporter(); } }, KPCAX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kpcax"); } public FontImporter createImporter() { return new KpcaxVectorFontImporter(); } public FontExporter createExporter() { return new KpcaxVectorFontExporter(); } }, KBITS { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kbits"); } public FontImporter createImporter() { return new KbitsBitmapFontImporter(); } }, KPCAS { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kpcas"); } public FontImporter createImporter() { return new KpcasVectorFontImporter(); } }, SFD { public boolean recognize(FileProxy fp) { return fp.hasExtension(".sfd"); } public FontImporter createImporter() { return new SFDBitmapFontImporter(); } }, BDF { public boolean recognize(FileProxy fp) { return fp.hasExtension(".bdf"); } public FontImporter createImporter() { return new BDFBitmapFontImporter(); } }, PSF { public boolean recognize(FileProxy fp) { return fp.hasExtension(".psf", ".psfu"); } public JFrame createOptionFrame(File file) throws IOException { return new PSFEncodingSelectionFrame(file, new PSFEncodingSelectionImporter() { public FontImporter createImporter(GlyphList low, GlyphList high, int puaBase) { return new PSFBitmapFontImporter(low, high, puaBase, false); } }); } }, PSFGZ { public boolean recognize(FileProxy fp) { return fp.hasExtension(".psf.gz", ".psfu.gz"); } public JFrame createOptionFrame(File file) throws IOException { return new PSFEncodingSelectionFrame(file, new PSFEncodingSelectionImporter() { public FontImporter createImporter(GlyphList low, GlyphList high, int puaBase) { return new PSFBitmapFontImporter(low, high, puaBase, true); } }); } }, SUIT(true) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".suit"); } public JFrame createOptionFrame(File file) throws IOException { return MoverFrame.forFile(file); } }, DFONT(false) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".dfont"); } public JFrame createOptionFrame(File file) throws IOException { return MoverFrame.forFile(file); } }, NFNT { public boolean recognize(FileProxy fp) { return fp.hasExtension(".nfnt"); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("MacRoman", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new NFNTBitmapFontImporter.FlatFile(encoding); } }); } }, SRFONT { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".png") && fp.isImage() && new SRFontBitmapFontImporter().canImportFont(fp.getImage()) ); } public FontImporter createImporter() { return new SRFontBitmapFontImporter(); } }, HEX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".hex"); } public FontImporter createImporter() { return new HexBitmapFontImporter(); } }, CVT { public boolean recognize(FileProxy fp) { return fp.hasExtension(".cvt"); } public JFrame createOptionFrame(File file) throws IOException { return GEOSMoverFrame.forFile(file); } }, FZX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".fzx"); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("FZX PUA", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new FZXBitmapFontImporter(encoding); } }); } }, U8M { public boolean recognize(FileProxy fp) { return fp.hasExtension(".u8m"); } public FontImporter createImporter() { return new U8MBitmapFontImporter(); } }, AMIGA { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".font") && (fp.startsWith(0x0F, 0x00) || fp.startsWith(0x0F, 0x02)) ); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("ISO-8859-1", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new AmigaBitmapFontImporter.ContentsFile(encoding); } }); } }, FNT { public boolean recognize(FileProxy fp) { if (!fp.hasExtension(".fnt")) return false; byte[] b = fp.getStartBytes(2); return b != null && b[0] == 0 && b[1] >= 1 && b[1] <= 3; } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("CP1252", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new FNTBitmapFontImporter(encoding); } }); } }, FONTX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".ftx", ".fnt") && fp.startsWith('F'); } public JFrame createOptionFrame(File file) throws IOException { String dben = Charset.forName("CP943").displayName(); return new DualEncodingSelectionFrame("CP437", dben, file, new DualEncodingSelectionImporter() { public FontImporter createImporter(GlyphList sbenc, String dbenc) { return new FONTXBitmapFontImporter(sbenc, dbenc); } }); } }, MGTK { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".mgf", ".mpf", ".fnt") && (fp.startsWith(0) || fp.startsWith(0x80)) ); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("MouseDesk", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new MGTKBitmapFontImporter(encoding); } }); } }, ROCKBOX { public boolean recognize(FileProxy fp) { return fp.hasExtension(".rbf", ".rb11", ".rb12", ".fnt") && fp.startsWith('R'); } public FontImporter createImporter() { return new RockboxBitmapFontImporter(); } }, CYBIKO { public boolean recognize(FileProxy fp) { return fp.hasExtension(".cyf", ".fntz", ".fnty", ".fnt") && fp.startsWith(1); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("Cybiko", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new CybikoBitmapFontImporter(encoding); } }); } }, PLAYDATE { public boolean recognize(FileProxy fp) { return PlaydateBitmapFontImporter.canImportFont(fp); } public FontImporter createImporter() { return new PlaydateBitmapFontImporter(); } }, HRCG { public boolean recognize(FileProxy fp) { return fp.hasExtension(".set"); } public FontImporter createImporter() { return new HRCGBitmapFontImporter(); } }, HMZK { public boolean recognize(FileProxy fp) { return fp.hasExtension(".hmzk"); } public FontImporter createImporter() { return new HMZKBitmapFontImporter(); } }, // **** Add new formats above this line. **** DSF { public boolean recognize(FileProxy fp) { return fp.hasExtension(".dsf"); } public FontImporter createImporter() { return new DSFBitmapFontImporter(); } }, SBF { public boolean recognize(FileProxy fp) { return fp.hasExtension(".sbf"); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("Kreative SuperLatin", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new SBFBitmapFontImporter(encoding); } }); } }, S10 { public boolean recognize(FileProxy fp) { return fp.hasExtension(".s10"); } public FontImporter createImporter() { return new S10BitmapFontImporter(); } }, DMOV(true) { public boolean recognize(FileProxy fp) { return ( fp.hasMacCreator("DMOV") || fp.hasMacCreator("movr") || ( (fp.hasMacCreator("MACS") || fp.hasMacCreator("macs")) && (fp.hasMacType("ZSYS") || fp.hasMacType("zsys")) ) ); } public JFrame createOptionFrame(File file) throws IOException { return MoverFrame.forFile(file); } }, BINARY { public boolean recognize(FileProxy fp) { return fp.hasExtension(".bin", ".rom"); } public JFrame createOptionFrame(File file) throws IOException { return new BinaryBitmapFontImporterFrame(file); } }, IMAGE { public boolean recognize(FileProxy fp) { return fp.isImage(); } public JFrame createOptionFrame(File file) throws IOException { return new ImageBitmapFontImporterFrame(file); } }, NFNT_NOEXT { public boolean recognize(FileProxy fp) { return fp.startsWith(0x90, 0x00); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("MacRoman", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new NFNTBitmapFontImporter.FlatFile(encoding); } }); } }, AMIGA_NOEXT { public boolean recognize(FileProxy fp) { return fp.startsWith(0x00, 0x00, 0x03, 0xF3); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("ISO-8859-1", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new AmigaBitmapFontImporter.DescriptorFile(encoding); } }); } }, MGTK_NOEXT { public boolean recognize(FileProxy fp) { return fp.startsWith(0) || fp.startsWith(0x80); } public JFrame createOptionFrame(File file) throws IOException { return new EncodingSelectionFrame("MouseDesk", file, new EncodingSelectionImporter() { public FontImporter createImporter(GlyphList encoding) { return new MGTKBitmapFontImporter(encoding); } }); } }; public final boolean macResFork; private ImportFormat() { this.macResFork = false; } private ImportFormat(boolean macResFork) { this.macResFork = macResFork; } public abstract boolean recognize(FileProxy fp); public FontImporter createImporter() { return null; } public FontExporter createExporter() { return null; } public JFrame createOptionFrame(File file) throws IOException { return null; } public static ImportFormat forFile(File file) { FileProxy fp = new FileProxy(file); for (ImportFormat f : values()) { if (f.recognize(fp)) { return f; } } return null; } } PSFEncodingSelectionFrame.java000066400000000000000000000011141506470510200357250ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.io.File; import javax.swing.JFrame; public class PSFEncodingSelectionFrame extends JFrame { private static final long serialVersionUID = 1L; private final PSFEncodingSelectionPanel panel; public PSFEncodingSelectionFrame(File file, PSFEncodingSelectionImporter importer) { this.panel = new PSFEncodingSelectionPanel(file, importer); setTitle("Open " + file.getName()); setContentPane(panel); setResizable(false); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } PSFEncodingSelectionImporter.java000066400000000000000000000004201506470510200364730ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import com.kreative.bitsnpicas.FontImporter; import com.kreative.unicode.data.GlyphList; public interface PSFEncodingSelectionImporter { public FontImporter createImporter(GlyphList low, GlyphList high, int puaBase); } PSFEncodingSelectionPanel.java000066400000000000000000000107121506470510200357360ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class PSFEncodingSelectionPanel extends JPanel { private static final long serialVersionUID = 1L; public PSFEncodingSelectionPanel(final File file, final PSFEncodingSelectionImporter importer) { final ArrayList lea = new ArrayList(); lea.add("None"); lea.addAll(EncodingList.instance().glyphLists()); final JComboBox le = new JComboBox(lea.toArray()); le.setEditable(false); new GLMLListCellRenderer("encoding").apply(le); final ArrayList hea = new ArrayList(); hea.add("None"); hea.addAll(EncodingList.instance().glyphLists()); final JComboBox he = new JComboBox(hea.toArray()); he.setEditable(false); new GLMLListCellRenderer("encoding").apply(he); final ArrayList sea = new ArrayList(); sea.add(new PuaBaseOption( "None", -1)); sea.add(new PuaBaseOption( "U+0000", 0x0000)); sea.add(new PuaBaseOption( "U+E000", 0xE000)); sea.add(new PuaBaseOption( "U+F000", 0xF000)); sea.add(new PuaBaseOption( "U+F0000", 0xF0000)); sea.add(new PuaBaseOption( "U+FE000", 0xFE000)); sea.add(new PuaBaseOption( "U+FF000", 0xFF000)); sea.add(new PuaBaseOption("U+100000", 0x100000)); sea.add(new PuaBaseOption("U+10E000", 0x10E000)); sea.add(new PuaBaseOption("U+10F000", 0x10F000)); final JComboBox se = new JComboBox(sea.toArray()); se.setEditable(false); final JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); labelPanel.add(new JLabel("Primary Character Set ($000-$0FF):")); labelPanel.add(new JLabel("Alternate Character Set ($100-$1FF):")); labelPanel.add(new JLabel("Passthrough Starting Code Point:")); final JPanel controlPanel = new JPanel(new GridLayout(0, 1, 4, 4)); controlPanel.add(le); controlPanel.add(he); controlPanel.add(se); final JPanel formPanel = new JPanel(new BorderLayout(8, 8)); formPanel.add(labelPanel, BorderLayout.LINE_START); formPanel.add(controlPanel, BorderLayout.CENTER); final JPanel contentPanel = new JPanel(new BorderLayout(12, 12)); contentPanel.add(new JLabel("Select an encoding for " + file.getName() + "."), BorderLayout.PAGE_START); contentPanel.add(formPanel, BorderLayout.CENTER); final JButton openButton = new JButton("Open"); final JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(openButton); final JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(contentPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { GlyphList lenc = (le.getSelectedIndex() > 0) ? (GlyphList)le.getSelectedItem() : null; GlyphList henc = (he.getSelectedIndex() > 0) ? (GlyphList)he.getSelectedItem() : null; int puaBase = (se.getSelectedIndex() > 0) ? ((PuaBaseOption)se.getSelectedItem()).value : -1; Font[] fonts = importer.createImporter(lenc, henc, puaBase).importFont(file); if (fonts != null && fonts.length > 0) { Main.openFonts(file, null, fonts); } else { JOptionPane.showMessageDialog( null, "The selected file did not contain any fonts.", "Open", JOptionPane.ERROR_MESSAGE ); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); } } }); } private static final class PuaBaseOption { public final String label; public final int value; public PuaBaseOption(String label, int value) { this.label = label; this.value = value; } @Override public String toString() { return label; } } } RawImportEncodingList.java000066400000000000000000000046441506470510200352470ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/importerpackage com.kreative.bitsnpicas.edit.importer; import java.util.AbstractList; import java.util.ArrayList; import java.util.List; import javax.swing.JComboBox; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; public class RawImportEncodingList extends JComboBox { private static final long serialVersionUID = 1L; public RawImportEncodingList() { super(getEncodingList()); setEditable(false); new GLMLListCellRenderer("encoding").apply(this); setSelectedIndex(7); } public List getSelectedEncoding() { if (getSelectedIndex() <= 0) return null; @SuppressWarnings("unchecked") List in = (List)getSelectedItem(); return in; } public void applySelectedEncoding(List out) { if (getSelectedIndex() <= 0) return; @SuppressWarnings("unchecked") List in = (List)getSelectedItem(); for (int i = 0, n = out.size(), m = in.size(); i < n; i++) { out.set(i, (i < m) ? in.get(i) : -1); } } private static final Object[] getEncodingList() { List encodings = new ArrayList(); encodings.add(new String("Custom")); encodings.add(new StartFrom(0x0000)); encodings.add(new StartFrom(0x0020)); encodings.add(new StartFrom(0xE000)); encodings.add(new StartFrom(0xE020)); encodings.add(new StartFrom(0xF000)); encodings.add(new StartFrom(0xF020)); encodings.add(new StartFrom(0xF0000)); encodings.add(new StartFrom(0x100000)); encodings.addAll(EncodingList.instance().glyphLists()); return encodings.toArray(); } private static final class StartFrom extends AbstractList { private final int start; private final String name; public StartFrom(int start) { this.start = start; String h = Integer.toHexString(start).toUpperCase(); while (h.length() < 4) h = "0" + h; this.name = "Start From U+" + h; } public boolean contains(Object o) { return ( (o instanceof Integer) && (((Integer)o) >= start) && (((Integer)o) < 0x110000) ); } public Integer get(int index) { return start + index; } public int indexOf(Object o) { return contains(o) ? (((Integer)o) - start) : -1; } public boolean isEmpty() { return false; } public int lastIndexOf(Object o) { return contains(o) ? (((Integer)o) - start) : -1; } public int size() { return 0x110000 - start; } public String toString() { return name; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/mac/000077500000000000000000000000001506470510200271235ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/mac/MacDummyWindow.java000066400000000000000000000016131506470510200326730ustar00rootroot00000000000000package com.kreative.bitsnpicas.edit.mac; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import com.kreative.bitsnpicas.edit.CommonMenuItems; public class MacDummyWindow extends JFrame { public static final long serialVersionUID = 1L; public MacDummyWindow() { JMenu fileMenu = new JMenu("File"); fileMenu.add(new CommonMenuItems.NewMenu()); fileMenu.add(new CommonMenuItems.OpenMenuItem()); JMenu editMenu = new JMenu("Edit"); editMenu.add(new CommonMenuItems.FontMapMenuItem()); JMenuBar mb = new JMenuBar(); mb.add(fileMenu); mb.add(editMenu); setJMenuBar(mb); setUndecorated(true); setResizable(false); setMinimumSize(new Dimension(0,0)); setPreferredSize(new Dimension(0,0)); setMaximumSize(new Dimension(0,0)); setSize(new Dimension(0,0)); setLocation(-1000000, -1000000); setVisible(true); } } MyApplicationListener.java000066400000000000000000000050751506470510200341750ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/edit/macpackage com.kreative.bitsnpicas.edit.mac; import java.awt.Window; import java.awt.desktop.OpenFilesEvent; import java.awt.desktop.OpenFilesHandler; import java.awt.desktop.PrintFilesEvent; import java.awt.desktop.PrintFilesHandler; import java.awt.desktop.QuitEvent; import java.awt.desktop.QuitHandler; import java.awt.desktop.QuitResponse; import java.awt.event.WindowEvent; import java.io.File; import java.lang.reflect.Method; import com.kreative.bitsnpicas.edit.Main; public class MyApplicationListener { private static final String[][] classAndMethodNames = { { "java.awt.Desktop", "getDesktop" }, { "com.kreative.ual.eawt.NewApplicationAdapter", "getInstance" }, { "com.kreative.ual.eawt.OldApplicationAdapter", "getInstance" }, }; public MyApplicationListener() { for (String[] classAndMethodName : classAndMethodNames) { try { Class cls = Class.forName(classAndMethodName[0]); Method getInstance = cls.getMethod(classAndMethodName[1]); Object instance = getInstance.invoke(null); cls.getMethod("setOpenFileHandler", OpenFilesHandler.class).invoke(instance, open); cls.getMethod("setPrintFileHandler", PrintFilesHandler.class).invoke(instance, print); cls.getMethod("setQuitHandler", QuitHandler.class).invoke(instance, quit); System.out.println("Registered app event handlers through " + classAndMethodName[0]); return; } catch (Exception e) { System.out.println("Failed to register app event handlers through " + classAndMethodName[0] + ": " + e); } } } private final OpenFilesHandler open = new OpenFilesHandler() { @Override public void openFiles(final OpenFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openFonts((File)o); } } }.start(); } }; private final PrintFilesHandler print = new PrintFilesHandler() { @Override public void printFiles(final PrintFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openFonts((File)o); } } }.start(); } }; private final QuitHandler quit = new QuitHandler() { @Override public void handleQuitRequestWith(final QuitEvent e, final QuitResponse r) { new Thread() { public void run() { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) { r.cancelQuit(); return; } } } r.performQuit(); System.exit(0); } }.start(); } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporter/000077500000000000000000000000001506470510200273065ustar00rootroot00000000000000AmigaBitmapFontExporter.java000066400000000000000000000361121506470510200346300ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public abstract class AmigaBitmapFontExporter implements BitmapFontExporter { public static final int STYLE_UNDERLINED = 0x01; public static final int STYLE_BOLD = 0x02; public static final int STYLE_ITALIC = 0x04; public static final int STYLE_EXTENDED = 0x08; public static final int STYLE_COLORFONT = 0x40; public static final int STYLE_TAGGED = 0x80; public static final int FLAGS_ROMFONT = 0x01; public static final int FLAGS_DISKFONT = 0x02; public static final int FLAGS_REVPATH = 0x04; public static final int FLAGS_TALLDOT = 0x08; public static final int FLAGS_WIDEDOT = 0x10; public static final int FLAGS_PROPORTIONAL = 0x20; public static final int FLAGS_DESIGNED = 0x40; public static final int FLAGS_REMOVED = 0x80; public static final int CTFFLAGS_COLORFONT = 0x0001; public static final int CTFFLAGS_GREYFONT = 0x0002; public static final int CTFFLAGS_ANTIALIAS = 0x0004; protected Boolean proportional; protected GlyphList encoding; protected AmigaBitmapFontExporter(Boolean proportional) { this.proportional = proportional; this.encoding = null; } protected AmigaBitmapFontExporter(Boolean proportional, GlyphList encoding) { this.proportional = proportional; this.encoding = encoding; } public static final class ContentsFile extends AmigaBitmapFontExporter { public ContentsFile(Boolean proportional) { super(proportional); } public ContentsFile(Boolean proportional, GlyphList encoding) { super(proportional, encoding); } public byte[] exportFontToBytes(BitmapFont font) throws IOException { boolean p = (proportional != null) ? proportional : !font.isMonospaced(); return exportContentsFile(null, null, p, font); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { boolean p = (proportional != null) ? proportional : !font.isMonospaced(); os.write(exportContentsFile(null, null, p, font)); } public void exportFontToFile(BitmapFont font, File file) throws IOException { File contentsFile, fontDirectory, descriptorFile; File fileParent = file.getParentFile(); String fileName = file.getName(); if (fileName.toLowerCase().endsWith(".font")) { contentsFile = file; String otherName = fileName.substring(0, fileName.length() - 5); fontDirectory = new File(fileParent, otherName); fontDirectory.mkdir(); descriptorFile = new File(fontDirectory, getFileName(font)); } else { String otherName = fileName + ".font"; contentsFile = new File(fileParent, otherName); fontDirectory = file; fontDirectory.mkdir(); descriptorFile = new File(fontDirectory, getFileName(font)); } boolean p = (proportional != null) ? proportional : !font.isMonospaced(); byte[] contents = exportContentsFile(contentsFile, fontDirectory.getName(), p, font); byte[] descriptor = exportDescriptorFile(font, p); OutputStream cos = new FileOutputStream(contentsFile); cos.write(contents); cos.close(); OutputStream dos = new FileOutputStream(descriptorFile); dos.write(descriptor); dos.close(); } } public static final class DescriptorFile extends AmigaBitmapFontExporter { public DescriptorFile(Boolean proportional) { super(proportional); } public DescriptorFile(Boolean proportional, GlyphList encoding) { super(proportional, encoding); } public byte[] exportFontToBytes(BitmapFont font) throws IOException { boolean p = (proportional != null) ? proportional : !font.isMonospaced(); return exportDescriptorFile(font, p); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { boolean p = (proportional != null) ? proportional : !font.isMonospaced(); os.write(exportDescriptorFile(font, p)); } public void exportFontToFile(BitmapFont font, File file) throws IOException { boolean p = (proportional != null) ? proportional : !font.isMonospaced(); OutputStream os = new FileOutputStream(file); os.write(exportDescriptorFile(font, p)); os.close(); } } protected byte[] exportContentsFile(File existing, String prefix, boolean proportional, BitmapFont... fonts) throws IOException { int id = 0x0F00; ArrayList items = new ArrayList(); if (existing != null && existing.exists()) { FileInputStream fin = new FileInputStream(existing); DataInputStream din = new DataInputStream(fin); id = din.readUnsignedShort(); if (!(id == 0x0F00 || id == 0x0F02)) { din.close(); fin.close(); throw new IOException("bad magic number"); } int count = din.readUnsignedShort(); for (int i = 0; i < count; i++) { byte[] data = new byte[260]; din.readFully(data); items.add(data); } din.close(); fin.close(); } for (BitmapFont font : fonts) { String dirName = prefix; if (dirName == null || dirName.length() == 0) { dirName = font.getName(BitmapFont.NAME_FAMILY); if (dirName == null || dirName.length() == 0) { dirName = "Untitled"; } } byte[] pdata = (dirName + "/" + getFileName(font)).getBytes("ISO-8859-1"); int len = pdata.length; if (len > 255) len = 255; ByteArrayOutputStream iout = new ByteArrayOutputStream(); DataOutputStream iin = new DataOutputStream(iout); iin.write(pdata, 0, len); iin.write(new byte[256 - len]); iin.writeShort(getYSize(font)); iin.writeByte(getStyle(font)); iin.writeByte(getFlags(font, proportional)); items.add(iout.toByteArray()); } ByteArrayOutputStream cout = new ByteArrayOutputStream(); DataOutputStream cin = new DataOutputStream(cout); cin.writeShort(id); cin.writeShort(items.size()); for (byte[] item : items) cin.write(item); return cout.toByteArray(); } protected byte[] exportDescriptorFile(BitmapFont font, boolean proportional) throws IOException { byte[] code = exportCodeHunk(font, proportional); int codeSize = (code.length + 3) / 4; int padSize = (codeSize * 4) - code.length; ByteArrayOutputStream dout = new ByteArrayOutputStream(); DataOutputStream din = new DataOutputStream(dout); din.writeInt(0x03F3); // HUNK_HEADER din.writeInt(0); // strList din.writeInt(1); // hunks din.writeInt(0); // firstHunk din.writeInt(0); // lastHunk din.writeInt(codeSize); // hunkSize din.writeInt(0x03E9); // HUNK_CODE din.writeInt(codeSize); // hunkSize din.write(code); din.write(new byte[padSize]); din.writeInt(0x03EC); // HUNK_RELOC32 din.writeInt(proportional ? 6 : 4); // number of offsets din.writeInt(0); // hunkNumber if (proportional) din.writeInt(0x6A); // tfCharKern if (proportional) din.writeInt(0x66); // tfCharSpace din.writeInt(0x62); // tfCharLoc din.writeInt(0x5C); // tfCharData din.writeInt(0x44); // lnName din.writeInt(0x0E); // lnName din.writeInt(0); // number of offsets din.writeInt(0x03F2); // HUNK_END return dout.toByteArray(); } protected byte[] exportCodeHunk(BitmapFont font, boolean proportional) throws IOException { byte[] textFont = exportTextFont(font, proportional); ByteArrayOutputStream chOut = new ByteArrayOutputStream(); DataOutputStream chIn = new DataOutputStream(chOut); chIn.writeInt(0x70644E75); // MOVEQ #0,D0; RTS chIn.writeInt(0); // lnSucc chIn.writeInt(0); // lnPred chIn.writeByte(0x0C); // lnType chIn.writeByte(0x00); // lnPri chIn.writeInt(0x1A); // lnName chIn.writeShort(0x0F80); // fileID chIn.writeShort(0); // revision chIn.writeInt(0); // segment String name = font.getName(Font.NAME_FAMILY); byte[] ndata = (name != null) ? name.getBytes("ISO-8859-1") : new byte[0]; int len = ndata.length; if (len > 31) len = 31; chIn.write(ndata, 0, len); chIn.write(new byte[32 - len]); chIn.writeInt(0); // lnSucc chIn.writeInt(0); // lnPred chIn.writeByte(0x0C); // lnType chIn.writeByte(0x00); // lnPri chIn.writeInt(0x1A); // lnName chIn.writeInt(0); // mnReplyPort chIn.writeShort(textFont.length + 20); // mnLength chIn.write(textFont); return chOut.toByteArray(); } protected byte[] exportTextFont(BitmapFont font, boolean proportional) throws IOException { int height = font.getLineAscent() + font.getLineDescent(); int ySize = getYSize(font); int style = getStyle(font); int flags = getFlags(font, proportional); int xSize = proportional ? height : 1; int baseline = font.getLineAscent() - 1; int boldSmear = 1; int accessors = 0; int loChar = Integer.MAX_VALUE; int hiChar = Integer.MIN_VALUE; // calculate metrics HashSet gset = new HashSet(); int width = 0; for (int i = 0; i < 256; i++) { int cp = (encoding != null) ? encoding.get(i) : i; BitmapFontGlyph c = font.getCharacter(cp); if (c != null) { if (i < loChar) loChar = i; if (i > hiChar) hiChar = i; GlyphKey key = new GlyphKey(c, proportional); if (gset.contains(key)) continue; gset.add(key); if (c.getCharacterWidth() > xSize) xSize = c.getCharacterWidth(); width += proportional ? c.getGlyphWidth() : c.getCharacterWidth(); } } BitmapFontGlyph notdef = font.getNamedGlyph(".notdef"); if (notdef != null) { if (notdef.getCharacterWidth() > xSize) xSize = notdef.getCharacterWidth(); width += proportional ? notdef.getGlyphWidth() : notdef.getCharacterWidth(); } int modulo = ((width + 15) / 16) * 2; byte[][] bitmap = new byte[ySize][modulo * 8]; int n = hiChar - loChar + 2; int[] bitOffset = new int[n]; int[] bitSize = new int[n]; int[] spacing = new int[n]; int[] kerning = new int[n]; int charLoc, charSpace, charKern, charData; if (proportional) { charLoc = 0x6E; charSpace = charLoc + n * 4; charKern = charSpace + n * 2; charData = charKern + n * 2; } else { charLoc = 0x6E; charSpace = 0; charKern = 0; charData = charLoc + n * 4; } // make bitmap and tables HashMap gmap = new HashMap(); int xcoord = 0; for (int i = loChar, o = 0; i <= hiChar && o < n; i++, o++) { int cp = (encoding != null) ? encoding.get(i) : i; BitmapFontGlyph c = font.getCharacter(cp); if (c != null) { xcoord = addGlyph(font, c, proportional, xcoord, o, bitmap, bitOffset, bitSize, spacing, kerning, gmap); } else if (notdef != null) { xcoord = addGlyph(font, notdef, proportional, xcoord, o, bitmap, bitOffset, bitSize, spacing, kerning, gmap); } } if (notdef != null) { xcoord = addGlyph(font, notdef, proportional, xcoord, n-1, bitmap, bitOffset, bitSize, spacing, kerning, gmap); } // make real bitmap byte[][] realBitmap = new byte[ySize][modulo]; for (int y = 0; y < bitmap.length; y++) { for (int rx = 0, x = 0; rx < realBitmap[y].length && x < bitmap[y].length; rx++) { for (int k = 0; x < bitmap[y].length && k < 8; x++, k++) { realBitmap[y][rx] <<= 1; if ((bitmap[y][x] & 0xFF) >= 0x80) realBitmap[y][rx] |= 1; } } } // make TextFont ByteArrayOutputStream tfOut = new ByteArrayOutputStream(); DataOutputStream tfIn = new DataOutputStream(tfOut); tfIn.writeShort(ySize); tfIn.writeByte(style); tfIn.writeByte(flags); tfIn.writeShort(xSize); tfIn.writeShort(baseline); tfIn.writeShort(boldSmear); tfIn.writeShort(accessors); tfIn.writeByte(loChar); tfIn.writeByte(hiChar); tfIn.writeInt(charData); tfIn.writeShort(modulo); tfIn.writeInt(charLoc); tfIn.writeInt(charSpace); tfIn.writeInt(charKern); for (int i = 0; i < n; i++) { tfIn.writeShort(bitOffset[i]); tfIn.writeShort(bitSize[i]); } if (proportional) { for (int s : spacing) tfIn.writeShort(s); for (int k : kerning) tfIn.writeShort(k); } for (byte[] line : realBitmap) tfIn.write(line); return tfOut.toByteArray(); } private static int addGlyph( BitmapFont font, BitmapFontGlyph c, boolean proportional, int xcoord, int o, byte[][] bitmap, int[] bitOffset, int[] bitSize, int[] spacing, int[] kerning, HashMap gmap ) { GlyphKey key = new GlyphKey(c, proportional); GlyphValues values = gmap.get(key); if (values == null) { int gbx = proportional ? 0 : (c.getGlyphOffset() < 0) ? -c.getGlyphOffset() : 0; int bbx = proportional ? xcoord : (c.getGlyphOffset() <= 0) ? xcoord : (xcoord + c.getGlyphOffset()); byte[][] g = c.getGlyph(); for (int gy = 0, by = font.getLineAscent() - c.getGlyphAscent(); gy < g.length && by < bitmap.length; gy++, by++) { if (by >= 0) { for (int gx = gbx, bx = bbx; gx < g[gy].length && bx < bitmap[by].length; gx++, bx++) { bitmap[by][bx] = g[gy][gx]; } } } values = new GlyphValues(); values.bitOffset = xcoord; values.bitSize = proportional ? c.getGlyphWidth() : c.getCharacterWidth(); xcoord += values.bitSize; gmap.put(key, values); } bitOffset[o] = values.bitOffset; bitSize[o] = values.bitSize; spacing[o] = (proportional && values.bitSize > 0) ? (c.getCharacterWidth() - c.getGlyphOffset()) : c.getCharacterWidth(); kerning[o] = (proportional && values.bitSize > 0) ? c.getGlyphOffset() : 0; return xcoord; } private static final class GlyphKey { private final BitmapFontGlyph glyph; private final Object[] keys; private GlyphKey(BitmapFontGlyph glyph, boolean proportional) { this.glyph = glyph; if (proportional) { this.keys = new Object[] { glyph.getGlyph(), glyph.getGlyphAscent() }; } else { this.keys = new Object[] { glyph.getGlyph(), glyph.getGlyphOffset(), glyph.getGlyphAscent(), glyph.getCharacterWidth() }; } } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof GlyphKey)) return false; if (this.glyph == ((GlyphKey)o).glyph) return true; return Arrays.deepEquals(keys, ((GlyphKey)o).keys); } public int hashCode() { return Arrays.deepHashCode(keys); } } private static final class GlyphValues { private int bitOffset; private int bitSize; } private static int getYSize(BitmapFont font) { return font.getLineAscent() + font.getLineDescent() + font.getLineGap(); } private static int getStyle(BitmapFont font) { int s = 0; if (font.isUnderlineStyle()) s |= STYLE_UNDERLINED; if (font.isBoldStyle()) s |= STYLE_BOLD; if (font.isItalicStyle()) s |= STYLE_ITALIC; if (font.isExtendedStyle()) s |= STYLE_EXTENDED; return s; } private static int getFlags(BitmapFont font, boolean proportional) { int f = FLAGS_DESIGNED; if (proportional) f |= FLAGS_PROPORTIONAL; return f; } private static String getFileName(BitmapFont font) { StringBuffer sb = new StringBuffer(); sb.append(getYSize(font)); if (font.isUnderlineStyle()) sb.append("U"); if (font.isBoldStyle()) sb.append("B"); if (font.isItalicStyle()) sb.append("I"); if (font.isExtendedStyle()) sb.append("E"); return sb.toString(); } } BDFBitmapFontExporter.java000077500000000000000000000121161506470510200342060ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Map; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class BDFBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"), true); exportFont(font, pw); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); } private void exportFont(BitmapFont font, PrintWriter pw) { int cnt = 0; int bbl = 0; int bbr = 0; int bbt = 0; int bbb = 0; for (int i = 0; i < 0x110000; i++) { if (font.containsCharacter(i)) { cnt++; BitmapFontGlyph g = font.getCharacter(i); if (g.getGlyphOffset() < bbl) { bbl = g.getGlyphOffset(); } if (g.getGlyphOffset() + g.getGlyphWidth() > bbr) { bbr = g.getGlyphOffset() + g.getGlyphWidth(); } if (g.getGlyphAscent() > bbt) { bbt = g.getGlyphAscent(); } if (g.getGlyphDescent() > bbb) { bbb = g.getGlyphDescent(); } } } Map props = new LinkedHashMap(); if (font.containsName(Font.NAME_FAMILY)) props.put("FAMILY_NAME", font.getName(Font.NAME_FAMILY)); if (font.containsName(Font.NAME_STYLE)) props.put("WEIGHT_NAME", font.getName(Font.NAME_STYLE)); if (font.containsName(Font.NAME_VERSION)) props.put("FONT_VERSION", font.getName(Font.NAME_VERSION)); if (font.containsName(Font.NAME_COPYRIGHT)) props.put("COPYRIGHT", font.getName(Font.NAME_COPYRIGHT)); if (font.containsName(Font.NAME_MANUFACTURER)) props.put("FOUNDRY", font.getName(Font.NAME_MANUFACTURER)); props.put("FONT_ASCENT", Integer.toString(font.getLineAscent())); props.put("FONT_DESCENT", Integer.toString(font.getLineDescent())); props.put("POINT_SIZE", Integer.toString(font.getEmAscent() + font.getEmDescent())); props.put("X_HEIGHT", Integer.toString(font.getXHeight())); props.put("CAP_HEIGHT", Integer.toString(font.getCapHeight())); pw.println("STARTFONT 2.1"); pw.println("FONT -" + font.getName(Font.NAME_MANUFACTURER) + "-" + font.getName(Font.NAME_FAMILY) + "-" + font.getName(Font.NAME_STYLE) + "-" + (font.isItalicStyle() ? "I" : "R") + "-" + font.getName(Font.NAME_STYLE) + "--" + (font.getLineAscent() + font.getLineDescent()) + "-" + (font.getLineAscent() + font.getLineDescent()) + "-75-75-c-80-iso10646-1"); pw.println("SIZE " + (font.getLineAscent() + font.getLineDescent()) + " 75 75"); pw.println("FONTBOUNDINGBOX " + (bbr-bbl) + " " + (bbt+bbb) + " " + bbl + " " + (-bbb)); pw.println("STARTPROPERTIES " + props.size()); for (Map.Entry e : props.entrySet()) { pw.println(e.getKey() + " " + enquote(e.getValue())); } pw.println("ENDPROPERTIES"); pw.println("CHARS " + cnt); for (int i = 0; i < 0x110000; i++) { if (font.containsCharacter(i)) { BitmapFontGlyph g = font.getCharacter(i); String h = Integer.toHexString(i).toUpperCase(); while (h.length() < 4) h = "0" + h; writeChar(pw, g, "U+" + h, i, bbl, bbr); } } for (String name : font.namedGlyphs(false).keySet()) { writeChar(pw, font.getNamedGlyph(name), name, -1, bbl, bbr); } pw.println("ENDFONT"); } private void writeChar(PrintWriter pw, BitmapFontGlyph g, String name, int i, int bbl, int bbr) { pw.println("STARTCHAR " + name); pw.println("ENCODING " + i); pw.println("SWIDTH " + (1000 * g.getCharacterWidth() / (bbr-bbl)) + " 0"); pw.println("DWIDTH " + g.getCharacterWidth() + " 0"); pw.println("BBX " + g.getGlyphWidth() + " " + g.getGlyphHeight() + " " + g.getGlyphOffset() + " " + (-g.getGlyphDescent())); pw.println("BITMAP"); for (byte[] row : g.getGlyph()) { StringBuffer s = new StringBuffer(); for (int col = 0; col < row.length; col += 8) { int b = 0; for (int c = 0; c < 8; c++) { b <<= 1; if (col+c < row.length && row[col+c] < 0) { b |= 1; } } String bh = "00" + Integer.toHexString(b).toUpperCase(); bh = bh.substring(bh.length() - 2); s.append(bh); } if (s.length() == 0) s.append("00"); pw.println(s.toString()); } pw.println("ENDCHAR"); } private static String enquote(String s) { if (s.matches("^-?[0-9]+$")) return s; return "\"" + s.replaceAll("\"", "\"\"") + "\""; } } CybikoBitmapFontExporter.java000066400000000000000000000116211506470510200350300ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class CybikoBitmapFontExporter implements BitmapFontExporter { private GlyphList encoding; public CybikoBitmapFontExporter() { this.encoding = null; } public CybikoBitmapFontExporter(GlyphList encoding) { this.encoding = encoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { int lastch = 32; int width = 1; int height = font.getLineAscent() + font.getLineDescent() + font.getLineGap(); for (int ch = 32; ch < 256; ch++) { int cp = (encoding != null) ? encoding.get(ch) : fromCybiko(ch); BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { lastch = ch; int w = g.getCharacterWidth(); if (w > width) width = w; } } out.writeByte(1); out.writeByte(lastch - 31); out.writeByte(width); out.writeByte(height); for (int ch = 32; ch <= lastch; ch++) { int cp = (encoding != null) ? encoding.get(ch) : fromCybiko(ch); BitmapFontGlyph g = font.getCharacter(cp); if (g == null) { out.writeByte(0); out.writeByte(0); out.writeByte(1); out.writeByte(1); out.writeByte(0); } else { int w = g.getCharacterWidth(); if (w < 1) w = 1; int y = font.getLineAscent() - g.getGlyphAscent(); int h = g.getGlyphHeight(); int r = 0; while (h < 1) { y--; r--; h++; } while (y >= height) { y--; r--; h++; } while (y < 0) { y++; r++; h--; } if (h > height - y) h = height - y; if (h < 1) h = 1; out.writeByte(0); out.writeByte(y); out.writeByte(w); out.writeByte(h); for (byte[][] gd = g.getGlyph(); h > 0; h--, r++) { byte[] row = new byte[(w+7)/8]; if (r >= 0 && r < gd.length) { for (int c = -g.getGlyphOffset(), p = 0, x = 0; x < w; x += 8, p++) { for (int m = 0x80, i = x; m != 0 && i < w; m >>= 1, i++, c++) { if (c >= 0 && c < gd[r].length && gd[r][c] < 0) { row[p] |= m; } } } } out.write(row); } } } } private static int fromCybiko(int ch) { switch (ch) { // Cybiko Symbols case 0x7F: return 0x2026; // horizontal ellipsis case 0x80: return 0x2665; // black heart suit case 0x81: return 0x25CF; // black circle case 0x82: return 0x25B6; // black right-pointing triangle case 0x83: return 0x25B7; // white right-pointing triangle case 0x84: return 0xFFC22; // white right-pointing triangle, duplicate? case 0x85: return 0xFFC23; // cy-sign // Windows CP-1252 case 0x86: return 0x2020; // dagger case 0x87: return 0x2021; // double dagger case 0x88: return 0x02C6; // modifier letter circumflex accent case 0x89: return 0x2030; // per mille sign case 0x8A: return 0x0160; // latin capital letter s with caron case 0x8B: return 0x2039; // single left-pointing angle quotation mark case 0x8C: return 0x0152; // latin capital ligature oe case 0x8D: return 0x0141; // latin capital letter l with stroke case 0x8E: return 0x017D; // latin capital letter z with caron case 0x8F: return 0x0131; // latin small letter dotless i case 0x90: return 0x20AC; // euro sign case 0x91: return 0x2018; // left single quotation mark case 0x92: return 0x2019; // right single quotation mark case 0x93: return 0x201C; // left double quotation mark case 0x94: return 0x201D; // right double quotation mark case 0x95: return 0x2022; // bullet case 0x96: return 0x2013; // en dash case 0x97: return 0x2014; // em dash case 0x98: return 0x02DC; // small tilde case 0x99: return 0x2122; // trade mark sign case 0x9A: return 0x0161; // latin small letter s with caron case 0x9B: return 0x203A; // single right-pointing angle quotation mark case 0x9C: return 0x0153; // latin small ligature oe case 0x9D: return 0x0142; // latin small letter l with stroke case 0x9E: return 0x017E; // latin small letter z with caron case 0x9F: return 0x0178; // latin capital letter y with diaeresis default: return ch; } } } FNTBitmapFontExporter.java000066400000000000000000000230121506470510200342340ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class FNTBitmapFontExporter implements BitmapFontExporter { private int magic; private GlyphList encoding; public FNTBitmapFontExporter() { this.magic = 3; this.encoding = null; } public FNTBitmapFontExporter(GlyphList encoding) { this.magic = 3; this.encoding = encoding; } public FNTBitmapFontExporter(int magic) { if (magic < 1 || magic > 3) throw new IllegalArgumentException("bad magic number"); this.magic = magic; this.encoding = null; } public FNTBitmapFontExporter(int magic, GlyphList encoding) { if (magic < 1 || magic > 3) throw new IllegalArgumentException("bad magic number"); this.magic = magic; this.encoding = encoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { // Vertical metrics. int ascent = font.getLineAscent(); int height = ascent + font.getLineDescent(); int points = font.getEmAscent() + font.getEmDescent(); int leading = font.getLineGap(); // Font style. String styleName = font.getName(BitmapFont.NAME_STYLE); styleName = (styleName != null) ? styleName.toLowerCase() : ""; int italic = (styleName.contains("italic") || styleName.contains("oblique")) ? 1 : 0; int underline = styleName.contains("underline") ? 1 : 0; int strikeOut = styleName.contains("strike") ? 1 : 0; int weight = ( styleName.contains("thin") ? 100 : styleName.contains("light") ? 300 : styleName.contains("bold") ? 700 : styleName.contains("black") ? 900 : 400 ); // Character set. String encName = (encoding != null) ? encoding.getName().toUpperCase() : "WINDOWS-1252"; int charSet = ( encName.equals("WINDOWS-1252") ? 0 : encName.equals("X-MACROMAN") ? 77 : encName.equals("SHIFT_JIS") ? 128 : encName.equals("X-MS932_0213") ? 128 : encName.equals("X-SJIS_0213") ? 128 : encName.equals("X-IBM949") ? 129 : encName.equals("X-IBM949C") ? 129 : encName.equals("X-WINDOWS-949") ? 129 : encName.equals("X-JOHAB") ? 130 : encName.equals("GB2312") ? 134 : encName.equals("X-MSWIN-936") ? 134 : encName.equals("BIG5") ? 136 : encName.equals("BIG5-HKSCS") ? 136 : encName.equals("X-BIG5-HKSCS-2001") ? 136 : encName.equals("X-BIG5-SOLARIS") ? 136 : encName.equals("X-IBM950") ? 136 : encName.equals("X-MS950-HKSCS") ? 136 : encName.equals("X-MS950-HKSCS-XP") ? 136 : encName.equals("X-WINDOWS-950") ? 136 : encName.equals("WINDOWS-1253") ? 161 : encName.equals("WINDOWS-1254") ? 162 : encName.equals("WINDOWS-1258") ? 163 : encName.equals("WINDOWS-1255") ? 177 : encName.equals("WINDOWS-1256") ? 178 : encName.equals("WINDOWS-1257") ? 186 : encName.equals("WINDOWS-1251") ? 204 : encName.equals("X-IBM874") ? 222 : encName.equals("X-WINDOWS-874") ? 222 : encName.equals("WINDOWS-1250") ? 238 : encName.equals("IBM437") ? 255 : 2 ); // Horizontal metrics and bitmaps. int maxWidth = 0; int avgWidth = 0; int numChars = 0; int firstChar = -1; int lastChar = -1; int defaultChar = -1; int breakChar = -1; int widthBytes = 0; HashMap widths = new HashMap(); HashMap bitmaps = new HashMap(); for (int idx = 0; idx < 256; idx++) { int ch = (encoding != null) ? encoding.get(idx) : fromCP1252(idx); if (ch < 0) ch = 0xF000 + idx; BitmapFontGlyph g = font.getCharacter(ch); if (g == null) continue; int width = g.getCharacterWidth(); if (width > maxWidth) maxWidth = width; avgWidth += width; numChars++; if (ch == 32) breakChar = idx; if (firstChar < 0) firstChar = idx; lastChar = idx; int rowBytes = (width + 7) / 8; widthBytes += rowBytes; byte[] data = new byte[rowBytes * height]; byte[][] glyphPixels = g.getGlyph(); for (int dy = 0, j = g.getGlyphAscent() - ascent, y = 0; y < height; y++, j++, dy++) { if (j >= 0 && j < glyphPixels.length) { for (int dx = dy, i = -g.getGlyphOffset(), x = 0; x < width; dx += height) { for (int m = 0x80; m != 0 && x < width; m >>= 1, x++, i++) { if (i >= 0 && i < glyphPixels[j].length) { if (glyphPixels[j][i] < 0) data[dx] |= m; } } } } } widths.put(idx, width); bitmaps.put(idx, data); } // Create notdef bitmap. avgWidth /= numChars; if (avgWidth < 1) avgWidth = 1; int rowBytes = (avgWidth + 7) / 8; byte[] data = new byte[rowBytes * height]; for (int dy = 0, y = 0; y < height; y++, dy++) { if (y > 0 && y < height-1) { for (int dx = dy, x = 0; x < avgWidth; dx += height) { for (int m = 0x80; m != 0 && x < avgWidth; m >>= 1, x++) { if (x > 0) { data[dx] |= m; } } } } } // Add notdef bitmaps. boolean isMono = true; for (int idx = firstChar; idx <= lastChar; idx++) { if (widths.containsKey(idx)) { if (widths.get(idx) != avgWidth) { isMono = false; } } else { if (defaultChar < 0) defaultChar = idx; widthBytes += rowBytes; numChars++; widths.put(idx, avgWidth); bitmaps.put(idx, data); } } // Add absolute space bitmap. if (breakChar < 0) breakChar = lastChar + 1; if (defaultChar < 0) defaultChar = lastChar + 1; widthBytes += rowBytes; numChars++; widths.put(lastChar + 1, avgWidth); bitmaps.put(lastChar + 1, new byte[rowBytes * height]); assert((lastChar - firstChar + 2) == numChars); assert(widths.size() == numChars); assert(bitmaps.size() == numChars); // Sizes and offsets and stuff. int charTableSize = numChars * ((magic >= 3) ? 6 : 4); int bitsOffset = charTableSize + ((magic >= 3) ? 148 : 118); int face = bitsOffset + (widthBytes * height); String copyright = font.getName(BitmapFont.NAME_COPYRIGHT); byte[] copyrightBytes = (copyright != null) ? copyright.getBytes("CP1252") : new byte[0]; String faceName = font.getName(BitmapFont.NAME_FAMILY); byte[] faceBytes = (faceName != null) ? faceName.getBytes("CP1252") : new byte[0]; int size = face + faceBytes.length + 1; // Write it out. out.writeShort(magic); out.writeInt(Integer.reverseBytes(size)); out.write(copyrightBytes, 0, Math.min(copyrightBytes.length, 60)); for (int i = copyrightBytes.length; i < 60; i++) out.write(0); out.writeShort(0); // type out.writeShort(Short.reverseBytes((short)points)); out.writeShort(Short.reverseBytes((short)96)); // vertRes out.writeShort(Short.reverseBytes((short)96)); // horizRes out.writeShort(Short.reverseBytes((short)ascent)); out.writeShort(0); // internalLeading out.writeShort(Short.reverseBytes((short)leading)); // externalLeading out.writeByte(italic); out.writeByte(underline); out.writeByte(strikeOut); out.writeShort(Short.reverseBytes((short)weight)); out.writeByte(charSet); out.writeShort(Short.reverseBytes((short)(isMono ? avgWidth : 0))); // pixWidth out.writeShort(Short.reverseBytes((short)height)); // pixHeight out.writeByte(isMono ? 0 : 1); // pitchAndFamily out.writeShort(Short.reverseBytes((short)avgWidth)); out.writeShort(Short.reverseBytes((short)maxWidth)); out.writeByte(firstChar); out.writeByte(lastChar); out.writeByte(defaultChar - firstChar); out.writeByte(breakChar - firstChar); out.writeShort(Short.reverseBytes((short)widthBytes)); out.writeInt(0); // device out.writeInt(Integer.reverseBytes(face)); out.writeInt(0); // bitsPointer out.writeInt(Integer.reverseBytes(bitsOffset)); out.writeByte(0); // reserved if (magic >= 3) { out.writeInt(Integer.reverseBytes(isMono ? 0x11 : 0x12)); // flags out.writeShort(0); // aSpace out.writeShort(0); // bSpace out.writeShort(0); // cSpace out.writeInt(0); // colorPointer out.write(new byte[16]); // reserved1 } // charTable for (int idx = firstChar; idx <= lastChar + 1; idx++) { out.writeShort(Short.reverseBytes(widths.get(idx).shortValue())); if (magic >= 3) out.writeInt(Integer.reverseBytes(bitsOffset)); else out.writeShort(Short.reverseBytes((short)bitsOffset)); bitsOffset += bitmaps.get(idx).length; } assert(bitsOffset == face); // bitmaps for (int idx = firstChar; idx <= lastChar + 1; idx++) { out.write(bitmaps.get(idx)); } // faceName out.write(faceBytes); out.write(0); } private static int fromCP1252(int ch) { if (ch < 0x80 || ch >= 0xA0) return ch; return CP1252_C1[ch - 0x80]; } private static final int[] CP1252_C1 = new int[] { 0x20AC, 0x25CA, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0141, 0x017D, 0x0131, 0x2318, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0142, 0x017E, 0x0178, }; } FONTXBitmapFontExporter.java000066400000000000000000000114771506470510200345170ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.LinkedList; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class FONTXBitmapFontExporter implements BitmapFontExporter { private int flag; private GlyphList singleByteEncoding; private String doubleByteEncoding; public FONTXBitmapFontExporter(boolean isDoubleByte) { this.flag = isDoubleByte ? 1 : 0; this.singleByteEncoding = null; this.doubleByteEncoding = "CP943"; // IBM's version of Shift-JIS } public FONTXBitmapFontExporter(GlyphList singleByteEncoding) { this.flag = 0; this.singleByteEncoding = singleByteEncoding; this.doubleByteEncoding = "CP943"; // IBM's version of Shift-JIS } public FONTXBitmapFontExporter(String doubleByteEncoding) { this.flag = 1; this.singleByteEncoding = null; this.doubleByteEncoding = doubleByteEncoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { out.writeInt(0x464F4E54); out.writeShort(0x5832); String name = font.getName(BitmapFont.NAME_FAMILY); byte[] nameBytes = (name != null) ? name.getBytes("US-ASCII") : new byte[0]; for (int i = 0; i < nameBytes.length && i < 8; i++) out.writeByte(nameBytes[i]); for (int i = nameBytes.length; i < 8; i++) out.writeByte(0x20); int a = font.getLineAscent(); int h = a + font.getLineDescent() + font.getLineGap(); if (flag == 0) { int maxWidth = 0; BitmapFontGlyph[] glyphs = new BitmapFontGlyph[256]; for (int i = 0; i < 256; i++) { BitmapFontGlyph g = font.getCharacter(fromSingleByte(i)); if (g != null) { int w = g.getCharacterWidth(); if (w > maxWidth) maxWidth = w; glyphs[i] = g; } } out.writeByte(maxWidth); out.writeByte(h); out.writeByte(flag); for (BitmapFontGlyph g : glyphs) { writeGlyph(out, maxWidth, h, a, g); } } else { int bp = -1; int[] bs = new int[256]; int[] be = new int[256]; int maxWidth = 0; LinkedList glyphs = new LinkedList(); for (int i = 0; i < 65536; i++) { BitmapFontGlyph g = font.getCharacter(fromDoubleByte(i)); if (g != null) { if (bp < 0 || (be[bp] + 1) != i) { if (bp >= 254) break; bp++; bs[bp] = i; } be[bp] = i; int w = g.getCharacterWidth(); if (w > maxWidth) maxWidth = w; glyphs.add(g); } } out.writeByte(maxWidth); out.writeByte(h); out.writeByte(flag); out.writeByte(bp + 1); for (int i = 0; i <= bp; i++) { out.writeShort(Short.reverseBytes((short)bs[i])); out.writeShort(Short.reverseBytes((short)be[i])); } for (BitmapFontGlyph g : glyphs) { writeGlyph(out, maxWidth, h, a, g); } } } private void writeGlyph(DataOutputStream out, int w, int h, int a, BitmapFontGlyph g) throws IOException { if (g == null) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } else { byte[][] data = g.getGlyph(); for (int j = g.getGlyphAscent() - a, y = 0; y < h; y++, j++) { if (j >= 0 && j < data.length) { int i = -g.getGlyphOffset(), x = 0; while (x < w) { int b = 0; for (int m = 0x80; m != 0 && x < w; m >>= 1, x++, i++) { if (i >= 0 && i < data[j].length) { if (data[j][i] < 0) b |= m; } } out.writeByte(b); } } else { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } } } private int fromSingleByte(int i) { if (singleByteEncoding != null) { int cp = singleByteEncoding.get(i); if (cp >= 0) return cp; } return 0xF000 + i; } private int fromDoubleByte(int i) { if (doubleByteEncoding != null) { try { byte[] b = { (byte)(i >> 8), (byte)i }; String s = new String(b, doubleByteEncoding); if (s.codePointCount(0, s.length()) == 1) { int cp = s.codePointAt(0); if (cp != 0xFFFD) return cp; } } catch (IOException e) { // Ignored. } } return 0xF0000 + i; } } FZXBitmapFontExporter.java000066400000000000000000000077411506470510200342670ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class FZXBitmapFontExporter implements BitmapFontExporter { private GlyphList encoding; public FZXBitmapFontExporter() { this.encoding = null; } public FZXBitmapFontExporter(GlyphList encoding) { this.encoding = encoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); exportFontToStream(font, os); os.close(); return os.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { int ascent = font.getLineAscent(); int height = ascent + font.getLineDescent(); int tracking = 255; int lastchar = 255; while (lastchar > 32 && !font.containsCharacter(zxcp(lastchar))) lastchar--; for (int ch = 32; ch <= lastchar; ch++) { BitmapFontGlyph g = font.getCharacter(zxcp(ch)); if (g != null) { int rsb = g.getCharacterWidth() - (g.getGlyphOffset() + g.getGlyphWidth()); if (rsb <= 0) { tracking = 0; break; } else if (rsb < tracking) tracking = rsb; } } if (height < 1) height = 1; if (height > 255) height = 255; int end = (lastchar - 30) * 3; int ptr = end + 2; int[] offset = new int[lastchar - 31]; int[] kern = new int[lastchar - 31]; int[] shift = new int[lastchar - 31]; int[] width = new int[lastchar - 31]; byte[][] cdef = new byte[lastchar - 31][]; for (int i = 0, ch = 32; ch <= lastchar; ch++, i++) { BitmapFontGlyph g = font.getCharacter(zxcp(ch)); if (g == null) { offset[i] = ptr; kern[i] = 0; shift[i] = 0; width[i] = 1; cdef[i] = new byte[0]; } else { int lsb = g.getGlyphOffset(); int tsb = ascent - g.getGlyphAscent(); int rsb = g.getCharacterWidth() - (lsb + g.getGlyphWidth()); offset[i] = ptr; kern[i] = (lsb <= -3) ? 3 : (lsb >= 0) ? 0 : -lsb; shift[i] = (tsb <= 0) ? 0 : (tsb >= 15) ? 15 : tsb; int kernExtra = lsb + kern[i]; int shiftExtra = tsb - shift[i]; int widthExtra = rsb - tracking; int zxw = g.getGlyphWidth() + kernExtra + widthExtra; int zxh = g.getGlyphHeight() + shiftExtra; int bpr = (zxw <= 8) ? 1 : 2; width[i] = (zxw <= 1) ? 1 : (zxw >= 16) ? 16 : zxw; cdef[i] = new byte[zxh * bpr]; boolean cdefChanged = false; byte[][] gd = g.getGlyph(); for (int gdy = -shiftExtra, cdy = 0, zxy = 0; zxy < zxh; zxy++, cdy += bpr, gdy++) { if (gdy >= 0 && gdy < gd.length) { for (int gdx = -kernExtra, cdx = 0x8000, zxx = 0; zxx < width[i]; zxx++, cdx >>= 1, gdx++) { if (gdx >= 0 && gdx < gd[gdy].length && gd[gdy][gdx] < 0) { if (cdx < 0x100) cdef[i][cdy + 1] |= cdx; else cdef[i][cdy] |= (cdx >> 8); cdefChanged = true; } } } } if (cdefChanged) { ptr += cdef[i].length; } else { kern[i] = 0; shift[i] = 0; cdef[i] = new byte[0]; } } } os.write(height); os.write(tracking); os.write(lastchar); for (int o = 3, i = 0, ch = 32; ch <= lastchar; ch++, i++, o += 3) { int ok = ((offset[i] - o) & 0x3FFF) | (kern[i] << 14); int sw = (shift[i] << 4) | ((width[i] - 1) & 0x0F); os.write(ok); os.write(ok >> 8); os.write(sw); } os.write(ptr - end); os.write((ptr - end) >> 8); for (byte[] cd : cdef) os.write(cd); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream os = new FileOutputStream(file); exportFontToStream(font, os); os.close(); } private int zxcp(int ch) { if (encoding != null) return encoding.get(ch); if (ch == 96) return 163; if (ch == 127) return 169; if (ch < 128) return ch; return (0xF000 + ch); } } GEOSBitmapFontExporter.java000066400000000000000000000157101506470510200343500ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.bitsnpicas.geos.GEOSFontFile; import com.kreative.bitsnpicas.geos.GEOSFontPointSize; import com.kreative.bitsnpicas.geos.GEOSFontStrike; import com.kreative.bitsnpicas.geos.UTF8StrikeEntry; public class GEOSBitmapFontExporter implements BitmapFontExporter { private IDGenerator idgen; private PointSizeGenerator sizegen; private boolean mega; private boolean kerning; private boolean utf8; public GEOSBitmapFontExporter(IDGenerator idgen, PointSizeGenerator sizegen) { this.idgen = idgen; this.sizegen = sizegen; this.mega = false; this.kerning = false; this.utf8 = false; } public GEOSBitmapFontExporter( IDGenerator idgen, PointSizeGenerator sizegen, boolean mega, boolean kerning, boolean utf8 ) { this.idgen = idgen; this.sizegen = sizegen; this.mega = mega; this.kerning = kerning; this.utf8 = utf8; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontToStream(font, out); out.flush(); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { font.autoFillNames(); String family = font.getName(BitmapFont.NAME_FAMILY); int id = idgen.generateID(font); int size = sizegen.generatePointSize(font); String desc = font.getName(BitmapFont.NAME_DESCRIPTION); if (desc == null || desc.length() == 0) desc = "Available in " + size + " point."; GEOSFontPointSize gfps = new GEOSFontPointSize(size); if (mega) { gfps.megaStrikes = new GEOSFontStrike[6]; gfps.megaStrikes[0] = createStrike(font, 0x20, 0x00, 16, 96, false, true); gfps.megaStrikes[1] = createStrike(font, 0x30, 0x10, 16, 96, false, true); gfps.megaStrikes[2] = createStrike(font, 0x40, 0x20, 16, 96, false, true); gfps.megaStrikes[3] = createStrike(font, 0x50, 0x30, 16, 96, false, true); gfps.megaStrikes[4] = createStrike(font, 0x60, 0x40, 16, 96, false, true); gfps.megaStrikes[5] = createStrike(font, 0x70, 0x50, 16, 96, false, true); gfps.megaStrikeIndex = createStrike(font, 0x20, 0, 96, 96, utf8, false); gfps.utf8Map = gfps.megaStrikeIndex.utf8Map; } else { gfps.strike = createStrike(font, 0x20, 0, 96, 96, utf8, true); gfps.utf8Map = gfps.strike.utf8Map; } if (utf8) { gfps.utf8Strikes = new HashMap(); for (int cp = 0x80, i = 0; cp < 0x110000; i++, cp += 64) { if (containsAnyChars(font, cp, 64)) { gfps.utf8Map.set(cp, i >> 8, i & 0xFF, 256); gfps.utf8Strikes.put( new UTF8StrikeEntry(i >> 8, i & 0xFF, 256), createStrike(font, cp, 0, 64, 64, false, true) ); } } } GEOSFontFile gff = new GEOSFontFile(); gff.setFontName(family); gff.setClassTextString(getClassText(font)); gff.setDescriptionString(desc); gff.setFontID(id); gff.setFontPointSize(size, gfps); gff.recalculate(); DataOutputStream out = new DataOutputStream(os); gff.write(out); out.flush(); } private GEOSFontStrike createStrike( BitmapFont font, int cpStart, int indexStart, int cpCount, int indexCount, boolean utf8, boolean bitmap ) { GEOSFontStrike gf = new GEOSFontStrike(indexCount, kerning, utf8); gf.height = font.getLineAscent() + font.getLineDescent(); gf.ascent = font.getLineAscent() - 1; for (int i = 0; i < indexStart; i++) { gf.rowWidth++; gf.xCoord[i+1] = gf.rowWidth; } for (int cp = cpStart, i = indexStart, j = 0; j < cpCount; j++, i++, cp++) { BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { gf.rowWidth += getWidth(g); if (kerning) { gf.offsetWidths[i] = getOffsetWidth(g); } } gf.xCoord[i+1] = gf.rowWidth; } for (int i = indexStart + cpCount; i < indexCount; i++) { gf.rowWidth++; gf.xCoord[i+1] = gf.rowWidth; } gf.rowWidth = (gf.rowWidth + 7) / 8; if (bitmap) { gf.bitmap = new byte[gf.rowWidth * gf.height]; for (int cp = cpStart, i = indexStart, j = 0; j < cpCount; j++, i++, cp++) { BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { byte[][] gd = convertGlyph(font, g, gf.height); gf.setGlyph(i, gd); } } } return gf; } private int getWidth(BitmapFontGlyph g) { int width = g.getCharacterWidth(); if (kerning) { int leftBearing = g.getGlyphOffset(); int rightBearing = width - leftBearing - g.getGlyphWidth(); if (leftBearing < 0) width -= leftBearing; if (rightBearing < 0) width -= rightBearing; } return width; } private GEOSFontStrike.OffsetWidth getOffsetWidth(BitmapFontGlyph g) { int width = g.getCharacterWidth(); int offset = g.getGlyphOffset(); if (offset > 0) offset = 0; return new GEOSFontStrike.OffsetWidth(offset, width); } private byte[][] convertGlyph(BitmapFont font, BitmapFontGlyph g, int height) { int width = g.getCharacterWidth(); int startgx = -g.getGlyphOffset(); int startgy = g.getGlyphAscent() - font.getLineAscent(); if (kerning) { int leftBearing = g.getGlyphOffset(); int rightBearing = width - leftBearing - g.getGlyphWidth(); if (leftBearing < 0) { width -= leftBearing; startgx = 0; } if (rightBearing < 0) width -= rightBearing; } byte[][] gd = g.getGlyph(); byte[][] ngd = new byte[height][width]; for (int gy = startgy, ny = 0; ny < height; ny++, gy++) { if (gy >= 0 && gy < gd.length) { for (int gx = startgx, nx = 0; nx < width; nx++, gx++) { if (gx >= 0 && gx < gd[gy].length) { ngd[ny][nx] = gd[gy][gx]; } } } } return ngd; } private static boolean containsAnyChars(BitmapFont font, int cp, int count) { while (count-- > 0) if (font.containsCharacter(cp++)) return true; return false; } private static final String VP = "[Vv][Ee][Rr]([.]|[Ss]([.]|[Ii][Oo][Nn])?)? *"; private static String getClassText(BitmapFont font) { String version = font.getName(BitmapFont.NAME_VERSION); if (version == null) { version = ""; } else { version = version.replaceAll(VP, "V").trim(); if (version.length() > 0) version = " " + version; } int vlen = version.length(); if (vlen >= 16) return version.substring(vlen - 16); int flen = 16 - vlen; String family = font.getName(BitmapFont.NAME_FAMILY); if (family == null) family = ""; while (family.length() < flen) family += " "; return family.substring(0, flen) + version; } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontToStream(font, out); out.flush(); out.close(); } } HMZKBitmapFontExporter.java000066400000000000000000000061721506470510200343660ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.*; import java.util.Map; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; /** * HMZK is the bitmap font format used for the Mi Band 2. * Reference */ public class HMZKBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFont(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFont(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFont(font, new DataOutputStream(out)); out.close(); } private void exportFont(BitmapFont font, DataOutputStream out) throws IOException { int len = 0; // header out.writeInt(0x484d5a4b); out.writeInt(0x01ffffff); //out.writeInt(0xff00ffff); // it's like this in Mili_pro.ft.en out.writeInt(0xffffffff); // and like this in Mili_pro.ft out.writeShort(0xffff); ByteArrayOutputStream chbuf = new ByteArrayOutputStream(); ByteArrayOutputStream glbuf = new ByteArrayOutputStream(); for (Map.Entry entry : font.characters(false).entrySet()) { len++; int ch = entry.getKey(); BitmapFontGlyph glyph = entry.getValue(); int gx = glyph.getX(); int gy = glyph.getY(); chbuf.write((byte)(ch & 0xFF)); chbuf.write((byte)((ch & 0xFF00) >> 8)); // construct bitmap byte[][] glarr = glyph.getGlyph(); int gytop = 16 - gy; for (int y = 0; y < 16; y++) { if(y < gytop || y - gytop >= glarr.length) { glbuf.write(0); glbuf.write(0); continue; } byte[] row = glarr[y - gytop]; byte b = 0; if(gx < 8) { for (int x = 0; x < 8 && x < row.length; x++) { if(row[x] != 0) { b |= 1 << (7 - x - gx); } } } glbuf.write(b); b = 0; if(gx < 16) { for (int x = 8; x < 16 && x < row.length; x++) { if(row[x] != 0) { b |= 1 << (15 - x - gx); } } } glbuf.write(b); } } out.writeShort(Short.reverseBytes((short)(len * 2))); chbuf.writeTo(out); glbuf.writeTo(out); } } HRCGBitmapFontExporter.java000066400000000000000000000042241506470510200343340ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class HRCGBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { boolean doubleWidth = false; boolean doubleHeight = font.getLineAscent() > 10; BitmapFontGlyph[] bfgs = new BitmapFontGlyph[96]; for (int i = 0; i < 96; i++) { if ((bfgs[i] = font.getCharacter(i + 32)) == null) continue; if (bfgs[i].getCharacterWidth() > 10) doubleWidth = true; } byte[] data = new byte[768]; for (int i = 0; i < 96; i++) { if (bfgs[i] == null) continue; int gy = -font.getLineAscent(); for (int dy = 0; dy < 8; dy++) { if (doubleWidth) { byte cb = 0, db = 0, eb = 0; for (int gx = 1, m = 1; m < 0x80; m <<= 1, gx += 2) { if (bfgs[i].getPixel(gx - 1, gy) < 0) cb |= m; if (bfgs[i].getPixel(gx, gy) < 0) db |= m; if (bfgs[i].getPixel(gx + 1, gy) < 0) eb |= m; } if (cb != db && db == eb) db |= 0x80; data[i * 8 + dy] = db; } else { byte db = 0; for (int gx = 0, m = 1; m < 0x80; m <<= 1, gx++) { if (bfgs[i].getPixel(gx, gy) < 0) db |= m; } data[i * 8 + dy] = db; } gy += doubleHeight ? 2 : 1; } } out.write(data); } } HexBitmapFontExporter.java000066400000000000000000000043241506470510200343360ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class HexBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"), true); exportFont(font, pw); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); } private void exportFont(BitmapFont font, PrintWriter pw) { for (int cp = 0; cp < 0x110000; cp++) { if (font.containsCharacter(cp)) { BitmapFontGlyph g = font.getCharacter(cp); int width = (g.getCharacterWidth() + 3) / 4; if (width > 0) { byte[][] glyph = g.getGlyph(); StringBuffer hex = new StringBuffer(); for (int y = g.getGlyphAscent() - 14, j = 0; j < 16; j++, y++) { for (int x = -g.getGlyphOffset(), i = 0; i < width; i++) { int b = 0; for (int m = 8; m > 0; m >>= 1, x++) { if ( y >= 0 && y < glyph.length && x >= 0 && x < glyph[y].length && glyph[y][x] < 0 ) { b |= m; } } char ch = Character.forDigit(b, 16); hex.append(Character.toUpperCase(ch)); } } String cps = Integer.toHexString(cp).toUpperCase(); while (!(cps.length() == 4 || cps.length() == 6)) cps = "0" + cps; pw.println(cps + ":" + hex.toString()); } } } } } KbitsBitmapFontExporter.java000066400000000000000000000043431506470510200346670ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class KbitsBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); exportFont(font, dos); dos.close(); bos.close(); return bos.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFont(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(fos); exportFont(font, dos); dos.close(); fos.close(); } private void exportFont(BitmapFont font, DataOutputStream out) throws IOException { out.writeInt(0x4B426E50); // KBnP out.writeInt(0x62697473); // bits out.writeInt(1); // version out.writeInt(font.getEmAscent()); out.writeInt(font.getEmDescent()); out.writeInt(font.getLineAscent()); out.writeInt(font.getLineDescent()); out.writeInt(font.getLineGap()); out.writeInt(font.getXHeight()); for (Map.Entry e : font.names(false).entrySet()) { out.writeInt(0x6E616D65); // name out.writeInt(1); // version out.writeInt(e.getKey()); out.writeUTF(e.getValue()); } for (Map.Entry e : font.characters(false).entrySet()) { out.writeInt(0x63686172); // char out.writeInt(1); // version out.writeInt(e.getKey()); BitmapFontGlyph g = e.getValue(); out.writeInt(g.getCharacterWidth()); out.writeInt(g.getGlyphOffset()); out.writeInt(g.getGlyphAscent()); byte[][] rows = g.getGlyph(); out.writeInt(rows.length); for (byte[] row : rows) { out.writeInt(row.length); out.write(row); } } out.writeInt(0x66696E2E); // fin. } } KbitxBitmapFontExporter.java000066400000000000000000000103521506470510200346710ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Map; import com.kreative.bitsnpicas.Base64OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.GlyphPair; import com.kreative.bitsnpicas.WIBOutputStream; import com.kreative.bitsnpicas.XMLUtility; public class KbitxBitmapFontExporter implements BitmapFontExporter { public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); return out.toByteArray(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"), true); exportFont(font, pw); } public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); } private void exportFont(BitmapFont font, PrintWriter out) throws IOException { out.println(""); out.println(""); out.println(""); for (Map.Entry e : getProperties(font).entrySet()) { out.println(XMLUtility.wrap("prop", true, "id", e.getKey(), "value", e.getValue())); } for (Map.Entry e : font.names(false).entrySet()) { out.println(XMLUtility.wrap("name", true, "id", e.getKey().toString(), "value", e.getValue())); } for (Map.Entry e : font.characters(false).entrySet()) { out.println(encodeGlyph(e.getKey(), e.getValue())); } for (Map.Entry e : font.namedGlyphs(false).entrySet()) { out.println(encodeGlyph(e.getKey(), e.getValue())); } for (Map.Entry e : font.kernPairs(false).entrySet()) { Object l = e.getKey().getLeft(); Object r = e.getKey().getRight(); out.println(XMLUtility.wrap( "k", true, ((l instanceof Integer) ? "lu" : "ln"), l.toString(), ((r instanceof Integer) ? "ru" : "rn"), r.toString(), "o", e.getValue().toString() )); } out.println(""); } private static Map getProperties(BitmapFont font) { Map props = new LinkedHashMap(); props.put("emAscent", Integer.toString(font.getEmAscent())); props.put("emDescent", Integer.toString(font.getEmDescent())); props.put("lineAscent", Integer.toString(font.getLineAscent())); props.put("lineDescent", Integer.toString(font.getLineDescent())); props.put("lineGap", Integer.toString(font.getLineGap())); props.put("xHeight", Integer.toString(font.getXHeight())); props.put("capHeight", Integer.toString(font.getCapHeight())); return props; } private static String encodeGlyph(Object id, BitmapFontGlyph g) throws IOException { StringBuffer sb = new StringBuffer(); Base64OutputStream bs = new Base64OutputStream(sb, false); byte[][] data = g.getGlyph(); int h = data.length, w = 0; for (byte[] row : data) { if (w < row.length) { w = row.length; } } writeLEB128(bs, h); writeLEB128(bs, w); WIBOutputStream ws = new WIBOutputStream(bs); for (byte[] row : data) { ws.write(row); ws.write(new byte[w - row.length]); } ws.close(); bs.close(); return XMLUtility.wrap( "g", true, ((id instanceof Integer) ? "u" : "n"), id.toString(), "x", Integer.toString(g.getX()), "y", Integer.toString(g.getY()), "w", Integer.toString(g.getCharacterWidth()), "d", sb.toString() ); } private static void writeLEB128(OutputStream out, int v) throws IOException { while (v >= 0x80) { out.write(v | 0x80); v >>= 7; } out.write(v); } } KpcasVectorFontExporter.java000066400000000000000000000077451506470510200347130ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.List; import java.util.Map; import com.kreative.bitsnpicas.VectorFont; import com.kreative.bitsnpicas.VectorFontExporter; import com.kreative.bitsnpicas.VectorFontGlyph; import com.kreative.bitsnpicas.VectorInstruction; import com.kreative.bitsnpicas.VectorPath; public class KpcasVectorFontExporter implements VectorFontExporter { @Override public byte[] exportFontToBytes(VectorFont font) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); exportFont(font, dos); dos.close(); bos.close(); return bos.toByteArray(); } @Override public void exportFontToStream(VectorFont font, OutputStream os) throws IOException { exportFont(font, new DataOutputStream(os)); } @Override public void exportFontToFile(VectorFont font, File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(fos); exportFont(font, dos); dos.close(); fos.close(); } private void exportFont(VectorFont font, DataOutputStream out) throws IOException { out.writeInt(0x4B426E50); // KBnP out.writeInt(0x70636173); // pcas out.writeInt(1); // version out.writeDouble(font.getEmAscent2D()); out.writeDouble(font.getEmDescent2D()); out.writeDouble(font.getLineAscent2D()); out.writeDouble(font.getLineDescent2D()); out.writeDouble(font.getLineGap2D()); out.writeDouble(font.getXHeight2D()); for (Map.Entry e : font.names(false).entrySet()) { out.writeInt(0x6E616D65); // name out.writeInt(1); // version out.writeInt(e.getKey()); out.writeUTF(e.getValue()); } for (Map.Entry e : font.characters(false).entrySet()) { out.writeInt(0x63686172); // char out.writeInt(1); // version out.writeInt(e.getKey()); VectorFontGlyph g = e.getValue(); out.writeDouble(g.getCharacterWidth2D()); Collection paths = g.getContours(); out.writeInt(paths.size()); for (VectorPath path : paths) { for (VectorInstruction inst : path) { List vals = inst.getOperands(); switch (inst.getOperation()) { case 'M': out.writeInt(0x6D6F7665); out.writeDouble((vals.size() > 0) ? vals.get(0).doubleValue() : 0); out.writeDouble((vals.size() > 1) ? vals.get(1).doubleValue() : 0); break; case 'L': out.writeInt(0x6C696E65); out.writeDouble((vals.size() > 0) ? vals.get(0).doubleValue() : 0); out.writeDouble((vals.size() > 1) ? vals.get(1).doubleValue() : 0); break; case 'Q': out.writeInt(0x71756164); out.writeDouble((vals.size() > 0) ? vals.get(0).doubleValue() : 0); out.writeDouble((vals.size() > 1) ? vals.get(1).doubleValue() : 0); out.writeDouble((vals.size() > 2) ? vals.get(2).doubleValue() : 0); out.writeDouble((vals.size() > 3) ? vals.get(3).doubleValue() : 0); break; case 'C': out.writeInt(0x63756265); out.writeDouble((vals.size() > 0) ? vals.get(0).doubleValue() : 0); out.writeDouble((vals.size() > 1) ? vals.get(1).doubleValue() : 0); out.writeDouble((vals.size() > 2) ? vals.get(2).doubleValue() : 0); out.writeDouble((vals.size() > 3) ? vals.get(3).doubleValue() : 0); out.writeDouble((vals.size() > 4) ? vals.get(4).doubleValue() : 0); out.writeDouble((vals.size() > 5) ? vals.get(5).doubleValue() : 0); break; case 'Z': out.writeInt(0x2F707468); break; default: out.writeShort(inst.getOperation()); out.writeShort(vals.size()); for (Number n : vals) out.writeDouble(n.doubleValue()); break; } } out.writeInt(0x2F637472); } } out.writeInt(0x66696E2E); // fin. } } KpcaxVectorFontExporter.java000066400000000000000000000075331506470510200347130ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import com.kreative.bitsnpicas.GlyphPair; import com.kreative.bitsnpicas.VectorFont; import com.kreative.bitsnpicas.VectorFontExporter; import com.kreative.bitsnpicas.VectorFontGlyph; import com.kreative.bitsnpicas.VectorPath; import com.kreative.bitsnpicas.XMLUtility; public class KpcaxVectorFontExporter implements VectorFontExporter { public byte[] exportFontToBytes(VectorFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); return out.toByteArray(); } public void exportFontToStream(VectorFont font, OutputStream os) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"), true); exportFont(font, pw); } public void exportFontToFile(VectorFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw); pw.close(); out.close(); } private void exportFont(VectorFont font, PrintWriter out) throws IOException { out.println(""); out.println(""); out.println(""); for (Map.Entry e : getProperties(font).entrySet()) { out.println(XMLUtility.wrap("prop", true, "id", e.getKey(), "value", e.getValue())); } for (Map.Entry e : font.names(false).entrySet()) { out.println(XMLUtility.wrap("name", true, "id", e.getKey().toString(), "value", e.getValue())); } for (Map.Entry e : font.characters(false).entrySet()) { out.println(encodeGlyph(e.getKey(), e.getValue())); } for (Map.Entry e : font.namedGlyphs(false).entrySet()) { out.println(encodeGlyph(e.getKey(), e.getValue())); } for (Map.Entry e : font.kernPairs(false).entrySet()) { Object l = e.getKey().getLeft(); Object r = e.getKey().getRight(); out.println(XMLUtility.wrap( "k", true, ((l instanceof Integer) ? "lu" : "ln"), l.toString(), ((r instanceof Integer) ? "ru" : "rn"), r.toString(), "o", e.getValue().toString() )); } out.println(""); } private static Map getProperties(VectorFont font) { Map props = new LinkedHashMap(); props.put("emAscent", Double.toString(font.getEmAscent2D())); props.put("emDescent", Double.toString(font.getEmDescent2D())); props.put("lineAscent", Double.toString(font.getLineAscent2D())); props.put("lineDescent", Double.toString(font.getLineDescent2D())); props.put("lineGap", Double.toString(font.getLineGap2D())); props.put("xHeight", Double.toString(font.getXHeight2D())); props.put("capHeight", Double.toString(font.getCapHeight2D())); return props; } private static String encodeGlyph(Object id, VectorFontGlyph g) throws IOException { return XMLUtility.wrap( "g", true, ((id instanceof Integer) ? "u" : "n"), id.toString(), "w", Integer.toString(g.getCharacterWidth()), "d", encodeVectorData(g.getContours()) ); } public static String encodeVectorData(Collection paths) { StringBuffer sb = new StringBuffer(); boolean first = true; for (VectorPath path : paths) { if (first) first = false; else sb.append(" ZZ "); sb.append(path.toString()); } return sb.toString(); } } MGTKBitmapFontExporter.java000066400000000000000000000057011506470510200343540ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class MGTKBitmapFontExporter implements BitmapFontExporter { private GlyphList encoding; public MGTKBitmapFontExporter() { this.encoding = null; } public MGTKBitmapFontExporter(GlyphList encoding) { this.encoding = encoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { int lastChar = 0; int maxWidth = 1; int height = font.getLineAscent() + font.getLineDescent() + font.getLineGap(); if (height > 255) height = 255; BitmapFontGlyph[] bfgs = new BitmapFontGlyph[256]; int[] widths = new int[256]; for (int i = 0; i < 256; i++) { widths[i] = 1; Integer cp = (encoding == null) ? i : encoding.get(i); if (cp == null || cp < 0) continue; bfgs[i] = font.getCharacter(cp); if (bfgs[i] == null) continue; widths[i] = bfgs[i].getCharacterWidth(); if (widths[i] < 1) widths[i] = 1; if (widths[i] > 14) widths[i] = 14; if (widths[i] > maxWidth) maxWidth = widths[i]; lastChar = i; } int fontType = (maxWidth > 7) ? 0x80 : 0; maxWidth = (fontType == 0) ? 7 : (fontType == 0x80) ? 14 : 0; byte[][][] glyphs = new byte[lastChar + 1][height][maxWidth]; for (int i = 0; i <= lastChar; i++) { if (bfgs[i] == null) continue; int y = font.getLineAscent() - bfgs[i].getGlyphAscent(); for (byte[] row : bfgs[i].getGlyph()) { if (y >= 0 && y < height) { int x = bfgs[i].getGlyphOffset(); for (byte b : row) { if (x >= 0 && x < maxWidth) { glyphs[i][y][x] = b; } x++; } } y++; } } out.writeByte(fontType); out.writeByte(lastChar); out.writeByte(height); for (int i = 0; i <= lastChar; i++) { out.writeByte(widths[i]); } for (int y = 0; y < height; y++) { for (int z = 0; z < maxWidth; z += 7) { for (int i = 0; i <= lastChar; i++) { int b = 0; for (int x = z, m = 1; m < 0x80; m <<= 1, x++) { if (glyphs[i][y][x] < 0) b |= m; } out.writeByte(b); } } } } } NFNTBitmapFontExporter.java000077500000000000000000000230201506470510200343540ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.*; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.bitsnpicas.mover.FONDEntry; import com.kreative.bitsnpicas.mover.FONDResource; import com.kreative.unicode.data.GlyphList; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; public abstract class NFNTBitmapFontExporter implements BitmapFontExporter { protected GlyphList encoding; protected NFNTBitmapFontExporter() { this.encoding = null; } protected NFNTBitmapFontExporter(GlyphList encoding) { this.encoding = encoding; } public static final class ResourceFile extends NFNTBitmapFontExporter { private IDGenerator idgen; private PointSizeGenerator sizegen; public ResourceFile(IDGenerator idgen, PointSizeGenerator sizegen) { super(); this.idgen = idgen; this.sizegen = sizegen; } public ResourceFile(IDGenerator idgen, PointSizeGenerator sizegen, GlyphList enc) { super(enc); this.idgen = idgen; this.sizegen = sizegen; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { // make meta font.autoFillNames(); String name = font.getName(Font.NAME_FAMILY); int id = idgen.generateID(font); int size = sizegen.generatePointSize(font); // make FOND FONDResource fond = new FONDResource(name, id); fond.entries.add(new FONDEntry(size, font.getMacStyle(), id)); byte[] fondData = fond.toByteArray(); byte[] nfntData = exportNFNT(font); // make resource fork DfontFile rsrc = new DfontFile(); rsrc.addResource(new DfontResource("FOND", id, 0x60, name, fondData, 0, fondData.length)); rsrc.addResource(new DfontResource("NFNT", id, 0x60, name, nfntData, 0, nfntData.length)); return rsrc.write(); } public void exportFontToFile(BitmapFont font, File file) throws IOException { OutputStream os = new FileOutputStream(file); os.write(exportFontToBytes(font)); os.close(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { os.write(exportFontToBytes(font)); } } public static final class FlatFile extends NFNTBitmapFontExporter { public FlatFile() { super(); } public FlatFile(GlyphList encoding) { super(encoding); } public byte[] exportFontToBytes(BitmapFont font) throws IOException { return exportNFNT(font); } public void exportFontToFile(BitmapFont font, File file) throws IOException { OutputStream os = new FileOutputStream(file); os.write(exportFontToBytes(font)); os.close(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { os.write(exportFontToBytes(font)); } } protected byte[] exportNFNT(BitmapFont font) throws IOException { int type = 0x9000; int firstChar = Integer.MAX_VALUE; int lastChar = Integer.MIN_VALUE; int maxWidth = 0; int kerning = 0; int nDescent = -font.getLineDescent(); int rectWidth = 0; int height = font.getLineAscent() + font.getLineDescent(); int wots; int ascent = font.getLineAscent(); int descent = font.getLineDescent(); int leading = font.getLineGap(); int rowWidth; byte[][] bitmap; short[] xcoords; byte[] offsets; byte[] widths; // calculate metrics int width = 0; for (int i = 0; i < 256; i++) { int cp = (encoding != null) ? encoding.get(i) : MACROMAN[i]; BitmapFontGlyph c = font.getCharacter(cp); if (c != null) { if (i < firstChar) firstChar = i; if (i > lastChar) lastChar = i; if (c.getCharacterWidth() > maxWidth) maxWidth = c.getCharacterWidth(); if (c.getGlyphOffset() < kerning) kerning = c.getGlyphOffset(); if (c.getGlyphOffset() + c.getGlyphWidth() - kerning > rectWidth) rectWidth = c.getGlyphOffset() + c.getGlyphWidth() - kerning; width += c.getGlyphWidth(); } } BitmapFontGlyph notdef = font.getNamedGlyph(".notdef"); if (notdef != null) { if (notdef.getCharacterWidth() > maxWidth) maxWidth = notdef.getCharacterWidth(); if (notdef.getGlyphOffset() < kerning) kerning = notdef.getGlyphOffset(); if (notdef.getGlyphOffset() + notdef.getGlyphWidth() - kerning > rectWidth) rectWidth = notdef.getGlyphOffset() + notdef.getGlyphWidth() - kerning; width += notdef.getGlyphWidth(); } rowWidth = (width + 15) / 16; wots = 5 + (rowWidth*height) + (lastChar-firstChar+3); bitmap = new byte[height][rowWidth * 16]; xcoords = new short[lastChar-firstChar+3]; offsets = new byte[lastChar-firstChar+2]; widths = new byte[lastChar-firstChar+2]; // make bitmap and tables int xcoord = 0; for (int i = firstChar, o = 0; i <= lastChar && o < offsets.length; i++, o++) { int cp = (encoding != null) ? encoding.get(i) : MACROMAN[i]; BitmapFontGlyph c = font.getCharacter(cp); if (c != null) { byte[][] g = c.getGlyph(); for (int gy = 0, by = font.getLineAscent() - c.getGlyphAscent(); gy < g.length && by < bitmap.length; gy++, by++) { if (by >= 0) { for (int gx = 0, bx = xcoord; gx < g[gy].length && bx < bitmap[by].length; gx++, bx++) { bitmap[by][bx] = g[gy][gx]; } } } xcoords[o] = (short)xcoord; offsets[o] = (byte)(c.getGlyphOffset()-kerning); widths[o] = (byte)c.getCharacterWidth(); xcoord += c.getGlyphWidth(); } else { xcoords[o] = (short)xcoord; offsets[o] = -1; widths[o] = -1; } } if (notdef != null) { byte[][] g = notdef.getGlyph(); for (int gy = 0, by = font.getLineAscent() - notdef.getGlyphAscent(); gy < g.length && by < bitmap.length; gy++, by++) { if (by >= 0) { for (int gx = 0, bx = xcoord; gx < g[gy].length && bx < bitmap[by].length; gx++, bx++) { bitmap[by][bx] = g[gy][gx]; } } } xcoords[lastChar-firstChar+1] = (short)xcoord; offsets[lastChar-firstChar+1] = (byte)(notdef.getGlyphOffset()-kerning); widths[lastChar-firstChar+1] = (byte)notdef.getCharacterWidth(); xcoord += notdef.getGlyphWidth(); } else { xcoords[lastChar-firstChar+1] = (short)xcoord; offsets[lastChar-firstChar+1] = -1; widths[lastChar-firstChar+1] = -1; } xcoords[lastChar-firstChar+2] = (short)xcoord; // make real bitmap byte[][] realBitmap = new byte[height][rowWidth*2]; for (int y = 0; y < bitmap.length; y++) { for (int rx = 0, x = 0; rx < realBitmap[y].length && x < bitmap[y].length; rx++) { for (int k = 0; x < bitmap[y].length && k < 8; x++, k++) { realBitmap[y][rx] <<= 1; if ((bitmap[y][x] & 0xFF) >= 0x80) realBitmap[y][rx] |= 1; } } } // make NFNT ByteArrayOutputStream nfntOut = new ByteArrayOutputStream(); DataOutputStream nfntIn = new DataOutputStream(nfntOut); nfntIn.writeShort(type); nfntIn.writeShort(firstChar); nfntIn.writeShort(lastChar); nfntIn.writeShort(maxWidth); nfntIn.writeShort(kerning); nfntIn.writeShort(nDescent); nfntIn.writeShort(rectWidth); nfntIn.writeShort(height); nfntIn.writeShort(wots); nfntIn.writeShort(ascent); nfntIn.writeShort(descent); nfntIn.writeShort(leading); nfntIn.writeShort(rowWidth); for (byte[] line : realBitmap) nfntIn.write(line); for (short x : xcoords) nfntIn.writeShort(x); for (int i = 0; i < offsets.length && i < widths.length; i++) { nfntIn.writeByte(offsets[i]); nfntIn.writeByte(widths[i]); } return nfntOut.toByteArray(); } private static final int[] MACROMAN = new int[] { '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', '\b', '\t', '\n', '\u000B', '\u000C', '\r', '\u000E', '\u000F', '\u0010', '\u2318', '\u2713', '\u25C6', '\uF8FF', '\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\u007F', '\u00C4', '\u00C5', '\u00C7', '\u00C9', '\u00D1', '\u00D6', '\u00DC', '\u00E1', '\u00E0', '\u00E2', '\u00E4', '\u00E3', '\u00E5', '\u00E7', '\u00E9', '\u00E8', '\u00EA', '\u00EB', '\u00ED', '\u00EC', '\u00EE', '\u00EF', '\u00F1', '\u00F3', '\u00F2', '\u00F4', '\u00F6', '\u00F5', '\u00FA', '\u00F9', '\u00FB', '\u00FC', '\u2020', '\u00B0', '\u00A2', '\u00A3', '\u00A7', '\u2022', '\u00B6', '\u00DF', '\u00AE', '\u00A9', '\u2122', '\u00B4', '\u00A8', '\u2260', '\u00C6', '\u00D8', '\u221E', '\u00B1', '\u2264', '\u2265', '\u00A5', '\u00B5', '\u2202', '\u2211', '\u220F', '\u03C0', '\u222B', '\u00AA', '\u00BA', '\u03A9', '\u00E6', '\u00F8', '\u00BF', '\u00A1', '\u00AC', '\u221A', '\u0192', '\u2248', '\u2206', '\u00AB', '\u00BB', '\u2026', '\u00A0', '\u00C0', '\u00C3', '\u00D5', '\u0152', '\u0153', '\u2013', '\u2014', '\u201C', '\u201D', '\u2018', '\u2019', '\u00F7', '\u25CA', '\u00FF', '\u0178', '\u2044', '\u20AC', '\u2039', '\u203A', '\uFB01', '\uFB02', '\u2021', '\u00B7', '\u201A', '\u201E', '\u2030', '\u00C2', '\u00CA', '\u00C1', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00D3', '\u00D4', '\uF8FF', '\u00D2', '\u00DA', '\u00DB', '\u00D9', '\u0131', '\u02C6', '\u02DC', '\u00AF', '\u02D8', '\u02D9', '\u02DA', '\u00B8', '\u02DD', '\u02DB', '\u02C7' }; } OTBBitmapFontExporter.java000066400000000000000000000336461506470510200342470ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.awt.Rectangle; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.truetype.*; public class OTBBitmapFontExporter implements BitmapFontExporter { private boolean extendWinMetrics; public OTBBitmapFontExporter() { this.extendWinMetrics = false; } public OTBBitmapFontExporter(boolean extendWinMetrics) { this.extendWinMetrics = extendWinMetrics; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { return createTrueTypeTables(font, 100, 100, extendWinMetrics).compile(); } public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); fos.write(createTrueTypeTables(font, 100, 100, extendWinMetrics).compile()); fos.close(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { os.write(createTrueTypeTables(font, 100, 100, extendWinMetrics).compile()); } private static final class ThingsToKeepTrackOf { private int numGlyphs = 0; private boolean maxBoundingBox = false; private int bbx1 = 0; private int bby1 = 0; private int bbx2 = 0; private int bby2 = 0; private int minLSB = 0; private int minRSB = 0; private int maxAdvance = 0; private int maxExtent = 0; private int averageWidth = 0; private int numAverages = 0; private int xHeight = 0; private int HHeight = 0; private boolean highUnicode = false; private Map charToGlyfMap = new HashMap(); } private static final TrueTypeFile createTrueTypeTables(BitmapFont bf, int xsize, int ysize, boolean extendWinMetrics) throws IOException { ThingsToKeepTrackOf a = new ThingsToKeepTrackOf(); bf.autoFillNames(); List entries = new ArrayList(); HmtxTable hmtxTable = new HmtxTable(); PostTable postTable = new PostTable(); if (bf.isItalicStyle()) postTable.italicAngle = PostTable.ITALIC_ANGLE_ISOMETRIC; postTable.underlinePosition = -ysize; postTable.underlineThickness = ysize; makeCharacterGlyph(bf, bf.getNamedGlyph(".notdef"), ".notdef", a, xsize, ysize, entries, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x00), 0x00, a, xsize, ysize, entries, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x0D), 0x0D, a, xsize, ysize, entries, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x20), 0x20, a, xsize, ysize, entries, hmtxTable, postTable); for (Map.Entry e : bf.characters(false).entrySet()) { int cp = e.getKey(); if (cp == 0x00 || cp == 0x0D || cp == 0x20) continue; makeCharacterGlyph(bf, e.getValue(), e.getKey(), a, xsize, ysize, entries, hmtxTable, postTable); } for (Map.Entry e : bf.namedGlyphs(false).entrySet()) { if (e.getKey().toString().equals(".notdef")) continue; makeCharacterGlyph(bf, e.getValue(), e.getKey(), a, xsize, ysize, entries, hmtxTable, postTable); } EbdtTable ebdtTable = new EbdtTable(SbitTableType.OPENTYPE); EblcIndexSubtable1 st = new EblcIndexSubtable1(); st.header = new EblcIndexSubtableHeader(); st.header.firstGlyphIndex = 0; st.header.lastGlyphIndex = a.numGlyphs - 1; st.header.indexFormat = 1; st.header.imageFormat = 1; for (EbdtEntry entry : entries) { int key = ebdtTable.getNextKey(); ebdtTable.put(key, entry); st.add(key); } st.add(ebdtTable.getNextKey()); EblcBitmapSize ebs = createBitmapSize(bf, a, xsize); ebs.startGlyphIndex = 0; ebs.endGlyphIndex = a.numGlyphs - 1; ebs.add(st); EblcTable eblcTable = new EblcTable(SbitTableType.OPENTYPE); eblcTable.add(ebs); TrueTypeFile ttf = new TrueTypeFile(); ttf.add(makeHeadTable(bf, a, ysize)); ttf.add(makeHheaTable(bf, a, ysize)); ttf.add(makeMaxpTable(a)); ttf.add(makeOs2Table(bf, a, xsize, ysize, extendWinMetrics)); ttf.add(hmtxTable); ttf.add(makeCmapTable(bf, a)); ttf.add(eblcTable); ttf.add(ebdtTable); ttf.add(makeNameTable(bf)); ttf.add(postTable); return ttf; } private static final void makeCharacterGlyph( BitmapFont bf, BitmapFontGlyph g, Object id, ThingsToKeepTrackOf a, int xsize, int ysize, List entries, HmtxTable hmtxTable, PostTable postTable ) { if (id instanceof Integer) a.charToGlyfMap.put((Integer)id, a.numGlyphs); if (g == null) { EbdtEntryFormat1 e = new EbdtEntryFormat1(); e.smallMetrics = new SbitSmallGlyphMetrics(); e.imageData = new byte[0]; entries.add(e); hmtxTable.add(new HmtxTableEntry()); } else { Rectangle r = new Rectangle( g.getGlyphOffset() * xsize, g.getGlyphAscent() * ysize, g.getGlyphWidth() * xsize, g.getGlyphHeight() * ysize ); int advance = g.getCharacterWidth() * xsize; if (!a.maxBoundingBox) { a.maxBoundingBox = true; a.bbx1 = r.x; a.bby1 = r.y; a.bbx2 = r.x+r.width; a.bby2 = r.y+r.height; a.minLSB = r.x; a.minRSB = advance-r.x-r.width; a.maxAdvance = advance; a.maxExtent = r.x+r.width; } else { if (r.x < a.bbx1) a.bbx1 = r.x; if (r.y < a.bby1) a.bby1 = r.y; if (r.x+r.width > a.bbx2) a.bbx2 = r.x+r.width; if (r.y+r.height > a.bby2) a.bby2 = r.y+r.height; if (r.x < a.minLSB) a.minLSB = r.x; if (advance-r.x-r.width < a.minRSB) a.minRSB = advance-r.x-r.width; if (advance > a.maxAdvance) a.maxAdvance = advance; if (r.x+r.width > a.maxExtent) a.maxExtent = r.x+r.width; } if (advance > 0) { a.averageWidth += advance; a.numAverages++; } if (id instanceof Integer && (Integer)id == 'x') a.xHeight = r.y+r.height; if (id instanceof Integer && (Integer)id == 'H') a.HHeight = r.y+r.height; if (id instanceof Integer && (Integer)id >= 0x10000) a.highUnicode = true; entries.add(createEbdtEntry(g)); hmtxTable.add(new HmtxTableEntry(advance, r.x)); } if (id instanceof Integer) postTable.add(PostTableEntry.forCharacter((Integer)id)); if (id instanceof String) postTable.add(PostTableEntry.forCharacterName(id.toString())); a.numGlyphs++; } private static final EblcBitmapSize createBitmapSize(BitmapFont bf, ThingsToKeepTrackOf a, int xsize) { EblcBitmapSize ebs = new EblcBitmapSize(); ebs.hori = new SbitLineMetrics(); ebs.vert = new SbitLineMetrics(); ebs.hori.ascender = ebs.vert.ascender = bf.getLineAscent(); ebs.hori.descender = ebs.vert.descender = -bf.getLineDescent(); ebs.hori.widthMax = ebs.vert.widthMax = a.maxAdvance / xsize; ebs.ppemX = ebs.ppemY = bf.getEmAscent() + bf.getEmDescent(); ebs.bitDepth = 8; ebs.flags = 1; return ebs; } private static final EbdtEntry createEbdtEntry(BitmapFontGlyph g) { int w = g.getGlyphWidth(); int h = g.getGlyphHeight(); byte[] data = new byte[w * h]; byte[][] rows = g.getGlyph(); for (int y = 0, j = 0; y < rows.length; j += w, y++) { byte[] cols = rows[y]; for (int x = 0, i = j; x < cols.length; i++, x++) { data[i] = cols[x]; } } EbdtEntryFormat1 e = new EbdtEntryFormat1(); e.smallMetrics = new SbitSmallGlyphMetrics(); e.smallMetrics.height = h; e.smallMetrics.width = w; e.smallMetrics.bearingX = g.getGlyphOffset(); e.smallMetrics.bearingY = g.getGlyphAscent(); e.smallMetrics.advance = g.getCharacterWidth(); e.imageData = data; return e; } private static final CmapTable makeCmapTable(BitmapFont bf, ThingsToKeepTrackOf a) { Collection chars = bf.characters(false).keySet(); CmapSubtableFormat4 lowTable = new CmapSubtableFormat4(); CmapSubtableFormat12 highTable = new CmapSubtableFormat12(); CmapSubtableSequentialEntry currentGroup = null; int lastGlyphIndex = 0; for (int ch : chars) { int gidx = a.charToGlyfMap.get(ch); if (currentGroup == null) { currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = ch; currentGroup.endCharCode = ch; currentGroup.glyphIndex = gidx; lastGlyphIndex = gidx; } else if ((ch == currentGroup.endCharCode + 1) && (gidx == lastGlyphIndex + 1)) { currentGroup.endCharCode = ch; lastGlyphIndex = gidx; } else { if (currentGroup.startCharCode < 0x10000) lowTable.add(currentGroup); highTable.add(currentGroup); currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = ch; currentGroup.endCharCode = ch; currentGroup.glyphIndex = gidx; lastGlyphIndex = gidx; } } if (currentGroup != null) { if (currentGroup.startCharCode < 0x10000) lowTable.add(currentGroup); highTable.add(currentGroup); } currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = 0xFFFF; currentGroup.endCharCode = 0xFFFF; currentGroup.glyphIndex = 0; lowTable.add(currentGroup); CmapTable cmapTable = new CmapTable(); cmapTable.subtables.add(lowTable); if (a.highUnicode) cmapTable.subtables.add(highTable); cmapTable.entries.add(CmapTableEntry.forUnicode(a.highUnicode ? highTable : lowTable)); cmapTable.entries.add(CmapTableEntry.forWindowsUnicode16(lowTable)); if (a.highUnicode) cmapTable.entries.add(CmapTableEntry.forWindowsUnicode32(highTable)); return cmapTable; } private static final HeadTable makeHeadTable(BitmapFont bf, ThingsToKeepTrackOf a, int ysize) { Calendar now = new GregorianCalendar(); double fontVersion; try { String s = bf.getName(Font.NAME_VERSION); if (s == null) fontVersion = 1.0; else if (s.startsWith("Version ")) fontVersion = Double.parseDouble(s.substring(8)); else fontVersion = Double.parseDouble(s); } catch (NumberFormatException nfe) { fontVersion = 1.0; } HeadTable headTable = new HeadTable(); headTable.setFontRevisionDouble(fontVersion); headTable.flags = HeadTable.FLAGS_Y_VALUE_OF_ZERO_SPECIFIES_BASELINE | HeadTable.FLAGS_MINIMUM_X_VALUE_IS_LEFT_SIDE_BEARING; headTable.unitsPerEm = (bf.getEmAscent() + bf.getEmDescent()) * ysize; headTable.setDateCreatedCalendar(now); headTable.setDateModifiedCalendar(now); headTable.xMin = a.bbx1; headTable.yMin = a.bby1; headTable.xMax = a.bbx2; headTable.yMax = a.bby2; headTable.macStyle = bf.getMacStyle(); headTable.lowestRecPPEM = bf.getEmAscent() + bf.getEmDescent(); headTable.fontDirectionHint = HeadTable.FONT_DIRECTION_HINT_MIXED; headTable.indexToLocFormat = HeadTable.INDEX_TO_LOC_FORMAT_LONG; return headTable; } private static final HheaTable makeHheaTable(BitmapFont bf, ThingsToKeepTrackOf a, int ysize) { HheaTable hheaTable = new HheaTable(); hheaTable.ascent = bf.getLineAscent() * ysize; hheaTable.descent = -bf.getLineDescent() * ysize; hheaTable.lineGap = bf.getLineGap() * ysize; hheaTable.advanceWidthMax = a.maxAdvance; hheaTable.minLeftSideBearing = a.minLSB; hheaTable.minRightSideBearing = a.minRSB; hheaTable.xMaxExtent = a.maxExtent; if (bf.isItalicStyle()) { hheaTable.caretSlopeRise = 2; hheaTable.caretSlopeRun = 1; } hheaTable.numLongHorMetrics = a.numGlyphs; return hheaTable; } private static final MaxpTable makeMaxpTable(ThingsToKeepTrackOf a) { MaxpTable maxpTable = new MaxpTable(); maxpTable.numGlyphs = a.numGlyphs; return maxpTable; } private static final Os2Table makeOs2Table(BitmapFont bf, ThingsToKeepTrackOf a, int xsize, int ysize, boolean extendWinMetrics) { Collection chars = bf.characters(false).keySet(); Os2Table os2Table = new Os2Table(); if (a.numAverages > 0) os2Table.averageCharWidth = a.averageWidth / a.numAverages; os2Table.weightClass = bf.isBoldStyle() ? Os2Table.WEIGHT_CLASS_BOLD : Os2Table.WEIGHT_CLASS_MEDIUM; os2Table.widthClass = bf.isCondensedStyle() ? Os2Table.WIDTH_CLASS_CONDENSED : bf.isExtendedStyle() ? Os2Table.WIDTH_CLASS_EXPANDED : Os2Table.WIDTH_CLASS_MEDIUM; os2Table.subscriptXSize = (bf.getEmAscent() + bf.getEmDescent()) * xsize; os2Table.subscriptYSize = (bf.getEmAscent() + bf.getEmDescent()) * ysize; os2Table.subscriptXOffset = 0; os2Table.subscriptYOffset = (bf.getEmAscent() + bf.getEmDescent()) * ysize / 2; os2Table.superscriptXSize = (bf.getEmAscent() + bf.getEmDescent()) * xsize; os2Table.superscriptYSize = (bf.getEmAscent() + bf.getEmDescent()) * ysize; os2Table.superscriptXOffset = 0; os2Table.superscriptYOffset = (bf.getEmAscent() + bf.getEmDescent()) * ysize / 2; os2Table.strikeoutWidth = ysize; os2Table.strikeoutPosition = bf.getEmAscent() * ysize / 2; os2Table.panoseFamilyType = Os2Table.PANOSE_FAMILY_TYPE_TEXT_AND_DISPLAY; if (bf.isMonospaced()) os2Table.panoseProportion = Os2Table.PANOSE_PROPORTION_MONOSPACED; os2Table.setUnicodeRanges(chars); os2Table.setVendorIDString("KBnP"); os2Table.fsSelection = bf.getFsSelection() | Os2Table.FS_SELECTION_USE_TYPO_METRICS; os2Table.setCharIndices(chars); os2Table.typoAscent = bf.getLineAscent() * ysize; os2Table.typoDescent = -bf.getLineDescent() * ysize; os2Table.typoLineGap = bf.getLineGap() * ysize; os2Table.winAscent = bf.getLineAscent() * ysize; os2Table.winDescent = bf.getLineDescent() * ysize; if (extendWinMetrics) { os2Table.winAscent = Math.max(a.bby2, os2Table.winAscent); os2Table.winDescent = Math.max(-a.bby1, os2Table.winDescent); } os2Table.setCodePages(chars); os2Table.xHeight = a.xHeight; os2Table.capHeight = a.HHeight; return os2Table; } private static final NameTable makeNameTable(BitmapFont bf) { NameTable nameTable = new NameTable(); for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forUnicode(e.getKey(), e.getValue())); } for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forMacintosh(e.getKey(), e.getValue())); } for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forWindows(e.getKey(), e.getValue())); } return nameTable; } } PSFBitmapFontExporter.java000066400000000000000000000146111506470510200342420ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.TreeSet; import java.util.zip.GZIPOutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class PSFBitmapFontExporter implements BitmapFontExporter { private int version; private GlyphList lowEncoding; private GlyphList highEncoding; private boolean useLowEncoding; private boolean useHighEncoding; private boolean useAllGlyphs; private boolean unicodeTable; private boolean gzip; public PSFBitmapFontExporter() { this.version = 2; this.lowEncoding = null; this.highEncoding = null; this.useLowEncoding = true; this.useHighEncoding = false; this.useAllGlyphs = true; this.unicodeTable = true; this.gzip = false; } public PSFBitmapFontExporter(boolean gzip) { this.version = 2; this.lowEncoding = null; this.highEncoding = null; this.useLowEncoding = true; this.useHighEncoding = false; this.useAllGlyphs = true; this.unicodeTable = true; this.gzip = gzip; } public PSFBitmapFontExporter( int version, GlyphList lowEncoding, GlyphList highEncoding, boolean useLowEncoding, boolean useHighEncoding, boolean useAllGlyphs, boolean unicodeTable ) { this.version = version; this.lowEncoding = lowEncoding; this.highEncoding = highEncoding; this.useLowEncoding = useLowEncoding; this.useHighEncoding = useHighEncoding; this.useAllGlyphs = useAllGlyphs; this.unicodeTable = unicodeTable; this.gzip = false; } public PSFBitmapFontExporter( int version, GlyphList lowEncoding, GlyphList highEncoding, boolean useLowEncoding, boolean useHighEncoding, boolean useAllGlyphs, boolean unicodeTable, boolean gzip ) { this.version = version; this.lowEncoding = lowEncoding; this.highEncoding = highEncoding; this.useLowEncoding = useLowEncoding; this.useHighEncoding = useHighEncoding; this.useAllGlyphs = useAllGlyphs; this.unicodeTable = unicodeTable; this.gzip = gzip; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontToStream(font, out); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { if (gzip) { GZIPOutputStream gz = new GZIPOutputStream(os); exportFontImpl(font, new DataOutputStream(gz)); gz.finish(); } else { exportFontImpl(font, new DataOutputStream(os)); } } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontToStream(font, out); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { ArrayList codePoints = new ArrayList(); if (useLowEncoding || version < 2) { for (int i = 0; i < 256; i++) { codePoints.add((lowEncoding != null) ? lowEncoding.get(i & 0xFF) : i); } } if (useHighEncoding) { for (int i = 256; i < 512; i++) { codePoints.add((highEncoding != null) ? highEncoding.get(i & 0xFF) : i); } } if (useAllGlyphs && version >= 2) { TreeSet remainder = new TreeSet(); remainder.addAll(font.characters(false).keySet()); remainder.removeAll(codePoints); codePoints.addAll(remainder); } int a = font.getLineAscent(); int h = a + font.getLineDescent() + font.getLineGap(); int w = (version < 2) ? 8 : getMaxWidth(font, codePoints); boolean mode512 = (codePoints.size() > 256); // Header if (version < 2) { out.writeShort(0x3604); out.writeByte((mode512 ? 1 : 0) | (unicodeTable ? 2 : 0)); out.writeByte(h); } else { out.writeInt(0x72B54A86); out.writeInt(0); out.writeInt(Integer.reverseBytes(32)); out.writeInt(Integer.reverseBytes(unicodeTable ? 1 : 0)); out.writeInt(Integer.reverseBytes(codePoints.size())); out.writeInt(Integer.reverseBytes(h * ((w + 7) / 8))); out.writeInt(Integer.reverseBytes(h)); out.writeInt(Integer.reverseBytes(w)); } // Bitmap Data for (int cp : codePoints) { writeGlyph(out, w, h, a, font.getCharacter(cp)); } // Unicode Table if (unicodeTable) { for (int cp : codePoints) { if (cp >= 0) { String[] entries = {String.valueOf(Character.toChars(cp))}; writeUnicodeEntry(out, version, entries); } else { writeUnicodeEntry(out, version, null); } } } } private int getMaxWidth(BitmapFont font, ArrayList codePoints) { int maxWidth = 0; for (int cp : codePoints) { BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { int w = g.getCharacterWidth(); if (w > maxWidth) maxWidth = w; } } return maxWidth; } private void writeGlyph(DataOutputStream out, int w, int h, int a, BitmapFontGlyph g) throws IOException { if (g == null) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } else { byte[][] data = g.getGlyph(); for (int j = g.getGlyphAscent() - a, y = 0; y < h; y++, j++) { if (j >= 0 && j < data.length) { int i = -g.getGlyphOffset(), x = 0; while (x < w) { int b = 0; for (int m = 0x80; m != 0 && x < w; m >>= 1, x++, i++) { if (i >= 0 && i < data[j].length) { if (data[j][i] < 0) b |= m; } } out.writeByte(b); } } else { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } } } private void writeUnicodeEntry(DataOutputStream out, int version, String[] entries) throws IOException { if (entries != null) { for (String s : entries) { if (s.length() == 1) { if (version < 2) { out.write(s.getBytes("UTF-16LE")); } else { out.write(s.getBytes("UTF-8")); } } } for (String s : entries) { if (s.length() > 1) { if (version < 2) { out.writeChar(Character.reverseBytes('\uFFFE')); out.write(s.getBytes("UTF-16LE")); } else { out.writeByte(0xFE); out.write(s.getBytes("UTF-8")); } } } } if (version < 2) { out.writeChar(0xFFFF); } else { out.writeByte(0xFF); } } } PlaydateBitmapFontExporter.java000066400000000000000000000170461506470510200353620ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import com.kreative.bitsnpicas.Base64OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.GlyphPair; public class PlaydateBitmapFontExporter implements BitmapFontExporter { private static final int MIN_CODE_POINT = 0x20; private static final int MAX_CODE_POINT = 0x3FFFF; private static final Pattern FNT_FILE_PATTERN = Pattern.compile("^(.+)\\.fnt$", Pattern.CASE_INSENSITIVE); private static final Pattern PNG_FILE_PATTERN = Pattern.compile("^(.+)-table-(\\d+)-(\\d+)\\.png$", Pattern.CASE_INSENSITIVE); private static File fntFile(File parent, String basename) { return new File(parent, basename + ".fnt"); } private static File pngFile(File parent, String basename, int cw, int ch) { return new File(parent, basename + "-table-" + cw + "-" + ch + ".png"); } private boolean separate; public PlaydateBitmapFontExporter(boolean separate) { this.separate = separate; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw, null, getMetrics(font)); pw.close(); out.close(); return out.toByteArray(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"), true); exportFont(font, pw, null, getMetrics(font)); } public void exportFontToFile(BitmapFont font, File file) throws IOException { int[] metrics = getMetrics(font); if (separate) { Matcher pm = PNG_FILE_PATTERN.matcher(file.getName()); if (pm.matches()) { File fnt = fntFile(file.getParentFile(), pm.group(1)); File png = pngFile(file.getParentFile(), pm.group(1), metrics[1], metrics[0]); exportFont(font, fnt, png, metrics); return; } Matcher fm = FNT_FILE_PATTERN.matcher(file.getName()); if (fm.matches()) { File fnt = file; File png = pngFile(file.getParentFile(), fm.group(1), metrics[1], metrics[0]); exportFont(font, fnt, png, metrics); return; } File fnt = fntFile(file.getParentFile(), file.getName()); File png = pngFile(file.getParentFile(), file.getName(), metrics[1], metrics[0]); exportFont(font, fnt, png, metrics); return; } exportFont(font, file, null, metrics); } private void exportFont(BitmapFont font, File fnt, File png, int[] metrics) throws IOException { FileOutputStream out = new FileOutputStream(fnt); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true); exportFont(font, pw, png, metrics); pw.close(); out.close(); } private void exportFont(BitmapFont font, PrintWriter out, File png, int[] metrics) throws IOException { int count = metrics[3]; int tracking = metrics[2]; int cw = metrics[1]; int ch = metrics[0]; if (cw < 1 || ch < 1) throw new IOException("invalid cell size: " + cw + ", " + ch); int cols = (count < 16) ? count : 16; int rows = (count + cols - 1) / cols; if (cols < 1 || rows < 1) throw new IOException("invalid cell count: " + cols + ", " + rows); Map charWidths = new TreeMap(); // Create the sprite sheet. BufferedImage img = new BufferedImage(cols * cw, rows * ch, BufferedImage.TYPE_INT_ARGB); int[] tmpRgb = new int[cw * ch]; for (int row = 0, col = 0, cp = MIN_CODE_POINT; cp <= MAX_CODE_POINT; cp++) { BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { BufferedImage tmpImg = new BufferedImage(cw, ch, BufferedImage.TYPE_INT_ARGB); Graphics2D gg = tmpImg.createGraphics(); gg.setColor(Color.black); g.paint(gg, 0, font.getLineAscent(), 1); gg.dispose(); tmpImg.getRGB(0, 0, cw, ch, tmpRgb, 0, cw); img.setRGB(col * cw, row * ch, cw, ch, tmpRgb, 0, cw); charWidths.put(cp, g.getCharacterWidth() - tracking); col++; if (col >= cols) { col = 0; row++; if (row >= rows) { row = 0; } } } } // Create the fnt file. String name = font.getName(BitmapFont.NAME_FAMILY_AND_STYLE); if (name == null) name = font.getName(BitmapFont.NAME_FAMILY); if (name != null) out.println("--name=" + name); int baseline = font.getLineAscent() - ch; int xHeight = font.getXHeight(); int capHeight = font.getCapHeight(); out.println("--metrics={\"baseline\":"+baseline+",\"xHeight\":"+xHeight+",\"capHeight\":"+capHeight+"}"); if (png != null) { ImageIO.write(img, "png", png); } else { StringBuffer sb = new StringBuffer(); Base64OutputStream bo = new Base64OutputStream(sb); ImageIO.write(img, "png", bo); bo.close(); out.println("datalen=" + sb.length()); out.println("data=" + sb.toString()); out.println("width=" + cw); out.println("height=" + ch); } out.println("tracking=" + tracking); for (Map.Entry e : charWidths.entrySet()) { out.println(joinCodePoints(e.getKey()) + "\t" + e.getValue()); } for (Map.Entry e : font.kernPairs(false).entrySet()) { Object l = e.getKey().getLeft(); Object r = e.getKey().getRight(); if (l instanceof Integer && r instanceof Integer) { int lcp = (Integer)l; int rcp = (Integer)r; if ( lcp >= MIN_CODE_POINT && lcp <= MAX_CODE_POINT && rcp >= MIN_CODE_POINT && rcp <= MAX_CODE_POINT ) { out.println(joinCodePoints(lcp, rcp) + "\t" + e.getValue()); } } } } private static int[] getMetrics(BitmapFont font) { int ch = font.getLineAscent() + font.getLineDescent() + font.getLineGap(); int cw = 0; Integer tracking = null; int count = 0; for (int cp = MIN_CODE_POINT; cp <= MAX_CODE_POINT; cp++) { BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { int gw = g.getGlyphOffset() + g.getGlyphWidth(); if (cw < gw) cw = gw; int gt = g.getCharacterWidth() - gw; if (tracking == null || tracking > gt) tracking = gt; count++; } } if (tracking == null) tracking = 1; return new int[]{ch, cw+1, tracking, count}; } private static String joinCodePoints(int... cps) { if (cps == null) return null; if (cps.length == 0) return ""; if (cps.length == 1 && cps[0] == 0x20) return "space"; StringBuffer sb = new StringBuffer(); boolean lastWasU = false; for (int cp : cps) { if (lastWasU && Character.digit(cp, 16) >= 0) { sb.append("U+"); sb.append(Integer.toHexString(cp).toUpperCase()); continue; } switch (Character.getType(cp)) { case Character.UNASSIGNED: case Character.NON_SPACING_MARK: case Character.ENCLOSING_MARK: case Character.COMBINING_SPACING_MARK: case Character.SPACE_SEPARATOR: case Character.LINE_SEPARATOR: case Character.PARAGRAPH_SEPARATOR: case Character.CONTROL: case Character.FORMAT: case Character.PRIVATE_USE: case Character.SURROGATE: sb.append("U+"); sb.append(Integer.toHexString(cp).toUpperCase()); lastWasU = true; break; default: sb.append(Character.toChars(cp)); lastWasU = false; break; } } return sb.toString(); } } RFontBitmapFontExporter.java000077500000000000000000000275111506470510200346500ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; public class RFontBitmapFontExporter implements BitmapFontExporter { private int color; public RFontBitmapFontExporter() { this.color = 0; } public RFontBitmapFontExporter(int color) { this.color = color; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream b = new ByteArrayOutputStream(); exportFontToStream(font, b); b.close(); return b.toByteArray(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { RFontBean r = exportFontToImage(font); //ImageIO.write(r.img, "png", os); ImageWriter writer = ImageIO.getImageWritersBySuffix("png").next(); writer.setOutput(ImageIO.createImageOutputStream(os)); IIOMetadata metadata = createMetadata(writer, r); writer.write(new IIOImage(r.img, null, metadata)); } public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontToStream(font, out); out.close(); } public class RFontBean { public String fname; public String sname; public String copy; public RenderedImage img; public byte[] vmtx; public byte[] hmtx; } public RFontBean exportFontToImage(BitmapFont font) { // calculate font metrics BitmapFontGlyph[][] g = new BitmapFontGlyph[4352][]; int[][] l = new int[4352][]; int[][] w = new int[4352][]; int[][] r = new int[4352][]; int maxascent = font.getLineAscent(); int maxdescent = font.getLineDescent(); int linegap = font.getLineGap(); int[] bw = new int[4352]; for (int b = 0; b < 4352; b++) { for (int c = 0; c < 256; c++) { if (font.containsCharacter((b << 8) | c)) { if (g[b] == null) g[b] = new BitmapFontGlyph[256]; g[b][c] = font.getCharacter((b << 8) | c); if (l[b] == null) l[b] = new int[256]; l[b][c] = g[b][c].getGlyphOffset(); l[b][c] = (l[b][c] < 0) ? (-l[b][c]) : 0; if (w[b] == null) w[b] = new int[256]; w[b][c] = g[b][c].getCharacterWidth(); if (r[b] == null) r[b] = new int[256]; r[b][c] = g[b][c].getGlyphOffset() + g[b][c].getGlyphWidth(); r[b][c] = (r[b][c] > w[b][c]) ? (r[b][c] - w[b][c]) : 0; if (g[b][c].getGlyphAscent() > maxascent) maxascent = g[b][c].getGlyphAscent(); if (g[b][c].getGlyphDescent() > maxdescent) maxdescent = g[b][c].getGlyphDescent(); bw[b] += 1 + l[b][c] + w[b][c] + r[b][c]; } } } int bh = 1+maxascent+maxdescent+linegap; // calculate image metrics int width = 0; int height = 0; for (int b = 0; b < 4352; b++) { if (bw[b] > width) width = bw[b]; if (bw[b] > 0) height += bh; } width += 2; // CONSTRUCT IMAGE BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); int y = 0; // for each row for (int b = 0; b < 4352; b++) { if (bw[b] > 0) { int x = 0; // control column - vertical metrics setVM(bi, x++, y, font, maxascent, maxdescent); // for each character for (int c = 0; c < 256; c++) { if (g[b][c] != null) { // control column - code point setCC(bi, x, y, bh, (b << 8) | c); // horizontal metrics - left overflow in red for (int lx = 0; lx < l[b][c]; lx++) { bi.setRGB(x+1+lx, y, 0xFFFF0000); } // horizontal metrics - right overflow in blue for (int rx = 0; rx < r[b][c]; rx++) { bi.setRGB(x+1+l[b][c]+w[b][c]+rx, y, 0xFF0000FF); } // glyph byte[][] gg = g[b][c].getGlyph(); for (int gy = 0, iy = y+1+maxascent-g[b][c].getGlyphAscent(); gy < gg.length && iy < height; gy++, iy++) { for (int gx = 0, ix = x+1+l[b][c]+g[b][c].getGlyphOffset(); gx < gg[gy].length && ix < width; gx++, ix++) { bi.setRGB(ix, iy, ((gg[gy][gx] & 0xFF) << 24) | (color & 0xFFFFFF)); } } // next character x += 1 + l[b][c] + w[b][c] + r[b][c]; } } // control column - end marker setCC(bi, x, y, bh, -1); // next row y += bh; } } // vertical metrics table ByteArrayOutputStream vmb = new ByteArrayOutputStream(); DataOutputStream vmd = new DataOutputStream(vmb); try { if (bh < 256) { vmd.writeShort(1); vmd.writeByte(maxascent); vmd.writeByte(font.getLineAscent()); vmd.writeByte(font.getEmAscent()); vmd.writeByte(font.getXHeight()); vmd.writeByte(font.getEmDescent()); vmd.writeByte(font.getLineDescent()); vmd.writeByte(maxdescent); vmd.writeByte(linegap); vmd.writeByte(maxascent-1); // y offset vmd.writeByte(bh-1); // line advance, bitmap height } else { vmd.writeShort(2); vmd.writeShort(maxascent); vmd.writeShort(font.getLineAscent()); vmd.writeShort(font.getEmAscent()); vmd.writeShort(font.getXHeight()); vmd.writeShort(font.getEmDescent()); vmd.writeShort(font.getLineDescent()); vmd.writeShort(maxdescent); vmd.writeShort(linegap); vmd.writeShort(maxascent-1); // y offset vmd.writeShort(bh-1); // line advance, bitmap height } vmd.close(); vmb.close(); } catch (IOException ignored) { // nothing } // horizontal metrics table ByteArrayOutputStream hmb = new ByteArrayOutputStream(); DataOutputStream hmd = new DataOutputStream(hmb); try { int maxM3 = 0; int lastch = 0; List start = new ArrayList(); List> mtx = new ArrayList>(); y = 0; for (int b = 0; b < 4352; b++) { if (bw[b] > 0) { int x = 1; for (int c = 0; c < 256; c++) { if (g[b][c] != null) { int ch = (b << 8) | c; int[] m = new int[]{ l[b][c], // x offset w[b][c], // character advance r[b][c], l[b][c] + w[b][c] + r[b][c], // bitmap width x+1, y+1 }; if (start.isEmpty() || ch != (lastch+1)) { start.add(ch); List nmtx = new ArrayList(); nmtx.add(m); mtx.add(nmtx); } else { mtx.get(mtx.size()-1).add(m); } if (m[3] > maxM3) maxM3 = m[3]; lastch = ch; x += 1 + l[b][c] + w[b][c] + r[b][c]; } } y += bh; } } if (maxM3 < 256 && width < 65536 && height < 65536) { hmd.writeShort(1); } else { hmd.writeShort(2); } hmd.writeInt(start.size()); for (int i = 0; i < start.size(); i++) { hmd.writeInt(start.get(i)); hmd.writeInt(mtx.get(i).size()); for (int[] m : mtx.get(i)) { if (maxM3 < 256 && width < 65536 && height < 65536) { hmd.writeByte(m[0]); hmd.writeByte(m[1]); hmd.writeByte(m[2]); hmd.writeByte(m[3]); hmd.writeShort(m[4]); hmd.writeShort(m[5]); } else { hmd.writeShort(m[0]); hmd.writeShort(m[1]); hmd.writeShort(m[2]); hmd.writeShort(m[3]); hmd.writeInt(m[4]); hmd.writeInt(m[5]); } } } hmd.close(); hmb.close(); } catch (IOException ignored) { // nothing } RFontBean rb = new RFontBean(); rb.fname = font.getName(Font.NAME_FAMILY); rb.sname = font.getName(Font.NAME_STYLE); rb.copy = font.getName(Font.NAME_COPYRIGHT); rb.img = bi; rb.vmtx = vmb.toByteArray(); rb.hmtx = hmb.toByteArray(); return rb; } // set Character Codepoint control column private static void setCC(BufferedImage bi, int x, int y, int bh, int ch) { int ccy = y; // control column header, in magenta bi.setRGB(x, ccy++, 0xFFFF00FF); // code point in 0xFFabcdef, 0xFFaabbcc, 0xFFddeeff, 0xFFaaabbb, 0xFFcccddd, 0xFFeeefff, ... for (int cpy = 0; cpy < bh-1; cpy++) { bi.setRGB(x, ccy++, codepixel(ch, cpy)); } } // get pixel color for code point private static int codepixel(int ch, int x) { // n(x) = 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ... int n = (int)Math.floor((1+Math.sqrt(1+8*x))/2); // i(x) = 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, ... int i = (x-((n*(n-1))/2)); // p is our pixel int p = 0xFF000000; // for each nybble 0..5 in the pixel for (int j = 0, m = 20; j < 6 && m >= 0; j++, m -= 4) { // w = which nybble a..f in the code point to use for this nybble 0..5 in the pixel int w = 5 - ((i*6 + j) / n); // copy this nybble a..f in the code point to this nybble 0..5 in the pixel p |= ((ch >> (w << 2)) & 0xF) << m; } return p; } // set Vertical Metrics control column private static void setVM(BufferedImage bi, int x, int y, BitmapFont font, int maxascent, int maxdescent) { int vmy = y; // control column header, in magenta bi.setRGB(x, vmy++, 0xFFFF00FF); // maxAscent to lineAscent, in red for (int may = maxascent; may > font.getLineAscent(); may--) { bi.setRGB(x, vmy++, 0xFFFF0000); } // lineAscent to emAscent, in orange for (int lay = font.getLineAscent(); lay > font.getEmAscent(); lay--) { bi.setRGB(x, vmy++, 0xFFFF8000); } // emAscent to xHeight, in yellow for (int eay = font.getEmAscent(); eay > font.getXHeight(); eay--) { bi.setRGB(x, vmy++, 0xFFFFFF00); } // xHeight to baseline, no color for (int xhy = font.getXHeight(); xhy > 0; xhy--) { bi.setRGB(x, vmy++, 0); } // baseline to emDescent, in green for (int edy = font.getEmDescent(); edy > 0; edy--) { bi.setRGB(x, vmy++, 0xFF00FF00); } // emDescent to lineDescent, in cyan for (int ldy = font.getLineDescent(); ldy > font.getEmDescent(); ldy--) { bi.setRGB(x, vmy++, 0xFF00FFFF); } // lineDescent to maxDescent, in blue for (int mdy = maxdescent; mdy > font.getLineDescent(); mdy--) { bi.setRGB(x, vmy++, 0xFF0000FF); } // line gap, in purple for (int lgy = font.getLineGap(); lgy > 0; lgy--) { bi.setRGB(x, vmy++, 0xFF8000FF); } } private static IIOMetadata createMetadata(ImageWriter w, RFontBean r) { ImageTypeSpecifier type = new ImageTypeSpecifier(r.img); ImageWriteParam param = w.getDefaultWriteParam(); IIOMetadata metadata = w.getDefaultImageMetadata(type, param); String format = metadata.getNativeMetadataFormatName(); Node root = metadata.getAsTree(format); if (r.fname != null || r.sname != null || r.copy != null) { IIOMetadataNode tEXt = new IIOMetadataNode("tEXt"); if (r.fname != null) { IIOMetadataNode n = new IIOMetadataNode("tEXtEntry"); n.setAttribute("keyword", "FontFamily"); n.setAttribute("value", r.fname); tEXt.appendChild(n); } if (r.sname != null) { IIOMetadataNode n = new IIOMetadataNode("tEXtEntry"); n.setAttribute("keyword", "FontStyle"); n.setAttribute("value", r.sname); tEXt.appendChild(n); } if (r.copy != null) { IIOMetadataNode n = new IIOMetadataNode("tEXtEntry"); n.setAttribute("keyword", "Copyright"); n.setAttribute("value", r.copy); tEXt.appendChild(n); } root.appendChild(tEXt); } IIOMetadataNode chunks = new IIOMetadataNode("UnknownChunks"); IIOMetadataNode rfVM = new IIOMetadataNode("UnknownChunk"); rfVM.setAttribute("type", "rfVM"); rfVM.setUserObject(r.vmtx); chunks.appendChild(rfVM); IIOMetadataNode rfHM = new IIOMetadataNode("UnknownChunk"); rfHM.setAttribute("type", "rfHM"); rfHM.setUserObject(r.hmtx); chunks.appendChild(rfHM); root.appendChild(chunks); try { metadata.mergeTree(format, root); } catch (IIOInvalidTreeException e) { e.printStackTrace(); } return metadata; } } RockboxBitmapFontExporter.java000066400000000000000000000155301506470510200352220ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class RockboxBitmapFontExporter implements BitmapFontExporter { public static final int RB11 = 0x52423131; public static final int RB12 = 0x52423132; private int magic; private int depth; public RockboxBitmapFontExporter(int magic) { if (magic != RB11 && magic != RB12) throw new IllegalArgumentException("bad magic number"); this.magic = magic; this.depth = 0; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFontImpl(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFontImpl(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFontImpl(font, new DataOutputStream(out)); out.close(); } private void exportFontImpl(BitmapFont font, DataOutputStream out) throws IOException { int ascent = font.getLineAscent(); int height = ascent + font.getLineDescent() + font.getLineGap(); int maxWidth = 0; int firstChar = -1; int numChars = 0; int numBits = 0; HashMap bitmaps = new HashMap(); HashMap offsets = new HashMap(); HashMap widths = new HashMap(); for (int ch = 0; ch < 0x110000; ch++) { BitmapFontGlyph g = font.getCharacter(ch); if (g == null) continue; int width = g.getCharacterWidth(); if (width > maxWidth) maxWidth = width; if (firstChar < 0) firstChar = ch; numChars = ch - firstChar + 1; int rowBytes = ((width + 15) / 16) * 2; byte[] glyphBitmap = new byte[rowBytes * height]; byte[][] glyphPixels = g.getGlyph(); for (int by = 0, j = g.getGlyphAscent() - ascent, y = 0; y < height; y++, j++, by += rowBytes) { if (j >= 0 && j < glyphPixels.length) { int bx = 0, i = -g.getGlyphOffset(), x = 0; while (x < width) { byte b = 0; for (int m = 0x80; m != 0 && x < width; m >>= 1, x++, i++) { if (i >= 0 && i < glyphPixels[j].length) { if (glyphPixels[j][i] < 0) b |= m; } } glyphBitmap[by + bx] = b; bx++; } } } if (magic == RB11) { glyphBitmap = swab(glyphBitmap, 0, width, height); } else { glyphBitmap = rotleft(glyphBitmap, 0, width, height); } widths.put(ch, width); offsets.put(ch, numBits); bitmaps.put(ch, glyphBitmap); numBits += glyphBitmap.length; } // Write magic number, name, and copyright string. out.writeInt(magic); if (magic == RB11) { String name = font.getName(BitmapFont.NAME_FAMILY); byte[] nameBytes = (name != null) ? name.getBytes("UTF-8") : new byte[0]; out.write(nameBytes, 0, Math.min(nameBytes.length, 64)); for (int i = nameBytes.length; i < 64; i++) out.write(0x20); String copyright = font.getName(BitmapFont.NAME_COPYRIGHT); byte[] copyrightBytes = (copyright != null) ? copyright.getBytes("UTF-8") : new byte[0]; out.write(copyrightBytes, 0, Math.min(copyrightBytes.length, 256)); for (int i = copyrightBytes.length; i < 256; i++) out.write(0x20); } // Write metrics. boolean pro = !isMono(firstChar, numChars, bitmaps); out.writeShort(Short.reverseBytes((short)maxWidth)); out.writeShort(Short.reverseBytes((short)height)); out.writeShort(Short.reverseBytes((short)ascent)); out.writeShort(Short.reverseBytes((short)depth)); out.writeInt(Integer.reverseBytes(firstChar)); out.writeInt(Integer.reverseBytes(firstChar)); out.writeInt(Integer.reverseBytes(numChars)); out.writeInt(Integer.reverseBytes((magic == RB11) ? (numBits / 2) : numBits)); out.writeInt(Integer.reverseBytes(pro ? numChars : 0)); out.writeInt(Integer.reverseBytes(pro ? numChars : 0)); // Write bitmaps. for (int i = 0; i < numChars; i++) { if (bitmaps.containsKey(firstChar + i)) { out.write(bitmaps.get(firstChar + i)); } } if (magic == RB11) { while ((numBits & 3) != 0) { out.writeByte(0); numBits++; } } else { while ((numBits & 1) != 0) { out.writeByte(0); numBits++; } } if (pro) { // Write offsets. for (int i = 0; i < numChars; i++) { if (offsets.containsKey(firstChar + i)) { if (magic == RB11) { out.writeInt(Integer.reverseBytes(offsets.get(firstChar + i).intValue() / 2)); } else { out.writeShort(Short.reverseBytes(offsets.get(firstChar + i).shortValue())); } } else { if (magic == RB11) { out.writeInt(0); } else { out.writeShort(0); } } } // Write widths. for (int i = 0; i < numChars; i++) { if (widths.containsKey(firstChar + i)) { out.writeByte(widths.get(firstChar + i)); } else { out.writeByte(widths.get(firstChar)); } } } } private static boolean isMono(int firstChar, int numChars, HashMap bitmaps) { byte[] bitmap = bitmaps.get(firstChar); if (bitmap == null) return true; int length = bitmap.length; for (int i = 1; i < numChars; i++) { bitmap = bitmaps.get(firstChar + i); if (bitmap == null) return false; if (bitmap.length != length) return false; } return true; } private static byte[] swab(byte[] bmpBytes, int bmpOffset, int width, int height) { int rowByteCount = ((width + 15) / 16) * 2; int bmpByteCount = rowByteCount * height; byte[] fntData = new byte[bmpByteCount]; for (int i = 0; i < bmpByteCount; i++) { fntData[i ^ 1] = bmpBytes[bmpOffset++]; } return fntData; } private static byte[] rotleft(byte[] bmpBytes, int bmpOffset, int width, int height) { int rowWordCount = (width + 15) / 16; int bmpWordCount = rowWordCount * height; int[] bmpWords = new int[bmpWordCount]; for (int wi = 0; wi < bmpWordCount; wi++) { bmpWords[wi] = (bmpBytes[bmpOffset++] & 0xFF) << 8; bmpWords[wi] |= (bmpBytes[bmpOffset++] & 0xFF) << 0; } byte[] fntData = new byte[((height + 7) / 8) * width]; int fntOffset = 0; int fntMask = 1; for (int i = 0; i < height; i++) { bmpOffset = i * rowWordCount; int bmpMask = 0x8000; for (int j = 0; j < width; j++) { if ((bmpWords[bmpOffset] & bmpMask) != 0) { fntData[fntOffset + j] |= fntMask; } bmpMask >>= 1; if (bmpMask == 0) { bmpMask = 0x8000; bmpOffset++; } } fntMask <<= 1; if (fntMask >= 256) { fntMask = 1; fntOffset += width; } } return fntData; } } SBFBitmapFontExporter.java000077500000000000000000000102051506470510200342220ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.unicode.data.GlyphList; public class SBFBitmapFontExporter implements BitmapFontExporter { private GlyphList encoding; public SBFBitmapFontExporter() { this.encoding = null; } public SBFBitmapFontExporter(GlyphList encoding) { this.encoding = encoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFont(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFont(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFont(font, new DataOutputStream(out)); out.close(); } private void exportFont(BitmapFont font, DataOutputStream out) throws IOException { int[] offset = new int[256]; int currentOffset = 2048; boolean first = true; int width = 0; int height = font.getLineAscent() + font.getLineDescent() + font.getLineGap(); for (int ch = 0; ch < 256; ch++) { offset[ch] = currentOffset; int cp = (encoding != null) ? encoding.get(ch) : fromSuperLatin(ch); BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { currentOffset += bitsToBytes(g.getGlyphWidth()) * g.getGlyphHeight(); if (first) { first = false; width = g.getCharacterWidth(); } else { if (width != 0) { if (width != g.getCharacterWidth()) { width = 0; } } } } } out.writeInt(0x10B17E5C); out.writeByte(width); out.writeByte(height); out.writeByte(font.getLineAscent()); out.writeByte(font.getLineDescent()); for (int ch = 1; ch < 256; ch++) { int cp = (encoding != null) ? encoding.get(ch) : fromSuperLatin(ch); BitmapFontGlyph g = font.getCharacter(cp); if (g == null) { out.writeLong(0); } else { int byteWidth = bitsToBytes(g.getGlyphWidth()); int overhang = (byteWidth << 3) - g.getGlyphWidth(); out.writeShort(Short.reverseBytes((short)offset[ch])); out.writeByte(byteWidth); out.writeByte(g.getGlyphHeight()); out.writeByte(g.getGlyphOffset()); out.writeByte(g.getGlyphAscent()); out.writeByte(g.getCharacterWidth()); out.writeByte(overhang); } } for (int ch = 0; ch < 256; ch++) { int cp = (encoding != null) ? encoding.get(ch) : fromSuperLatin(ch); BitmapFontGlyph g = font.getCharacter(cp); if (g != null) { for (byte[] row : g.getGlyph()) { byte[] newrow = new byte[bitsToBytes(row.length)]; int i = 0; int m = 0x80; for (byte col : row) { if (col < 0) { newrow[i] |= m; } m >>= 1; if (m == 0) { i++; m = 0x80; } } out.write(newrow); } } } } private static final int[] C0 = { 0x0000, 0x02CB, 0x02DD, 0x02D9, 0x02DA, 0x02C7, 0x02D8, 0x02DB, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0xFB01, 0xFB02, 0xF8FF, 0x2044, 0x221A, 0x2211, 0x220F, 0x222B, 0x2206, 0x03A9, 0x03C0, 0x2202, 0x221E, 0x001B, 0x2264, 0x2260, 0x2265, 0x2248, }; private static final int[] C1 = { 0x20AC, 0x25CA, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0141, 0x017D, 0x0131, 0x2318, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0142, 0x017E, 0x0178, }; private static int fromSuperLatin(int ch) { ch &= 0xFF; if (ch < 0x20) { return C0[ch]; } else if (ch < 0x80) { return ch; } else if (ch < 0xA0) { return C1[ch & 0x1F]; } else { return ch; } } private static int bitsToBytes(int bits) { int bytes = bits >> 3; if ((bits & 7) != 0) bytes++; return bytes; } } SFontBitmapFontExporter.java000077500000000000000000000051761506470510200346540ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class SFontBitmapFontExporter implements BitmapFontExporter { private int color; public SFontBitmapFontExporter() { this.color = 0; } public SFontBitmapFontExporter(int color) { this.color = color; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream b = new ByteArrayOutputStream(); RenderedImage r = exportFontToImage(font); ImageIO.write(r, "png", b); return b.toByteArray(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { RenderedImage r = exportFontToImage(font); ImageIO.write(r, "png", os); } public void exportFontToFile(BitmapFont font, File file) throws IOException { RenderedImage r = exportFontToImage(font); ImageIO.write(r, "png", file); } public RenderedImage exportFontToImage(BitmapFont font) { BitmapFontGlyph[] g = new BitmapFontGlyph[94]; int[] l = new int[94]; int[] w = new int[94]; int[] r = new int[94]; for (int i = 0; i < 94; i++) { g[i] = font.getCharacter(i+33); if (g[i] == null) g[i] = new BitmapFontGlyph(new byte[1][1], 0, 1, 1); l[i] = g[i].getGlyphOffset(); l[i] = (l[i] < 0) ? (-l[i]) : 1; w[i] = g[i].getCharacterWidth(); if (w[i] < 1) w[i] = 1; r[i] = g[i].getGlyphOffset()+g[i].getGlyphWidth(); r[i] = (r[i] > w[i]) ? (r[i] - w[i]) : 1; } for (int i = 0; i+1 < 94; i++) { r[i] = l[i+1] = Math.max(r[i], l[i+1]); } int width = 0; for (int i = 0; i < 94; i++) { width += l[i] + w[i] + r[i]; } int height = 1+font.getLineAscent()+font.getLineDescent()+font.getLineGap(); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int x = 0, i = 0; i < 94; x += l[i]+w[i]+r[i], i++) { for (int lx = 0; lx < l[i]; lx++) { bi.setRGB(x+lx, 0, 0xFFFF00FF); } for (int rx = 0; rx < r[i]; rx++) { bi.setRGB(x+l[i]+w[i]+rx, 0, 0xFFFF00FF); } byte[][] gg = g[i].getGlyph(); for (int gy = 0, iy = 1+font.getLineAscent()-g[i].getGlyphAscent(); gy < gg.length; gy++, iy++) { if (iy > 0 && iy < height) { for (int gx = 0, ix = x+l[i]+g[i].getGlyphOffset(); gx < gg[gy].length; gx++, ix++) { bi.setRGB(ix, iy, ((gg[gy][gx] & 0xFF) << 24) | (color & 0xFFFFFF)); } } } } return bi; } } TOSBitmapFontExporter.java000077500000000000000000000042141506470510200342600ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.*; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; public class TOSBitmapFontExporter implements BitmapFontExporter { @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); exportFont(font, new DataOutputStream(out)); out.close(); return out.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { exportFont(font, new DataOutputStream(os)); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream out = new FileOutputStream(file); exportFont(font, new DataOutputStream(out)); out.close(); } private void exportFont(BitmapFont font, DataOutputStream out) throws IOException { int w = 0; int a = font.getLineAscent(); int d = font.getLineDescent(); int h = a+d; int maxchar = 0; for (int i = 0; i < 0x110000; i++) { if (font.containsCharacter(i)) { int cw = font.getCharacter(i).getCharacterWidth(); if (cw > w) w = cw; maxchar = i+1; } } out.writeInt(0x7056F097); out.writeShort(Short.reverseBytes((short)w)); out.writeShort(Short.reverseBytes((short)h)); for (int i = 0; i < maxchar; i++) { if (font.containsCharacter(i)) { BitmapFontGlyph g = font.getCharacter(i); int by = a-g.getGlyphAscent(); int bx = g.getGlyphOffset(); byte[][] gg = g.getGlyph(); for (int y = 0; y < h; y++) { int gy = y-by; if (gy >= 0 && gy < gg.length) { for (int x = 0; x < w; x += 8) { byte b = 0; for (int ix = 0; ix < 8; ix++) { int gx = x+ix-bx; b <<= 1; if (gx >= 0 && gx < gg[gy].length && gg[gy][gx] < 0) { b |= 1; } } out.writeByte(b); } } else { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } } else { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { out.writeByte(0); } } } } } } TTFBitmapFontExporter.java000077500000000000000000000326121506470510200342530ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.awt.Rectangle; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.PathGraph; import com.kreative.bitsnpicas.truetype.*; public class TTFBitmapFontExporter implements BitmapFontExporter { private int xsize, ysize; private boolean extendWinMetrics; public TTFBitmapFontExporter() { this.xsize = 100; this.ysize = 100; this.extendWinMetrics = false; } public TTFBitmapFontExporter(int size) { this.xsize = size; this.ysize = size; this.extendWinMetrics = false; } public TTFBitmapFontExporter(int xsize, int ysize) { this.xsize = xsize; this.ysize = ysize; this.extendWinMetrics = false; } public TTFBitmapFontExporter(boolean extendWinMetrics) { this.xsize = 100; this.ysize = 100; this.extendWinMetrics = extendWinMetrics; } public TTFBitmapFontExporter(int size, boolean extendWinMetrics) { this.xsize = size; this.ysize = size; this.extendWinMetrics = extendWinMetrics; } public TTFBitmapFontExporter(int xsize, int ysize, boolean extendWinMetrics) { this.xsize = xsize; this.ysize = ysize; this.extendWinMetrics = extendWinMetrics; } public byte[] exportFontToBytes(BitmapFont font) throws IOException { return createTrueTypeTables(font, xsize, ysize, extendWinMetrics).compile(); } public void exportFontToFile(BitmapFont font, File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); fos.write(createTrueTypeTables(font, xsize, ysize, extendWinMetrics).compile()); fos.close(); } public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { os.write(createTrueTypeTables(font, xsize, ysize, extendWinMetrics).compile()); } private static final class ThingsToKeepTrackOf { private int numGlyphs = 0; private int maxPoints = 0; private int maxContours = 0; private boolean maxBoundingBox = false; private int bbx1 = 0; private int bby1 = 0; private int bbx2 = 0; private int bby2 = 0; private int minLSB = 0; private int minRSB = 0; private int maxAdvance = 0; private int maxExtent = 0; private int averageWidth = 0; private int numAverages = 0; private int xHeight = 0; private int HHeight = 0; private boolean highUnicode = false; private Map charToGlyfMap = new HashMap(); private int currentLocation = 0; } private static final TrueTypeFile createTrueTypeTables(BitmapFont bf, int xsize, int ysize, boolean extendWinMetrics) throws IOException { ThingsToKeepTrackOf a = new ThingsToKeepTrackOf(); bf.autoFillNames(); GlyfTable glyfTable = new GlyfTable(); LocaTable locaTable = new LocaTable(); HmtxTable hmtxTable = new HmtxTable(); PostTable postTable = new PostTable(); if (bf.isItalicStyle()) postTable.italicAngle = PostTable.ITALIC_ANGLE_ISOMETRIC; postTable.underlinePosition = -ysize; postTable.underlineThickness = ysize; makeCharacterGlyph(bf, bf.getNamedGlyph(".notdef"), ".notdef", a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x00), 0x00, a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x0D), 0x0D, a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); makeCharacterGlyph(bf, bf.getCharacter(0x20), 0x20, a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); for (Map.Entry e : bf.characters(false).entrySet()) { int cp = e.getKey(); if (cp == 0x00 || cp == 0x0D || cp == 0x20) continue; makeCharacterGlyph(bf, e.getValue(), e.getKey(), a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); } for (Map.Entry e : bf.namedGlyphs(false).entrySet()) { if (e.getKey().toString().equals(".notdef")) continue; makeCharacterGlyph(bf, e.getValue(), e.getKey(), a, xsize, ysize, glyfTable, locaTable, hmtxTable, postTable); } locaTable.add(a.currentLocation); TrueTypeFile ttf = new TrueTypeFile(); ttf.add(makeHeadTable(bf, a, ysize)); ttf.add(makeHheaTable(bf, a, ysize)); ttf.add(makeMaxpTable(a)); ttf.add(makeOs2Table(bf, a, xsize, ysize, extendWinMetrics)); ttf.add(hmtxTable); ttf.add(makeCmapTable(bf, a)); ttf.add(locaTable); ttf.add(glyfTable); ttf.add(makeNameTable(bf)); ttf.add(postTable); return ttf; } private static final void makeCharacterGlyph( BitmapFont bf, BitmapFontGlyph g, Object id, ThingsToKeepTrackOf a, int xsize, int ysize, GlyfTable glyfTable, LocaTable locaTable, HmtxTable hmtxTable, PostTable postTable ) { if (id instanceof Integer) a.charToGlyfMap.put((Integer)id, a.numGlyphs); if (g == null) { locaTable.add(a.currentLocation); hmtxTable.add(new HmtxTableEntry()); } else { PathGraph pg = g.convertToPathGraph(xsize, ysize); pg.removeOverlap(); pg.simplifyPaths(); PathGraph.ImmutablePoint[][] contours = pg.getContours(); int pc = 0; for (PathGraph.ImmutablePoint[] contour : contours) pc += contour.length - 1; Rectangle r = pg.getBoundingRect(); int advance = g.getCharacterWidth() * xsize; if (a.maxContours < contours.length) a.maxContours = contours.length; if (a.maxPoints < pc) a.maxPoints = pc; if (!a.maxBoundingBox) { a.maxBoundingBox = true; a.bbx1 = r.x; a.bby1 = r.y; a.bbx2 = r.x+r.width; a.bby2 = r.y+r.height; a.minLSB = r.x; a.minRSB = advance-r.x-r.width; a.maxAdvance = advance; a.maxExtent = r.x+r.width; } else { if (r.x < a.bbx1) a.bbx1 = r.x; if (r.y < a.bby1) a.bby1 = r.y; if (r.x+r.width > a.bbx2) a.bbx2 = r.x+r.width; if (r.y+r.height > a.bby2) a.bby2 = r.y+r.height; if (r.x < a.minLSB) a.minLSB = r.x; if (advance-r.x-r.width < a.minRSB) a.minRSB = advance-r.x-r.width; if (advance > a.maxAdvance) a.maxAdvance = advance; if (r.x+r.width > a.maxExtent) a.maxExtent = r.x+r.width; } if (advance > 0) { a.averageWidth += advance; a.numAverages++; } if (id instanceof Integer && (Integer)id == 'x') a.xHeight = r.y+r.height; if (id instanceof Integer && (Integer)id == 'H') a.HHeight = r.y+r.height; if (id instanceof Integer && (Integer)id >= 0x10000) a.highUnicode = true; if (id instanceof Integer) a.charToGlyfMap.put((Integer)id, a.numGlyphs); byte[] glyf = ((contours.length == 0) ? new byte[0] : pg.getGlyfData()); glyfTable.add(glyf); locaTable.add(a.currentLocation); hmtxTable.add(new HmtxTableEntry(advance, r.x)); a.currentLocation += glyf.length; } if (id instanceof Integer) postTable.add(PostTableEntry.forCharacter((Integer)id)); if (id instanceof String) postTable.add(PostTableEntry.forCharacterName(id.toString())); a.numGlyphs++; } private static final CmapTable makeCmapTable(BitmapFont bf, ThingsToKeepTrackOf a) { Collection chars = bf.characters(false).keySet(); CmapSubtableFormat4 lowTable = new CmapSubtableFormat4(); CmapSubtableFormat12 highTable = new CmapSubtableFormat12(); CmapSubtableSequentialEntry currentGroup = null; int lastGlyphIndex = 0; for (int ch : chars) { int gidx = a.charToGlyfMap.get(ch); if (currentGroup == null) { currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = ch; currentGroup.endCharCode = ch; currentGroup.glyphIndex = gidx; lastGlyphIndex = gidx; } else if ((ch == currentGroup.endCharCode + 1) && (gidx == lastGlyphIndex + 1)) { currentGroup.endCharCode = ch; lastGlyphIndex = gidx; } else { if (currentGroup.startCharCode < 0x10000) lowTable.add(currentGroup); highTable.add(currentGroup); currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = ch; currentGroup.endCharCode = ch; currentGroup.glyphIndex = gidx; lastGlyphIndex = gidx; } } if (currentGroup != null) { if (currentGroup.startCharCode < 0x10000) lowTable.add(currentGroup); highTable.add(currentGroup); } currentGroup = new CmapSubtableSequentialEntry(); currentGroup.startCharCode = 0xFFFF; currentGroup.endCharCode = 0xFFFF; currentGroup.glyphIndex = 0; lowTable.add(currentGroup); CmapTable cmapTable = new CmapTable(); cmapTable.subtables.add(lowTable); if (a.highUnicode) cmapTable.subtables.add(highTable); cmapTable.entries.add(CmapTableEntry.forUnicode(a.highUnicode ? highTable : lowTable)); cmapTable.entries.add(CmapTableEntry.forWindowsUnicode16(lowTable)); if (a.highUnicode) cmapTable.entries.add(CmapTableEntry.forWindowsUnicode32(highTable)); return cmapTable; } private static final HeadTable makeHeadTable(BitmapFont bf, ThingsToKeepTrackOf a, int ysize) { Calendar now = new GregorianCalendar(); double fontVersion; try { String s = bf.getName(Font.NAME_VERSION); if (s == null) fontVersion = 1.0; else if (s.startsWith("Version ")) fontVersion = Double.parseDouble(s.substring(8)); else fontVersion = Double.parseDouble(s); } catch (NumberFormatException nfe) { fontVersion = 1.0; } HeadTable headTable = new HeadTable(); headTable.setFontRevisionDouble(fontVersion); headTable.flags = HeadTable.FLAGS_Y_VALUE_OF_ZERO_SPECIFIES_BASELINE | HeadTable.FLAGS_MINIMUM_X_VALUE_IS_LEFT_SIDE_BEARING; headTable.unitsPerEm = (bf.getEmAscent() + bf.getEmDescent()) * ysize; headTable.setDateCreatedCalendar(now); headTable.setDateModifiedCalendar(now); headTable.xMin = a.bbx1; headTable.yMin = a.bby1; headTable.xMax = a.bbx2; headTable.yMax = a.bby2; headTable.macStyle = bf.getMacStyle(); headTable.lowestRecPPEM = bf.getEmAscent() + bf.getEmDescent(); headTable.fontDirectionHint = HeadTable.FONT_DIRECTION_HINT_MIXED; headTable.indexToLocFormat = HeadTable.INDEX_TO_LOC_FORMAT_LONG; return headTable; } private static final HheaTable makeHheaTable(BitmapFont bf, ThingsToKeepTrackOf a, int ysize) { HheaTable hheaTable = new HheaTable(); hheaTable.ascent = bf.getLineAscent() * ysize; hheaTable.descent = -bf.getLineDescent() * ysize; hheaTable.lineGap = bf.getLineGap() * ysize; hheaTable.advanceWidthMax = a.maxAdvance; hheaTable.minLeftSideBearing = a.minLSB; hheaTable.minRightSideBearing = a.minRSB; hheaTable.xMaxExtent = a.maxExtent; if (bf.isItalicStyle()) { hheaTable.caretSlopeRise = 2; hheaTable.caretSlopeRun = 1; } hheaTable.numLongHorMetrics = a.numGlyphs; return hheaTable; } private static final MaxpTable makeMaxpTable(ThingsToKeepTrackOf a) { MaxpTable maxpTable = new MaxpTable(); maxpTable.numGlyphs = a.numGlyphs; maxpTable.maxPoints = a.maxPoints; maxpTable.maxContours = a.maxContours; return maxpTable; } private static final Os2Table makeOs2Table(BitmapFont bf, ThingsToKeepTrackOf a, int xsize, int ysize, boolean extendWinMetrics) { Collection chars = bf.characters(false).keySet(); Os2Table os2Table = new Os2Table(); if (a.numAverages > 0) os2Table.averageCharWidth = a.averageWidth / a.numAverages; os2Table.weightClass = bf.isBoldStyle() ? Os2Table.WEIGHT_CLASS_BOLD : Os2Table.WEIGHT_CLASS_MEDIUM; os2Table.widthClass = bf.isCondensedStyle() ? Os2Table.WIDTH_CLASS_CONDENSED : bf.isExtendedStyle() ? Os2Table.WIDTH_CLASS_EXPANDED : Os2Table.WIDTH_CLASS_MEDIUM; os2Table.subscriptXSize = (bf.getEmAscent() + bf.getEmDescent()) * xsize; os2Table.subscriptYSize = (bf.getEmAscent() + bf.getEmDescent()) * ysize; os2Table.subscriptXOffset = 0; os2Table.subscriptYOffset = (bf.getEmAscent() + bf.getEmDescent()) * ysize / 2; os2Table.superscriptXSize = (bf.getEmAscent() + bf.getEmDescent()) * xsize; os2Table.superscriptYSize = (bf.getEmAscent() + bf.getEmDescent()) * ysize; os2Table.superscriptXOffset = 0; os2Table.superscriptYOffset = (bf.getEmAscent() + bf.getEmDescent()) * ysize / 2; os2Table.strikeoutWidth = ysize; os2Table.strikeoutPosition = bf.getEmAscent() * ysize / 2; os2Table.panoseFamilyType = Os2Table.PANOSE_FAMILY_TYPE_TEXT_AND_DISPLAY; if (bf.isMonospaced()) os2Table.panoseProportion = Os2Table.PANOSE_PROPORTION_MONOSPACED; os2Table.setUnicodeRanges(chars); os2Table.setVendorIDString("KBnP"); os2Table.fsSelection = bf.getFsSelection() | Os2Table.FS_SELECTION_USE_TYPO_METRICS; os2Table.setCharIndices(chars); os2Table.typoAscent = bf.getLineAscent() * ysize; os2Table.typoDescent = -bf.getLineDescent() * ysize; os2Table.typoLineGap = bf.getLineGap() * ysize; os2Table.winAscent = bf.getLineAscent() * ysize; os2Table.winDescent = bf.getLineDescent() * ysize; if (extendWinMetrics) { os2Table.winAscent = Math.max(a.bby2, os2Table.winAscent); os2Table.winDescent = Math.max(-a.bby1, os2Table.winDescent); } os2Table.setCodePages(chars); os2Table.xHeight = a.xHeight; os2Table.capHeight = a.HHeight; return os2Table; } private static final NameTable makeNameTable(BitmapFont bf) { NameTable nameTable = new NameTable(); for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forUnicode(e.getKey(), e.getValue())); } for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forMacintosh(e.getKey(), e.getValue())); } for (Map.Entry e : bf.names(false).entrySet()) { nameTable.add(NameTableEntry.forWindows(e.getKey(), e.getValue())); } return nameTable; } } U8MBitmapFontExporter.java000066400000000000000000000064001506470510200342200ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporterpackage com.kreative.bitsnpicas.exporter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.u8m.U8MFile; import com.kreative.bitsnpicas.u8m.U8MGlyph; import com.kreative.unicode.data.GlyphList; public class U8MBitmapFontExporter implements BitmapFontExporter { private Integer loadAddress; private GlyphList nativeEncoding; public U8MBitmapFontExporter() { this.loadAddress = null; this.nativeEncoding = null; } public U8MBitmapFontExporter(Integer loadAddress) { this.loadAddress = loadAddress; this.nativeEncoding = null; } public U8MBitmapFontExporter(GlyphList nativeEncoding) { this.loadAddress = null; this.nativeEncoding = nativeEncoding; } public U8MBitmapFontExporter(Integer loadAddress, GlyphList nativeEncoding) { this.loadAddress = loadAddress; this.nativeEncoding = nativeEncoding; } @Override public byte[] exportFontToBytes(BitmapFont font) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); exportFontToStream(font, os); os.close(); return os.toByteArray(); } @Override public void exportFontToStream(BitmapFont font, OutputStream os) throws IOException { File file = File.createTempFile("u8m", ".u8m"); exportFontToFile(font, file); FileInputStream in = new FileInputStream(file); int read; byte[] buf = new byte[65536]; while ((read = in.read(buf)) >= 0) os.write(buf, 0, read); in.close(); file.delete(); } @Override public void exportFontToFile(BitmapFont font, File file) throws IOException { U8MFile u = new U8MFile(); u.familyName = font.getName(Font.NAME_FAMILY); u.familyID = (int)(((u.familyName.hashCode() & 0xFFFFFFFFL) % 65535L) + 1L); u.style = font.getMacStyle(); u.pointSize = font.getEmAscent() + font.getEmDescent(); u.lineAscent = font.getLineAscent(); u.lineDescent = font.getLineDescent(); u.lineGap = font.getLineGap(); u.lineHeight = u.lineAscent + u.lineDescent + u.lineGap; u.createMap(); // map zero which must be the empty map u.createGlyph(); // glyph zero which must be the notdef glyph for (int i = 0; i < 0x110000; i++) { if (font.containsCharacter(i)) { BitmapFontGlyph g = font.getCharacter(i); int index = (i == 0) ? 0 : u.createGlyph(); U8MGlyph ug = u.glyphs.get(index); ug.advanceWidth = g.getCharacterWidth(); ug.yOffset = -g.getGlyphAscent(); ug.xOffset = g.getGlyphOffset(); ug.from2DArray(g.getGlyph()); if (i != 0) u.setUnicodeGlyphIndex(i, index); } } if (nativeEncoding != null) { for (int i = 0; i < 256; i++) { int cp = nativeEncoding.get(i); if (cp > 0) { int index = u.getUnicodeGlyphIndex(cp); if (index > 0) { u.setNativeGlyphIndex(i, index); } } } } RandomAccessFile raf = new RandomAccessFile(file, "rwd"); raf.setLength(0); if (loadAddress != null) { raf.writeShort(Short.reverseBytes(loadAddress.shortValue())); u.write(raf, 0, 2); } else { u.write(raf, 0, 0); } raf.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/000077500000000000000000000000001506470510200263735ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/CBMConstants.java000066400000000000000000000026631506470510200315430ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; public interface CBMConstants { public static final int CBM_FILE_TYPE_DEL = 0x00; public static final int CBM_FILE_TYPE_SEQ = 0x01; public static final int CBM_FILE_TYPE_PRG = 0x02; public static final int CBM_FILE_TYPE_USR = 0x03; public static final int CBM_FILE_TYPE_REL = 0x04; public static final int CBM_FILE_TYPE_MASK = 0x0F; public static final int CBM_FILE_TYPE_LOCKED = 0x40; public static final int CBM_FILE_TYPE_CLOSED = 0x80; public static final int FILE_STRUCTURE_SEQ = 0x00; public static final int FILE_STRUCTURE_VLIR = 0x01; public static final int GEOS_FILE_TYPE_NONE = 0x00; public static final int GEOS_FILE_TYPE_BASIC = 0x01; public static final int GEOS_FILE_TYPE_ASSEMBLER = 0x02; public static final int GEOS_FILE_TYPE_DATA = 0x03; public static final int GEOS_FILE_TYPE_SYSTEM = 0x04; public static final int GEOS_FILE_TYPE_DESK_ACCESSORY = 0x05; public static final int GEOS_FILE_TYPE_APPLICATION = 0x06; public static final int GEOS_FILE_TYPE_DOCUMENT = 0x07; public static final int GEOS_FILE_TYPE_FONT = 0x08; public static final int GEOS_FILE_TYPE_PRINTER_DRIVER = 0x09; public static final int GEOS_FILE_TYPE_INPUT_DRIVER = 0x0A; public static final int GEOS_FILE_TYPE_DISK_DRIVER = 0x0B; public static final int GEOS_FILE_TYPE_BOOT = 0x0C; public static final int GEOS_FILE_TYPE_TEMPORARY = 0x0D; public static final int GEOS_FILE_TYPE_AUTO_EXECUTE = 0x0E; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/CBMDirectoryBlock.java000066400000000000000000000157031506470510200325050ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Calendar; import java.util.GregorianCalendar; public class CBMDirectoryBlock implements CBMConstants { public static final String COMMENT_PRG = "PRG formatted GEOS file"; public static final String COMMENT_SEQ = "SEQ formatted GEOS file"; public int cbmFileType; public int startingTrack; public int startingSector; public byte[] fileName; public int sideTrack; public int sideSector; public int recordLength; public int infoTrack; public int infoSector; public int fileStructure; public int geosFileType; public int year; public int month; public int day; public int hour; public int minute; public int sectorSize; public byte[] comment; public CBMDirectoryBlock() { clear(); } public void clear() { cbmFileType = CBM_FILE_TYPE_CLOSED; startingTrack = 0; startingSector = 0; fileName = new byte[0]; sideTrack = 0; sideSector = 0; recordLength = 0; infoTrack = 0; infoSector = 0; fileStructure = 0; geosFileType = 0; GregorianCalendar now = new GregorianCalendar(); year = now.get(Calendar.YEAR); month = now.get(Calendar.MONTH) + 1; day = now.get(Calendar.DAY_OF_MONTH); hour = now.get(Calendar.HOUR_OF_DAY); minute = now.get(Calendar.MINUTE); sectorSize = 0; comment = new byte[0]; } public String getFileTypeString() { int type = cbmFileType & CBM_FILE_TYPE_MASK; switch (type) { case CBM_FILE_TYPE_DEL: return "DEL"; case CBM_FILE_TYPE_SEQ: return "SEQ"; case CBM_FILE_TYPE_PRG: return "PRG"; case CBM_FILE_TYPE_USR: return "USR"; case CBM_FILE_TYPE_REL: return "REL"; default: return "[" + Integer.toHexString(type).toUpperCase() + "]"; } } public boolean setFileTypeString(String s) { char[] ch = s.trim().toCharArray(); if (ch.length > 0) { switch (ch[0]) { case 'D': case 'd': cbmFileType &=~ CBM_FILE_TYPE_MASK; cbmFileType |= CBM_FILE_TYPE_DEL; return true; case 'S': case 's': cbmFileType &=~ CBM_FILE_TYPE_MASK; cbmFileType |= CBM_FILE_TYPE_SEQ; return true; case 'P': case 'p': cbmFileType &=~ CBM_FILE_TYPE_MASK; cbmFileType |= CBM_FILE_TYPE_PRG; return true; case 'U': case 'u': cbmFileType &=~ CBM_FILE_TYPE_MASK; cbmFileType |= CBM_FILE_TYPE_USR; return true; case 'R': case 'r': cbmFileType &=~ CBM_FILE_TYPE_MASK; cbmFileType |= CBM_FILE_TYPE_REL; return true; } } return false; } public String getFileName(boolean alt, boolean geos) { if (geos && (geosFileType != 0)) { try { return new String(fileName, "US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } else { return PETSCII.toString(fileName, alt); } } public void setFileName(String name, boolean alt, boolean geos) { if (geos && (geosFileType != 0)) { try { fileName = name.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } else { fileName = PETSCII.fromString(name, alt); } } public GregorianCalendar getDate() { if (year == 1900 && month == 0 && day == 0 && hour == 0 && minute == 0) { return null; } else { return new GregorianCalendar(year, month - 1, day, hour, minute); } } public void setDate(GregorianCalendar cal) { if (cal == null) { year = 1900; month = 0; day = 0; hour = 0; minute = 0; } else { year = cal.get(Calendar.YEAR); month = cal.get(Calendar.MONTH) + 1; day = cal.get(Calendar.DAY_OF_MONTH); hour = cal.get(Calendar.HOUR_OF_DAY); minute = cal.get(Calendar.MINUTE); } } public String getCommentString() { try { return new String(comment, "US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } public void setCommentString(String s) { try { comment = s.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } @Override public String toString() { return toString(false, false); } public String toString(boolean alt, boolean geos) { StringBuffer sb = new StringBuffer(); sb.append(sectorSize); while (sb.codePointCount(0, sb.length()) < 5) sb.append(' '); sb.append('"'); sb.append(getFileName(alt, geos)); sb.append('"'); while (sb.codePointCount(0, sb.length()) < 23) sb.append(' '); if ((cbmFileType & CBM_FILE_TYPE_CLOSED) == 0) sb.append('*'); else if ((cbmFileType & CBM_FILE_TYPE_LOCKED) != 0) sb.append('>'); else sb.append(' '); sb.append(getFileTypeString()); sb.append(' '); sb.append(toString(year, 4)); sb.append('-'); sb.append(toString(month, 2)); sb.append('-'); sb.append(toString(day, 2)); sb.append(' '); sb.append(toString(hour, 2)); sb.append(':'); sb.append(toString(minute, 2)); return sb.toString(); } private String toString(int val, int len) { String s = Integer.toString(val); while (s.length() < len) s = "0" + s; return s.substring(s.length() - len); } public void read(DataInput in) throws IOException { cbmFileType = in.readUnsignedByte(); startingTrack = in.readByte(); startingSector = in.readByte(); fileName = read(in, 16, (byte)0xA0); sideTrack = infoTrack = in.readByte(); sideSector = infoSector = in.readByte(); recordLength = fileStructure = in.readUnsignedByte(); geosFileType = in.readUnsignedByte(); year = in.readUnsignedByte() + 1900; month = in.readUnsignedByte(); day = in.readUnsignedByte(); hour = in.readUnsignedByte(); minute = in.readUnsignedByte(); sectorSize = Short.reverseBytes(in.readShort()) & 0xFFFF; comment = read(in, 0xE0, (byte)0); } public void write(DataOutput out) throws IOException { out.writeByte(cbmFileType); out.writeByte(startingTrack); out.writeByte(startingSector); write(out, fileName, 16, (byte)0xA0); if (geosFileType == 0) { out.writeByte(sideTrack); out.writeByte(sideSector); out.writeByte(recordLength); } else { out.writeByte(infoTrack); out.writeByte(infoSector); out.writeByte(fileStructure); } out.writeByte(geosFileType); out.writeByte(year - 1900); out.writeByte(month); out.writeByte(day); out.writeByte(hour); out.writeByte(minute); out.writeShort(Short.reverseBytes((short)sectorSize)); write(out, comment, 0xE0, (byte)0); } private static byte[] read(DataInput in, int len, byte fill) throws IOException { byte[] buf = new byte[len]; in.readFully(buf); while (len > 0 && buf[len-1] == fill) len--; byte[] trimmed = new byte[len]; while (len > 0) { len--; trimmed[len] = buf[len]; } return trimmed; } private static void write(DataOutput out, byte[] data, int len, byte fill) throws IOException { for (int i = 0; i < data.length && i < len; i++) out.writeByte(data[i]); for (int i = data.length; i < len; i++) out.writeByte(fill); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/CBMList.java000066400000000000000000000032351506470510200304760ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; public class CBMList { public static void main(String[] args) { PrintWriter out; try { out = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"), true); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } boolean recursive = false; boolean alt = false; boolean geos = false; if (args.length == 0) args = new String[]{"."}; for (String arg : args) { if (arg.equals("-r")) { recursive = true; } else if (arg.equals("-p")) { alt = false; } else if (arg.equals("-a")) { alt = true; } else if (arg.equals("-c")) { geos = false; } else if (arg.equals("-g")) { geos = true; } else { process(out, new File(arg), recursive, alt, geos); } } } private static void process(PrintWriter out, File f, boolean recursive, boolean alt, boolean geos) { if (f.isDirectory()) { for (File ff : f.listFiles()) { if (!ff.getName().startsWith(".")) { if (recursive || ff.isFile()) { process(out, ff, recursive, alt, geos); } } } } else if (f.isFile()) { if (f.getName().toLowerCase().endsWith(".cvt")) { try { CBMDirectoryBlock db = new CBMDirectoryBlock(); FileInputStream in = new FileInputStream(f); db.read(new DataInputStream(in)); in.close(); out.println(db.toString(alt, geos)); } catch (IOException e) { // Ignored } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/ConvertFile.java000066400000000000000000000107061506470510200314620ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.DataOutput; import java.io.EOFException; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ConvertFile implements CBMConstants { public CBMDirectoryBlock directoryBlock; public GEOSInfoBlock infoBlock; public VLIRRecordBlock recordBlock; public byte[] sequentialData; public List vlirData; public ConvertFile() { clear(CBM_FILE_TYPE_CLOSED, 0, 0); } public ConvertFile(int cbmFileType) { clear(cbmFileType, 0, 0); } public ConvertFile(int cbmFileType, int geosFileType) { clear(cbmFileType, geosFileType, 0); } public ConvertFile(int cbmFileType, int geosFileType, int fileStructure) { clear(cbmFileType, geosFileType, fileStructure); } public void clear() { clear(CBM_FILE_TYPE_CLOSED, 0, 0); } public void clear(int cbmFileType) { clear(cbmFileType, 0, 0); } public void clear(int cbmFileType, int geosFileType) { clear(cbmFileType, geosFileType, 0); } public void clear(int cbmFileType, int geosFileType, int fileStructure) { directoryBlock = new CBMDirectoryBlock(); directoryBlock.cbmFileType = cbmFileType; directoryBlock.geosFileType = geosFileType; directoryBlock.fileStructure = fileStructure; if (geosFileType == 0) { infoBlock = null; recordBlock = null; sequentialData = new byte[0]; vlirData = null; } else { directoryBlock.sectorSize++; infoBlock = new GEOSInfoBlock(); infoBlock.cbmFileType = cbmFileType; infoBlock.geosFileType = geosFileType; infoBlock.fileStructure = fileStructure; if (fileStructure == FILE_STRUCTURE_VLIR) { directoryBlock.sectorSize++; directoryBlock.setCommentString(CBMDirectoryBlock.COMMENT_PRG); recordBlock = new VLIRRecordBlock(); sequentialData = null; vlirData = new ArrayList(); } else { directoryBlock.setCommentString(CBMDirectoryBlock.COMMENT_SEQ); recordBlock = null; sequentialData = new byte[0]; vlirData = null; } } } public void recalculate() { directoryBlock.sectorSize = 0; if (directoryBlock.geosFileType == 0) { directoryBlock.sectorSize += (sequentialData.length + 253) / 254; } else { directoryBlock.sectorSize++; // info block if (infoBlock.fileStructure == FILE_STRUCTURE_VLIR) { directoryBlock.sectorSize++; // record block recordBlock.clear(); for (byte[] data : vlirData) { VLIRRecordBlock.Entry e = new VLIRRecordBlock.Entry(data.length); directoryBlock.sectorSize += e.sectorCount; recordBlock.add(e); } } else { directoryBlock.sectorSize += (sequentialData.length + 253) / 254; } } } public void read(DataInput in) throws IOException { directoryBlock = new CBMDirectoryBlock(); directoryBlock.read(in); if (directoryBlock.geosFileType == 0) { infoBlock = null; recordBlock = null; sequentialData = readRemainder(in); vlirData = null; } else { infoBlock = new GEOSInfoBlock(); infoBlock.read(in); if (infoBlock.fileStructure == FILE_STRUCTURE_VLIR) { recordBlock = new VLIRRecordBlock(); recordBlock.read(in); sequentialData = null; vlirData = new ArrayList(); int lastFillLength = 0; for (VLIRRecordBlock.Entry e : recordBlock) { byte[] data = new byte[e.length]; if (e.length > 0) { in.readFully(new byte[lastFillLength]); in.readFully(data); lastFillLength = e.sectorCount * 254 - e.length; } vlirData.add(data); } } else { recordBlock = null; sequentialData = readRemainder(in); vlirData = null; } } } public void write(DataOutput out) throws IOException { directoryBlock.write(out); if (directoryBlock.geosFileType == 0) { out.write(sequentialData); } else { infoBlock.write(out); if (infoBlock.fileStructure == FILE_STRUCTURE_VLIR) { recordBlock.write(out); int lastFillLength = 0; for (byte[] data : vlirData) { if (data.length > 0) { out.write(new byte[lastFillLength]); out.write(data); int sectorCount = (data.length + 253) / 254; lastFillLength = sectorCount * 254 - data.length; } } } else { out.write(sequentialData); } } } private static byte[] readRemainder(DataInput in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); while (true) { try { out.write(in.readByte()); } catch (EOFException e) { break; } } return out.toByteArray(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSFontFile.java000066400000000000000000000301201506470510200314160ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class GEOSFontFile extends ConvertFile { public GEOSFontFile() { super( CBM_FILE_TYPE_CLOSED | CBM_FILE_TYPE_USR, GEOS_FILE_TYPE_FONT, FILE_STRUCTURE_VLIR ); infoBlock.iconBitmap = GEOSIcons.fontIcon(); for (int i = 0; i < 127; i++) { vlirData.add(new byte[0]); } } public GEOSFontFile(DataInput in) throws IOException { super(); read(in); } public boolean isValid() { return ( directoryBlock != null && directoryBlock.geosFileType == GEOS_FILE_TYPE_FONT && directoryBlock.fileStructure == FILE_STRUCTURE_VLIR && infoBlock != null && infoBlock.geosFileType == GEOS_FILE_TYPE_FONT && infoBlock.fileStructure == FILE_STRUCTURE_VLIR && recordBlock != null && vlirData != null ); } public boolean isMega() { byte[] r54 = vlirData.get(54); if (r54 != null && r54.length > 8) { int bo = (r54[6] & 0xFF) | ((r54[7] & 0xFF) << 8); if (bo >= r54.length) { return true; } } return false; } public boolean isUTF8() { byte[] r126 = vlirData.get(126); return (r126 != null && r126.length > 0); } public String getFontName() { return directoryBlock.getFileName(true, true); } public void setFontName(String name) { directoryBlock.setFileName(name, true, true); } public String getClassTextString() { return infoBlock.getClassTextString(); } public void setClassTextString(String s) { infoBlock.setClassTextString(s); } public String getDescriptionString() { return infoBlock.getDescriptionString(); } public void setDescriptionString(String s) { infoBlock.setDescriptionString(s); } public int getFontID() { return ( (infoBlock.getByte(0x80) & 0xFF) | ((infoBlock.getByte(0x81) & 0xFF) << 8) ); } public void setFontID(int fontID) { infoBlock.setByte(0x80, (byte)fontID); infoBlock.setByte(0x81, (byte)(fontID >> 8)); fontID <<= 6; for (int a = 0x82, i = 0; i < 15; i++, a += 2) { int index = infoBlock.getByte(a) & 0x3F; if (index == 0) break; infoBlock.setByte(a, (byte)(index | fontID)); infoBlock.setByte(a+1, (byte)(fontID >> 8)); } } private GEOSFontStrike getFontStrike(int index) { if (index >= 0 && index < vlirData.size()) { byte[] data = vlirData.get(index); if (data != null && data.length > 8) { return new GEOSFontStrike(data); } } return null; } private GEOSFontStrike getFontStrike(int record, int sector, int length) { if (record >= 0 && record < vlirData.size()) { byte[] data = vlirData.get(record); if (data != null && data.length >= (sector * 254 + length)) { return new GEOSFontStrike(data, sector * 254, length); } } return null; } private void removeFontStrike(int index) { if (index >= 0 && index < vlirData.size()) { vlirData.set(index, new byte[0]); } } private void setFontStrike(int index, GEOSFontStrike gfs) { if (index >= 0 && index < vlirData.size()) { vlirData.set(index, gfs.write()); } } public List getFontPointSizes() { Set exclusions = new HashSet(); if (isMega()) { for (int i = 49; i <= 54; i++) { exclusions.add(i); } } byte[] r126 = vlirData.get(126); if (r126 != null && r126.length > 0) { exclusions.add(126); for (int i = 0; i + 4 <= r126.length; i += 4) { exclusions.add(r126[i] & 0xFF); } } List pointSizes = new ArrayList(); for (int index = 0; index < vlirData.size(); index++) { if (!exclusions.contains(index)) { byte[] data = vlirData.get(index); if (data.length > 8) pointSizes.add(index); } } return pointSizes; } public GEOSFontPointSize getFontPointSize(int pointSize) { GEOSFontPointSize f = new GEOSFontPointSize(pointSize); if (pointSize >= 48 && pointSize <= 54 && isMega()) { f.megaStrikes = new GEOSFontStrike[6]; f.megaStrikes[0] = getFontStrike(48); f.megaStrikes[1] = getFontStrike(49); f.megaStrikes[2] = getFontStrike(50); f.megaStrikes[3] = getFontStrike(51); f.megaStrikes[4] = getFontStrike(52); f.megaStrikes[5] = getFontStrike(53); f.megaStrikeIndex = getFontStrike(54); f.utf8Map = f.megaStrikeIndex.utf8Map; } else { f.strike = getFontStrike(pointSize); if (f.strike == null) return null; f.utf8Map = f.strike.utf8Map; } if (f.utf8Map != null) { f.utf8Strikes = new HashMap(); for (UTF8StrikeEntry e : f.utf8Map.lowEntries) { if (e != null) { f.utf8Strikes.put(e, getFontStrike( e.recordIndex, e.sectorIndex, e.length )); } } for (UTF8StrikeMap.SubMap sm : f.utf8Map.highEntries) { if (sm != null) { for (UTF8StrikeEntry e : sm.entries) { if (e != null) { f.utf8Strikes.put(e, getFontStrike( e.recordIndex, e.sectorIndex, e.length )); } } } } for (UTF8StrikeMap.AstralMap am : f.utf8Map.astralEntries) { if (am != null) { for (UTF8StrikeMap.SubMap sm : am.entries) { if (sm != null) { for (UTF8StrikeEntry e : sm.entries) { if (e != null) { f.utf8Strikes.put(e, getFontStrike( e.recordIndex, e.sectorIndex, e.length )); } } } } } } } return f; } public int getFontPointSizeSectorCount(int pointSize) { int sectorCount = 0; UTF8StrikeMap utf8Map = null; if (pointSize >= 48 && pointSize <= 54 && isMega()) { for (int i = 48; i <= 54; i++) { byte[] data = vlirData.get(i); if (data != null) sectorCount += (data.length + 253) / 254; } GEOSFontStrike gfs = getFontStrike(54); if (gfs != null) utf8Map = gfs.utf8Map; } else { byte[] data = vlirData.get(pointSize); if (data != null) sectorCount += (data.length + 253) / 254; GEOSFontStrike gfs = getFontStrike(pointSize); if (gfs != null) utf8Map = gfs.utf8Map; } if (utf8Map != null) { Set records = new HashSet(); for (UTF8StrikeEntry e : utf8Map.entryList()) { records.add(e.recordIndex); } for (int i : records) { byte[] data = vlirData.get(i); if (data != null) sectorCount += (data.length + 253) / 254; } } return sectorCount; } public String getFontPointSizeTypeString(int pointSize) { String typeString = "font"; UTF8StrikeMap utf8Map = null; if (pointSize >= 48 && pointSize <= 54 && isMega()) { typeString = "mega " + typeString; GEOSFontStrike gfs = getFontStrike(54); if (gfs != null) utf8Map = gfs.utf8Map; } else { GEOSFontStrike gfs = getFontStrike(pointSize); if (gfs != null) utf8Map = gfs.utf8Map; } if (utf8Map != null) { typeString = "UTF-8 " + typeString; } return typeString; } public void removeFontPointSize(int pointSize) { UTF8StrikeMap utf8Map = null; if (pointSize >= 48 && pointSize <= 54 && isMega()) { GEOSFontStrike gfs = getFontStrike(54); if (gfs != null) utf8Map = gfs.utf8Map; removeFontStrike(48); removeFontStrike(49); removeFontStrike(50); removeFontStrike(51); removeFontStrike(52); removeFontStrike(53); removeFontStrike(54); } else { GEOSFontStrike gfs = getFontStrike(pointSize); if (gfs != null) utf8Map = gfs.utf8Map; removeFontStrike(pointSize); } if (utf8Map != null) { UTF8StrikeIndex si = getUTF8StrikeIndex(); if (si == null) si = new UTF8StrikeIndex(); for (UTF8StrikeEntry e : utf8Map.entryList()) { removeFontStrike(e.recordIndex); si.remove(e); } setUTF8StrikeIndex(si); } } public void setFontPointSize(int pointSize, GEOSFontPointSize f) { if (f.isUTF8()) { Map remap = new HashMap(); UTF8StrikeIndex si = getUTF8StrikeIndex(); if (si == null) si = new UTF8StrikeIndex(); int recordLength = 0; int recordIndex = nextRecordIndex(); ByteArrayOutputStream recordOut = new ByteArrayOutputStream(); for (UTF8StrikeEntry e : f.utf8Map.entryList()) { byte[] data = f.utf8Strikes.get(e).write(); int nextSector = ((recordLength + 253) / 254); int nextStart = nextSector * 254; if (nextStart + data.length > 12192) { vlirData.set(recordIndex, recordOut.toByteArray()); recordLength = 0; recordIndex = nextRecordIndex(); recordOut = new ByteArrayOutputStream(); nextSector = 0; nextStart = 0; } remap.put(e, new UTF8StrikeEntry(recordIndex, nextSector, data.length)); si.add(new UTF8StrikeEntry(recordIndex, nextSector, data.length)); while (recordLength < nextStart) { recordOut.write(0); recordLength++; } for (byte b : data) { recordOut.write(b); recordLength++; } } if (recordLength > 0) { vlirData.set(recordIndex, recordOut.toByteArray()); } setUTF8StrikeIndex(si); f.remap(remap); } if (f.isMega()) { setFontStrike(48, f.megaStrikes[0]); setFontStrike(49, f.megaStrikes[1]); setFontStrike(50, f.megaStrikes[2]); setFontStrike(51, f.megaStrikes[3]); setFontStrike(52, f.megaStrikes[4]); setFontStrike(53, f.megaStrikes[5]); setFontStrike(54, f.megaStrikeIndex); } else { setFontStrike(pointSize, f.strike); } } private int nextRecordIndex() { int nextID = 125; while (nextID > 0) { byte[] data = vlirData.get(nextID); if (data == null || data.length == 0) break; nextID--; } return nextID; } private UTF8StrikeIndex getUTF8StrikeIndex() { byte[] r126 = vlirData.get(126); if (r126 != null && r126.length > 0) { UTF8StrikeIndex index = new UTF8StrikeIndex(); index.read(r126); return index; } return null; } private void setUTF8StrikeIndex(UTF8StrikeIndex index) { vlirData.set(126, index.write()); } public void recalculate() { Set pointSizeExclusions = new HashSet(); if (isMega()) { for (int i = 49; i <= 54; i++) { pointSizeExclusions.add(i); } } Set recordExclusions = new HashSet(); byte[] r126 = vlirData.get(126); if (r126 != null && r126.length > 0) { recordExclusions.add(126); for (int i = 0; i + 4 <= r126.length; i += 4) { recordExclusions.add(r126[i] & 0xFF); } } List pointSizes = new ArrayList(); List indices = new ArrayList(); List lengths = new ArrayList(); for (int index = 0; index < vlirData.size(); index++) { if (!recordExclusions.contains(index)) { byte[] data = vlirData.get(index); if (data.length > 8) { if (!pointSizeExclusions.contains(index)) { pointSizes.add(index); } indices.add(index); lengths.add(data.length); } } } updateDescription(pointSizes); setFontStrikes(indices); setFontRecordLengths(lengths); super.recalculate(); } private void updateDescription(List pointSizes) { StringBuffer sb = new StringBuffer(); sb.append("Available in "); int count = pointSizes.size(); for (int pointSize : pointSizes) { sb.append(pointSize); count--; if (count > 1) sb.append(", "); if (count == 1) sb.append(" and "); } sb.append(" point."); String d = infoBlock.getDescriptionString(); if (d.trim().length() == 0) d = sb.toString(); else d = d.replaceAll("Available in [^.]+ point.", sb.toString()); infoBlock.setDescriptionString(d); } private void setFontStrikes(List indices) { int fontID = getFontID() << 6; int a = 0x82, i = 0, n = indices.size(); while (i < n && i < 15) { int index = indices.get(i) & 0x3F; infoBlock.setByte(a, (byte)(index | fontID)); infoBlock.setByte(a+1, (byte)(fontID >> 8)); i++; a += 2; } while (i < 15) { infoBlock.setByte(a, (byte)0); infoBlock.setByte(a+1, (byte)0); i++; a += 2; } } private void setFontRecordLengths(List lengths) { int a = 0x61, i = 0, n = lengths.size(); while (i < n && i < 15) { int length = lengths.get(i); infoBlock.setByte(a, (byte)length); infoBlock.setByte(a+1, (byte)(length >> 8)); i++; a += 2; } while (i < 15) { infoBlock.setByte(a, (byte)0); infoBlock.setByte(a+1, (byte)0); i++; a += 2; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSFontPointSize.java000066400000000000000000000023541506470510200324730ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.util.HashMap; import java.util.Map; public class GEOSFontPointSize { public int pointSize; public GEOSFontStrike strike; public GEOSFontStrike[] megaStrikes; public GEOSFontStrike megaStrikeIndex; public UTF8StrikeMap utf8Map; public Map utf8Strikes; public GEOSFontPointSize(int pointSize) { this.pointSize = pointSize; this.strike = null; this.megaStrikes = null; this.megaStrikeIndex = null; this.utf8Map = null; this.utf8Strikes = null; } public boolean isMega() { return (megaStrikes != null && megaStrikeIndex != null); } public boolean isUTF8() { return (utf8Map != null && utf8Strikes != null); } public void remap(Map remap) { if (utf8Map != null) { utf8Map.remap(remap); } if (utf8Strikes != null) { Map newStrikes = new HashMap(); for (Map.Entry e : utf8Strikes.entrySet()) { if (remap.containsKey(e.getKey())) { newStrikes.put(remap.get(e.getKey()), e.getValue()); } else { newStrikes.put(e.getKey(), e.getValue()); } } utf8Strikes = newStrikes; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSFontStrike.java000066400000000000000000000152171506470510200320120ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.ByteArrayOutputStream; public class GEOSFontStrike { public int ascent; public int rowWidth; public int height; public int[] xCoord; public byte[] bitmap; public OffsetWidth[] offsetWidths; public UTF8StrikeMap utf8Map; public GEOSFontStrike() { this.clear(96, false, false); } public GEOSFontStrike(int numChars) { this.clear(numChars, false, false); } public GEOSFontStrike(boolean kerning, boolean utf8) { this.clear(96, kerning, utf8); } public GEOSFontStrike(int numChars, boolean kerning, boolean utf8) { this.clear(numChars, kerning, utf8); } public GEOSFontStrike(byte[] data) { this.read(data, 0, data.length); } public GEOSFontStrike(byte[] data, int offset, int length) { this.read(data, offset, length); } public void clear() { this.clear(96, false, false); } public void clear(int numChars) { this.clear(numChars, false, false); } public void clear(boolean kerning, boolean utf8) { this.clear(96, kerning, utf8); } public void clear(int numChars, boolean kerning, boolean utf8) { this.ascent = 0; this.rowWidth = 0; this.height = 0; this.xCoord = new int[numChars + 1]; this.bitmap = new byte[0]; this.offsetWidths = kerning ? new OffsetWidth[numChars] : null; this.utf8Map = utf8 ? new UTF8StrikeMap() : null; } public int getGlyphCount() { return xCoord.length - 1; } public byte[][] getGlyph(int i) { if (xCoord == null || xCoord.length == 0) return null; if (bitmap == null || bitmap.length == 0) return null; if (xCoord[i] > xCoord[i+1] || xCoord[i] > (rowWidth*8) || xCoord[i+1] > (rowWidth*8)) { System.err.println("Warning: Bad X coordinates: " + xCoord[i] + ", " + xCoord[i+1] + ", " + (rowWidth*8)); return null; } byte[][] gd = new byte[height][xCoord[i+1] - xCoord[i]]; for (int ba = 0, y = 0; y < height; y++, ba += rowWidth) { int a = ba + (xCoord[i] >> 3); int m = 0x80 >> (xCoord[i] & 7); for (int gx = 0, bx = xCoord[i]; bx < xCoord[i+1]; bx++, gx++) { if ((bitmap[a] & m) != 0) gd[y][gx] = -1; m >>= 1; if (m == 0) { m = 0x80; a++; } } } return gd; } public void setGlyph(int i, byte[][] gd) { if (xCoord == null || xCoord.length == 0) return; if (bitmap == null || bitmap.length == 0) return; if (xCoord[i] > xCoord[i+1] || xCoord[i] > (rowWidth*8) || xCoord[i+1] > (rowWidth*8)) { System.err.println("Warning: Bad X coordinates: " + xCoord[i] + ", " + xCoord[i+1] + ", " + (rowWidth*8)); return; } for (int ba = 0, y = 0; y < height; y++, ba += rowWidth) { int a = ba + (xCoord[i] >> 3); int m = 0x80 >> (xCoord[i] & 7); for (int gx = 0, bx = xCoord[i]; bx < xCoord[i+1]; bx++, gx++) { if (gd[y][gx] < 0) bitmap[a] |= m; m >>= 1; if (m == 0) { m = 0x80; a++; } } } } public void read(byte[] data) { read(data, 0, data.length); } public void read(byte[] data, int offset, int length) { // Read header. ascent = data[offset + 0] & 0xFF; rowWidth = (data[offset + 1] & 0xFF) | ((data[offset + 2] & 0xFF) << 8); height = data[offset + 3] & 0xFF; int xo = (data[offset + 4] & 0xFF) | ((data[offset + 5] & 0xFF) << 8); int bo = (data[offset + 6] & 0xFF) | ((data[offset + 7] & 0xFF) << 8); int flags = (data[offset + 8] & 0xFF) | ((data[offset + 9] & 0xFF) << 8); boolean extended = ((flags & 0x8000) != 0); boolean kerning = extended && ((flags & 0x2000) != 0); boolean utf8 = extended && ((flags & 0x1000) != 0); int ko = kerning ? ((data[offset + 10] & 0xFF) | ((data[offset + 11] & 0xFF) << 8)) : length; int uo = utf8 ? ((data[offset + 12] & 0xFF) | ((data[offset + 13] & 0xFF) << 8)) : length; // Calculate lengths. int xl = calculateLength(xo, length, bo, ko, uo); int bl = calculateLength(bo, length, xo, ko, uo); int kl = calculateLength(ko, length, xo, bo, uo); // Read x coordinate table. xCoord = new int[xl / 2]; for (int a = offset + xo, i = 0; i < xCoord.length; i++, a += 2) { xCoord[i] = (data[a] & 0xFF) | ((data[a+1] & 0xFF) << 8); } // Read bitmap. bitmap = new byte[bl]; for (int a = offset + bo, i = 0; i < bitmap.length; i++, a++) { bitmap[i] = data[a]; } // Read kerning table. if (kerning) { offsetWidths = new OffsetWidth[kl / 2]; for (int a = offset + ko, i = 0; i < offsetWidths.length; i++, a += 2) { offsetWidths[i] = new OffsetWidth(data[a], (data[a+1] & 0xFF)); } } else { offsetWidths = null; } // Read UTF-8 table. if (utf8) { utf8Map = new UTF8StrikeMap(); utf8Map.read(data, offset + uo); } else { utf8Map = null; } } public byte[] write() { ByteArrayOutputStream out = new ByteArrayOutputStream(); boolean extended = (offsetWidths != null || utf8Map != null); // Calculate offsets. int offset = extended ? 14 : 8; int xo = offset; offset += xCoord.length * 2; int ko = offset; if (offsetWidths != null) offset += offsetWidths.length * 2; int bo = offset; offset += bitmap.length; int uo = offset; // Write header. out.write(ascent); out.write(rowWidth); out.write(rowWidth >> 8); out.write(height); out.write(xo); out.write(xo >> 8); out.write(bo); out.write(bo >> 8); if (extended) { int flags = 0x8000; if (xCoord.length < 96) flags |= 0x4000; if (offsetWidths != null) flags |= 0x2000; if (utf8Map != null) flags |= 0x1000; out.write(flags); out.write(flags >> 8); out.write(ko); out.write(ko >> 8); out.write(uo); out.write(uo >> 8); } // Write x coordinate table. for (int i = 0; i < xCoord.length; i++) { out.write(xCoord[i]); out.write(xCoord[i] >> 8); } // Write kerning table. if (offsetWidths != null) { for (int i = 0; i < offsetWidths.length; i++) { if (offsetWidths[i] != null) { out.write(offsetWidths[i].offset); out.write(offsetWidths[i].width); } else { out.write(0); out.write(0); } } } // Write bitmap. for (int i = 0; i < bitmap.length; i++) { out.write(bitmap[i]); } // Write UTF-8 table. if (utf8Map != null) { byte[] utf8Data = utf8Map.write(uo); for (int i = 0; i < utf8Data.length; i++) { out.write(utf8Data[i]); } } return out.toByteArray(); } private static int calculateLength(int thisStart, int finalEnd, int... otherStart) { int thisEnd = finalEnd; for (int otherEnd : otherStart) { if (otherEnd >= thisStart && otherEnd < thisEnd) { thisEnd = otherEnd; } } return thisEnd - thisStart; } public static final class OffsetWidth { public final int offset; public final int width; public OffsetWidth(int offset, int width) { this.offset = offset; this.width = width; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSIcons.java000066400000000000000000000155241506470510200307760ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.awt.image.BufferedImage; public class GEOSIcons { public static byte[] blankIcon() { return new byte[]{ (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0xFF,(byte)0xFF,(byte)0xFF, }; } public static byte[] fontIcon() { return new byte[]{ (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0xBF,(byte)0x80,(byte)0x01,(byte)0x98,(byte)0x80,(byte)0x09, (byte)0x98,(byte)0x00,(byte)0x19,(byte)0x98,(byte)0x00,(byte)0x19,(byte)0x9E,(byte)0x00,(byte)0x3D, (byte)0x98,(byte)0xE7,(byte)0x99,(byte)0x99,(byte)0xB6,(byte)0xD9,(byte)0x99,(byte)0xB6,(byte)0xD9, (byte)0x99,(byte)0xB6,(byte)0xD9,(byte)0xBC,(byte)0xE6,(byte)0xCD,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0xFF,(byte)0xFF,(byte)0xFF, }; } public static byte[] printerIcon() { return new byte[]{ (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x3F,(byte)0xF1, (byte)0x80,(byte)0x40,(byte)0x61,(byte)0x80,(byte)0x57,(byte)0x61,(byte)0x80,(byte)0x40,(byte)0x61, (byte)0x80,(byte)0x42,(byte)0x61,(byte)0x80,(byte)0x80,(byte)0xC1,(byte)0x83,(byte)0x08,(byte)0xFD, (byte)0x85,(byte)0x00,(byte)0xCD,(byte)0x89,(byte)0xFF,(byte)0xDD,(byte)0x90,(byte)0x00,(byte)0x3D, (byte)0xBF,(byte)0xFF,(byte)0xFD,(byte)0xA0,(byte)0x00,(byte)0x79,(byte)0xA7,(byte)0xF3,(byte)0x71, (byte)0xA0,(byte)0x00,(byte)0x61,(byte)0xBF,(byte)0xFF,(byte)0xC1,(byte)0x80,(byte)0x00,(byte)0x01, (byte)0x80,(byte)0x00,(byte)0x01,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0xFF,(byte)0xFF,(byte)0xFF, }; } public static byte[] paintIcon() { return new byte[]{ (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xC0,(byte)0x00,(byte)0x03,(byte)0xA0,(byte)0x00,(byte)0x05, (byte)0x9F,(byte)0xFF,(byte)0xF9,(byte)0x95,(byte)0x55,(byte)0x59,(byte)0x9A,(byte)0xAA,(byte)0xA9, (byte)0x95,(byte)0x55,(byte)0x59,(byte)0x9A,(byte)0xAA,(byte)0xA9,(byte)0x95,(byte)0x55,(byte)0x59, (byte)0x9A,(byte)0xAA,(byte)0xA9,(byte)0x95,(byte)0x55,(byte)0x59,(byte)0x9A,(byte)0xAA,(byte)0xA9, (byte)0x9F,(byte)0xFF,(byte)0xF9,(byte)0xA0,(byte)0x00,(byte)0x05,(byte)0xC0,(byte)0x00,(byte)0x03, (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x03, (byte)0x7F,(byte)0xFF,(byte)0xB6,(byte)0x80,(byte)0x00,(byte)0xFE,(byte)0x7F,(byte)0xFF,(byte)0xBC, }; } public static byte[] writeIcon() { return new byte[]{ (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x80,(byte)0x00,(byte)0x01,(byte)0x8F,(byte)0xFF,(byte)0x01, (byte)0x88,(byte)0x01,(byte)0x01,(byte)0x8B,(byte)0xFF,(byte)0xC1,(byte)0x8A,(byte)0x00,(byte)0x41, (byte)0x8A,(byte)0xFF,(byte)0xF1,(byte)0x8A,(byte)0x80,(byte)0x11,(byte)0x8A,(byte)0x8E,(byte)0x11, (byte)0x8A,(byte)0x80,(byte)0x11,(byte)0x8A,(byte)0xBF,(byte)0x91,(byte)0x8A,(byte)0x80,(byte)0x11, (byte)0x8A,(byte)0x9F,(byte)0x11,(byte)0x8A,(byte)0x80,(byte)0x11,(byte)0x8A,(byte)0xBF,(byte)0x91, (byte)0x8E,(byte)0x80,(byte)0x11,(byte)0x82,(byte)0xBF,(byte)0x91,(byte)0x83,(byte)0x80,(byte)0x11, (byte)0x80,(byte)0x80,(byte)0x11,(byte)0x80,(byte)0xFF,(byte)0xF1,(byte)0xFF,(byte)0xFF,(byte)0xFF, }; } public static String toString(byte[] iconBitmap) { int[] cps = new int[91]; for (int ci = 0, by = 0; by < 63; by += 9) { for (int bx = 0; bx < 3; bx++) { for (int m = 0x80; m != 0; m >>= 2, ci++) { if ((iconBitmap[by+bx+0] & (m >> 0)) != 0) cps[ci] |= 0x01; if ((iconBitmap[by+bx+0] & (m >> 1)) != 0) cps[ci] |= 0x02; if ((iconBitmap[by+bx+3] & (m >> 0)) != 0) cps[ci] |= 0x04; if ((iconBitmap[by+bx+3] & (m >> 1)) != 0) cps[ci] |= 0x08; if ((iconBitmap[by+bx+6] & (m >> 0)) != 0) cps[ci] |= 0x10; if ((iconBitmap[by+bx+6] & (m >> 1)) != 0) cps[ci] |= 0x20; switch (cps[ci]) { case 0x00: cps[ci] = 0x00A0; break; case 0x15: cps[ci] = 0x258C; break; case 0x2A: cps[ci] = 0x2590; break; case 0x3F: cps[ci] = 0x2588; break; default: if (cps[ci] > 0x2A) cps[ci]--; if (cps[ci] > 0x15) cps[ci]--; if (cps[ci] > 0x00) cps[ci]--; cps[ci] |= 0x1FB00; break; } } } cps[ci] = '\n'; ci++; } StringBuffer sb = new StringBuffer(); for (int cp : cps) sb.append(Character.toChars(cp)); return sb.toString(); } public static byte[][] toGlyph(byte[] iconBitmap) { byte[][] gd = new byte[21][24]; for (int bi = 0, y = 0; y < 21; y++) { for (int x = 0, i = 0; i < 3; i++, bi++) { for (int m = 0x80; m != 0; m >>= 1, x++) { gd[y][x] = ((iconBitmap[bi] & m) == 0) ? (byte)0 : (byte)(-1); } } } return gd; } public static byte[] fromGlyph(byte[][] gd) { byte[] iconBitmap = new byte[63]; for (int bi = 0, y = 0; y < 21; y++) { for (int x = 0, i = 0; i < 3; i++, bi++) { for (int m = 0x80; m != 0; m >>= 1, x++) { if (gd[y][x] < 0) iconBitmap[bi] |= m; } } } return iconBitmap; } public static int[] toRGB(byte[] iconBitmap) { int[] rgb = new int[504]; for (int pi = 0, bi = 0, y = 0; y < 21; y++) { for (int x = 0; x < 3; x++, bi++) { for (int m = 0x80; m != 0; m >>= 1, pi++) { rgb[pi] = ((iconBitmap[bi] & m) == 0) ? 0 : 0xFF000000; } } } return rgb; } public static byte[] fromRGB(int[] rgb) { byte[] iconBitmap = new byte[63]; for (int pi = 0, bi = 0, y = 0; y < 21; y++) { for (int x = 0; x < 3; x++, bi++) { for (int m = 0x80; m != 0; m >>= 1, pi++) { int a = (rgb[pi] >> 24) & 0xFF; int r = (rgb[pi] >> 16) & 0xFF; int g = (rgb[pi] >> 8) & 0xFF; int b = (rgb[pi] >> 0) & 0xFF; int k = (30 * r + 59 * g + 11 * b) / 100; if (a >= 0x80 && k < 0x80) iconBitmap[bi] |= m; } } } return iconBitmap; } public static BufferedImage toImage(byte[] iconBitmap) { BufferedImage image = new BufferedImage(24, 21, BufferedImage.TYPE_INT_ARGB); image.setRGB(0, 0, 24, 21, toRGB(iconBitmap), 0, 24); return image; } public static byte[] fromImage(BufferedImage image, int x, int y) { int[] rgb = new int[504]; image.getRGB(x, y, 24, 21, rgb, 0, 24); return fromRGB(rgb); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSInfoBlock.java000066400000000000000000000155131506470510200315670ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.awt.image.BufferedImage; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.UnsupportedEncodingException; public class GEOSInfoBlock implements CBMConstants { public static final int ICON_WIDTH = 3; public static final int ICON_HEIGHT = 21; public static final int ICON_FLAGS = 0xBF; public int iconWidth; public int iconHeight; public int iconFlags; public byte[] iconBitmap; public int cbmFileType; public int geosFileType; public int fileStructure; public int loadAddress; public int endAddress; public int startAddress; public byte[] classText; public byte[] author; public byte[] creator; public byte[] appData; public byte[] description; public GEOSInfoBlock() { clear(); } public void clear() { iconWidth = ICON_WIDTH; iconHeight = ICON_HEIGHT; iconFlags = ICON_FLAGS; iconBitmap = new byte[63]; cbmFileType = CBM_FILE_TYPE_CLOSED; geosFileType = 0; fileStructure = 0; loadAddress = 0; endAddress = 0xFFFF; startAddress = 0; classText = new byte[20]; author = new byte[20]; creator = new byte[20]; appData = new byte[23]; description = new byte[96]; } public String getIconString() { return GEOSIcons.toString(iconBitmap); } public byte[][] getIconGlyph() { return GEOSIcons.toGlyph(iconBitmap); } public int[] getIconRGB() { return GEOSIcons.toRGB(iconBitmap); } public BufferedImage getIconImage() { return GEOSIcons.toImage(iconBitmap); } public void setIconGlyph(byte[][] gd) { iconBitmap = GEOSIcons.fromGlyph(gd); } public void setIconRGB(int[] rgb) { iconBitmap = GEOSIcons.fromRGB(rgb); } public void setIconImage(BufferedImage image, int x, int y) { iconBitmap = GEOSIcons.fromImage(image, x, y); } public boolean hasAuthorString() { switch (geosFileType) { case GEOS_FILE_TYPE_BASIC: case GEOS_FILE_TYPE_ASSEMBLER: case GEOS_FILE_TYPE_DESK_ACCESSORY: case GEOS_FILE_TYPE_APPLICATION: case GEOS_FILE_TYPE_PRINTER_DRIVER: case GEOS_FILE_TYPE_INPUT_DRIVER: return true; default: return false; } } public boolean hasCreatorString() { return (geosFileType == GEOS_FILE_TYPE_DOCUMENT); } public String getClassTextString() { return toString(classText); } public String getAuthorString() { return toString(author); } public String getCreatorString() { return toString(creator); } public String getDescriptionString() { return toString(description); } public void setClassTextString(String s) { classText = toByteArray(s); } public void setAuthorString(String s) { author = toByteArray(s); } public void setCreatorString(String s) { creator = toByteArray(s); } public void setDescriptionString(String s) { description = toByteArray(s); } public byte getByte(int a) { a &= 0xFF; switch (a) { case 0x02: return (byte)iconWidth; case 0x03: return (byte)iconHeight; case 0x04: return (byte)iconFlags; case 0x44: return (byte)cbmFileType; case 0x45: return (byte)geosFileType; case 0x46: return (byte)fileStructure; case 0x47: return (byte)loadAddress; case 0x48: return (byte)(loadAddress >> 8); case 0x49: return (byte)endAddress; case 0x4A: return (byte)(endAddress >> 8); case 0x4B: return (byte)startAddress; case 0x4C: return (byte)(startAddress >> 8); default: if (a >= 0x05 && a <= 0x43) return iconBitmap [a - 0x05]; if (a >= 0x4D && a <= 0x60) return classText [a - 0x4D]; if (a >= 0x61 && a <= 0x74) return author [a - 0x61]; if (a >= 0x75 && a <= 0x88) return creator [a - 0x75]; if (a >= 0x89 && a <= 0x9F) return appData [a - 0x89]; if (a >= 0xA0 && a <= 0xFF) return description[a - 0xA0]; return 0; } } public void setByte(int a, byte b) { a &= 0xFF; switch (a) { case 0x02: iconWidth = (b & 0xFF); break; case 0x03: iconHeight = (b & 0xFF); break; case 0x04: iconFlags = (b & 0xFF); break; case 0x44: cbmFileType = (b & 0xFF); break; case 0x45: geosFileType = (b & 0xFF); break; case 0x46: fileStructure = (b & 0xFF); break; case 0x47: loadAddress = (loadAddress & 0xFF00) | (b & 0xFF); break; case 0x48: loadAddress = (loadAddress & 0xFF) | ((b & 0xFF) << 8); break; case 0x49: endAddress = (endAddress & 0xFF00) | (b & 0xFF); break; case 0x4A: endAddress = (endAddress & 0xFF) | ((b & 0xFF) << 8); break; case 0x4B: startAddress = (startAddress & 0xFF00) | (b & 0xFF); break; case 0x4C: startAddress = (startAddress & 0xFF) | ((b & 0xFF) << 8); break; default: if (a >= 0x05 && a <= 0x43) iconBitmap [a - 0x05] = b; if (a >= 0x4D && a <= 0x60) classText [a - 0x4D] = b; if (a >= 0x61 && a <= 0x74) author [a - 0x61] = b; if (a >= 0x75 && a <= 0x88) creator [a - 0x75] = b; if (a >= 0x89 && a <= 0x9F) appData [a - 0x89] = b; if (a >= 0xA0 && a <= 0xFF) description[a - 0xA0] = b; break; } } public void read(DataInput in) throws IOException { iconWidth = in.readUnsignedByte(); iconHeight = in.readUnsignedByte(); iconFlags = in.readUnsignedByte(); iconBitmap = new byte[63]; in.readFully(iconBitmap); cbmFileType = in.readUnsignedByte(); geosFileType = in.readUnsignedByte(); fileStructure = in.readUnsignedByte(); loadAddress = Short.reverseBytes(in.readShort()) & 0xFFFF; endAddress = Short.reverseBytes(in.readShort()) & 0xFFFF; startAddress = Short.reverseBytes(in.readShort()) & 0xFFFF; classText = new byte[20]; in.readFully(classText); author = new byte[20]; in.readFully(author); creator = new byte[20]; in.readFully(creator); appData = new byte[23]; in.readFully(appData); description = new byte[96]; in.readFully(description); } public void write(DataOutput out) throws IOException { out.writeByte(iconWidth); out.writeByte(iconHeight); out.writeByte(iconFlags); write(out, iconBitmap, 63); out.writeByte(cbmFileType); out.writeByte(geosFileType); out.writeByte(fileStructure); out.writeShort(Short.reverseBytes((short)loadAddress)); out.writeShort(Short.reverseBytes((short)endAddress)); out.writeShort(Short.reverseBytes((short)startAddress)); write(out, classText, 20); write(out, author, 20); write(out, creator, 20); write(out, appData, 23); write(out, description, 96); } private static String toString(byte[] data) { int len = 0; while (len < data.length && data[len] != 0) len++; try { return new String(data, 0, len, "US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } private static byte[] toByteArray(String s) { try { return s.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } } private static void write(DataOutput out, byte[] data, int len) throws IOException { for (int i = 0; i < data.length && i < len; i++) out.writeByte(data[i]); for (int i = data.length; i < len; i++) out.writeByte(0); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSList.java000066400000000000000000000070021506470510200306260ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class GEOSList { public static void main(String[] args) { PrintWriter out; try { out = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"), true); } catch (UnsupportedEncodingException e) { // Should not happen. throw new RuntimeException(e); } boolean recursive = false; if (args.length == 0) args = new String[]{"."}; for (String arg : args) { if (arg.equals("-r")) { recursive = true; } else { process(out, new File(arg), recursive); } } } private static void process(PrintWriter out, File f, boolean recursive) { if (f.isDirectory()) { for (File ff : f.listFiles()) { if (!ff.getName().startsWith(".")) { if (recursive || ff.isFile()) { process(out, ff, recursive); } } } } else if (f.isFile()) { if (f.getName().toLowerCase().endsWith(".cvt")) { try { FileInputStream in = new FileInputStream(f); CBMDirectoryBlock db = new CBMDirectoryBlock(); db.read(new DataInputStream(in)); if (db.geosFileType != 0) { GEOSInfoBlock ib = new GEOSInfoBlock(); ib.read(new DataInputStream(in)); out.print(ib.getIconString()); out.println(db.getFileName(true, true)); out.println("Class: " + safe(ib.getClassTextString())); if (ib.hasAuthorString()) out.println("Author: " + safe(ib.getAuthorString())); if (ib.hasCreatorString()) out.println("Creator: " + safe(ib.getCreatorString())); out.println("Description: " + safe(ib.getDescriptionString())); if (ib.geosFileType == CBMConstants.GEOS_FILE_TYPE_FONT) { out.println("Font ID: " + getFontID(ib)); out.println("Point Sizes: " + join(getFontPointSizes(ib))); } if (ib.fileStructure == CBMConstants.FILE_STRUCTURE_VLIR) { VLIRRecordBlock rb = new VLIRRecordBlock(); rb.read(new DataInputStream(in)); out.println("VLIR Records: " + join(listRecords(rb))); } out.println(); } in.close(); } catch (IOException e) { // Ignored } } } } private static String safe(String s) { return s.replaceAll("[^!-~]+", " "); } private static int getFontID(GEOSInfoBlock infoBlock) { return ( (infoBlock.getByte(0x80) & 0xFF) | ((infoBlock.getByte(0x81) & 0xFF) << 8) ); } private static List getFontPointSizes(GEOSInfoBlock infoBlock) { List indices = new ArrayList(); for (int a = 0x82, i = 0; i < 15; i++, a += 2) { int index = infoBlock.getByte(a) & 0x3F; if (index == 0) break; indices.add(index); } if (indices.containsAll(Arrays.asList(48,49,50,51,52,53,54))) { indices.removeAll(Arrays.asList(49,50,51,52,53,54)); } return indices; } private static List listRecords(VLIRRecordBlock rb) { List strings = new ArrayList(); for (int i = 0; i < rb.size(); i++) { VLIRRecordBlock.Entry e = rb.get(i); if (e != null && e.length > 0) { strings.add("#" + i + ": " + e); } } return strings; } private static String join(List list) { StringBuffer sb = new StringBuffer(); boolean first = true; for (Object o : list) { if (first) first = false; else sb.append(", "); sb.append(o); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/GEOSSplit.java000066400000000000000000000066431506470510200310200ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.imageio.ImageIO; public class GEOSSplit { public static void main(String[] args) { if (args.length > 0) { boolean recursive = false; for (String arg : args) { if (arg.equals("-r")) { recursive = true; } else { process(new File(arg), recursive); } } } else { System.out.println("Splits GEOS .cvt files into their constituent parts. As applicable:"); System.out.println(" .dir.bin - CBM directory entry"); System.out.println(" .info.bin - GEOS info block"); System.out.println(" .icon.bin - GEOS icon sprite data"); System.out.println(" .icon.png - GEOS icon converted to PNG"); System.out.println(" .rec.bin - VLIR record block"); System.out.println(" .seq.bin - sequential data"); System.out.println(" .0.bin, .1.bin, ... - VLIR records"); } } private static void process(File f, boolean recursive) { if (f.isDirectory()) { for (File ff : f.listFiles()) { if (!ff.getName().startsWith(".")) { if (recursive || ff.isFile()) { process(ff, recursive); } } } } else if (f.isFile()) { if (f.getName().toLowerCase().endsWith(".cvt")) { try { ConvertFile cvt = new ConvertFile(); FileInputStream in = new FileInputStream(f); cvt.read(new DataInputStream(in)); in.close(); if (cvt.directoryBlock != null) { DataOutputStream out = new DataOutputStream( new FileOutputStream(sibling(f, ".dir.bin"))); out.write(0); out.write(0); cvt.directoryBlock.write(out); out.flush(); out.close(); } if (cvt.infoBlock != null) { DataOutputStream out = new DataOutputStream( new FileOutputStream(sibling(f, ".info.bin"))); out.write(0); out.write(0); cvt.infoBlock.write(out); out.flush(); out.close(); FileOutputStream iout = new FileOutputStream(sibling(f, ".icon.bin")); iout.write(cvt.infoBlock.iconBitmap); iout.flush(); iout.close(); ImageIO.write(cvt.infoBlock.getIconImage(), "png", sibling(f, ".icon.png")); } if (cvt.recordBlock != null) { DataOutputStream out = new DataOutputStream( new FileOutputStream(sibling(f, ".rec.bin"))); out.write(0); out.write(0); cvt.recordBlock.write(out); out.flush(); out.close(); } if (cvt.sequentialData != null) { DataOutputStream out = new DataOutputStream( new FileOutputStream(sibling(f, ".seq.bin"))); out.write(cvt.sequentialData); out.flush(); out.close(); } if (cvt.vlirData != null) { for (int i = 0; i < cvt.vlirData.size(); i++) { byte[] data = cvt.vlirData.get(i); if (data.length > 0) { DataOutputStream out = new DataOutputStream( new FileOutputStream(sibling(f, "." + i + ".bin"))); out.write(data); out.flush(); out.close(); } } } } catch (IOException e) { System.err.println("Error reading " + f.getName() + ":"); e.printStackTrace(); } } } } private static File sibling(File f, String suffix) { return new File(f.getParentFile(), f.getName() + suffix); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/PETSCII.java000066400000000000000000000112051506470510200303350ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.ByteArrayOutputStream; public class PETSCII { public static final int[] PRIMARY_G0 = new int[] { 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x00A3, 0x005D, 0x2191, 0x2190, 0x2500, 0x2660, 0x1FB72, 0x1FB78, 0x1FB77, 0x1FB76, 0x1FB7A, 0x1FB71, 0x1FB74, 0x256E, 0x2570, 0x256F, 0x1FB7C, 0x2572, 0x2571, 0x1FB7D, 0x1FB7E, 0x2022, 0x1FB7B, 0x2665, 0x1FB70, 0x256D, 0x2573, 0x25CB, 0x2663, 0x1FB75, 0x2666, 0x253C, 0x1FB8C, 0x2502, 0x03C0, 0x25E5, }; public static final int[] PRIMARY_G1 = new int[] { 0x00A0, 0x258C, 0x2584, 0x2594, 0x2581, 0x258F, 0x2592, 0x2595, 0x1FB8F, 0x25E4, 0x1FB87, 0x251C, 0x2597, 0x2514, 0x2510, 0x2582, 0x250C, 0x2534, 0x252C, 0x2524, 0x258E, 0x258D, 0x1FB88, 0x1FB82, 0x1FB83, 0x2583, 0x1FB7F, 0x2596, 0x259D, 0x2518, 0x2598, 0x259A, 0x2500, 0x2660, 0x1FB72, 0x1FB78, 0x1FB77, 0x1FB76, 0x1FB7A, 0x1FB71, 0x1FB74, 0x256E, 0x2570, 0x256F, 0x1FB7C, 0x2572, 0x2571, 0x1FB7D, 0x1FB7E, 0x2022, 0x1FB7B, 0x2665, 0x1FB70, 0x256D, 0x2573, 0x25CB, 0x2663, 0x1FB75, 0x2666, 0x253C, 0x1FB8C, 0x2502, 0x03C0, 0x25E5, 0x00A0, 0x258C, 0x2584, 0x2594, 0x2581, 0x258F, 0x2592, 0x2595, 0x1FB8F, 0x25E4, 0x1FB87, 0x251C, 0x2597, 0x2514, 0x2510, 0x2582, 0x250C, 0x2534, 0x252C, 0x2524, 0x258E, 0x258D, 0x1FB88, 0x1FB82, 0x1FB83, 0x2583, 0x1FB7F, 0x2596, 0x259D, 0x2518, 0x2598, 0x259A, }; public static final int[] ALTERNATE_G0 = new int[] { 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x00A3, 0x005D, 0x2191, 0x2190, 0x2500, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x253C, 0x1FB8C, 0x2502, 0x1FB96, 0x1FB98, }; public static final int[] ALTERNATE_G1 = new int[] { 0x00A0, 0x258C, 0x2584, 0x2594, 0x2581, 0x258F, 0x2592, 0x2595, 0x1FB8F, 0x1FB99, 0x1FB87, 0x251C, 0x2597, 0x2514, 0x2510, 0x2582, 0x250C, 0x2534, 0x252C, 0x2524, 0x258E, 0x258D, 0x1FB88, 0x1FB82, 0x1FB83, 0x2583, 0x2713, 0x2596, 0x259D, 0x2518, 0x2598, 0x259A, 0x2500, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x253C, 0x1FB8C, 0x2502, 0x1FB96, 0x1FB98, 0x00A0, 0x258C, 0x2584, 0x2594, 0x2581, 0x258F, 0x2592, 0x2595, 0x1FB8F, 0x1FB99, 0x1FB87, 0x251C, 0x2597, 0x2514, 0x2510, 0x2582, 0x250C, 0x2534, 0x252C, 0x2524, 0x258E, 0x258D, 0x1FB88, 0x1FB82, 0x1FB83, 0x2583, 0x2713, 0x2596, 0x259D, 0x2518, 0x2598, 0x259A, }; public static int toUnicode(int cp, boolean alt) { cp &= 0xFF; if (cp >= 0x20 && cp <= 0x7F) return (alt ? ALTERNATE_G0 : PRIMARY_G0)[cp - 0x20]; if (cp >= 0xA0 && cp <= 0xFF) return (alt ? ALTERNATE_G1 : PRIMARY_G1)[cp - 0xA0]; return cp; } public static int fromUnicode(int cp, boolean alt) { if (cp >= 0x00 && cp <= 0x1F) return cp; if (cp >= 0x80 && cp <= 0x9F) return cp; for (int i = 0; i < 96; i++) { if ((alt ? ALTERNATE_G0 : PRIMARY_G0)[i] == cp) { return i + 0x20; } } for (int i = 0; i < 96; i++) { if ((alt ? ALTERNATE_G1 : PRIMARY_G1)[i] == cp) { return i + 0xA0; } } return 0x3F; } public static String toString(byte[] b, boolean alt) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < b.length; i++) { int cp = toUnicode(b[i], alt); sb.append(Character.toChars(cp)); } return sb.toString(); } public static byte[] fromString(String s, boolean alt) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; while (i < s.length()) { int cp = s.codePointAt(i); out.write(fromUnicode(cp, alt)); i += Character.charCount(cp); } return out.toByteArray(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/UTF8StrikeEntry.java000066400000000000000000000021141506470510200321660ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; public class UTF8StrikeEntry implements Comparable { public final int recordIndex; public final int sectorIndex; public final int offset; public final int length; public UTF8StrikeEntry(int recordIndex, int sectorIndex, int length) { this.recordIndex = recordIndex; this.sectorIndex = sectorIndex; this.offset = sectorIndex * 254; this.length = length; } @Override public int compareTo(UTF8StrikeEntry that) { if (this.recordIndex != that.recordIndex) { return this.recordIndex - that.recordIndex; } else { return this.sectorIndex - that.sectorIndex; } } @Override public boolean equals(Object o) { if (o instanceof UTF8StrikeEntry) { UTF8StrikeEntry that = (UTF8StrikeEntry)o; return ( this.recordIndex == that.recordIndex && this.sectorIndex == that.sectorIndex ); } return false; } @Override public int hashCode() { return (this.recordIndex << 16) ^ this.sectorIndex; } @Override public String toString() { return recordIndex + ":" + sectorIndex + ":" + length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/UTF8StrikeIndex.java000066400000000000000000000015411506470510200321370ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.util.TreeSet; public class UTF8StrikeIndex extends TreeSet { private static final long serialVersionUID = 1L; public void read(byte[] data) { this.clear(); for (int i = 0; i + 4 <= data.length; i += 4) { int recordIndex = data[i+0] & 0xFF; int sectorIndex = data[i+1] & 0xFF; int length = (data[i+2] & 0xFF) | ((data[i+3] & 0xFF) << 8); if (recordIndex == 0 && sectorIndex == 0 && length == 0) break; this.add(new UTF8StrikeEntry(recordIndex, sectorIndex, length)); } } public byte[] write() { byte[] data = new byte[this.size() * 4]; int i = 0; for (UTF8StrikeEntry e : this) { data[i+0] = (byte)(e.recordIndex); data[i+1] = (byte)(e.sectorIndex); data[i+2] = (byte)(e.length); data[i+3] = (byte)(e.length >> 8); i += 4; } return data; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/UTF8StrikeMap.java000066400000000000000000000213741506470510200316130ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.util.ArrayList; import java.util.List; import java.util.Map; public class UTF8StrikeMap { public final UTF8StrikeEntry[] lowEntries = new UTF8StrikeEntry[32]; public final SubMap[] highEntries = new SubMap[16]; public final AstralMap[] astralEntries = new AstralMap[6]; public void clear() { for (int i = 0; i < 32; i++) lowEntries[i] = null; for (int i = 0; i < 16; i++) highEntries[i] = null; for (int i = 0; i < 6; i++) astralEntries[i] = null; } public List entryList() { List list = new ArrayList(); for (UTF8StrikeEntry e : lowEntries) { if (e != null) { list.add(e); } } for (SubMap e : highEntries) { if (e != null) { list.addAll(e.entryList()); } } for (AstralMap e : astralEntries) { if (e != null) { list.addAll(e.entryList()); } } return list; } public UTF8StrikeEntry get(int cp) { if (cp < 0x800) { return lowEntries[cp >> 6]; } else if (cp < 0x10000) { SubMap sm = highEntries[cp >> 12]; if (sm == null) return null; return sm.entries[(cp >> 6) & 0x3F]; } else if (cp < 0x180000) { AstralMap am = astralEntries[cp >> 18]; if (am == null) return null; SubMap sm = am.entries[(cp >> 12) & 0x3F]; if (sm == null) return null; return sm.entries[(cp >> 6) & 0x3F]; } else { return null; } } public boolean isEmpty() { for (UTF8StrikeEntry e : lowEntries) { if (e != null) { return false; } } for (SubMap e : highEntries) { if (e != null && !e.isEmpty()) { return false; } } for (AstralMap e : astralEntries) { if (e != null && !e.isEmpty()) { return false; } } return true; } public void remap(Map remap) { for (int i = 0; i < 32; i++) { if (remap.containsKey(lowEntries[i])) { lowEntries[i] = remap.get(lowEntries[i]); } } for (SubMap e : highEntries) { if (e != null) { e.remap(remap); } } for (AstralMap e : astralEntries) { if (e != null) { e.remap(remap); } } } public void remove(int cp) { if (cp < 0x800) { lowEntries[cp >> 6] = null; } else if (cp < 0x10000) { SubMap sm = highEntries[cp >> 12]; if (sm == null) return; sm.entries[(cp >> 6) & 0x3F] = null; if (sm.isEmpty()) highEntries[cp >> 12] = null; } else if (cp < 0x180000) { AstralMap am = astralEntries[cp >> 18]; if (am == null) return; SubMap sm = am.entries[(cp >> 12) & 0x3F]; if (sm == null) return; sm.entries[(cp >> 6) & 0x3F] = null; if (sm.isEmpty()) am.entries[(cp >> 12) & 0x3F] = null; if (am.isEmpty()) astralEntries[cp >> 18] = null; } } public void set(int cp, int ri, int si, int len) { if (cp < 0x800) { lowEntries[cp >> 6] = new UTF8StrikeEntry(ri, si, len); } else if (cp < 0x10000) { SubMap sm = highEntries[cp >> 12]; if (sm == null) sm = highEntries[cp >> 12] = new SubMap(); sm.entries[(cp >> 6) & 0x3F] = new UTF8StrikeEntry(ri, si, len); } else if (cp < 0x180000) { AstralMap am = astralEntries[cp >> 18]; if (am == null) am = astralEntries[cp >> 18] = new AstralMap(); SubMap sm = am.entries[(cp >> 12) & 0x3F]; if (sm == null) sm = am.entries[(cp >> 12) & 0x3F] = new SubMap(); sm.entries[(cp >> 6) & 0x3F] = new UTF8StrikeEntry(ri, si, len); } } public void read(byte[] data, int offset) { this.clear(); for (int i = 0; i < 32; i++) { if (offset + 4 <= data.length) { int ri = data[offset+0] & 0xFF; int si = data[offset+1] & 0xFF; int len = data[offset+2] & 0xFF; len |= ((data[offset+3] & 0xFF) << 8); if (ri != 0 || si != 0 || len != 0) { lowEntries[i] = new UTF8StrikeEntry(ri, si, len); } offset += 4; } else { break; } } for (int i = 0; i < 16; i++) { if (offset + 2 <= data.length) { int eo = data[offset+0] & 0xFF; eo |= ((data[offset+1] & 0xFF) << 8); if (eo != 0) { highEntries[i] = new SubMap(); highEntries[i].read(data, eo); } offset += 2; } else { break; } } for (int i = 0; i < 6; i++) { if (offset + 2 <= data.length) { int eo = data[offset+0] & 0xFF; eo |= ((data[offset+1] & 0xFF) << 8); if (eo != 0) { astralEntries[i] = new AstralMap(); astralEntries[i].read(data, eo); } offset += 2; } else { break; } } } public byte[] write(int offset) { int length = 172; byte[][] smd = new byte[16][]; for (int i = 0; i < 16; i++) { if (highEntries[i] != null) { smd[i] = highEntries[i].write(); length += smd[i].length; } } byte[][] amd = new byte[6][]; for (int i = 0; i < 6; i++) { if (astralEntries[i] != null) { amd[i] = astralEntries[i].write(offset + length); length += amd[i].length; } } byte[] data = new byte[length]; int ptr = 172; for (int a = 0, i = 0; i < 32; i++, a += 4) { if (lowEntries[i] != null) { data[a+0] = (byte)(lowEntries[i].recordIndex); data[a+1] = (byte)(lowEntries[i].sectorIndex); data[a+2] = (byte)(lowEntries[i].length); data[a+3] = (byte)(lowEntries[i].length >> 8); } } for (int a = 128, i = 0; i < 16; i++, a += 2) { if (smd[i] != null) { data[a+0] = (byte)(offset + ptr); data[a+1] = (byte)((offset + ptr) >> 8); for (int j = 0; j < smd[i].length; j++) { data[ptr] = smd[i][j]; ptr++; } } } for (int a = 160, i = 0; i < 6; i++, a += 2) { if (amd[i] != null) { data[a+0] = (byte)(offset + ptr); data[a+1] = (byte)((offset + ptr) >> 8); for (int j = 0; j < amd[i].length; j++) { data[ptr] = amd[i][j]; ptr++; } } } return data; } public static final class SubMap { public final UTF8StrikeEntry[] entries = new UTF8StrikeEntry[64]; public void clear() { for (int i = 0; i < 64; i++) { entries[i] = null; } } public List entryList() { List list = new ArrayList(); for (UTF8StrikeEntry e : entries) { if (e != null) { list.add(e); } } return list; } public boolean isEmpty() { for (UTF8StrikeEntry e : entries) { if (e != null) { return false; } } return true; } public void remap(Map remap) { for (int i = 0; i < 64; i++) { if (remap.containsKey(entries[i])) { entries[i] = remap.get(entries[i]); } } } public void read(byte[] data, int offset) { this.clear(); for (int i = 0; i < 64; i++) { if (offset + 4 <= data.length) { int ri = data[offset+0] & 0xFF; int si = data[offset+1] & 0xFF; int len = data[offset+2] & 0xFF; len |= ((data[offset+3] & 0xFF) << 8); if (ri != 0 || si != 0 || len != 0) { entries[i] = new UTF8StrikeEntry(ri, si, len); } offset += 4; } else { break; } } } public byte[] write() { byte[] data = new byte[256]; for (int a = 0, i = 0; i < 64; i++, a += 4) { if (entries[i] != null) { data[a+0] = (byte)(entries[i].recordIndex); data[a+1] = (byte)(entries[i].sectorIndex); data[a+2] = (byte)(entries[i].length); data[a+3] = (byte)(entries[i].length >> 8); } } return data; } } public static final class AstralMap { public final SubMap[] entries = new SubMap[64]; public void clear() { for (int i = 0; i < 64; i++) { entries[i] = null; } } public List entryList() { List list = new ArrayList(); for (SubMap e : entries) { if (e != null) { list.addAll(e.entryList()); } } return list; } public boolean isEmpty() { for (SubMap e : entries) { if (e != null && !e.isEmpty()) { return false; } } return true; } public void remap(Map remap) { for (SubMap e : entries) { if (e != null) { e.remap(remap); } } } public void read(byte[] data, int offset) { this.clear(); for (int i = 0; i < 64; i++) { if (offset + 2 <= data.length) { int eo = data[offset+0] & 0xFF; eo |= ((data[offset+1] & 0xFF) << 8); if (eo != 0) { entries[i] = new SubMap(); entries[i].read(data, eo); } offset += 2; } else { break; } } } public byte[] write(int offset) { int length = 128; byte[][] smd = new byte[64][]; for (int i = 0; i < 64; i++) { if (entries[i] != null) { smd[i] = entries[i].write(); length += smd[i].length; } } byte[] data = new byte[length]; int ptr = 128; for (int a = 0, i = 0; i < 64; i++, a += 2) { if (smd[i] != null) { data[a+0] = (byte)(offset + ptr); data[a+1] = (byte)((offset + ptr) >> 8); for (int j = 0; j < smd[i].length; j++) { data[ptr] = smd[i][j]; ptr++; } } } return data; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/VLIRRecordBlock.java000066400000000000000000000027301506470510200321260ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; public class VLIRRecordBlock extends ArrayList { private static final long serialVersionUID = 1L; public void read(DataInput in) throws IOException { this.clear(); boolean eof = false; for (int i = 0; i < 127; i++) { int sectorCount = in.readUnsignedByte(); int byteCount = in.readUnsignedByte(); if (!eof) { if (sectorCount == 0 && byteCount == 0) eof = true; else this.add(new Entry(sectorCount, byteCount)); } } } public void write(DataOutput out) throws IOException { for (int i = 0; i < this.size() && i < 127; i++) { Entry e = this.get(i); out.writeByte(e.sectorCount); out.writeByte(e.byteCount); } for (int i = this.size(); i < 127; i++) { out.writeByte(0); out.writeByte(0); } } public static final class Entry { public final int sectorCount; public final int byteCount; public final int length; public Entry(int sectorCount, int byteCount) { this.sectorCount = sectorCount; this.byteCount = byteCount; this.length = (sectorCount * 254) - (255 - byteCount); } public Entry(int length) { this.sectorCount = (length + 253) / 254; this.byteCount = 255 - (sectorCount * 254 - length); this.length = length; } @Override public String toString() { return sectorCount + "." + byteCount + ":" + length; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/000077500000000000000000000000001506470510200275235ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/FontIcon.png000066400000000000000000000017401506470510200317520ustar00rootroot00000000000000PNG  IHDRk7tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp s&PLTETUxBIDATxb` $  "K0 K&,"fB Q`ED`4#r"$pQ>LIENDB`GEOSFontInfoPanel.java000066400000000000000000000112261506470510200334710ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/moverpackage com.kreative.bitsnpicas.geos.mover; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class GEOSFontInfoPanel extends JPanel { private static final long serialVersionUID = 1L; private GEOSFontFile gff; private GEOSIconWell iconWell; private JTextField nameField; private SpinnerNumberModel idSpinner; private JTextField classField; private JLabel classLengthLabel; private JTextField descriptionField; public GEOSFontInfoPanel(GEOSFontFile gff) { this.gff = gff; this.iconWell = new GEOSIconWell(gff.infoBlock.iconBitmap); this.nameField = new JTextField(gff.getFontName()); this.idSpinner = new SpinnerNumberModel(gff.getFontID(), 0, 1023, 1); String classText = gff.getClassTextString(); String ctLen = Integer.toString(classText.length()); this.classField = new JTextField(classText); this.classLengthLabel = new JLabel(ctLen); this.descriptionField = new JTextField(gff.getDescriptionString()); JPanel rightLabelPanel = new JPanel(new GridLayout(0,1,4,4)); rightLabelPanel.add(new JLabel("Font ID:")); rightLabelPanel.add(new JLabel("Length:")); rightLabelPanel.add(new JLabel(" ")); JPanel rightControlPanel = new JPanel(new GridLayout(0,1,4,4)); rightControlPanel.add(new JSpinner(idSpinner)); rightControlPanel.add(classLengthLabel); rightControlPanel.add(new JLabel(" ")); JPanel rightPanel = new JPanel(new BorderLayout(8,8)); rightPanel.add(rightLabelPanel, BorderLayout.LINE_START); rightPanel.add(rightControlPanel, BorderLayout.CENTER); JPanel centerLabelPanel = new JPanel(new GridLayout(0,1,4,4)); centerLabelPanel.add(new JLabel("Font Name:")); centerLabelPanel.add(new JLabel("Class Text:")); centerLabelPanel.add(new JLabel("Description:")); JPanel centerControlPanel = new JPanel(new GridLayout(0,1,4,4)); centerControlPanel.add(nameField); centerControlPanel.add(classField); centerControlPanel.add(descriptionField); JPanel centerPanel = new JPanel(new BorderLayout(8,8)); centerPanel.add(centerLabelPanel, BorderLayout.LINE_START); centerPanel.add(centerControlPanel, BorderLayout.CENTER); JPanel mainPanel = new JPanel(new BorderLayout(12,12)); mainPanel.add(iconWell, BorderLayout.LINE_START); mainPanel.add(centerPanel, BorderLayout.CENTER); mainPanel.add(rightPanel, BorderLayout.LINE_END); setLayout(new GridLayout()); add(mainPanel); init(); } private void init() { iconWell.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { gff.infoBlock.iconBitmap = iconWell.getIconData(); fireChangeEvent(); } }); nameField.getDocument().addDocumentListener(new DocumentAdapter() { public void documentUpdate(DocumentEvent e) { gff.setFontName(nameField.getText()); fireChangeEvent(); } }); idSpinner.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { gff.setFontID(idSpinner.getNumber().intValue()); fireChangeEvent(); } }); classField.getDocument().addDocumentListener(new DocumentAdapter() { public void documentUpdate(DocumentEvent e) { String classText = classField.getText(); String ctLen = Integer.toString(classText.length()); gff.setClassTextString(classText); classLengthLabel.setText(ctLen); fireChangeEvent(); } }); descriptionField.getDocument().addDocumentListener(new DocumentAdapter() { public void documentUpdate(DocumentEvent e) { gff.setDescriptionString(descriptionField.getText()); fireChangeEvent(); } }); } public void addChangeListener(ChangeListener cl) { this.listenerList.add(ChangeListener.class, cl); } public void removeChangeListener(ChangeListener cl) { this.listenerList.remove(ChangeListener.class, cl); } public ChangeListener[] getChangeListeners() { return this.listenerList.getListeners(ChangeListener.class); } private void fireChangeEvent() { ChangeEvent e = new ChangeEvent(this); for (ChangeListener cl : getChangeListeners()) { cl.stateChanged(e); } } private static abstract class DocumentAdapter implements DocumentListener { public void changedUpdate(DocumentEvent e) { documentUpdate(e); } public void insertUpdate(DocumentEvent e) { documentUpdate(e); } public void removeUpdate(DocumentEvent e) { documentUpdate(e); } public abstract void documentUpdate(DocumentEvent e); } } GEOSFontPointSizeSelection.java000066400000000000000000000032301506470510200354040ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/moverpackage com.kreative.bitsnpicas.geos.mover; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.kreative.bitsnpicas.geos.GEOSFontPointSize; public class GEOSFontPointSizeSelection implements ClipboardOwner, Transferable { // I has a flavor. public static final DataFlavor geosFontPointSizeFlavor = new DataFlavor(GEOSFontPointSize.class, "GEOS Font Point Size"); private List gfps; public GEOSFontPointSizeSelection(GEOSFontPointSize gfps) { this.gfps = new ArrayList(); this.gfps.add(gfps); } public GEOSFontPointSizeSelection(GEOSFontPointSize[] gfps) { this.gfps = new ArrayList(); this.gfps.addAll(Arrays.asList(gfps)); } public GEOSFontPointSizeSelection(List gfps) { this.gfps = new ArrayList(); this.gfps.addAll(gfps); } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (geosFontPointSizeFlavor.equals(flavor)) { return gfps; } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{geosFontPointSizeFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return (geosFontPointSizeFlavor.equals(flavor)); } public void lostOwnership(Clipboard clipboard, Transferable contents) { // nothing } } GEOSFontPointSizeTable.java000066400000000000000000000176211506470510200345170ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/moverpackage com.kreative.bitsnpicas.geos.mover; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.DefaultCellEditor; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.border.Border; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.geos.GEOSFontFile; import com.kreative.bitsnpicas.geos.GEOSFontPointSize; import com.kreative.bitsnpicas.importer.GEOSBitmapFontImporter; public class GEOSFontPointSizeTable extends JTable { private static final long serialVersionUID = 1L; public GEOSFontPointSizeTable(GEOSFontPointSizeTableModel model) { super(model); setColumnWidth(0, 40); setColumnWidth(1, 100); setColumnWidth(2, 100); setDefaultEditor(Integer.class, new MyCellEditor()); setDefaultRenderer(Integer.class, new MyCellRenderer()); setDefaultRenderer(String.class, new MyCellRenderer()); setIntercellSpacing(new Dimension(0,1)); setRowHeight(26); this.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() >= 2) { doOpen(); } } }); InputMap im = getInputMap(); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, skm), "Cut"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, skm), "Copy"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, skm), "Paste"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, skm), "Clear"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, skm), "Clear"); ActionMap am = getActionMap(); am.put("Cut", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCut(); } }); am.put("Copy", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCopy(); } }); am.put("Paste", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doPaste(); } }); am.put("Clear", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doClear(); } }); DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY, new DragGestureListener() { public void dragGestureRecognized(DragGestureEvent e) { if (e.getDragOrigin().x < 40) { List gfps = getSelectedPointSizeObjects(); if (gfps.isEmpty()) return; e.startDrag(null, new GEOSFontPointSizeSelection(gfps)); } } } ); } public void createDropTarget(JComponent c) { new DropTarget(c, new DropTargetListener() { public void dragEnter(DropTargetDragEvent e) {} public void dragExit(DropTargetEvent e) {} public void dragOver(DropTargetDragEvent e) {} public void dropActionChanged(DropTargetDragEvent e) {} public void drop(DropTargetDropEvent e) { try { e.acceptDrop(e.getDropAction()); Transferable t = e.getTransferable(); DataFlavor fl = GEOSFontPointSizeSelection.geosFontPointSizeFlavor; if (t.isDataFlavorSupported(fl)) { List gfpsl = (List)t.getTransferData(fl); if (gfpsl != null && !gfpsl.isEmpty()) { GEOSFontPointSizeTableModel model = getPointSizeModel(); GEOSFontFile gff = model.getFontFile(); for (Object gfpso : gfpsl) { GEOSFontPointSize gfps = (GEOSFontPointSize)gfpso; gff.setFontPointSize(gfps.pointSize, gfps); } model.refresh(); e.dropComplete(true); } else { e.dropComplete(false); } } else { e.dropComplete(false); } } catch (Exception ex) { e.dropComplete(false); } } }); } public GEOSFontPointSizeTableModel getPointSizeModel() { return (GEOSFontPointSizeTableModel)getModel(); } public List getSelectedPointSizes() { List list = new ArrayList(); GEOSFontPointSizeTableModel model = getPointSizeModel(); for (int i : getSelectedRows()) list.add(model.getPointSize(i)); return list; } public List getSelectedPointSizeObjects() { List list = new ArrayList(); GEOSFontFile gff = getPointSizeModel().getFontFile(); for (int i : getSelectedPointSizes()) list.add(gff.getFontPointSize(i)); return list; } public void doOpen() { GEOSBitmapFontImporter importer = new GEOSBitmapFontImporter(); GEOSFontFile gff = getPointSizeModel().getFontFile(); for (int i : getSelectedPointSizes()) { BitmapFont font = importer.importFont(gff, i); Main.openFont(null, null, font); } } public void doCut() { doCopy(); doClear(); } public void doCopy() { List gfps = getSelectedPointSizeObjects(); if (gfps.isEmpty()) return; Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new GEOSFontPointSizeSelection(gfps), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); } public void doPaste() { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); DataFlavor flavor = GEOSFontPointSizeSelection.geosFontPointSizeFlavor; if (cb.isDataFlavorAvailable(flavor)) { try { List gfpsl = (List)cb.getData(flavor); if (gfpsl == null || gfpsl.isEmpty()) return; GEOSFontPointSizeTableModel model = getPointSizeModel(); GEOSFontFile gff = model.getFontFile(); for (Object gfpso : gfpsl) { GEOSFontPointSize gfps = (GEOSFontPointSize)gfpso; gff.setFontPointSize(gfps.pointSize, gfps); } model.refresh(); } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void doClear() { GEOSFontPointSizeTableModel model = getPointSizeModel(); GEOSFontFile gff = model.getFontFile(); for (int i : getSelectedPointSizes()) gff.removeFontPointSize(i); model.refresh(); } private void setColumnWidth(int i, int width) { TableColumn col = getColumnModel().getColumn(i); col.setWidth(width); col.setMinWidth(width); col.setMaxWidth(width); } private static class MyCellEditor extends DefaultCellEditor { private static final long serialVersionUID = 1L; public MyCellEditor() { super(new JTextField()); } } private static class MyCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private static final Border padding = BorderFactory.createEmptyBorder(0, 4, 0, 4); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JComponent c = (JComponent)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); c.setBorder(BorderFactory.createCompoundBorder(c.getBorder(), padding)); return c; } } } GEOSFontPointSizeTableModel.java000066400000000000000000000057001506470510200354730ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/moverpackage com.kreative.bitsnpicas.geos.mover; import java.util.ArrayList; import java.util.List; import javax.swing.ImageIcon; import javax.swing.table.AbstractTableModel; import com.kreative.bitsnpicas.geos.GEOSFontFile; import com.kreative.bitsnpicas.geos.GEOSFontPointSize; public class GEOSFontPointSizeTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private static final ImageIcon ICON = new ImageIcon( GEOSFontPointSizeTableModel.class.getResource("FontIcon.png") ); private GEOSFontFile gff; private List items; private static final class Item { public int pointSize; public int sectorCount; public String typeString; } public GEOSFontPointSizeTableModel(GEOSFontFile gff) { this.gff = gff; refresh(); } public GEOSFontFile getFontFile() { return gff; } public int getPointSize(int row) { return items.get(row).pointSize; } public void refresh() { items = new ArrayList(); for (int pointSize : gff.getFontPointSizes()) { Item item = new Item(); item.pointSize = pointSize; item.sectorCount = gff.getFontPointSizeSectorCount(pointSize); item.typeString = gff.getFontPointSizeTypeString(pointSize); items.add(item); } fireTableDataChanged(); } @Override public Class getColumnClass(int col) { switch (col) { case 0: return ImageIcon.class; case 1: return Integer.class; case 2: return Integer.class; case 3: return String.class; default: return null; } } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int col) { switch (col) { case 0: return ""; case 1: return "Point Size"; case 2: return "Sectors"; case 3: return "Type"; default: return null; } } @Override public int getRowCount() { return items.size(); } @Override public Object getValueAt(int row, int col) { switch (col) { case 0: return ICON; case 1: return items.get(row).pointSize; case 2: return items.get(row).sectorCount; case 3: return items.get(row).typeString; default: return null; } } @Override public boolean isCellEditable(int row, int col) { if (col == 1) { int pointSize = items.get(row).pointSize; if (pointSize == 48 && gff.isMega()) return false; return true; } return false; } @Override public void setValueAt(Object value, int row, int col) { if (col == 1) { try { int oldPointSize = items.get(row).pointSize; if (oldPointSize == 48 && gff.isMega()) return; int newPointSize = Integer.parseInt(value.toString()); if ( newPointSize != oldPointSize && newPointSize > 0 && newPointSize < 64 ) { GEOSFontPointSize gfps = gff.getFontPointSize(oldPointSize); if (gfps == null) return; gff.removeFontPointSize(newPointSize); gff.removeFontPointSize(oldPointSize); gff.setFontPointSize(newPointSize, gfps); refresh(); } } catch (NumberFormatException nfe) { return; } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/GEOSIconWell.java000066400000000000000000000156651506470510200325750ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos.mover; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.IOException; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.kreative.bitsnpicas.datatransfer.ImageSelection; import com.kreative.bitsnpicas.geos.GEOSIcons; public class GEOSIconWell extends JComponent { private static final long serialVersionUID = 1L; private byte[] iconData; private BufferedImage iconImage; public GEOSIconWell() { resetIcon(); init(); } public GEOSIconWell(byte[] iconData) { setIcon(iconData); init(); } public GEOSIconWell(Image iconImage) { setIcon(iconImage); init(); } private void init() { this.setFocusable(true); this.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { requestFocusInWindow(); } }); this.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { repaint(); } public void focusLost(FocusEvent e) { repaint(); } }); InputMap im = getInputMap(); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, skm), "Cut"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, skm), "Copy"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, skm), "Paste"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, skm), "Clear"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, skm), "Clear"); ActionMap am = getActionMap(); am.put("Cut", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCut(); } }); am.put("Copy", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCopy(); } }); am.put("Paste", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doPaste(); } }); am.put("Clear", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { resetIcon(); } }); DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY, new DragGestureListener() { public void dragGestureRecognized(DragGestureEvent e) { e.startDrag(null, new ImageSelection(iconImage)); } } ); new DropTarget(this, new DropTargetListener() { public void dragEnter(DropTargetDragEvent e) {} public void dragExit(DropTargetEvent e) {} public void dragOver(DropTargetDragEvent e) {} public void dropActionChanged(DropTargetDragEvent e) {} public void drop(DropTargetDropEvent e) { try { e.acceptDrop(e.getDropAction()); Transferable t = e.getTransferable(); if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image = (Image)t.getTransferData(DataFlavor.imageFlavor); setIcon(image); e.dropComplete(true); } else { e.dropComplete(false); } } catch (Exception ex) { e.dropComplete(false); } } }); } public byte[] getIconData() { return iconData; } public BufferedImage getIconImage() { return iconImage; } public void resetIcon() { this.iconData = GEOSIcons.fontIcon(); this.iconImage = GEOSIcons.toImage(iconData); this.repaint(); this.fireChangeEvent(); } public void setIcon(byte[] iconData) { this.iconData = iconData; this.iconImage = GEOSIcons.toImage(iconData); this.repaint(); this.fireChangeEvent(); } public void setIcon(Image image) { BufferedImage bi = new BufferedImage(24, 21, BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); g.drawImage(image, 0, 0, 24, 21, null); g.dispose(); this.iconData = GEOSIcons.fromImage(bi, 0, 0); this.iconImage = GEOSIcons.toImage(iconData); this.repaint(); this.fireChangeEvent(); } public void doCut() { doCopy(); resetIcon(); } public void doCopy() { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new ImageSelection(iconImage), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); } public void doPaste() { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(DataFlavor.imageFlavor)) { try { Image image = (Image)cb.getData(DataFlavor.imageFlavor); if (image != null) setIcon(image); } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void addChangeListener(ChangeListener cl) { this.listenerList.add(ChangeListener.class, cl); } public void removeChangeListener(ChangeListener cl) { this.listenerList.remove(ChangeListener.class, cl); } public ChangeListener[] getChangeListeners() { return this.listenerList.getListeners(ChangeListener.class); } private void fireChangeEvent() { ChangeEvent e = new ChangeEvent(this); for (ChangeListener cl : getChangeListeners()) { cl.stateChanged(e); } } public Dimension getMinimumSize() { Insets i = getInsets(); int w = 52 + i.left + i.right; int h = 46 + i.top + i.bottom; return new Dimension(w, h); } public Dimension getPreferredSize() { Insets i = getInsets(); int w = 52 + i.left + i.right; int h = 46 + i.top + i.bottom; return new Dimension(w, h); } protected void paintComponent(Graphics g) { Insets insets = getInsets(); int w = getWidth() - insets.left - insets.right - 4; int h = getHeight() - insets.top - insets.bottom - 4; int sf = Math.max(1, Math.min(w / 24, h / 21)); int x = insets.left + (w - sf * 24) / 2 + 2; int y = insets.top + (h - sf * 21) / 2 + 2; w = sf * 24; h = sf * 21; if (this.hasFocus()) { g.setColor(new Color(0x99CCDD)); g.fillRect(x-2, y-2, w+4, h+4); } else { g.setColor(new Color(0xEEEEEE)); g.fillRect(x, y, w, h); } if (iconImage != null) g.drawImage(iconImage, x, y, w, h, null); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/GEOSMoverFrame.java000066400000000000000000000024111506470510200331050ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos.mover; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import javax.swing.JFrame; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class GEOSMoverFrame extends JFrame { private static final long serialVersionUID = 1L; private final SaveManager sm; private final GEOSMoverPanel panel; private final GEOSMoverMenuBar mb; public GEOSMoverFrame(File file, GEOSFontFile gff) { super(gff.getFontName()); this.sm = new SaveManager(this, file, gff); this.panel = new GEOSMoverPanel(this, gff, sm); this.mb = new GEOSMoverMenuBar(this, sm, panel.getTable()); setJMenuBar(mb); setContentPane(panel); setSize(600, 400); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(sm); } public static GEOSMoverFrame forNewFile() { return new GEOSMoverFrame(null, new GEOSFontFile()); } public static GEOSMoverFrame forFile(File file) throws IOException { DataInputStream in = new DataInputStream( new FileInputStream(file)); GEOSFontFile gff = new GEOSFontFile(); gff.read(in); in.close(); if (gff.isValid()) { return new GEOSMoverFrame(file, gff); } else { return null; } } } GEOSMoverMenuBar.java000066400000000000000000000041631506470510200333330ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/moverpackage com.kreative.bitsnpicas.geos.mover; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.datatransfer.ClearMenuItem; import com.kreative.bitsnpicas.datatransfer.CopyMenuItem; import com.kreative.bitsnpicas.datatransfer.CutMenuItem; import com.kreative.bitsnpicas.datatransfer.PasteMenuItem; import com.kreative.bitsnpicas.edit.CommonMenuItems; public class GEOSMoverMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public GEOSMoverMenuBar(final Window window, final SaveManager sm, final GEOSFontPointSizeTable table) { add(new FileMenu(window, sm)); add(new EditMenu(table)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Window window, final SaveManager sm) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(window)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(final GEOSFontPointSizeTable table) { super("Edit"); add(new CutMenuItem()); add(new CopyMenuItem()); add(new PasteMenuItem()); add(new ClearMenuItem()); addSeparator(); add(new OpenItemsMenuItem(table)); } } public static class OpenItemsMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenItemsMenuItem(final GEOSFontPointSizeTable table) { super("Open Items"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { table.doOpen(); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/GEOSMoverPanel.java000066400000000000000000000037501506470510200331210ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos.mover; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class GEOSMoverPanel extends JPanel { private static final long serialVersionUID = 1L; private final GEOSFontInfoPanel infoPanel; private final GEOSFontPointSizeTableModel tableModel; private final GEOSFontPointSizeTable table; private final JScrollPane tablePane; public GEOSMoverPanel(JFrame parent, GEOSFontFile gff, final SaveManager sm) { this.infoPanel = new GEOSFontInfoPanel(gff); this.tableModel = new GEOSFontPointSizeTableModel(gff); this.table = new GEOSFontPointSizeTable(tableModel); this.tablePane = new JScrollPane( table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ); JPanel mainPanel = new JPanel(new BorderLayout()); infoPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); mainPanel.add(infoPanel, BorderLayout.PAGE_START); mainPanel.add(tablePane); table.createDropTarget(tablePane); setLayout(new BorderLayout()); add(mainPanel, BorderLayout.CENTER); infoPanel.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { sm.setChanged(); } }); tableModel.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { sm.setChanged(); } }); parent.addWindowListener(new WindowAdapter() { public void windowOpened(WindowEvent e) { table.requestFocusInWindow(); } }); } public GEOSFontPointSizeTableModel getTableModel() { return tableModel; } public GEOSFontPointSizeTable getTable() { return table; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/geos/mover/SaveManager.java000066400000000000000000000043061506470510200325620ustar00rootroot00000000000000package com.kreative.bitsnpicas.geos.mover; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.JFrame; import com.kreative.bitsnpicas.edit.CommonMenuItems; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.edit.SaveChangesDialog; import com.kreative.bitsnpicas.edit.SaveInterface; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class SaveManager extends WindowAdapter implements SaveInterface { private JFrame frame; private File file; private GEOSFontFile gff; private boolean changed; public SaveManager(JFrame frame, File file, GEOSFontFile gff) { this.frame = frame; this.file = file; this.gff = gff; this.changed = false; updateWindow(); } public void setChanged() { this.changed = true; updateWindow(); } public boolean save() { if (file == null) return saveAs(); boolean succeeded = write(); if (succeeded) changed = false; updateWindow(); return succeeded; } public boolean saveAs() { File newFile = Main.getSaveFile(".cvt"); if (newFile == null) return false; file = newFile; boolean succeeded = write(); if (succeeded) changed = false; updateWindow(); return succeeded; } private boolean write() { try { DataOutputStream out = new DataOutputStream( new FileOutputStream(file)); gff.write(out); out.flush(); out.close(); return true; } catch (IOException e) { return false; } } public void windowClosing(WindowEvent e) { Window w = e.getWindow(); if (!changed) w.dispose(); else switch (new SaveChangesDialog(w, gff.getFontName()).showDialog()) { case SAVE: if (save()) w.dispose(); break; case DONT_SAVE: w.dispose(); break; case CANCEL: break; } } private void updateWindow() { if (CommonMenuItems.IS_MAC_OS) { frame.getRootPane().putClientProperty("Window.documentFile", file); frame.getRootPane().putClientProperty("Window.documentModified", changed); frame.setTitle(gff.getFontName()); } else { frame.setTitle(changed ? (gff.getFontName() + " \u2022") : gff.getFontName()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importer/000077500000000000000000000000001506470510200272775ustar00rootroot00000000000000AmigaBitmapFontImporter.java000066400000000000000000000270241506470510200346140ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.*; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public abstract class AmigaBitmapFontImporter implements BitmapFontImporter { public static final int STYLE_UNDERLINED = 0x01; public static final int STYLE_BOLD = 0x02; public static final int STYLE_ITALIC = 0x04; public static final int STYLE_EXTENDED = 0x08; public static final int STYLE_COLORFONT = 0x40; public static final int STYLE_TAGGED = 0x80; public static final int FLAGS_ROMFONT = 0x01; public static final int FLAGS_DISKFONT = 0x02; public static final int FLAGS_REVPATH = 0x04; public static final int FLAGS_TALLDOT = 0x08; public static final int FLAGS_WIDEDOT = 0x10; public static final int FLAGS_PROPORTIONAL = 0x20; public static final int FLAGS_DESIGNED = 0x40; public static final int FLAGS_REMOVED = 0x80; public static final int CTFFLAGS_COLORFONT = 0x0001; public static final int CTFFLAGS_GREYFONT = 0x0002; public static final int CTFFLAGS_ANTIALIAS = 0x0004; protected GlyphList encoding; protected AmigaBitmapFontImporter() { this.encoding = null; } protected AmigaBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } public static final class ContentsFile extends AmigaBitmapFontImporter { public ContentsFile() { super(); } public ContentsFile(GlyphList encoding) { super(encoding); } public BitmapFont[] importFont(File file) throws IOException { FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis); BitmapFont[] f = importFont(file.getParentFile(), dis); dis.close(); fis.close(); return f; } public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bis); BitmapFont[] f = importFont(new File("."), dis); dis.close(); bis.close(); return f; } public BitmapFont[] importFont(InputStream is) throws IOException { return importFont(new File("."), new DataInputStream(is)); } public BitmapFont[] importFont(File parent, DataInput in) throws IOException { int id = in.readUnsignedShort(); if (!(id == 0x0F00 || id == 0x0F02)) throw new IOException("bad magic number"); int count = in.readUnsignedShort(); BitmapFont[] f = new BitmapFont[count]; for (int i = 0; i < count; i++) { byte[] pdata = new byte[256]; in.readFully(pdata); int len = 0; while (len < 256 && pdata[len] != 0) len++; String[] path = new String(pdata, 0, len, "UTF-8").split("/"); File ff = findFile(parent, path); in.readUnsignedShort(); // YSize in.readUnsignedByte(); // Style in.readUnsignedByte(); // Flags f[i] = importFont1(ff, path[0]); } return f; } private static File findFile(File parent, String[] path) { for (String name : path) { File[] children = parent.listFiles(); parent = new File(parent, name); if (children != null) { for (File child : children) { if (child.getName().equalsIgnoreCase(name)) { parent = child; } } } } return parent; } } public static final class DescriptorFile extends AmigaBitmapFontImporter { public DescriptorFile() { super(); } public DescriptorFile(GlyphList encoding) { super(encoding); } public BitmapFont[] importFont(File file) throws IOException { BitmapFont f = importFont1(file, "Untitled"); return new BitmapFont[]{f}; } public BitmapFont[] importFont(InputStream is) throws IOException { BitmapFont f = importFont1(is, "Untitled"); return new BitmapFont[]{f}; } public BitmapFont[] importFont(byte[] data) throws IOException { BitmapFont f = importFont1(data, "Untitled"); return new BitmapFont[]{f}; } } protected BitmapFont importFont1(File file, String fontName) throws IOException { FileInputStream is = new FileInputStream(file); BitmapFont f = importFont1(is, fontName); is.close(); return f; } protected BitmapFont importFont1(InputStream is, String fontName) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int count; while ((count = is.read(buf)) > 0) os.write(buf, 0, count); os.flush(); os.close(); buf = os.toByteArray(); return importFont1(buf, fontName); } protected BitmapFont importFont1(byte[] data, String fontName) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); DataInputStream fontIn = new DataInputStream(in); int hunkHeader = fontIn.readInt(); if (hunkHeader != 0x03F3) throw new IOException("bad magic number"); int strList = fontIn.readInt(); if (strList != 0) throw new IOException("bad magic number"); int hunks = fontIn.readInt(); if (hunks != 1) throw new IOException("bad magic number"); int firstHunk = fontIn.readInt(); if (firstHunk != 0) throw new IOException("bad magic number"); int lastHunk = fontIn.readInt(); if (lastHunk != 0) throw new IOException("bad magic number"); fontIn.readInt(); // hunk size int hunkType = fontIn.readInt(); if (hunkType != 0x03E9) throw new IOException("bad magic number"); fontIn.readInt(); // hunk size int base = 32; // current position; start of code hunk data fontIn.readInt(); // MOVEQ #0,D0; RTS int lnSucc = fontIn.readInt(); if (lnSucc != 0) throw new IOException("bad magic number"); int lnPred = fontIn.readInt(); if (lnPred != 0) throw new IOException("bad magic number"); int lnType = fontIn.readUnsignedByte(); if (lnType != 0x0C) throw new IOException("bad magic number"); int lnPri = fontIn.readUnsignedByte(); if (lnPri != 0) throw new IOException("bad magic number"); int lnName = fontIn.readInt(); if (lnName != 0x1A) throw new IOException("bad magic number"); int fileID = fontIn.readUnsignedShort(); if (fileID != 0x0F80) throw new IOException("bad magic number"); fontIn.readUnsignedShort(); // revision int segment = fontIn.readInt(); if (segment != 0) throw new IOException("bad magic number"); byte[] ndata = new byte[32]; fontIn.readFully(ndata); int len = 0; while (len < 32 && ndata[len] != 0) len++; if (len > 0) fontName = new String(ndata, 0, len, "ISO-8859-1"); lnSucc = fontIn.readInt(); if (lnSucc != 0) throw new IOException("bad magic number"); lnPred = fontIn.readInt(); if (lnPred != 0) throw new IOException("bad magic number"); lnType = fontIn.readUnsignedByte(); if (lnType != 0x0C) throw new IOException("bad magic number"); lnPri = fontIn.readUnsignedByte(); if (lnPri != 0) throw new IOException("bad magic number"); lnName = fontIn.readInt(); if (lnName != 0x1A) throw new IOException("bad magic number"); int mnReplyPort = fontIn.readInt(); if (mnReplyPort != 0) throw new IOException("bad magic number"); fontIn.readUnsignedShort(); // mnLength int ySize = fontIn.readUnsignedShort(); int style = fontIn.readUnsignedByte(); fontIn.readUnsignedByte(); // flags int xSize = fontIn.readUnsignedShort(); int baseline = fontIn.readUnsignedShort(); fontIn.readUnsignedShort(); // boldSmear fontIn.readUnsignedShort(); // accessors int loChar = fontIn.readUnsignedByte(); int hiChar = fontIn.readUnsignedByte(); int charData = fontIn.readInt(); int modulo = fontIn.readUnsignedShort(); int charLoc = fontIn.readInt(); int charSpace = fontIn.readInt(); int charKern = fontIn.readInt(); /* boolean isColor = ((style & STYLE_COLORFONT) != 0); int ctfFlags = isColor ? fontIn.readUnsignedShort() : 0; int ctfDepth = isColor ? fontIn.readUnsignedByte() : 0; int ctfFgColor = isColor ? fontIn.readUnsignedByte() : 0; int ctfLowColor = isColor ? fontIn.readUnsignedByte() : 0; int ctfHighColor = isColor ? fontIn.readUnsignedByte() : 0; int ctfPlanePick = isColor ? fontIn.readUnsignedByte() : 0; int ctfPlaneOnOff = isColor ? fontIn.readUnsignedByte() : 0; int ctfColorFontColors = isColor ? fontIn.readInt() : 0; int[] ctfCharData = new int[ctfDepth]; for (int i = 0; i < ctfDepth; i++) ctfCharData[i] = fontIn.readInt(); */ fontIn.close(); in.close(); byte[][] bitmap = new byte[ySize][modulo * 8]; if (charData > 0) { for (int j = base + charData, y = 0; y < ySize; y++, j += modulo) { for (int di = 0, si = j, x = 0; x < modulo; x++, si++) { for (int m = 0x80; m != 0; m >>= 1, di++) { if ((data[si] & m) != 0) bitmap[y][di] = -1; } } } } int n = hiChar - loChar + 2; int[] bitOffset = new int[n]; int[] bitSize = new int[n]; int[] spacing = new int[n]; int[] kerning = new int[n]; if (charLoc > 0) { in = new ByteArrayInputStream(data, base + charLoc, data.length - (base + charLoc)); fontIn = new DataInputStream(in); for (int i = 0; i < n; i++) { bitOffset[i] = fontIn.readUnsignedShort(); bitSize[i] = fontIn.readUnsignedShort(); } fontIn.close(); in.close(); } if (charSpace > 0) { in = new ByteArrayInputStream(data, base + charSpace, data.length - (base + charSpace)); fontIn = new DataInputStream(in); for (int i = 0; i < n; i++) spacing[i] = fontIn.readShort(); fontIn.close(); in.close(); } else { for (int i = 0; i < n; i++) spacing[i] = xSize; } if (charKern > 0) { in = new ByteArrayInputStream(data, base + charKern, data.length - (base + charKern)); fontIn = new DataInputStream(in); for (int i = 0; i < n; i++) kerning[i] = fontIn.readShort(); fontIn.close(); in.close(); } /* if (ctfColorFontColors > 0) { in = new ByteArrayInputStream(data, base + ctfColorFontColors, data.length - (base + ctfColorFontColors)); fontIn = new DataInputStream(in); int cfcReserved = fontIn.readUnsignedShort(); int cfcCount = fontIn.readUnsignedShort(); int[] cfcColorTable = new int[cfcCount]; for (int i = 0; i < cfcCount; i++) cfcColorTable[i] = fontIn.readUnsignedShort(); fontIn.close(); in.close(); } */ // Add glyphs for characters int ascent = baseline + 1; int descent = ySize - ascent; BitmapFont font = new BitmapFont(ascent, descent, ascent, descent, 0, 0, 0); for (int i = 0, ch = loChar; ch <= hiChar; i++, ch++) { byte[][] glyph = new byte[ySize][bitSize[i]]; for (int y = 0; y < ySize; y++) { for (int gx = 0, bx = bitOffset[i]; gx < bitSize[i]; gx++, bx++) { glyph[y][gx] = bitmap[y][bx]; } } int offset = kerning[i]; int advance = spacing[i] + kerning[i]; BitmapFontGlyph g = new BitmapFontGlyph(glyph, offset, advance, ascent); int cp = (encoding != null) ? encoding.get(ch) : ch; if (cp >= 0) font.putCharacter(cp, g); } // Add .notdef glyph byte[][] glyph = new byte[ySize][bitSize[n-1]]; for (int y = 0; y < ySize; y++) { for (int gx = 0, bx = bitOffset[n-1]; gx < bitSize[n-1]; gx++, bx++) { glyph[y][gx] = bitmap[y][bx]; } } int offset = kerning[n-1]; int advance = spacing[n-1] + kerning[n-1]; BitmapFontGlyph g = new BitmapFontGlyph(glyph, offset, advance, ascent); font.putNamedGlyph(".notdef", g); // Set font properties font.setName(Font.NAME_FAMILY, fontName); font.setName(Font.NAME_STYLE, styleToString(style)); font.setXHeight(); font.setCapHeight(); return font; } private static String styleToString(int style) { StringBuffer sb = new StringBuffer(); if ((style & STYLE_BOLD) != 0) sb.append(" Bold"); if ((style & STYLE_ITALIC) != 0) sb.append(" Italic"); if ((style & STYLE_UNDERLINED) != 0) sb.append(" Underline"); if ((style & STYLE_EXTENDED) != 0) sb.append(" Extended"); return (sb.length() > 0) ? sb.toString().trim() : "Normal"; } } BDFBitmapFontImporter.java000066400000000000000000000162771506470510200342010ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class BDFBitmapFontImporter implements BitmapFontImporter { // List of mappings from charsets encountered in BDF files to ones supported by Java. private static final String[][] CHARSET_REGISTRIES = { {"JISX0208.1990", "JIS0208"}, }; public BitmapFont[] importFont(byte[] data) throws IOException { return importFont(new Scanner(new ByteArrayInputStream(data), "UTF-8")); } public BitmapFont[] importFont(InputStream is) throws IOException { return importFont(new Scanner(is, "UTF-8")); } public BitmapFont[] importFont(File file) throws IOException { return importFont(new Scanner(new FileInputStream(file), "UTF-8")); } public BitmapFont[] importFont(Scanner scan) throws IOException { List fonts = new ArrayList(); while (scan.hasNextLine()) { String[] kv = scan.nextLine().trim().split("\\s+", 2); if (kv[0].equals("STARTFONT")) fonts.add(readFont(scan)); } return fonts.toArray(new BitmapFont[fonts.size()]); } private BitmapFont readFont(Scanner scan) throws IOException { BitmapFont bm = new BitmapFont(); Charset cs = null; while (scan.hasNextLine()) { String[] kv = scan.nextLine().trim().split("\\s+", 2); if (kv[0].equals("STARTCHAR")) readChar(scan, bm, cs, kv[1]); else if (kv[0].equals("ENDFONT")) break; else if (kv.length < 2) continue; else if (kv[0].equals("FAMILY_NAME")) bm.setName(Font.NAME_FAMILY, dequote(kv[1])); else if (kv[0].equals("WEIGHT_NAME")) bm.setName(Font.NAME_STYLE, dequote(kv[1])); else if (kv[0].equals("FONT_VERSION")) bm.setName(Font.NAME_VERSION, dequote(kv[1])); else if (kv[0].equals("COPYRIGHT")) bm.setName(Font.NAME_COPYRIGHT, dequote(kv[1])); else if (kv[0].equals("FOUNDRY")) bm.setName(Font.NAME_MANUFACTURER, dequote(kv[1])); else if (kv[0].equals("FONT_ASCENT")) { try { int i = Integer.parseInt(dequote(kv[1])); bm.setLineAscent(i); bm.setEmAscent(i); } catch (NumberFormatException nfe) {} } else if (kv[0].equals("FONT_DESCENT")) { try { int i = Integer.parseInt(dequote(kv[1])); bm.setLineDescent(i); bm.setEmDescent(i); } catch (NumberFormatException nfe) {} } else if (kv[0].equals("X_HEIGHT")) { try { int i = Integer.parseInt(dequote(kv[1])); bm.setXHeight(i); } catch (NumberFormatException nfe) {} } else if (kv[0].equals("CAP_HEIGHT")) { try { int i = Integer.parseInt(dequote(kv[1])); bm.setCapHeight(i); } catch (NumberFormatException nfe) {} } else if (kv[0].equals("CHARSET_REGISTRY")) { String name = dequote(kv[1]); if (name.equalsIgnoreCase("ISO10646")) { cs = null; } else if (name.equalsIgnoreCase("FontSpecific")) { cs = FONT_SPECIFIC; } else try { cs = Charset.forName(name); } catch (Exception e1) { cs = null; for (String[] entry : CHARSET_REGISTRIES) { if (name.equalsIgnoreCase(entry[0])) { try { cs = Charset.forName(entry[1]); break; } catch (Exception e2) { continue; } } } if (cs == null) { System.err.println("Warning: Unsupported CHARSET_REGISTRY: " + name); } } } } return bm; } private void readChar(Scanner scan, BitmapFont bm, Charset cs, String gn) throws IOException { BitmapFontGlyph g = new BitmapFontGlyph(); int encoding = -1; while (scan.hasNextLine()) { String[] kv = scan.nextLine().trim().split("\\s+", 2); if (kv[0].equals("BITMAP")) { if (readBitmap(scan, g)) break; } else if (kv[0].equals("ENDCHAR")) break; else if (kv.length < 2) continue; else if (kv[0].equals("ENCODING")) { try { encoding = Integer.parseInt(dequote(kv[1])); if (cs == FONT_SPECIFIC) encoding += 0xF000; else if (cs != null) { String es = new String(toByteArray(encoding), cs); if (es.codePointCount(0, es.length()) == 1) { encoding = es.codePointAt(0); } else { System.err.println("Warning: Undecodable ENCODING: " + encoding); encoding = -1; } } } catch (NumberFormatException nfe) { encoding = -1; } } else if (kv[0].equals("DWIDTH")) { try { String[] va = dequote(kv[1]).split("\\s+"); int i = Integer.parseInt(va[0]); g.setCharacterWidth(i); } catch (NumberFormatException nfe) {} } else if (kv[0].equals("BBX")) { try { String[] va = dequote(kv[1]).split("\\s+"); int w = (va.length > 0) ? Integer.parseInt(va[0]) : 0; int h = (va.length > 1) ? Integer.parseInt(va[1]) : 0; int o = (va.length > 2) ? Integer.parseInt(va[2]) : 0; int d = (va.length > 3) ? Integer.parseInt(va[3]) : 0; g.setGlyph(new byte[h][w]); g.setXY(o, h + d); } catch (NumberFormatException nfe) {} } } if (encoding >= 0) bm.putCharacter(encoding, g); else bm.putNamedGlyph(gn, g); } private boolean readBitmap(Scanner scan, BitmapFontGlyph g) { byte[][] glyph = g.getGlyph(); int row = 0; while (scan.hasNextLine() && row < glyph.length) { String[] kv = scan.nextLine().trim().split("\\s+", 2); if (kv[0].equals("ENDCHAR")) return true; else unpack(kv[0], glyph[row++]); } return false; } private static String dequote(String s) { if (s.length() < 2) { return s; } else if (s.startsWith("\"") && s.endsWith("\"")) { return s.substring(1, s.length() - 1).replaceAll("\"\"", "\""); } else { return s; } } private static byte[] toByteArray(int v) { if ((v & 0xFFFFFF00) == 0) return new byte[]{(byte)v}; if ((v & 0xFFFF0000) == 0) return new byte[]{(byte)(v >> 8), (byte)v}; if ((v & 0xFF000000) == 0) return new byte[]{(byte)(v >> 16), (byte)(v >> 8), (byte)v}; return new byte[]{(byte)(v >> 24), (byte)(v >> 16), (byte)(v >> 8), (byte)v}; } private static void unpack(String h, byte[] b) { int i = 0; CharacterIterator ci = new StringCharacterIterator(h); for (char ch = ci.first(); ch != CharacterIterator.DONE; ch = ci.next()) { int v; if (ch >= '0' && ch <= '9') v = (ch - '0'); else if (ch >= 'A' && ch <= 'F') v = (ch - 'A' + 10); else if (ch >= 'a' && ch <= 'f') v = (ch - 'a' + 10); else continue; if (i < b.length) b[i++] = (byte)(((v & 0x08) == 0) ? 0 : -1); if (i < b.length) b[i++] = (byte)(((v & 0x04) == 0) ? 0 : -1); if (i < b.length) b[i++] = (byte)(((v & 0x02) == 0) ? 0 : -1); if (i < b.length) b[i++] = (byte)(((v & 0x01) == 0) ? 0 : -1); } } // This is only used as a marker and is handled internally. private static final Charset FONT_SPECIFIC = new Charset("X", null) { public boolean contains(Charset cs) { return false; } public CharsetDecoder newDecoder() { return null; } public CharsetEncoder newEncoder() { return null; } }; } BinaryBitmapFontImporter.java000066400000000000000000000073421506470510200350230ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; public class BinaryBitmapFontImporter implements BitmapFontImporter { public int offset = 0, bytesPerChar = 8, bytesPerRow = 1; public int cellWidth = 8, cellHeight = 8, ascent = 7; public int bitsPerPixel = 1; public boolean invert = false, rightAlign = false; public boolean flipBits = false, flipBytes = false; public int cellCount = 128; public List encoding = null; public List preview(byte[] b) { List images = new ArrayList(); int[] rgb = new int[cellWidth * cellHeight]; for (int off = offset, i = 0; i < cellCount; i++, off += bytesPerChar) { BufferedImage image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_INT_ARGB); for (int ro = 0, yo = off, y = 0; y < cellHeight; y++, yo += bytesPerRow, ro += cellWidth) { byte[] row = unpackRow(b, yo); for (int x = 0; x < cellWidth; x++) { int k = 255 - (row[x] & 0xFF); rgb[ro + x] = (0xFF << 24) | (k << 16) | (k << 8) | (k << 0); if (y == ascent) rgb[ro + x] ^= 0x00FFFF; } } image.setRGB(0, 0, cellWidth, cellHeight, rgb, 0, cellWidth); images.add(image); } return images; } public BitmapFont[] importFont(byte[] b) { BitmapFont bm = new BitmapFont(ascent, cellHeight - ascent, ascent, cellHeight - ascent, 0, 0, 0); for (int off = offset, i = 0; i < cellCount; i++, off += bytesPerChar) { byte[][] gd = new byte[cellHeight][]; for (int yo = off, y = 0; y < cellHeight; y++, yo += bytesPerRow) { gd[y] = unpackRow(b, yo); } BitmapFontGlyph glyph = new BitmapFontGlyph(gd, 0, cellWidth, ascent); if (encoding == null || encoding.isEmpty()) { bm.putCharacter(0xF0000 + i, glyph); } else if (i < encoding.size()) { Integer e = encoding.get(i); if (e != null && e.intValue() >= 0) { bm.putCharacter(e.intValue(), glyph); } } else { bm.putCharacter(0xF0000 + i - encoding.size(), glyph); } } bm.setXHeight(); bm.setCapHeight(); return new BitmapFont[]{bm}; } public BitmapFont[] importFont(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); return importFont(out.toByteArray()); } public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); in.close(); return importFont(out.toByteArray()); } private byte[] unpackRow(byte[] b, int off) { byte[] row = new byte[cellWidth]; int mask = ((1 << bitsPerPixel) - 1); int bits = cellWidth * bitsPerPixel; int bytes = (bits + 7) / 8; int bit = rightAlign ? (bytes * 8 - bits) : 0; for (int i = 0; i < cellWidth; i++, bit += bitsPerPixel) { int value = 0; int m = (1 << (bitsPerPixel - 1)); for (int j = 0; j < bitsPerPixel; j++, m >>= 1) { int bytei = (bit + j) / 8; if (flipBytes) bytei = (bytes - 1) - bytei; int biti = (bit + j) % 8; if (!flipBits) biti = 7 - biti; if (off + bytei < b.length && ((b[off + bytei] >> biti) & 1) != 0) value |= m; } if (invert) value ^= mask; row[i] = (byte)(255 * value / mask); } return row; } } CybikoBitmapFontImporter.java000066400000000000000000000120021506470510200350040ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public class CybikoBitmapFontImporter implements BitmapFontImporter { private GlyphList encoding; public CybikoBitmapFontImporter() { this.encoding = null; } public CybikoBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); String name = file.getName(); if (name.toLowerCase().endsWith(".cyf")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".fnt")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".fntz")) { name = name.substring(0, name.length() - 5); } else if (name.toLowerCase().endsWith(".fnty")) { name = name.substring(0, name.length() - 5); } f.setName(Font.NAME_FAMILY, name); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { if (in.readUnsignedByte() != 1) throw new IOException("bad magic number"); int cc = in.readUnsignedByte(); /* mw */ in.readUnsignedByte(); int mh = in.readUnsignedByte(); int ascent = mh; BitmapFont f = new BitmapFont(mh, 0, mh, 0, 0, 0, 0); for (int c = 0; c < cc; c++) { int l = in.readUnsignedByte(); int t = in.readUnsignedByte(); int w = in.readUnsignedByte(); int h = in.readUnsignedByte(); boolean ok = l > 0 || t > 0 || w > 1 || h > 1; byte[][] gd = new byte[h][w]; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = in.readUnsignedByte(); for (int m = 0x80, i = x; m != 0 && i < w; m >>= 1, i++) { if ((b & m) != 0) { ok = true; gd[y][i] = -1; } } } } if (ok) { if (c == 0) { ascent = t + h; f.setEmAscent(ascent); f.setLineAscent(ascent); f.setEmDescent(mh - ascent); f.setLineDescent(mh - ascent); } BitmapFontGlyph g = new BitmapFontGlyph(gd, l, w, ascent - t); int ch = (c + 32) & 0xFF; int cp = (encoding != null) ? encoding.get(ch) : fromCybiko(ch); if (cp >= 0) f.putCharacter(cp, g); } } f.setXHeight(); f.setCapHeight(); return f; } private static int fromCybiko(int ch) { switch (ch) { // Cybiko Symbols case 0x7F: return 0x2026; // horizontal ellipsis case 0x80: return 0x2665; // black heart suit case 0x81: return 0x25CF; // black circle case 0x82: return 0x25B6; // black right-pointing triangle case 0x83: return 0x25B7; // white right-pointing triangle case 0x84: return 0xFFC22; // white right-pointing triangle, duplicate? case 0x85: return 0xFFC23; // cy-sign // Windows CP-1252 case 0x86: return 0x2020; // dagger case 0x87: return 0x2021; // double dagger case 0x88: return 0x02C6; // modifier letter circumflex accent case 0x89: return 0x2030; // per mille sign case 0x8A: return 0x0160; // latin capital letter s with caron case 0x8B: return 0x2039; // single left-pointing angle quotation mark case 0x8C: return 0x0152; // latin capital ligature oe case 0x8D: return 0x0141; // latin capital letter l with stroke case 0x8E: return 0x017D; // latin capital letter z with caron case 0x8F: return 0x0131; // latin small letter dotless i case 0x90: return 0x20AC; // euro sign case 0x91: return 0x2018; // left single quotation mark case 0x92: return 0x2019; // right single quotation mark case 0x93: return 0x201C; // left double quotation mark case 0x94: return 0x201D; // right double quotation mark case 0x95: return 0x2022; // bullet case 0x96: return 0x2013; // en dash case 0x97: return 0x2014; // em dash case 0x98: return 0x02DC; // small tilde case 0x99: return 0x2122; // trade mark sign case 0x9A: return 0x0161; // latin small letter s with caron case 0x9B: return 0x203A; // single right-pointing angle quotation mark case 0x9C: return 0x0153; // latin small ligature oe case 0x9D: return 0x0142; // latin small letter l with stroke case 0x9E: return 0x017E; // latin small letter z with caron case 0x9F: return 0x0178; // latin capital letter y with diaeresis default: return ch; } } } DSFBitmapFontImporter.java000077500000000000000000000150151506470510200342120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.Scanner; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class DSFBitmapFontImporter implements BitmapFontImporter { public BitmapFont[] importFont(byte[] data) throws IOException { Scanner in = new Scanner(new ByteArrayInputStream(data), "UTF-8"); BitmapFont f = importFont(in); in.close(); if (f == null) return new BitmapFont[0]; return new BitmapFont[]{f}; } public BitmapFont[] importFont(InputStream is) throws IOException { Scanner in = new Scanner(is, "UTF-8"); BitmapFont f = importFont(in); if (f == null) return new BitmapFont[0]; return new BitmapFont[]{f}; } public BitmapFont[] importFont(File file) throws IOException { Scanner in = new Scanner(new FileInputStream(file), "UTF-8"); BitmapFont f = importFont(in); in.close(); if (f == null) return new BitmapFont[0]; return new BitmapFont[]{f}; } private static BitmapFont importFont(Scanner in) { if (in.nextLine().equals("DosStartFont")) { String[] tmp; String fontName = in.nextLine(); tmp = in.nextLine().split("\\s*,\\s*"); int format = Integer.parseInt(tmp[0].trim()); if (format == 0 || format == 1) { int[] widths = new int[95]; int[][] bboxes = new int[widths.length][]; boolean[][][] bitmaps = new boolean[widths.length][][]; int ascent = 0; int descent = 0; if (format == 1) { ascent = Integer.parseInt(tmp[1].trim()); } for (int i=0; i maxy) maxy = bbox[1]; if (bbox[2] > maxx) maxx = bbox[2]; if (bbox[3] < miny) miny = bbox[3]; } BitmapFont bf = new BitmapFont(ascent, descent, ascent, descent, 0, 0, 0); bf.setName(Font.NAME_FAMILY, fontName); for (int i=0; i 0) return 1; return 0; } private static int[] dsfBBox(String str) { int minx = 0, miny = 0, maxx = 0, maxy = 0, curx = 0, cury = 0; Iterator ti = new DSFTokenIterator(str); while (ti.hasNext()) { int t = ti.next(); int attr = t & 0x3F; int val = t >>> 6; int nextx = ((attr & 0x10) != 0) ? (curx - val) : ((attr & 0x20) != 0) ? (curx + val) : curx; int nexty = ((attr & 0x04) != 0) ? (cury + val) : ((attr & 0x08) != 0) ? (cury - val) : cury; if (nextx < minx) minx = nextx; if (nextx > maxx) maxx = nextx; if (nexty < miny) miny = nexty; if (nexty > maxy) maxy = nexty; if ((attr & 0x01) != 0) { curx = nextx; cury = nexty; } } return new int[]{minx, maxy+1, maxx+1, miny}; } private static boolean[][] dsfBitmap(String str, int[] bbox) { int rows = bbox[1] - bbox[3]; int cols = bbox[2] - bbox[0]; boolean[][] bmap = new boolean[rows][cols]; int curx = -bbox[0]; int cury = bbox[1]-1; Iterator ti = new DSFTokenIterator(str); while (ti.hasNext()) { int t = ti.next(); int attr = t & 0x3F; int val = t >>> 6; int nextx = ((attr & 0x10) != 0) ? (curx - val) : ((attr & 0x20) != 0) ? (curx + val) : curx; int nexty = ((attr & 0x04) != 0) ? (cury - val) : ((attr & 0x08) != 0) ? (cury + val) : cury; if ((attr & 0x02) != 0) { int xstep = sgn(nextx - curx); int ystep = sgn(nexty - cury); for (int x = curx, y = cury; val >= 0; x += xstep, y += ystep) { if (x >= 0 && y >= 0 && x < cols && y < rows) bmap[y][x] = true; val--; } } if ((attr & 0x01) != 0) { curx = nextx; cury = nexty; } } return bmap; } private static class DSFTokenIterator implements Iterator { private String str; private int strl; private int pos; public DSFTokenIterator(String str) { this.str = str+"xxx"; this.strl = str.length(); this.pos = 0; } public boolean hasNext() { return (pos < strl); } public Integer next() { int attr = 0x01 | 0x02; char ch = str.charAt(pos++); switch (ch) { case 'n': case 'N': attr = 0x02; ch = str.charAt(pos++); break; case 'b': case 'B': attr = 0x01; ch = str.charAt(pos++); break; } switch (ch) { case 'u': case 'U': attr |= 0x04; break; case 'd': case 'D': attr |= 0x08; break; case 'l': case 'L': attr |= 0x10; break; case 'r': case 'R': attr |= 0x20; break; case 'e': case 'E': attr |= 0x24; break; case 'f': case 'F': attr |= 0x28; break; case 'g': case 'G': attr |= 0x18; break; case 'h': case 'H': attr |= 0x14; break; } int val = 0; while (Character.isDigit(str.charAt(pos))) { val = val * 10 + Character.getNumericValue(str.charAt(pos++)); } if (val == 0) val = 1; return (val << 6) | attr; } public void remove() { throw new UnsupportedOperationException(); } } } FNTBitmapFontImporter.java000066400000000000000000000172041506470510200342240ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.unicode.data.GlyphList; public class FNTBitmapFontImporter implements BitmapFontImporter { private GlyphList encoding; public FNTBitmapFontImporter() { this.encoding = null; } public FNTBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { int magic = in.readUnsignedShort(); if (magic < 1 || magic > 3) throw new IOException("bad magic number: " + magic); int size = Integer.reverseBytes(in.readInt()); if (size < 118) throw new IOException("bad size: " + size); byte[] data = new byte[size]; in.readFully(data, 6, size - 6); in = new DataInputStream(new ByteArrayInputStream(data, 6, size - 6)); byte[] copyrightBytes = new byte[60]; in.readFully(copyrightBytes); int copyrightLength = 0; while (copyrightLength < 60 && copyrightBytes[copyrightLength] != 0) copyrightLength++; String copyright = new String(copyrightBytes, 0, copyrightLength, "CP1252"); int type = Short.reverseBytes(in.readShort()) & 0xFFFF; if ((type & 1) != 0) throw new IOException("vector fonts are not supported"); int points = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readShort(); // int vertRes = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readShort(); // int horizRes = Short.reverseBytes(in.readShort()) & 0xFFFF; int ascent = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readShort(); // int internalLeading = Short.reverseBytes(in.readShort()) & 0xFFFF; int externalLeading = Short.reverseBytes(in.readShort()) & 0xFFFF; int italic = in.readUnsignedByte(); int underline = in.readUnsignedByte(); int strikeOut = in.readUnsignedByte(); int weight = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readByte(); // int charSet = in.readUnsignedByte(); in.readShort(); // int pixWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int pixHeight = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readByte(); // int pitchAndFamily = in.readUnsignedByte(); in.readShort(); // int avgWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readShort(); // int maxWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int firstChar = in.readUnsignedByte(); int lastChar = in.readUnsignedByte(); in.readByte(); // int defaultChar = in.readUnsignedByte(); in.readByte(); // int breakChar = in.readUnsignedByte(); in.readShort(); // int widthBytes = Short.reverseBytes(in.readShort()) & 0xFFFF; in.readInt(); // int device = Integer.reverseBytes(in.readInt()); int face = Integer.reverseBytes(in.readInt()); in.readInt(); // int bitsPointer = Integer.reverseBytes(in.readInt()); in.readInt(); // int bitsOffset = Integer.reverseBytes(in.readInt()); in.readByte(); // int reserved = in.readUnsignedByte(); int flags = (magic >= 3) ? Integer.reverseBytes(in.readInt()) : 0; if (magic >= 3) in.readShort(); // int aSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; if (magic >= 3) in.readShort(); // int bSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; if (magic >= 3) in.readShort(); // int cSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; if (magic >= 3) in.readInt(); // int colorPointer = (magic >= 3) ? Integer.reverseBytes(in.readInt()) : 0; byte[] reserved1 = new byte[16]; if (magic >= 3) in.readFully(reserved1); // int deviceEnd = device; // while (deviceEnd < size && data[deviceEnd] != 0) deviceEnd++; // String deviceName = new String(data, device, deviceEnd - device, "CP1252"); int faceEnd = face; while (faceEnd < size && data[faceEnd] != 0) faceEnd++; String faceName = new String(data, face, faceEnd - face, "CP1252"); int n = lastChar - firstChar + 2; int[] geWidth = new int[n]; int[] geOffset = new int[n]; int[] geHeight = new int[n]; int[] geAspace = new int[n]; int[] geBspace = new int[n]; int[] geCspace = new int[n]; if (magic < 3) { for (int i = 0; i < n; i++) { geWidth[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geOffset[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geHeight[i] = pixHeight; } } else { for (int i = 0; i < n; i++) { geWidth[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geOffset[i] = Integer.reverseBytes(in.readInt()); if ((flags & 0xF0) < 0x20) { geHeight[i] = pixHeight; } else { geHeight[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; } if ((flags & 0x0F) >= 0x04) { geAspace[i] = Integer.reverseBytes(in.readInt()); geBspace[i] = Integer.reverseBytes(in.readInt()); geCspace[i] = Integer.reverseBytes(in.readInt()); } } } int descent = pixHeight - ascent; int emAscent = points * ascent / pixHeight; int emDescent = points - emAscent; String styleName = styleName(italic, underline, strikeOut, weight); BitmapFont f = new BitmapFont(emAscent, emDescent, ascent, descent, 0, 0, externalLeading); f.setName(BitmapFont.NAME_COPYRIGHT, copyright); f.setName(BitmapFont.NAME_FAMILY, faceName); f.setName(BitmapFont.NAME_STYLE, styleName); f.setName(BitmapFont.NAME_FAMILY_AND_STYLE, faceName + " " + styleName); for (int i = 0; i < n-1; i++) { byte[][] bitmap = new byte[geHeight[i]][geWidth[i]]; for (int dy = geOffset[i], by = 0; by < geHeight[i]; by++, dy++) { for (int dx = dy, bx = 0; bx < geWidth[i]; dx += geHeight[i]) { for (int m = 0x80; bx < geWidth[i] && m != 0; bx++, m >>= 1) { if ((data[dx] & m) != 0) { bitmap[by][bx] = -1; } } } } BitmapFontGlyph g = new BitmapFontGlyph(bitmap, 0, geWidth[i], ascent); int ch = (encoding != null) ? encoding.get(firstChar + i) : fromCP1252(firstChar + i); if (ch < 0) ch = 0xF000 + firstChar + i; f.putCharacter(ch, g); } f.setXHeight(); f.setCapHeight(); return f; } private static String styleName(int italic, int underline, int strikeOut, int weight) { StringBuffer sb = new StringBuffer(); if (weight < 400) sb.append((weight < 200) ? " Thin" : " Light"); if (weight >= 600) sb.append((weight >= 900) ? " Black" : " Bold"); if (italic != 0) sb.append(" Italic"); if (underline != 0) sb.append(" Underline"); if (strikeOut != 0) sb.append(" Strikeout"); return (sb.length() > 0) ? sb.toString().trim() : "Normal"; } private static int fromCP1252(int ch) { if (ch < 0x80 || ch >= 0xA0) return ch; return CP1252_C1[ch - 0x80]; } private static final int[] CP1252_C1 = new int[] { 0x20AC, 0x25CA, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0141, 0x017D, 0x0131, 0x2318, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0142, 0x017E, 0x0178, }; } FONTXBitmapFontImporter.java000066400000000000000000000077111506470510200344750ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.unicode.data.GlyphList; public class FONTXBitmapFontImporter implements BitmapFontImporter { private GlyphList singleByteEncoding; private String doubleByteEncoding; public FONTXBitmapFontImporter() { this.singleByteEncoding = null; this.doubleByteEncoding = "CP943"; // IBM's version of Shift-JIS } public FONTXBitmapFontImporter(GlyphList singleByteEncoding) { this.singleByteEncoding = singleByteEncoding; this.doubleByteEncoding = "CP943"; // IBM's version of Shift-JIS } public FONTXBitmapFontImporter(GlyphList singleByteEncoding, String doubleByteEncoding) { this.singleByteEncoding = singleByteEncoding; this.doubleByteEncoding = doubleByteEncoding; } public FONTXBitmapFontImporter(String doubleByteEncoding) { this.singleByteEncoding = null; this.doubleByteEncoding = doubleByteEncoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { if (in.readInt() != 0x464F4E54) throw new IOException("bad magic number"); if (in.readShort() != 0x5832) throw new IOException("bad magic number"); byte[] nameBytes = new byte[8]; in.readFully(nameBytes); String name = new String(nameBytes, "US-ASCII").trim(); int w = in.readUnsignedByte(); int h = in.readUnsignedByte(); int flag = in.readByte(); BitmapFont f = new BitmapFont(h, 0, h, 0, h, h, 0); f.setName(BitmapFont.NAME_FAMILY, name); if (flag == 0) { for (int i = 0; i < 256; i++) { BitmapFontGlyph g = readGlyph(in, w, h); int cp = fromSingleByte(i); f.putCharacter(cp, g); } } else { int n = in.readUnsignedByte(); int[] bs = new int[n]; int[] be = new int[n]; for (int i = 0; i < n; i++) { bs[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; be[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; } for (int i = 0; i < n; i++) { for (int j = bs[i]; j <= be[i]; j++) { BitmapFontGlyph g = readGlyph(in, w, h); int cp = fromDoubleByte(j); f.putCharacter(cp, g); } } } f.setAscentDescent(); f.setXHeight(); f.setCapHeight(); return f; } private BitmapFontGlyph readGlyph(DataInputStream in, int w, int h) throws IOException { byte[][] data = new byte[h][w]; for (int y = 0; y < h; y++) { int x = 0; while (x < w) { int b = in.readByte(); for (int m = 0x80; x < w && m != 0; x++, m >>= 1) { if ((b & m) != 0) { data[y][x] = -1; } } } } return new BitmapFontGlyph(data, 0, w, h); } private int fromSingleByte(int i) { if (singleByteEncoding != null) { int cp = singleByteEncoding.get(i); if (cp >= 0) return cp; } return 0xF000 + i; } private int fromDoubleByte(int i) { if (doubleByteEncoding != null) { try { byte[] b = { (byte)(i >> 8), (byte)i }; String s = new String(b, doubleByteEncoding); if (s.codePointCount(0, s.length()) == 1) { int cp = s.codePointAt(0); if (cp != 0xFFFD) return cp; } } catch (IOException e) { // Ignored. } } return 0xF0000 + i; } } FZXBitmapFontImporter.java000066400000000000000000000072021506470510200342410ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public class FZXBitmapFontImporter implements BitmapFontImporter { private GlyphList encoding; public FZXBitmapFontImporter() { this.encoding = null; } public FZXBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { // HEADER if (data.length < 3) return new BitmapFont[0]; int height = data[0] & 0xFF; int tracking = data[1] & 0xFF; int lastchar = data[2] & 0xFF; if (lastchar < 32) return new BitmapFont[0]; // TABLE int end = (lastchar - 30) * 3; if (data.length < end + 2) return new BitmapFont[0]; int[] offset = new int[lastchar - 30]; int[] kern = new int[lastchar - 31]; int[] shift = new int[lastchar - 31]; int[] width = new int[lastchar - 31]; for (int o = 3, i = 0, ch = 32; ch <= lastchar; ch++, i++, o += 3) { int ok = (data[o] & 0xFF) | ((data[o + 1] & 0xFF) << 8); int sw = (data[o + 2] & 0xFF); offset[i] = (ok & 0x3FFF) + o; kern[i] = ok >> 14; shift[i] = sw >> 4; width[i] = (sw & 0x0F) + 1; } offset[lastchar - 31] = ((data[end] & 0xFF) | ((data[end + 1] & 0xFF) << 8)) + end; // CHARACTER DEFINITIONS byte[][][] gd = new byte[lastchar - 31][][]; for (int i = 0, ch = 32; ch <= lastchar; ch++, i++) { int bpr = ((width[i] <= 8) ? 1 : 2); int rows = (offset[i + 1] - offset[i]) / bpr; if (rows < 0) rows = 0; gd[i] = new byte[rows][width[i]]; for (int o = offset[i], y = 0; y < rows; y++, o += bpr) { int row = (o < data.length) ? ((data[o] & 0xFF) << 8) : 0; row |= (o + 1 < data.length) ? (data[o + 1] & 0xFF) : 0; for (int m = 0x8000, x = 0; x < width[i]; x++, m >>= 1) { if ((row & m) != 0) gd[i][y][x] = -1; } } } BitmapFont f = new BitmapFont(height, 0, height, 0, height, height, 0); for (int i = 0, ch = 32; ch <= lastchar; ch++, i++) { int cp = zxcp(ch); if (cp >= 0) { BitmapFontGlyph g = new BitmapFontGlyph( gd[i], -kern[i], width[i] - kern[i] + tracking, height - shift[i] ); f.putCharacter(cp, g); } } f.setAscentDescent(); f.setXHeight(); f.setCapHeight(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); return importFont(out.toByteArray()); } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); in.close(); BitmapFont[] f = importFont(out.toByteArray()); if (f.length > 0) { String name = file.getName(); if (name.toLowerCase().endsWith(".fzx")) { name = name.substring(0, name.length() - 4); } for (BitmapFont ff : f) { ff.setName(Font.NAME_FAMILY, name); } } return f; } private int zxcp(int ch) { if (encoding != null) return encoding.get(ch); if (ch == 96) return 163; if (ch == 127) return 169; if (ch < 128) return ch; return (0xF000 + ch); } } GEOSBitmapFontImporter.java000066400000000000000000000073041506470510200343320ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.geos.GEOSFontFile; import com.kreative.bitsnpicas.geos.GEOSFontPointSize; import com.kreative.bitsnpicas.geos.GEOSFontStrike; public class GEOSBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont[] bf = importFont(in); in.close(); return bf; } @Override public BitmapFont[] importFont(InputStream is) throws IOException { List fonts = new ArrayList(); DataInputStream in = new DataInputStream(is); GEOSFontFile gff = new GEOSFontFile(in); if (gff.isValid()) { for (int pointSize : gff.getFontPointSizes()) { BitmapFont f = importFont(gff, pointSize); if (f != null) fonts.add(f); } } return fonts.toArray(new BitmapFont[fonts.size()]); } public BitmapFont importFont(GEOSFontFile gff, int pointSize) { GEOSFontPointSize gfps = gff.getFontPointSize(pointSize); GEOSFontStrike gfs = gfps.isMega() ? gfps.megaStrikeIndex : gfps.strike; int ascent = gfs.ascent + 1; int descent = gfs.height - ascent; int emAscent = ascent; int emDescent = descent; while (emAscent + emDescent < pointSize) { if (emAscent + emDescent < pointSize) emAscent++; if (emAscent + emDescent < pointSize) emDescent++; } while (emAscent + emDescent > pointSize) { if (emAscent + emDescent > pointSize) emAscent--; if (emAscent + emDescent > pointSize) emDescent--; } String classText = gff.getClassTextString(); String[] classFields = classText.split(" +"); BitmapFont f = new BitmapFont(emAscent, emDescent, ascent, descent, 0, 0, 0); for (int cp = 0x20; cp < 0x80; cp++) { BitmapFontGlyph g = getASCIIGlyph(gfps, cp); if (g != null) f.putCharacter(cp, g); } if (gfps.isUTF8()) { for (int cp = 0x80; cp < 0x110000; cp++) { BitmapFontGlyph g = getUTF8Glyph(gfps, cp); if (g != null) f.putCharacter(cp, g); } } if (f.isEmpty()) return null; f.setName(BitmapFont.NAME_FAMILY, gff.getFontName()); f.setName(BitmapFont.NAME_VERSION, classFields[classFields.length - 1]); f.setName(BitmapFont.NAME_DESCRIPTION, gff.getDescriptionString()); f.setXHeight(); f.setCapHeight(); return f; } private static BitmapFontGlyph getASCIIGlyph(GEOSFontPointSize gfps, int cp) { int i = cp - 0x20; GEOSFontStrike gfs = gfps.isMega() ? gfps.megaStrikes[i >> 4] : gfps.strike; return getGlyph(gfs, i); } private static BitmapFontGlyph getUTF8Glyph(GEOSFontPointSize gfps, int cp) { GEOSFontStrike gfs = gfps.utf8Strikes.get(gfps.utf8Map.get(cp)); return getGlyph(gfs, cp & 0x3F); } private static BitmapFontGlyph getGlyph(GEOSFontStrike gfs, int index) { if (gfs == null) return null; byte[][] gd = gfs.getGlyph(index); if (gd == null) return null; int offset, width; if (gfs.offsetWidths != null) { offset = gfs.offsetWidths[index].offset; width = gfs.offsetWidths[index].width; } else { offset = 0; width = gd[0].length; } if (width == 0 && gd[0].length == 0) return null; return new BitmapFontGlyph(gd, offset, width, gfs.ascent + 1); } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont[] bf = importFont(in); in.close(); return bf; } } HMZKBitmapFontImporter.java000066400000000000000000000044301506470510200343430ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; /** * HMZK is the monochrome bitmap font format used for the Mi Band 2 * Reference */ public class HMZKBitmapFontImporter implements BitmapFontImporter { public BitmapFont[] importFont(byte[] b) { BitmapFont bm = new BitmapFont(16, 0, 16, 0, 16, 16, 0); // skip magic and padding // FIXME: check magic number/charsLen and throw exceptions int offset = 14; int charsLen = ((b[offset + 1] & 0xFF) << 8) | (b[offset] & 0xFF); int cellCount = charsLen / 2; int charOff = offset + 2; int bitmOff = charOff + charsLen; for (int i = 0; i < cellCount; i++, charOff += 2, bitmOff += 32) { byte[][] gd = new byte[16][16]; for (int yo = bitmOff, y = 0; y < 16; y++, yo += 2) { for (int j = 0; j < 8; j++) { gd[y][7 - j] = (byte)(((b[yo] >> j) & 1) * 0xFF); gd[y][15 - j] = (byte)(((b[yo + 1] >> j) & 1) * 0xFF); } } BitmapFontGlyph glyph = new BitmapFontGlyph(gd, 0, 16, 16); int ch = ((b[charOff + 1] & 0xFF) << 8) | (b[charOff] & 0xFF); bm.putCharacter(ch, glyph); } return new BitmapFont[]{bm}; } public BitmapFont[] importFont(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); return importFont(out.toByteArray()); } public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); in.close(); return importFont(out.toByteArray()); } } HRCGBitmapFontImporter.java000066400000000000000000000036211506470510200343160ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class HRCGBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); String name = file.getName(); if (name.toLowerCase().endsWith(".set")) { name = name.substring(0, name.length() - 4); } f.setName(Font.NAME_FAMILY, name); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { byte[] data = new byte[768]; in.readFully(data); BitmapFont f = new BitmapFont(14, 2, 14, 2, 10, 14, 0); for (int i = 0; i < 96; i++) { byte[][] glyph = new byte[16][16]; for (int y = 0; y < 8; y++) { byte b = data[i * 8 + y]; for (int m = 1, x = ((b < 0) ? 1 : 0); x < 14; x += 2, m <<= 1) { if ((b & m) != 0) { glyph[y * 2][x] = -1; glyph[y * 2][x + 1] = -1; glyph[y * 2 + 1][x] = -1; glyph[y * 2 + 1][x + 1] = -1; } } } f.putCharacter(i + 32, new BitmapFontGlyph(glyph, 0, 14, 14)); } return f; } } HexBitmapFontImporter.java000066400000000000000000000042751506470510200343250ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Scanner; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; public class HexBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { Scanner in = new Scanner(new ByteArrayInputStream(data), "UTF-8"); BitmapFont f = importFont(in); in.close(); if (f.isEmpty()) return new BitmapFont[0]; return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream is) throws IOException { Scanner in = new Scanner(is, "UTF-8"); BitmapFont f = importFont(in); if (f.isEmpty()) return new BitmapFont[0]; return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { Scanner in = new Scanner(new FileInputStream(file), "UTF-8"); BitmapFont f = importFont(in); in.close(); if (f.isEmpty()) return new BitmapFont[0]; return new BitmapFont[]{f}; } private static BitmapFont importFont(Scanner in) { BitmapFont f = new BitmapFont(10, 2, 14, 2, 8, 10, 0); lines: while (in.hasNextLine()) { String[] fields = in.nextLine().split(":"); if (fields.length != 2) continue lines; int cp; try { cp = Integer.parseInt(fields[0].trim(), 16); } catch (NumberFormatException nfe) { continue lines; } char[] hex = fields[1].trim().toCharArray(); int width = hex.length / 16; if (width < 1) continue lines; byte[][] glyph = new byte[16][width * 4]; for (int i = 0, y = 0; y < 16; y++) { for (int x = 0, j = 0; j < width; j++) { int b = Character.getNumericValue(hex[i++]); if (b < 0 || b > 15) continue lines; glyph[y][x++] = ((b & 8) != 0) ? (byte)0xFF : 0; glyph[y][x++] = ((b & 4) != 0) ? (byte)0xFF : 0; glyph[y][x++] = ((b & 2) != 0) ? (byte)0xFF : 0; glyph[y][x++] = ((b & 1) != 0) ? (byte)0xFF : 0; } } BitmapFontGlyph g = new BitmapFontGlyph(glyph, 0, width * 4, 14); f.putCharacter(cp, g); } return f; } } ImageBitmapFontImporter.java000066400000000000000000000132101506470510200346100ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.imageio.ImageIO; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.WindingOrder; public class ImageBitmapFontImporter implements BitmapFontImporter { public int matte = -1; public int startX = 0, startY = 0; public int cellWidth = 8, cellHeight = 8, ascent = 7; public int deltaX = 0, deltaY = 0; public int columnCount = 0, rowCount = 0; public WindingOrder order = WindingOrder.LTR_TTB; public boolean invert = false; public int threshold = 128; public List encoding = null; public static final class PreviewResult { public final BufferedImage preview; public final Point[] points; private PreviewResult(BufferedImage preview, int count) { this.preview = preview; this.points = new Point[count]; } } public PreviewResult preview(BufferedImage in) { int w = in.getWidth(), h = in.getHeight(); int rows = 0; for (int y = startY; (y + cellHeight <= h) && (rowCount <= 0 || rows < rowCount); y += cellHeight + deltaY, rows++); int columns = 0; for (int x = startX; (x + cellWidth <= w) && (columnCount <= 0 || columns < columnCount); x += cellWidth + deltaX, columns++); BufferedImage out = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D gr = out.createGraphics(); gr.setColor(new Color(matte)); gr.fillRect(0, 0, w, h); gr.drawImage(in, null, 0, 0); gr.setColor(new Color(0x80808080, true)); gr.fillRect(0, 0, w, h); gr.dispose(); PreviewResult result = new PreviewResult(out, rows * columns); int[] rgb = new int[cellHeight * cellWidth]; for (int y = startY, j = 0; j < rows; y += cellHeight + deltaY, j++) { for (int x = startX, i = 0; i < columns; x += cellWidth + deltaX, i++) { in.getRGB(x, y, cellWidth, cellHeight, rgb, 0, cellWidth); for (int z = 0, gy = 0; gy < cellHeight; gy++) { for (int gx = 0; gx < cellWidth; gx++, z++) { int a = (rgb[z] >> 24) & 0xFF; int r = (((rgb[z] >> 16) & 0xFF) * a / 255); int g = (((rgb[z] >> 8) & 0xFF) * a / 255); int b = (((rgb[z] >> 0) & 0xFF) * a / 255); r += (((matte >> 16) & 0xFF) * (255 - a) / 255); g += (((matte >> 8) & 0xFF) * (255 - a) / 255); b += (((matte >> 0) & 0xFF) * (255 - a) / 255); int k = (30 * r + 59 * g + 11 * b) / 100; if (invert) k = 255 - k; if (threshold > 0) k = (k < threshold) ? 0 : 255; rgb[z] = (0xFF << 24) | (k << 16) | (k << 8) | (k << 0); if (deltaX <= 0 && (gx == 0 || gx == cellWidth - 1)) rgb[z] ^= 0xFF0000; else if (deltaY <= 0 && (gy == 0 || gy == cellHeight - 1)) rgb[z] ^= 0xFF0000; else if (gy == ascent) rgb[z] ^= 0x00FFFF; } } int ci = order.getIndex(rows, columns, j, i); out.setRGB(x, y, cellWidth, cellHeight, rgb, 0, cellWidth); result.points[ci] = new Point(x, y); } } return result; } public BitmapFont importFont(BufferedImage in) { BitmapFont bm = new BitmapFont(ascent, cellHeight - ascent, ascent, cellHeight - ascent, 0, 0, 0); int w = in.getWidth(), h = in.getHeight(); int rows = 0; for (int y = startY; (y + cellHeight <= h) && (rowCount <= 0 || rows < rowCount); y += cellHeight + deltaY, rows++); int columns = 0; for (int x = startX; (x + cellWidth <= w) && (columnCount <= 0 || columns < columnCount); x += cellWidth + deltaX, columns++); int[] rgb = new int[cellHeight * cellWidth]; for (int y = startY, j = 0; j < rows; y += cellHeight + deltaY, j++) { for (int x = startX, i = 0; i < columns; x += cellWidth + deltaX, i++) { byte[][] gd = new byte[cellHeight][cellWidth]; in.getRGB(x, y, cellWidth, cellHeight, rgb, 0, cellWidth); for (int z = 0, gy = 0; gy < cellHeight; gy++) { for (int gx = 0; gx < cellWidth; gx++, z++) { int a = (rgb[z] >> 24) & 0xFF; int r = (((rgb[z] >> 16) & 0xFF) * a / 255); int g = (((rgb[z] >> 8) & 0xFF) * a / 255); int b = (((rgb[z] >> 0) & 0xFF) * a / 255); r += (((matte >> 16) & 0xFF) * (255 - a) / 255); g += (((matte >> 8) & 0xFF) * (255 - a) / 255); b += (((matte >> 0) & 0xFF) * (255 - a) / 255); int k = (30 * r + 59 * g + 11 * b) / 100; if (invert) k = 255 - k; if (threshold > 0) k = (k < threshold) ? 0 : 255; gd[gy][gx] = (byte)(255 - k); } } int ci = order.getIndex(rows, columns, j, i); BitmapFontGlyph glyph = new BitmapFontGlyph(gd, 0, cellWidth, ascent); if (encoding == null || encoding.isEmpty()) { bm.putCharacter(0xF0000 + ci, glyph); } else if (ci < encoding.size()) { Integer e = encoding.get(ci); if (e != null && e.intValue() >= 0) { bm.putCharacter(e.intValue(), glyph); } } else { bm.putCharacter(0xF0000 + ci - encoding.size(), glyph); } } } bm.setXHeight(); bm.setCapHeight(); return bm; } public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream b = new ByteArrayInputStream(data); BitmapFont[] f = importFont(b); b.close(); return f; } public BitmapFont[] importFont(InputStream is) throws IOException { BufferedImage bi = ImageIO.read(is); BitmapFont f = importFont(bi); return new BitmapFont[]{f}; } public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont[] f = importFont(in); in.close(); return f; } } KbitsBitmapFontImporter.java000066400000000000000000000051631506470510200346520ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; public class KbitsBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bis); BitmapFont f = importFont(dis); dis.close(); bis.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream is) throws IOException { BitmapFont f = importFont(new DataInputStream(is)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis); BitmapFont f = importFont(dis); dis.close(); fis.close(); return new BitmapFont[]{f}; } private BitmapFont importFont(DataInputStream in) throws IOException { if (in.readInt() != 0x4B426E50) throw new IOException("bad magic number"); if (in.readInt() != 0x62697473) throw new IOException("bad magic number"); if (in.readInt() != 1) throw new IOException("bad version number"); int ma = in.readInt(); int md = in.readInt(); int la = in.readInt(); int ld = in.readInt(); int lg = in.readInt(); int xh = in.readInt(); BitmapFont font = new BitmapFont(ma, md, la, ld, xh, xh, lg); while (true) { int blockType = in.readInt(); switch (blockType) { case 0x6E616D65: // name if (in.readInt() != 1) throw new IOException("bad version number"); int nameType = in.readInt(); String name = in.readUTF(); font.setName(nameType, name); break; case 0x63686172: // char if (in.readInt() != 1) throw new IOException("bad version number"); int codePoint = in.readInt(); int a = in.readInt(); int x = in.readInt(); int y = in.readInt(); int rowCount = in.readInt(); byte[][] rows = new byte[rowCount][]; for (int i = 0; i < rowCount; i++) { int colCount = in.readInt(); rows[i] = new byte[colCount]; in.readFully(rows[i]); } BitmapFontGlyph glyph = new BitmapFontGlyph(rows, x, a, y); font.putCharacter(codePoint, glyph); break; case 0x66696E2E: // fin. font.setCapHeight(); return font; default: throw new IOException("bad magic number"); } } } } KbitxBitmapFontImporter.java000066400000000000000000000134221506470510200346540ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.kreative.bitsnpicas.Base64InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.GlyphPair; import com.kreative.bitsnpicas.WIBInputStream; import com.kreative.bitsnpicas.XMLUtility; public class KbitxBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = parse("", in); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream is) throws IOException { BitmapFont f = parse("", is); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = parse(file.getName(), in); in.close(); return new BitmapFont[]{f}; } private static BitmapFont parse(String name, InputStream in) throws IOException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); // make sure the XML is valid factory.setExpandEntityReferences(false); // don't allow custom entities DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(XMLUtility.entityResolver("BitsNPicasBitmap", "kbitx.dtd", KbitxBitmapFontImporter.class)); builder.setErrorHandler(XMLUtility.errorHandler(name)); Document document = builder.parse(new InputSource(in)); return parseDocument(document); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException saxe) { throw new IOException(saxe); } } private static BitmapFont parseDocument(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("#document")) { for (Node child : XMLUtility.getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("kbits")) { if (child.hasAttributes() || child.hasChildNodes()) { return parseKbits(child); } } else { throw new IOException("Unknown element: " + ctype); } } throw new IOException("Empty document."); } else { throw new IOException("Unknown element: " + type); } } private static BitmapFont parseKbits(Node node) throws IOException { BitmapFont f = new BitmapFont(); for (Node child : XMLUtility.getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("prop")) { String id = XMLUtility.parseString(cattr, "id"); Integer iv = XMLUtility.parseInt(cattr, "value"); if ("emAscent".equalsIgnoreCase(id) && iv != null) f.setEmAscent(iv); if ("emDescent".equalsIgnoreCase(id) && iv != null) f.setEmDescent(iv); if ("lineAscent".equalsIgnoreCase(id) && iv != null) f.setLineAscent(iv); if ("lineDescent".equalsIgnoreCase(id) && iv != null) f.setLineDescent(iv); if ("lineGap".equalsIgnoreCase(id) && iv != null) f.setLineGap(iv); if ("xHeight".equalsIgnoreCase(id) && iv != null) f.setXHeight(iv); if ("capHeight".equalsIgnoreCase(id) && iv != null) f.setCapHeight(iv); } else if (ctype.equalsIgnoreCase("name")) { Integer id = XMLUtility.parseInt(cattr, "id"); String name = XMLUtility.parseString(cattr, "value"); if (id != null && name != null) f.setName(id, name); } else if (ctype.equalsIgnoreCase("g")) { Integer cp = XMLUtility.parseInt(cattr, "u"); String gn = XMLUtility.parseString(cattr, "n"); if (cp != null) f.putCharacter(cp, parseGlyph(cattr)); if (gn != null) f.putNamedGlyph(gn, parseGlyph(cattr)); } else if (ctype.equalsIgnoreCase("k")) { Integer o = XMLUtility.parseInt(cattr, "o"); if (o != null) { Integer lu = XMLUtility.parseInt(cattr, "lu"); String ln = XMLUtility.parseString(cattr, "ln"); Integer ru = XMLUtility.parseInt(cattr, "ru"); String rn = XMLUtility.parseString(cattr, "rn"); if (lu != null) { if (ru != null) f.setKernPair(new GlyphPair(lu, ru), o); if (rn != null) f.setKernPair(new GlyphPair(lu, rn), o); } if (ln != null) { if (ru != null) f.setKernPair(new GlyphPair(ln, ru), o); if (rn != null) f.setKernPair(new GlyphPair(ln, rn), o); } } } } return f; } private static BitmapFontGlyph parseGlyph(NamedNodeMap cattr) throws IOException { byte[][] data; String d = XMLUtility.parseString(cattr, "d"); if (d == null || d.length() == 0) { data = new byte[0][0]; } else { Base64InputStream bs = new Base64InputStream(d); int dh = readLEB128(bs); int dw = readLEB128(bs); data = new byte[dh][dw]; WIBInputStream ws = new WIBInputStream(bs); for (byte[] row : data) ws.read(row); ws.close(); bs.close(); } Integer x = XMLUtility.parseInt(cattr, "x"); Integer y = XMLUtility.parseInt(cattr, "y"); Integer w = XMLUtility.parseInt(cattr, "w"); return new BitmapFontGlyph( data, ((x == null) ? 0 : x), ((w == null) ? 0 : w), ((y == null) ? 0 : y) ); } private static int readLEB128(InputStream in) throws IOException { int v = 0, s = 0; for (int b = in.read(); b >= 0; b = in.read()) { v |= (b & 0x7F) << s; if ((b & 0x80) == 0) break; s += 7; } return v; } } KpcasVectorFontImporter.java000066400000000000000000000102441506470510200346610ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.VectorFont; import com.kreative.bitsnpicas.VectorFontGlyph; import com.kreative.bitsnpicas.VectorFontImporter; import com.kreative.bitsnpicas.VectorInstruction; import com.kreative.bitsnpicas.VectorPath; public class KpcasVectorFontImporter implements VectorFontImporter { @Override public VectorFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bis); VectorFont f = importFont(dis); dis.close(); bis.close(); return new VectorFont[]{f}; } @Override public VectorFont[] importFont(InputStream is) throws IOException { VectorFont f = importFont(new DataInputStream(is)); return new VectorFont[]{f}; } @Override public VectorFont[] importFont(File file) throws IOException { FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis); VectorFont f = importFont(dis); dis.close(); fis.close(); return new VectorFont[]{f}; } private VectorFont importFont(DataInputStream in) throws IOException { if (in.readInt() != 0x4B426E50) throw new IOException("bad magic number"); if (in.readInt() != 0x70636173) throw new IOException("bad magic number"); if (in.readInt() != 1) throw new IOException("bad version number"); double ma = in.readDouble(); double md = in.readDouble(); double la = in.readDouble(); double ld = in.readDouble(); double lg = in.readDouble(); double xh = in.readDouble(); VectorFont font = new VectorFont(ma, md, la, ld, xh, xh, lg); while (true) { int blockType = in.readInt(); switch (blockType) { case 0x6E616D65: // name if (in.readInt() != 1) throw new IOException("bad version number"); int nameType = in.readInt(); String name = in.readUTF(); font.setName(nameType, name); break; case 0x63686172: // char if (in.readInt() != 1) throw new IOException("bad version number"); int codePoint = in.readInt(); double advance = in.readDouble(); List paths = new ArrayList(); int pathCount = in.readInt(); for (int i = 0; i < pathCount; i++) { VectorPath path = new VectorPath(); while (true) { int type = in.readInt(); if (type == 0x2F637472) { break; } else if (type == 0x6D6F7665) { double x = in.readDouble(); double y = in.readDouble(); path.add(new VectorInstruction('M', x, y)); } else if (type == 0x6C696E65) { double x = in.readDouble(); double y = in.readDouble(); path.add(new VectorInstruction('L', x, y)); } else if (type == 0x71756164) { double x1 = in.readDouble(); double y1 = in.readDouble(); double x2 = in.readDouble(); double y2 = in.readDouble(); path.add(new VectorInstruction('Q', x1, y1, x2, y2)); } else if (type == 0x63756265) { double x1 = in.readDouble(); double y1 = in.readDouble(); double x2 = in.readDouble(); double y2 = in.readDouble(); double x3 = in.readDouble(); double y3 = in.readDouble(); path.add(new VectorInstruction('C', x1, y1, x2, y2, x3, y3)); } else if (type == 0x2F707468) { path.add(new VectorInstruction('Z')); } else if ((type & 0xFFC0FFF0) == 0x00400000) { char operation = (char)(type >> 16); Double[] args = new Double[type & 0x0F]; for (int j = 0; j < args.length; j++) args[j] = in.readDouble(); path.add(new VectorInstruction(operation, args)); } else { throw new IOException("bad magic number"); } } paths.add(path); } VectorFontGlyph glyph = new VectorFontGlyph(paths, advance); font.putCharacter(codePoint, glyph); break; case 0x66696E2E: // fin. font.setCapHeight2D(); return font; default: throw new IOException("bad magic number"); } } } } KpcaxVectorFontImporter.java000066400000000000000000000155341506470510200346750ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.kreative.bitsnpicas.GlyphPair; import com.kreative.bitsnpicas.PathExtensions; import com.kreative.bitsnpicas.VectorFont; import com.kreative.bitsnpicas.VectorFontGlyph; import com.kreative.bitsnpicas.VectorFontImporter; import com.kreative.bitsnpicas.VectorInstruction; import com.kreative.bitsnpicas.VectorPath; import com.kreative.bitsnpicas.XMLUtility; public class KpcaxVectorFontImporter implements VectorFontImporter { @Override public VectorFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); VectorFont f = parse("", in); in.close(); return new VectorFont[]{f}; } @Override public VectorFont[] importFont(InputStream is) throws IOException { VectorFont f = parse("", is); return new VectorFont[]{f}; } @Override public VectorFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); VectorFont f = parse(file.getName(), in); in.close(); return new VectorFont[]{f}; } private static VectorFont parse(String name, InputStream in) throws IOException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); // make sure the XML is valid factory.setExpandEntityReferences(false); // don't allow custom entities DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(XMLUtility.entityResolver("BitsNPicasVector", "kpcax.dtd", KpcaxVectorFontImporter.class)); builder.setErrorHandler(XMLUtility.errorHandler(name)); Document document = builder.parse(new InputSource(in)); return parseDocument(document); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException saxe) { throw new IOException(saxe); } } private static VectorFont parseDocument(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("#document")) { for (Node child : XMLUtility.getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("kpcas")) { if (child.hasAttributes() || child.hasChildNodes()) { return parseKpcas(child); } } else { throw new IOException("Unknown element: " + ctype); } } throw new IOException("Empty document."); } else { throw new IOException("Unknown element: " + type); } } private static VectorFont parseKpcas(Node node) throws IOException { VectorFont f = new VectorFont(); for (Node child : XMLUtility.getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("prop")) { String id = XMLUtility.parseString(cattr, "id"); Double dv = XMLUtility.parseDouble(cattr, "value"); if ("emAscent".equalsIgnoreCase(id) && dv != null) f.setEmAscent2D(dv); if ("emDescent".equalsIgnoreCase(id) && dv != null) f.setEmDescent2D(dv); if ("lineAscent".equalsIgnoreCase(id) && dv != null) f.setLineAscent2D(dv); if ("lineDescent".equalsIgnoreCase(id) && dv != null) f.setLineDescent2D(dv); if ("lineGap".equalsIgnoreCase(id) && dv != null) f.setLineGap2D(dv); if ("xHeight".equalsIgnoreCase(id) && dv != null) f.setXHeight2D(dv); if ("capHeight".equalsIgnoreCase(id) && dv != null) f.setCapHeight2D(dv); } else if (ctype.equalsIgnoreCase("name")) { Integer id = XMLUtility.parseInt(cattr, "id"); String name = XMLUtility.parseString(cattr, "value"); if (id != null && name != null) f.setName(id, name); } else if (ctype.equalsIgnoreCase("g")) { Integer cp = XMLUtility.parseInt(cattr, "u"); String gn = XMLUtility.parseString(cattr, "n"); if (cp != null) f.putCharacter(cp, parseGlyph(cattr)); if (gn != null) f.putNamedGlyph(gn, parseGlyph(cattr)); } else if (ctype.equalsIgnoreCase("k")) { Integer o = XMLUtility.parseInt(cattr, "o"); if (o != null) { Integer lu = XMLUtility.parseInt(cattr, "lu"); String ln = XMLUtility.parseString(cattr, "ln"); Integer ru = XMLUtility.parseInt(cattr, "ru"); String rn = XMLUtility.parseString(cattr, "rn"); if (lu != null) { if (ru != null) f.setKernPair(new GlyphPair(lu, ru), o); if (rn != null) f.setKernPair(new GlyphPair(lu, rn), o); } if (ln != null) { if (ru != null) f.setKernPair(new GlyphPair(ln, ru), o); if (rn != null) f.setKernPair(new GlyphPair(ln, rn), o); } } } } return f; } private static VectorFontGlyph parseGlyph(NamedNodeMap cattr) throws IOException { VectorFontGlyph g = new VectorFontGlyph(); String d = XMLUtility.parseString(cattr, "d"); if (d != null && d.length() > 0) parseVectorData(g.getContours(), d); Double w = XMLUtility.parseDouble(cattr, "w"); g.setCharacterWidth2D((w == null) ? 0 : w); return g; } private static final Pattern PATH_TOKEN = Pattern.compile( "(ZZ|[A-Z])|([+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)(E[+-]?[0-9]+)?)", Pattern.CASE_INSENSITIVE ); public static void parseVectorData(Collection paths, String d) { VectorPath path = null; char operation = 'M'; List args = null; Matcher m = PATH_TOKEN.matcher(d); while (m.find()) { String os = m.group(1); if (os != null && os.length() > 0) { if (args != null) { if (path == null) path = new VectorPath(); path.add(new VectorInstruction(operation, args)); args = null; } if (os.equalsIgnoreCase("ZZ")) { if (path != null) { paths.add(path); path = null; } } else { operation = os.charAt(0); args = new ArrayList(); } } String ns = m.group(2); if (ns != null && ns.length() > 0) { if (path == null) path = new VectorPath(); if (args == null) args = new ArrayList(); try { args.add(Double.parseDouble(ns)); } catch (NumberFormatException nfe) {} if (args.size() >= PathExtensions.getOperandCount(operation)) { path.add(new VectorInstruction(operation, args)); if (operation == 'M') operation = 'L'; if (operation == 'm') operation = 'l'; args = null; } } } if (args != null) { if (path == null) path = new VectorPath(); path.add(new VectorInstruction(operation, args)); args = null; } if (path != null) { paths.add(path); path = null; } } } MGTKBitmapFontImporter.java000066400000000000000000000057241506470510200343430ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public class MGTKBitmapFontImporter implements BitmapFontImporter { private GlyphList encoding; public MGTKBitmapFontImporter() { this.encoding = null; } public MGTKBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); String name = file.getName(); if (name.toLowerCase().endsWith(".fnt")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".mgf")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".mpf")) { name = name.substring(0, name.length() - 4); } f.setName(Font.NAME_FAMILY, name); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { int fontType = in.readUnsignedByte(); int maxWidth = (fontType == 0) ? 7 : (fontType == 0x80) ? 14 : 0; if (maxWidth == 0) throw new IOException("bad magic number"); int lastChar = in.readUnsignedByte(); int height = in.readUnsignedByte(); if (height == 0) throw new IOException("bad magic number"); int[] widths = new int[lastChar + 1]; for (int i = 0; i <= lastChar; i++) { widths[i] = in.readUnsignedByte(); if (widths[i] > maxWidth) throw new IOException("bad magic number"); } byte[][][] glyphs = new byte[lastChar + 1][height][maxWidth]; for (int y = 0; y < height; y++) { for (int z = 0; z < maxWidth; z += 7) { for (int i = 0; i <= lastChar; i++) { int b = in.readUnsignedByte(); for (int x = z, m = 1; m < 0x80; m <<= 1, x++) { if ((b & m) != 0) glyphs[i][y][x] = -1; } } } } BitmapFont f = new BitmapFont(height, 0, height, 0, 0, 0, 0); for (int i = 0; i <= lastChar; i++) { Integer cp = (encoding == null) ? i : encoding.get(i); if (cp == null || cp < 0) continue; BitmapFontGlyph g = new BitmapFontGlyph(glyphs[i], 0, widths[i], height); f.putCharacter(cp, g); } f.setAscentDescent(); f.setCapHeight(); f.setXHeight(); return f; } } NFNTBitmapFontImporter.java000066400000000000000000000263151506470510200343450ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.*; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.mover.FONDEntry; import com.kreative.bitsnpicas.mover.MoverFile; import com.kreative.bitsnpicas.mover.ResourceBundle; import com.kreative.unicode.data.GlyphList; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; public abstract class NFNTBitmapFontImporter implements BitmapFontImporter { protected GlyphList encoding; protected NFNTBitmapFontImporter() { this.encoding = null; } protected NFNTBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } public static final class ResourceFile extends NFNTBitmapFontImporter { public ResourceFile() { super(); } public ResourceFile(GlyphList encoding) { super(encoding); } public BitmapFont[] importFont(byte[] data) throws IOException { return importFont(new DfontFile(data)); } public BitmapFont[] importFont(File file) throws IOException { return importFont(new DfontFile(file)); } public BitmapFont[] importFont(InputStream is) throws IOException { return importFont(new DfontFile(is)); } public BitmapFont[] importFont(DfontFile rsrc) throws IOException { List fonts = new ArrayList(); MoverFile mf = new MoverFile(rsrc); for (int i = 0, n = mf.size(); i < n; i++) { for (BitmapFont font : importFont(mf.get(i))) { fonts.add(font); } } return fonts.toArray(new BitmapFont[fonts.size()]); } public BitmapFont[] importFont(ResourceBundle rb) throws IOException { List fonts = new ArrayList(); if (rb.fond != null) { Map resData = new HashMap(); for (DfontResource res : rb.resources) { if ( res.getTypeString().equals("NFNT") || (res.getTypeString().equals("FONT") && !resData.containsKey(res.getId())) ) { resData.put(res.getId(), res.getData()); } } for (FONDEntry e : rb.fond.entries) { if (e.size != 0) { fonts.add(importFont( resData.get(e.id), rb.fond.id, e.size, e.style, rb.fond.name )); } } } return fonts.toArray(new BitmapFont[fonts.size()]); } } private static final Pattern COMPONENT_PATTERN = Pattern.compile( "\\s+(#([0-9]+)|([0-9]+)|Bold|Italic|Underline|Outline|Shadow|Condensed|Extended)", Pattern.CASE_INSENSITIVE ); public static final class FlatFile extends NFNTBitmapFontImporter { public FlatFile() { super(); } public FlatFile(GlyphList encoding) { super(encoding); } public BitmapFont[] importFont(File file) throws IOException { int fontId = 12; int fontSize = 12; int fontStyle = 0; StringBuffer sb = new StringBuffer(); Matcher m = COMPONENT_PATTERN.matcher(file.getName()); while (m.find()) { if (m.group(2) != null) fontId = Integer.parseInt(m.group(2)); else if (m.group(3) != null) fontSize = Integer.parseInt(m.group(3)); else if (m.group(1).equalsIgnoreCase("Bold")) fontStyle |= 1; else if (m.group(1).equalsIgnoreCase("Italic")) fontStyle |= 2; else if (m.group(1).equalsIgnoreCase("Underline")) fontStyle |= 4; else if (m.group(1).equalsIgnoreCase("Outline")) fontStyle |= 8; else if (m.group(1).equalsIgnoreCase("Shadow")) fontStyle |= 16; else if (m.group(1).equalsIgnoreCase("Condensed")) fontStyle |= 32; else if (m.group(1).equalsIgnoreCase("Extended")) fontStyle |= 64; m.appendReplacement(sb, ""); } m.appendTail(sb); String fontName = sb.toString().trim(); if (fontName.length() == 0) fontName = "Untitled"; BitmapFont f = importFont(file, fontId, fontSize, fontStyle, fontName); return new BitmapFont[]{f}; } public BitmapFont[] importFont(InputStream is) throws IOException { BitmapFont f = importFont(is, 12, 12, 0, "Untitled"); return new BitmapFont[]{f}; } public BitmapFont[] importFont(byte[] data) throws IOException { BitmapFont f = importFont(data, 12, 12, 0, "Untitled"); return new BitmapFont[]{f}; } } protected BitmapFont importFont(File file, int fontId, int fontSize, int fontStyle, String fontName) throws IOException { FileInputStream is = new FileInputStream(file); BitmapFont f = importFont(is, fontId, fontSize, fontStyle, fontName); is.close(); return f; } protected BitmapFont importFont(InputStream is, int fontId, int fontSize, int fontStyle, String fontName) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int count; while ((count = is.read(buf)) > 0) os.write(buf, 0, count); os.flush(); os.close(); buf = os.toByteArray(); return importFont(buf, fontId, fontSize, fontStyle, fontName); } protected BitmapFont importFont(byte[] data, int fontId, int fontSize, int fontStyle, String fontName) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); DataInputStream nfntIn = new DataInputStream(in); /* int type = */ nfntIn.readShort(); int firstChar = nfntIn.readShort(); int lastChar = nfntIn.readShort(); /* int maxWidth = */ nfntIn.readShort(); int kerning = nfntIn.readShort(); int nDescent = nfntIn.readShort(); /* int rectWidth = */ nfntIn.readShort(); int height = nfntIn.readShort(); int wots = nfntIn.readUnsignedShort(); if (nDescent > 0) wots |= (nDescent << 16); int ascent = nfntIn.readShort(); int descent = nfntIn.readShort(); int leading = nfntIn.readShort(); int rowWidth = nfntIn.readUnsignedShort(); byte[][] realBitmap = new byte[height][rowWidth * 2]; for (int i = 0; i < height; i++) nfntIn.readFully(realBitmap[i]); short[] xcoords = new short[lastChar - firstChar + 3]; for (int i = 0; i < xcoords.length; i++) xcoords[i] = nfntIn.readShort(); nfntIn.skip(2 * (wots - (5 + (rowWidth * height) + (lastChar - firstChar + 3)))); byte[] offsets = new byte[lastChar - firstChar + 2]; byte[] widths = new byte[lastChar - firstChar + 2]; for (int i = 0; i < offsets.length && i < widths.length; i++) { offsets[i] = nfntIn.readByte(); widths[i] = nfntIn.readByte(); } nfntIn.close(); in.close(); byte[][] bitmap = new byte[height][rowWidth * 16]; for (int y = 0; y < height; y++) { for (int rx = 0, x = 0; rx < realBitmap[y].length && x < bitmap[y].length; rx++) { for (int k = 0; x < bitmap[y].length && k < 8; x++, k++) { if (((realBitmap[y][rx] << k) & 0x80) != 0) bitmap[y][x] = -1; } } } int emAscent = ascent; int emDescent = descent; while (emAscent + emDescent < fontSize) { if (emAscent + emDescent < fontSize) emAscent++; if (emAscent + emDescent < fontSize) emDescent++; } while (emAscent + emDescent > fontSize) { if (emAscent + emDescent > fontSize) emAscent--; if (emAscent + emDescent > fontSize) emDescent--; } BitmapFont font = new BitmapFont(emAscent, emDescent, ascent, descent, 0, 0, leading); for (int i = 0, ch = firstChar; ch <= lastChar; i++, ch++) { if (widths[i] != -1) { int xcoord = xcoords[i] & 0xFFFF; int width = (xcoords[i + 1] & 0xFFFF) - xcoord; if (width < 0 || (xcoord + width) > (rowWidth * 16)) continue; byte[][] glyph = new byte[height][width]; for (int y = 0; y < height; y++) { for (int gx = 0, bx = xcoord; gx < width; gx++, bx++) { glyph[y][gx] = bitmap[y][bx]; } } int offset = offsets[i] + kerning; int advance = widths[i] & 0xFF; BitmapFontGlyph g = new BitmapFontGlyph(glyph, offset, advance, ascent); int cp = (encoding != null) ? encoding.get(ch) : MACROMAN[ch]; if (cp >= 0) font.putCharacter(cp, g); } } if (widths[lastChar - firstChar + 1] != -1) { int xcoord = xcoords[lastChar - firstChar + 1] & 0xFFFF; int width = (xcoords[lastChar - firstChar + 2] & 0xFFFF) - xcoord; if (!(width < 0 || (xcoord + width) > (rowWidth * 16))) { byte[][] glyph = new byte[height][width]; for (int y = 0; y < height; y++) { for (int gx = 0, bx = xcoord; gx < width; gx++, bx++) { glyph[y][gx] = bitmap[y][bx]; } } int offset = offsets[lastChar - firstChar + 1] + kerning; int advance = widths[lastChar - firstChar + 1] & 0xFF; BitmapFontGlyph g = new BitmapFontGlyph(glyph, offset, advance, ascent); font.putNamedGlyph(".notdef", g); } } font.setName(Font.NAME_FAMILY, fontName); font.setName(Font.NAME_STYLE, fontStyleToString(fontStyle)); font.setXHeight(); font.setCapHeight(); return font; } private static String fontStyleToString(int fontStyle) { StringBuffer sb = new StringBuffer(); if ((fontStyle & 0x01) != 0) sb.append(" Bold"); if ((fontStyle & 0x02) != 0) sb.append(" Italic"); if ((fontStyle & 0x04) != 0) sb.append(" Underline"); if ((fontStyle & 0x08) != 0) sb.append(" Outline"); if ((fontStyle & 0x10) != 0) sb.append(" Shadow"); if ((fontStyle & 0x20) != 0) sb.append(" Condensed"); if ((fontStyle & 0x40) != 0) sb.append(" Extended"); return (sb.length() > 0) ? sb.toString().trim() : "Normal"; } private static final int[] MACROMAN = new int[] { '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', '\b', '\t', '\n', '\u000B', '\u000C', '\r', '\u000E', '\u000F', '\u0010', '\u2318', '\u2713', '\u25C6', '\uF8FF', '\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\u007F', '\u00C4', '\u00C5', '\u00C7', '\u00C9', '\u00D1', '\u00D6', '\u00DC', '\u00E1', '\u00E0', '\u00E2', '\u00E4', '\u00E3', '\u00E5', '\u00E7', '\u00E9', '\u00E8', '\u00EA', '\u00EB', '\u00ED', '\u00EC', '\u00EE', '\u00EF', '\u00F1', '\u00F3', '\u00F2', '\u00F4', '\u00F6', '\u00F5', '\u00FA', '\u00F9', '\u00FB', '\u00FC', '\u2020', '\u00B0', '\u00A2', '\u00A3', '\u00A7', '\u2022', '\u00B6', '\u00DF', '\u00AE', '\u00A9', '\u2122', '\u00B4', '\u00A8', '\u2260', '\u00C6', '\u00D8', '\u221E', '\u00B1', '\u2264', '\u2265', '\u00A5', '\u00B5', '\u2202', '\u2211', '\u220F', '\u03C0', '\u222B', '\u00AA', '\u00BA', '\u03A9', '\u00E6', '\u00F8', '\u00BF', '\u00A1', '\u00AC', '\u221A', '\u0192', '\u2248', '\u2206', '\u00AB', '\u00BB', '\u2026', '\u00A0', '\u00C0', '\u00C3', '\u00D5', '\u0152', '\u0153', '\u2013', '\u2014', '\u201C', '\u201D', '\u2018', '\u2019', '\u00F7', '\u25CA', '\u00FF', '\u0178', '\u2044', '\u20AC', '\u2039', '\u203A', '\uFB01', '\uFB02', '\u2021', '\u00B7', '\u201A', '\u201E', '\u2030', '\u00C2', '\u00CA', '\u00C1', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00D3', '\u00D4', '\uF8FF', '\u00D2', '\u00DA', '\u00DB', '\u00D9', '\u0131', '\u02C6', '\u02DC', '\u00AF', '\u02D8', '\u02D9', '\u02DA', '\u00B8', '\u02DD', '\u02DB', '\u02C7' }; } PSFBitmapFontImporter.java000066400000000000000000000155521506470510200342310ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.zip.GZIPInputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public class PSFBitmapFontImporter implements BitmapFontImporter { private GlyphList lowEncoding; private GlyphList highEncoding; private int puaBase; private boolean gzip; public PSFBitmapFontImporter() { this.lowEncoding = null; this.highEncoding = null; this.puaBase = -1; this.gzip = false; } public PSFBitmapFontImporter(boolean gzip) { this.lowEncoding = null; this.highEncoding = null; this.puaBase = -1; this.gzip = gzip; } public PSFBitmapFontImporter(GlyphList low, GlyphList high, int puaBase) { this.lowEncoding = low; this.highEncoding = high; this.puaBase = puaBase; this.gzip = false; } public PSFBitmapFontImporter(GlyphList low, GlyphList high, int puaBase, boolean gzip) { this.lowEncoding = low; this.highEncoding = high; this.puaBase = puaBase; this.gzip = gzip; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { InputStream in = new ByteArrayInputStream(data); if (gzip) in = new GZIPInputStream(in); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { if (gzip) in = new GZIPInputStream(in); BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { InputStream in = new FileInputStream(file); if (gzip) in = new GZIPInputStream(in); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); String name = file.getName(); if (name.toLowerCase().endsWith(".psf")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".psfu")) { name = name.substring(0, name.length() - 5); } else if (name.toLowerCase().endsWith(".psf.gz")) { name = name.substring(0, name.length() - 7); } else if (name.toLowerCase().endsWith(".psfu.gz")) { name = name.substring(0, name.length() - 8); } f.setName(Font.NAME_FAMILY, name); return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { int version = readVersion(in); int headerSize = (version < 2) ? 4 : Integer.reverseBytes(in.readInt()); int flags = (version < 2) ? in.readUnsignedByte() : Integer.reverseBytes(in.readInt()); int numGlyphs = (version < 2) ? (((flags&1)==0)?256:512) : Integer.reverseBytes(in.readInt()); int charSize = (version < 2) ? in.readUnsignedByte() : Integer.reverseBytes(in.readInt()); int height = (version < 2) ? charSize : Integer.reverseBytes(in.readInt()); int width = (version < 2) ? 8 : Integer.reverseBytes(in.readInt()); if (version >= 2 && headerSize > 32) in.readFully(new byte[headerSize - 32]); byte[][][] glyphs = new byte[numGlyphs][][]; byte[] data = new byte[charSize]; for (int i = 0; i < numGlyphs; i++) { in.readFully(data); glyphs[i] = new byte[height][width]; for (int j = 0, y = 0; y < height; y++) { for (int x = 0; x < width; j++) { for (int m = 0x80; x < width && m != 0; x++, m >>= 1) { if ((data[j] & m) != 0) { glyphs[i][y][x] = -1; } } } } } HashMap unicodeTable = new HashMap(); if ((flags & ((version < 2) ? 2 : 1)) != 0) { for (int i = 0; i < numGlyphs; i++) { String[] entry = readUnicodeEntry(in, version); for (String s : entry) unicodeTable.put(s, i); } } BitmapFont f = new BitmapFont(height, 0, height, 0, height, height, 0); if (lowEncoding != null) { for (int i = 0; i < 256 && i < numGlyphs; i++) { Integer cp = lowEncoding.get(i & 0xFF); if (cp != null && cp >= 0) { f.putCharacter(cp, new BitmapFontGlyph(glyphs[i], 0, width, height)); } } } if (highEncoding != null) { for (int i = 256; i < 512 && i < numGlyphs; i++) { Integer cp = highEncoding.get(i & 0xFF); if (cp != null && cp >= 0) { f.putCharacter(cp, new BitmapFontGlyph(glyphs[i], 0, width, height)); } } } if (puaBase >= 0) { for (int i = 0; i < numGlyphs; i++) { f.putCharacter(puaBase + i, new BitmapFontGlyph(glyphs[i], 0, width, height)); } } for (HashMap.Entry e : unicodeTable.entrySet()) { String key = e.getKey(); if (key.codePointCount(0, key.length()) == 1) { int cp = key.codePointAt(0); int i = e.getValue().intValue(); f.putCharacter(cp, new BitmapFontGlyph(glyphs[i], 0, width, height)); } } if (f.isEmpty()) { for (int i = 0; i < numGlyphs; i++) { f.putCharacter(i, new BitmapFontGlyph(glyphs[i], 0, width, height)); } } f.setAscentDescent(); f.setXHeight(); f.setCapHeight(); return f; } private int readVersion(DataInputStream in) throws IOException { int m1 = in.readUnsignedShort(); if (m1 == 0x3604) return 1; if (m1 == 0x72B5) { int m2 = in.readUnsignedShort(); if (m2 == 0x4A86) { int m3 = in.readInt(); if (m3 == 0) return 2; throw new IOException("bad magic number m3: " + m3); } throw new IOException("bad magic number m2: " + m2); } throw new IOException("bad magic number m1: " + m1); } private String[] readUnicodeEntry(DataInputStream in, int version) throws IOException { if (version < 2) { StringBuffer sb = new StringBuffer(); while (true) { char ch = Character.reverseBytes(in.readChar()); if (ch == (char)0xFFFF) break; sb.append(ch); } String s = sb.toString(); return splitUnicodeEntry(s); } else { ByteArrayOutputStream out = new ByteArrayOutputStream(); while (true) { int b = in.readUnsignedByte(); if (b == 0xFF) break; if (b == 0xFE) { out.write(0xEF); out.write(0xBF); out.write(0xBE); } else { out.write(b); } } byte[] b = out.toByteArray(); String s = new String(b, "UTF-8"); return splitUnicodeEntry(s); } } private String[] splitUnicodeEntry(String s) { ArrayList a = new ArrayList(); String[] pieces = s.split("\uFFFE+"); for (int i = 0, n = pieces[0].length(); i < n;) { int cp = pieces[0].codePointAt(i); a.add(String.valueOf(Character.toChars(cp))); i += Character.charCount(cp); } for (int i = 1, n = pieces.length; i < n; i++) { a.add(pieces[i]); } return a.toArray(new String[a.size()]); } } PlaydateBitmapFontImporter.java000066400000000000000000000216751506470510200353470ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import com.kreative.bitsnpicas.Base64InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.FileProxy; import com.kreative.bitsnpicas.GlyphPair; public class PlaydateBitmapFontImporter implements BitmapFontImporter { private static final Pattern FNT_FILE_PATTERN = Pattern.compile("^(.+)\\.fnt$", Pattern.CASE_INSENSITIVE); private static final Pattern PNG_FILE_PATTERN = Pattern.compile("^(.+)-table-(\\d+)-(\\d+)\\.png$", Pattern.CASE_INSENSITIVE); private static Pattern fntFilePattern(String basename) { return Pattern.compile("^(" + Pattern.quote(basename) + ")\\.fnt$", Pattern.CASE_INSENSITIVE); } private static Pattern pngFilePattern(String basename) { return Pattern.compile("^(" + Pattern.quote(basename) + ")-table-(\\d+)-(\\d+)\\.png$", Pattern.CASE_INSENSITIVE); } private static File findFileMatching(Pattern pattern, File parent) { for (File child : parent.listFiles()) { if (pattern.matcher(child.getName()).matches()) { return child; } } return null; } private static boolean looksLikeFnt(FileProxy fp) { return ( fp.startsWith('t','r','a','c','k','i','n','g') || fp.startsWith('d','a','t','a') || fp.startsWith('w','i','d','t','h') || fp.startsWith('h','e','i','g','h','t') || fp.startsWith('s','p','a','c','e') || fp.startsWith('-','-') ); } public static boolean canImportFont(FileProxy fp) { File file = fp.getFile(); Matcher pm = PNG_FILE_PATTERN.matcher(file.getName()); if (pm.matches()) { File fnt = findFileMatching(fntFilePattern(pm.group(1)), file.getParentFile()); return fnt != null && looksLikeFnt(new FileProxy(fnt)); } Matcher fm = FNT_FILE_PATTERN.matcher(file.getName()); return fm.matches() && looksLikeFnt(fp); } public BitmapFont[] importFont(byte[] data) throws IOException { return importFont(new ByteArrayInputStream(data)); } public BitmapFont[] importFont(InputStream is) throws IOException { Scanner scan = new Scanner(is, "UTF-8"); BitmapFont f = importFont(scan, null, null, -1, -1); return new BitmapFont[]{f}; } public BitmapFont[] importFont(File file) throws IOException { Matcher pm = PNG_FILE_PATTERN.matcher(file.getName()); if (pm.matches()) { File fnt = findFileMatching(fntFilePattern(pm.group(1)), file.getParentFile()); if (fnt == null) throw new FileNotFoundException(); int cw = Integer.parseInt(pm.group(2)); int ch = Integer.parseInt(pm.group(3)); BufferedImage img = ImageIO.read(file); return importFont(fnt, pm.group(1), img, cw, ch); } Matcher fm = FNT_FILE_PATTERN.matcher(file.getName()); if (fm.matches()) { File png = findFileMatching(pngFilePattern(fm.group(1)), file.getParentFile()); if (png != null) { pm = PNG_FILE_PATTERN.matcher(png.getName()); if (pm.matches()) { int cw = Integer.parseInt(pm.group(2)); int ch = Integer.parseInt(pm.group(3)); BufferedImage img = ImageIO.read(png); return importFont(file, pm.group(1), img, cw, ch); } } return importFont(file, fm.group(1), null, -1, -1); } return importFont(file, file.getName(), null, -1, -1); } private BitmapFont[] importFont(File file, String name, BufferedImage img, int cw, int ch) throws IOException { Scanner scan = new Scanner(new FileInputStream(file), "UTF-8"); BitmapFont f = importFont(scan, name, img, cw, ch); return new BitmapFont[]{f}; } private static final Pattern PROPERTY_LINE = Pattern.compile("^(--\\s*)?(\\w+)\\s*=\\s*(.+)$"); private static final Pattern METRICS_LINE = Pattern.compile("\"(\\w+)\"\\s*:\\s*(-?\\d+)"); private BitmapFont importFont(Scanner scan, String name, BufferedImage img, int cw, int ch) throws IOException { Integer baseline = null; Integer xHeight = null; Integer capHeight = null; int tracking = 1; ArrayList codePoints = new ArrayList(); ArrayList charWidths = new ArrayList(); ArrayList kernPairLeft = new ArrayList(); ArrayList kernPairRight = new ArrayList(); ArrayList kernPairWidths = new ArrayList(); // Read the fnt file. while (scan.hasNextLine()) { String line = scan.nextLine(); Matcher plm = PROPERTY_LINE.matcher(line); if (plm.matches()) { String key = plm.group(2); String value = plm.group(3); if (key.equals("name")) { name = value; } else if (key.equals("metrics")) { Matcher mlm = METRICS_LINE.matcher(value); while (mlm.find()) { key = mlm.group(1); value = mlm.group(2); if (key.equals("baseline")) { try { baseline = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } else if (key.equals("xHeight")) { try { xHeight = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } else if (key.equals("capHeight")) { try { capHeight = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } } } else if (key.equals("tracking")) { try { tracking = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } else if (key.equals("data")) { try { img = ImageIO.read(new Base64InputStream(value)); } catch (IOException ioe) { continue; } } else if (key.equals("width")) { try { cw = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } else if (key.equals("height")) { try { ch = Integer.parseInt(value); } catch (NumberFormatException nfe) { continue; } } continue; } if (line.startsWith("--")) continue; String[] fields = line.contains("\t") ? line.split("\t+") : line.split("\\s+"); if (fields.length != 2) continue; int width; try { width = Integer.parseInt(fields[1]); } catch (NumberFormatException nfe) { continue; } ArrayList cps = splitCodePoints(fields[0]); switch (cps.size()) { case 1: codePoints.add(cps.get(0)); charWidths.add(width); break; case 2: kernPairLeft.add(cps.get(0)); kernPairRight.add(cps.get(1)); kernPairWidths.add(width); break; } } // Check properties. if (name == null) name = "Untitled"; if (img == null) throw new IOException("no png data found"); if (cw < 1 || ch < 1) throw new IOException("invalid cell size: " + cw + ", " + ch); int cols = img.getWidth() / cw; int rows = img.getHeight() / ch; if (cols < 1 || rows < 1) throw new IOException("invalid cell count: " + cols + ", " + rows); int ascent = (baseline == null) ? ch : (baseline > 0) ? baseline : (ch + baseline); // Create the glyphs. ArrayList glyphs = new ArrayList(); BufferedImage tmpImg = new BufferedImage(cw, ch, BufferedImage.TYPE_INT_ARGB); int[] tmpRgb = new int[cw * ch]; for (int row = 0, col = 0, i = 0, n = codePoints.size(); i < n; i++) { img.getRGB(col * cw, row * ch, cw, ch, tmpRgb, 0, cw); tmpImg.setRGB(0, 0, cw, ch, tmpRgb, 0, cw); BitmapFontGlyph g = new BitmapFontGlyph(); g.setCharacterWidth(charWidths.get(i) + tracking); g.setToImage(0, -ascent, tmpImg); g.contract(); glyphs.add(g); col++; if (col >= cols) { col = 0; row++; if (row >= rows) { row = 0; } } } // Create the font. BitmapFont f = new BitmapFont(ascent, ch - ascent, ascent, ch - ascent, 0, 0, 0); f.setName(BitmapFont.NAME_FAMILY, name); f.setName(BitmapFont.NAME_FAMILY_AND_STYLE, name); for (int i = 0, n = codePoints.size(); i < n; i++) { f.putCharacter(codePoints.get(i), glyphs.get(i)); } for (int i = 0, n = kernPairWidths.size(); i < n; i++) { f.setKernPair(new GlyphPair(kernPairLeft.get(i), kernPairRight.get(i)), kernPairWidths.get(i)); } if (baseline == null) f.setAscentDescent(); if (xHeight == null) f.setXHeight(); else f.setXHeight(xHeight); if (capHeight == null) f.setCapHeight(); else f.setCapHeight(capHeight); return f; } private static ArrayList splitCodePoints(String s) { ArrayList cps = new ArrayList(); int i = 0, n = s.length(); while (i < n) { if (s.regionMatches(i, "space", 0, 5)) { i += 5; cps.add(0x20); } else if (s.regionMatches(i, "U+", 0, 2)) { i += 2; int cp = 0; while (i < n) { int dcp = s.codePointAt(i); int d = Character.digit(dcp, 16); if (d < 0) break; i += Character.charCount(dcp); cp = ((cp << 4) | d); } cps.add(cp); } else { int cp = s.codePointAt(i); i += Character.charCount(cp); cps.add(cp); } } return cps; } } RockboxBitmapFontImporter.java000066400000000000000000000143011506470510200351770ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class RockboxBitmapFontImporter implements BitmapFontImporter { private static final int RB11 = 0x52423131; private static final int RB12 = 0x52423132; @Override public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(data); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { BitmapFont f = importFontImpl(new DataInputStream(in)); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont f = importFontImpl(new DataInputStream(in)); in.close(); String name = f.getName(Font.NAME_FAMILY); if (name == null || name.length() == 0) { name = file.getName(); if (name.toLowerCase().endsWith(".fnt")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".rbf")) { name = name.substring(0, name.length() - 4); } else if (name.toLowerCase().endsWith(".rb11")) { name = name.substring(0, name.length() - 5); } else if (name.toLowerCase().endsWith(".rb12")) { name = name.substring(0, name.length() - 5); } f.setName(Font.NAME_FAMILY, name); } return new BitmapFont[]{f}; } private BitmapFont importFontImpl(DataInputStream in) throws IOException { // Read magic number. int magic = in.readInt(); if (magic != RB11 && magic != RB12) throw new IOException("bad magic number"); // Read name and copyright info. String name; String copyright; if (magic == RB11) { byte[] nameBytes = new byte[64]; byte[] copyrightBytes = new byte[256]; in.readFully(nameBytes); in.readFully(copyrightBytes); name = new String(nameBytes, "UTF-8").trim(); copyright = new String(copyrightBytes, "UTF-8").trim(); } else { name = null; copyright = null; } // Read metrics. int maxWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int height = Short.reverseBytes(in.readShort()) & 0xFFFF; int ascent = Short.reverseBytes(in.readShort()) & 0xFFFF; int depth = Short.reverseBytes(in.readShort()) & 0xFFFF; int firstChar = Integer.reverseBytes(in.readInt()); int defaultChar = Integer.reverseBytes(in.readInt()); int numChars = Integer.reverseBytes(in.readInt()); int numBits = Integer.reverseBytes(in.readInt()); int numOffsets = Integer.reverseBytes(in.readInt()); int numWidths = Integer.reverseBytes(in.readInt()); if (depth != 0) throw new IOException("anti-aliased not supported right now"); // Read bitmap. byte[] bitmap; if (magic == RB11) { bitmap = new byte[(((numBits * 2) + 3) / 4) * 4]; } else { bitmap = new byte[((numBits + 1) / 2) * 2]; } in.readFully(bitmap); // Read offsets and widths. int[] offsets = new int[numOffsets]; int[] widths = new int[numWidths]; if (magic == RB11) { for (int i = 0; i < numOffsets; i++) { offsets[i] = Integer.reverseBytes(in.readInt()); } } else { for (int i = 0; i < numOffsets; i++) { offsets[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; } } for (int i = 0; i < numWidths; i++) { widths[i] = in.readUnsignedByte(); } BitmapFont f = new BitmapFont(ascent, height-ascent, ascent, height-ascent, 0, 0, 0); if (name != null) f.setName(BitmapFont.NAME_FAMILY, name); if (copyright != null) f.setName(BitmapFont.NAME_COPYRIGHT, copyright); int defIndex = defaultChar - firstChar; int defOffset = (defIndex >= 0 && defIndex < numOffsets) ? offsets[defIndex] : 0; for (int i = 0; i < numChars; i++) { if (i != defIndex && i < numOffsets && offsets[i] == defOffset) continue; int width = (i < numWidths) ? widths[i] : maxWidth; int rowBytes = ((width + 15) / 16) * 2; byte[] glyphBitmap; if (magic == RB11) { int offset = (i < numOffsets) ? (offsets[i] * 2) : (rowBytes * height * i); glyphBitmap = swab(bitmap, offset, width, height); } else { int offset = (i < numOffsets) ? offsets[i] : (((height + 7) / 8) * maxWidth * i); glyphBitmap = rotright(bitmap, offset, width, height); } byte[][] glyphPixels = new byte[height][width]; for (int by = 0, py = 0; py < height; py++, by += rowBytes) { for (int px = 0, bx = 0; bx < rowBytes; bx++) { for (int m = 0x80; m != 0; m >>= 1, px++) { if (px < width && (glyphBitmap[by + bx] & m) != 0) { glyphPixels[py][px] = -1; } } } } BitmapFontGlyph glyph = new BitmapFontGlyph(glyphPixels, 0, width, ascent); f.putCharacter(firstChar + i, glyph); } f.setXHeight(); f.setCapHeight(); return f; } private static byte[] swab(byte[] fntData, int fntOffset, int width, int height) { int rowByteCount = ((width + 15) / 16) * 2; int bmpByteCount = rowByteCount * height; byte[] bmpBytes = new byte[bmpByteCount]; for (int i = 0; i < bmpByteCount; i++) { bmpBytes[i ^ 1] = fntData[fntOffset++]; } return bmpBytes; } private static byte[] rotright(byte[] fntData, int fntOffset, int width, int height) { int rowWordCount = (width + 15) / 16; int bmpWordCount = rowWordCount * height; int[] bmpWords = new int[bmpWordCount]; int fntMask = 1; for (int i = 0; i < height; i++) { int bmpOffset = i * rowWordCount; int bmpMask = 0x8000; for (int j = 0; j < width; j++) { if ((fntData[fntOffset + j] & fntMask) != 0) { bmpWords[bmpOffset] |= bmpMask; } bmpMask >>= 1; if (bmpMask == 0) { bmpMask = 0x8000; bmpOffset++; } } fntMask <<= 1; if (fntMask >= 256) { fntMask = 1; fntOffset += width; } } byte[] bmpBytes = new byte[bmpWordCount * 2]; for (int bi = 0, wi = 0; wi < bmpWordCount; wi++) { bmpBytes[bi++] = (byte)(bmpWords[wi] >> 8); bmpBytes[bi++] = (byte)(bmpWords[wi] >> 0); } return bmpBytes; } } S10BitmapFontImporter.java000077500000000000000000002703551506470510200341530ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.*; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class S10BitmapFontImporter implements BitmapFontImporter { public BitmapFont[] importFont(byte[] data) throws IOException { return importFont(new ByteArrayInputStream(data)); } public BitmapFont[] importFont(File file) throws IOException { return importFont(new FileInputStream(file)); } public BitmapFont[] importFont(InputStream is) throws IOException { BitmapFont[] fonts = new BitmapFont[] { new BitmapFont(7,1,7,1,5,7,0), new BitmapFont(7,1,7,1,5,7,0), new BitmapFont(7,1,7,1,5,7,0), new BitmapFont(7,1,7,1,5,7,0), new BitmapFont(7,1,7,1,5,7,0), new BitmapFont(7,1,7,1,5,7,0) }; for (BitmapFont font : fonts) font.setName(Font.NAME_COPYRIGHT, "From SabineOS 1.0 (*shudder*), (c) 2000 Kreative Software"); fonts[0].setName(Font.NAME_FAMILY, "Sabine Doscbthm"); fonts[0].setName(Font.NAME_STYLE, "Normal"); fonts[1].setName(Font.NAME_FAMILY, "Sabine Doscbthm Serif"); fonts[1].setName(Font.NAME_STYLE, "Normal"); fonts[2].setName(Font.NAME_FAMILY, "Sabine Doscbthm"); fonts[2].setName(Font.NAME_STYLE, "Black"); fonts[3].setName(Font.NAME_FAMILY, "Sabine Doscbthm"); fonts[3].setName(Font.NAME_STYLE, "Oblique"); fonts[4].setName(Font.NAME_FAMILY, "Sabine Doscbthm Small"); fonts[4].setName(Font.NAME_STYLE, "Normal"); fonts[5].setName(Font.NAME_FAMILY, "Sabine Doscbthm Script"); fonts[5].setName(Font.NAME_STYLE, "Normal"); for (int i = 0; i < 1024 && is.available() > 0; i++) { byte[] stuff = new byte[8]; is.read(stuff); stuff = unpack(stuff); byte[][] glyph = new byte[8][8]; for (int idx = 0, y = 0; y < 8; y++) { for (int x = 0; x < 8; x++, idx++) { glyph[y][x] = ((stuff[idx] != 0) ? (byte)0xFF : (byte)0x00); } } BitmapFontGlyph g = new BitmapFontGlyph(glyph, 0, 8, 7); for (BitmapFont font : fonts) font.putCharacter(0xF000+i, g); int[] chs = getMap(MAP_SANS_LO, MAP_SANS_HI, i); if (chs != null) { for (int ch : chs) { fonts[0].putCharacter(ch, g); } } chs = getMap(MAP_SERIF_LO, MAP_SERIF_HI, i); if (chs != null) { for (int ch : chs) { fonts[1].putCharacter(ch, g); } } chs = getMap(MAP_SOLID_LO, MAP_SOLID_HI, i); if (chs != null) { for (int ch : chs) { fonts[2].putCharacter(ch, g); } } chs = getMap(MAP_SLANTED_LO, MAP_SLANTED_HI, i); if (chs != null) { for (int ch : chs) { fonts[3].putCharacter(ch, g); } } chs = getMap(MAP_SMALL_LO, MAP_SMALL_HI, i); if (chs != null) { for (int ch : chs) { fonts[4].putCharacter(ch, g); } } chs = getMap(MAP_SCRIPT_LO, MAP_SCRIPT_HI, i); if (chs != null) { for (int ch : chs) { fonts[5].putCharacter(ch, g); } } } return fonts; } private static byte[] unpack(byte[] data) { byte[] nd = new byte[data.length*8]; for (int s=0, d=0; s> 7) & 1); nd[d+1] = (byte)((data[s] >> 6) & 1); nd[d+2] = (byte)((data[s] >> 5) & 1); nd[d+3] = (byte)((data[s] >> 4) & 1); nd[d+4] = (byte)((data[s] >> 3) & 1); nd[d+5] = (byte)((data[s] >> 2) & 1); nd[d+6] = (byte)((data[s] >> 1) & 1); nd[d+7] = (byte)((data[s] >> 0) & 1); } return nd; } private static int[] getMap(int[][] lo, int[][] hi, int i) { if (i < 512) return lo[i]; else return hi[i - 512]; } private static final int[][] MAP_SANS_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, new int[]{33}, new int[]{34}, new int[]{35}, new int[]{36}, new int[]{37}, new int[]{38}, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{42}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51,1047}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, new int[]{64}, new int[]{65,913,1040}, new int[]{66,914,1042}, new int[]{67,1057}, new int[]{68}, new int[]{69,917,1045}, new int[]{70}, new int[]{71}, new int[]{72,919,1053}, new int[]{73,921}, new int[]{74}, new int[]{75,922,1050}, new int[]{76}, new int[]{77,924,1052}, new int[]{78,925}, new int[]{79,927,1054}, new int[]{80,929,1056}, new int[]{81}, new int[]{82}, new int[]{83}, new int[]{84,932,1058}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88,935,1061}, new int[]{89,933}, new int[]{90,918}, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, new int[]{97,1072}, new int[]{98}, new int[]{99,1089}, new int[]{100}, new int[]{101,1077}, new int[]{102}, new int[]{103}, new int[]{104}, new int[]{105}, new int[]{106}, new int[]{107}, new int[]{108}, new int[]{109}, new int[]{110,951}, new int[]{111,959,1086}, new int[]{112,1088}, new int[]{113}, new int[]{114}, new int[]{115}, new int[]{116}, new int[]{117}, new int[]{118}, new int[]{119}, new int[]{120,967,1093}, new int[]{121,1091}, new int[]{122}, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{127,63253}, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{915,1043}, null, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, null, new int[]{923}, new int[]{955}, null, new int[]{181,956}, new int[]{957}, new int[]{926}, null, new int[]{928,1055}, new int[]{960,1087}, new int[]{8719}, new int[]{961}, new int[]{8721}, new int[]{931}, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, new int[]{1041}, null, new int[]{1073}, new int[]{1074}, null, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, null, new int[]{1059}, new int[]{1062}, new int[]{1094}, null, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, null, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, new int[]{1067}, null, new int[]{1069}, null, new int[]{1101}, new int[]{1070}, new int[]{1102}, null, null, new int[]{1071}, null, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SANS_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{63281}, new int[]{63282}, new int[]{63283}, new int[]{63284}, new int[]{63285}, new int[]{63286}, new int[]{63287}, new int[]{63288,1085}, new int[]{63289}, new int[]{63290}, new int[]{63291}, new int[]{63292}, new int[]{63293,1084}, new int[]{63294}, new int[]{63295}, new int[]{63296}, new int[]{63297}, new int[]{63298}, new int[]{63299}, new int[]{63300,1090}, new int[]{63301}, new int[]{63302}, new int[]{63303}, new int[]{63304}, new int[]{63305}, new int[]{63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63280}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; private static final int[][] MAP_SERIF_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, new int[]{33}, new int[]{34}, new int[]{35}, new int[]{36}, new int[]{37}, new int[]{38}, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{42}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51,1047}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, new int[]{64}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{127,63253}, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, new int[]{65,913,1040}, new int[]{66,914,1042}, new int[]{67,1057}, new int[]{68}, new int[]{69,917,1045}, new int[]{70}, new int[]{71}, new int[]{72,919,1053}, new int[]{73,921}, new int[]{74}, new int[]{75,922,1050}, new int[]{76}, new int[]{77,924,1052}, new int[]{78,925}, new int[]{79,927,1054}, new int[]{80,929,1056}, new int[]{81}, new int[]{82}, new int[]{83}, new int[]{84,932,1058}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88,935,1061}, new int[]{89,933}, new int[]{90,918}, new int[]{97,1072}, new int[]{98}, new int[]{99,1089}, new int[]{100}, new int[]{101,1077}, new int[]{102}, new int[]{103}, new int[]{104}, new int[]{105}, new int[]{106}, new int[]{107}, new int[]{108}, new int[]{109}, new int[]{110,951}, new int[]{111,959,1086}, new int[]{112,1088}, new int[]{113}, new int[]{114}, new int[]{115}, new int[]{116}, new int[]{117}, new int[]{118}, new int[]{119}, new int[]{120,967,1093}, new int[]{121,1091}, new int[]{122}, null, new int[]{915,1043}, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, new int[]{923}, null, null, new int[]{955}, new int[]{181,956}, new int[]{957}, null, new int[]{926}, null, new int[]{960,1087}, new int[]{928,1055,8719}, new int[]{961}, new int[]{931,8721}, null, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, null, new int[]{1041}, new int[]{1073}, null, new int[]{1074}, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, null, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, new int[]{1059}, null, null, new int[]{1062}, new int[]{1094}, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, null, new int[]{1067}, null, new int[]{1069}, new int[]{1101}, null, null, new int[]{1070}, new int[]{1102}, null, new int[]{1071}, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SERIF_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{63281}, new int[]{63282}, new int[]{63283}, new int[]{63284}, new int[]{63285}, new int[]{63286}, new int[]{63287}, new int[]{63288,1085}, new int[]{63289}, new int[]{63290}, new int[]{63291}, new int[]{63292}, new int[]{63293,1084}, new int[]{63294}, new int[]{63295}, new int[]{63296}, new int[]{63297}, new int[]{63298}, new int[]{63299}, new int[]{63300,1090}, new int[]{63301}, new int[]{63302}, new int[]{63303}, new int[]{63304}, new int[]{63305}, new int[]{63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63280}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; private static final int[][] MAP_SOLID_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, null, null, new int[]{35}, new int[]{36}, null, new int[]{38}, null, null, null, new int[]{42}, null, null, null, null, null, null, null, null, new int[]{1047}, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{64}, new int[]{913,1040}, new int[]{914,1042}, new int[]{1057}, null, new int[]{917,1045}, null, null, new int[]{919,1053}, new int[]{921}, null, new int[]{922,1050}, null, new int[]{924,1052}, new int[]{925}, new int[]{927,1054}, new int[]{929,1056}, null, null, null, new int[]{932,1058}, null, null, null, new int[]{935,1061}, new int[]{933}, new int[]{918}, null, null, null, null, null, null, new int[]{1072}, null, new int[]{1089}, null, new int[]{1077}, null, null, null, null, null, null, null, null, new int[]{951}, new int[]{959,1086}, new int[]{1088}, null, null, null, null, null, null, null, new int[]{967,1093}, new int[]{1091}, null, null, null, null, null, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{127,63253}, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{915,1043}, null, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, null, new int[]{923}, new int[]{955}, null, new int[]{181,956}, new int[]{957}, new int[]{926}, null, new int[]{928,1055}, new int[]{960,1087}, new int[]{8719}, new int[]{961}, new int[]{8721}, new int[]{931}, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, new int[]{1041}, null, new int[]{1073}, new int[]{1074}, null, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, null, new int[]{1059}, new int[]{1062}, new int[]{1094}, null, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, null, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, new int[]{1067}, null, new int[]{1069}, null, new int[]{1101}, new int[]{1070}, new int[]{1102}, null, null, new int[]{1071}, null, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SOLID_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{63281}, new int[]{63282}, new int[]{63283}, new int[]{63284}, new int[]{63285}, new int[]{63286}, new int[]{63287}, new int[]{63288,1085}, new int[]{63289}, new int[]{63290}, new int[]{63291}, new int[]{63292}, new int[]{63293,1084}, new int[]{63294}, new int[]{63295}, new int[]{63296}, new int[]{63297}, new int[]{63298}, new int[]{63299}, new int[]{63300,1090}, new int[]{63301}, new int[]{63302}, new int[]{63303}, new int[]{63304}, new int[]{63305}, new int[]{63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63280}, new int[]{33}, new int[]{34}, new int[]{37}, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, new int[]{65}, new int[]{66}, new int[]{67}, new int[]{68}, new int[]{69}, new int[]{70}, new int[]{71}, new int[]{72}, new int[]{73}, new int[]{74}, new int[]{75}, new int[]{76}, new int[]{77}, new int[]{78}, new int[]{79}, new int[]{80}, new int[]{81}, new int[]{82}, new int[]{83}, new int[]{84}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88}, new int[]{89}, new int[]{90}, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, new int[]{97}, new int[]{98}, new int[]{99}, new int[]{100}, new int[]{101}, new int[]{102}, new int[]{103}, new int[]{104}, new int[]{105}, new int[]{106}, new int[]{107}, new int[]{108}, new int[]{109}, new int[]{110}, new int[]{111}, new int[]{112}, new int[]{113}, new int[]{114}, new int[]{115}, new int[]{116}, new int[]{117}, new int[]{118}, new int[]{119}, new int[]{120}, new int[]{121}, new int[]{122}, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; private static final int[][] MAP_SLANTED_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{1047}, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{913,1040}, new int[]{914,1042}, new int[]{1057}, null, new int[]{917,1045}, null, null, new int[]{919,1053}, new int[]{921}, null, new int[]{922,1050}, null, new int[]{924,1052}, new int[]{925}, new int[]{927,1054}, new int[]{929,1056}, null, null, null, new int[]{932,1058}, null, null, null, new int[]{935,1061}, new int[]{933}, new int[]{918}, null, null, null, null, null, null, new int[]{1072}, null, new int[]{1089}, null, new int[]{1077}, null, null, null, null, null, null, null, null, new int[]{951}, new int[]{959,1086}, new int[]{1088}, null, null, null, null, null, null, null, new int[]{967,1093}, new int[]{1091}, null, null, null, null, null, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{915,1043}, null, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, null, new int[]{923}, new int[]{955}, null, new int[]{181,956}, new int[]{957}, new int[]{926}, null, new int[]{928,1055}, new int[]{960,1087}, new int[]{8719}, new int[]{961}, new int[]{8721}, new int[]{931}, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, new int[]{1041}, null, new int[]{1073}, new int[]{1074}, null, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, null, new int[]{1059}, new int[]{1062}, new int[]{1094}, null, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, null, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, new int[]{1067}, null, new int[]{1069}, null, new int[]{1101}, new int[]{1070}, new int[]{1102}, null, null, new int[]{1071}, null, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SLANTED_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{63281}, new int[]{63282}, new int[]{63283}, new int[]{63284}, new int[]{63285}, new int[]{63286}, new int[]{63287}, new int[]{63288,1085}, new int[]{63289}, new int[]{63290}, new int[]{63291}, new int[]{63292}, new int[]{63293,1084}, new int[]{63294}, new int[]{63295}, new int[]{63296}, new int[]{63297}, new int[]{63298}, new int[]{63299}, new int[]{63300,1090}, new int[]{63301}, new int[]{63302}, new int[]{63303}, new int[]{63304}, new int[]{63305}, new int[]{63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63280}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{33}, new int[]{34}, new int[]{35}, new int[]{36}, new int[]{37}, new int[]{38}, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{42}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, null, new int[]{64}, new int[]{65}, new int[]{66}, new int[]{67}, new int[]{68}, new int[]{69}, new int[]{70}, new int[]{71}, new int[]{72}, new int[]{73}, new int[]{74}, new int[]{75}, new int[]{76}, new int[]{77}, new int[]{78}, new int[]{79}, new int[]{80}, new int[]{81}, new int[]{82}, new int[]{83}, new int[]{84}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88}, new int[]{89}, new int[]{90}, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, new int[]{97}, new int[]{98}, new int[]{99}, new int[]{100}, new int[]{101}, new int[]{102}, new int[]{103}, new int[]{104}, new int[]{105}, new int[]{106}, new int[]{107}, new int[]{108}, new int[]{109}, new int[]{110}, new int[]{111}, new int[]{112}, new int[]{113}, new int[]{114}, new int[]{115}, new int[]{116}, new int[]{117}, new int[]{118}, new int[]{119}, new int[]{120}, new int[]{121}, new int[]{122}, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, new int[]{127,63253}, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; private static final int[][] MAP_SMALL_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, new int[]{33}, new int[]{34}, new int[]{35}, new int[]{36}, new int[]{37}, new int[]{38}, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{42}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51,1047}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, new int[]{64}, new int[]{65,913,1040}, new int[]{66,914,1042}, new int[]{67,1057}, new int[]{68}, new int[]{69,917,1045}, new int[]{70}, new int[]{71}, new int[]{72,919,1053}, new int[]{73,921}, new int[]{74}, new int[]{75,922,1050}, new int[]{76}, new int[]{77,924,1052}, new int[]{78,925}, new int[]{79,927,1054}, new int[]{80,929,1056}, new int[]{81}, new int[]{82}, new int[]{83}, new int[]{84,932,1058}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88,935,1061}, new int[]{89,933}, new int[]{90,918}, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, new int[]{1072}, null, new int[]{1089}, null, new int[]{1077}, null, null, null, null, null, null, null, null, new int[]{951}, new int[]{959,1086}, new int[]{1088}, null, null, null, null, null, null, null, new int[]{967,1093}, new int[]{1091}, null, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{127,63253}, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{915,1043}, null, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, null, new int[]{923}, new int[]{955}, null, new int[]{181,956}, new int[]{957}, new int[]{926}, null, new int[]{928,1055}, new int[]{960,1087}, new int[]{8719}, new int[]{961}, new int[]{8721}, new int[]{931}, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, new int[]{1041}, null, new int[]{1073}, new int[]{1074}, null, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, null, new int[]{1059}, new int[]{1062}, new int[]{1094}, null, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, null, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, new int[]{1067}, null, new int[]{1069}, null, new int[]{1101}, new int[]{1070}, new int[]{1102}, null, null, new int[]{1071}, null, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SMALL_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{97,63281}, new int[]{98,63282}, new int[]{99,63283}, new int[]{100,63284}, new int[]{101,63285}, new int[]{102,63286}, new int[]{103,63287}, new int[]{104,63288,1085}, new int[]{105,63289}, new int[]{106,63290}, new int[]{107,63291}, new int[]{108,63292}, new int[]{109,63293,1084}, new int[]{110,63294}, new int[]{111,63295}, new int[]{112,63296}, new int[]{113,63297}, new int[]{114,63298}, new int[]{115,63299}, new int[]{116,63300,1090}, new int[]{117,63301}, new int[]{118,63302}, new int[]{119,63303}, new int[]{120,63304}, new int[]{121,63305}, new int[]{122,63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63280}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; private static final int[][] MAP_SCRIPT_LO = new int[][] { new int[]{9216}, new int[]{9217}, new int[]{9218}, new int[]{9219}, new int[]{9220}, new int[]{9221}, new int[]{9222}, new int[]{9223}, new int[]{9224}, new int[]{9225}, new int[]{9226}, new int[]{9227}, new int[]{9228}, new int[]{9229}, new int[]{9230}, new int[]{9231}, new int[]{9232}, new int[]{9233}, new int[]{9234}, new int[]{9235}, new int[]{9236}, new int[]{9237}, new int[]{9238}, new int[]{9239}, new int[]{9240}, new int[]{9241}, new int[]{9242}, new int[]{9243}, new int[]{9244}, new int[]{9245}, new int[]{9246}, new int[]{9247}, new int[]{32}, new int[]{33}, new int[]{34}, new int[]{35}, new int[]{36}, new int[]{37}, null, new int[]{39}, new int[]{40}, new int[]{41}, new int[]{42}, new int[]{43}, new int[]{44}, new int[]{45,173}, new int[]{46}, new int[]{47}, new int[]{48}, new int[]{49}, new int[]{50}, new int[]{51,1047}, new int[]{52}, new int[]{53}, new int[]{54}, new int[]{55}, new int[]{56}, new int[]{57}, new int[]{58}, new int[]{59}, new int[]{60}, new int[]{61}, new int[]{62}, new int[]{63}, new int[]{64}, new int[]{65,913,1040}, new int[]{66,914,1042}, new int[]{67,1057}, new int[]{68}, new int[]{917,1045}, new int[]{70}, null, new int[]{72,919,1053}, new int[]{73,921}, null, new int[]{75,922,1050}, new int[]{76}, new int[]{77,924,1052}, new int[]{78,925}, new int[]{79,927,1054}, new int[]{80,929,1056}, new int[]{81}, new int[]{82}, null, new int[]{84,932,1058}, new int[]{85}, new int[]{86}, new int[]{87}, new int[]{88,935,1061}, new int[]{933}, new int[]{90,918}, new int[]{91}, new int[]{92}, new int[]{93}, new int[]{94}, new int[]{95}, new int[]{96}, new int[]{1072}, null, new int[]{1089}, null, new int[]{1077}, null, null, null, null, null, null, null, null, new int[]{951}, new int[]{959,1086}, new int[]{1088}, null, null, null, null, null, null, null, new int[]{967,1093}, new int[]{1091}, null, new int[]{123}, new int[]{124}, new int[]{125}, new int[]{126}, null, new int[]{8254}, null, new int[]{8212}, null, null, null, null, null, null, null, null, new int[]{1075}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{127,63253}, null, null, null, null, null, null, new int[]{63376}, new int[]{8987}, new int[]{63490}, new int[]{63432}, new int[]{63433}, new int[]{63434}, new int[]{63378}, new int[]{63379}, new int[]{63380}, new int[]{63381}, new int[]{8224}, new int[]{176}, new int[]{163}, new int[]{162}, new int[]{174}, new int[]{169}, new int[]{8482}, new int[]{8230}, new int[]{8984}, new int[]{8997}, new int[]{8679}, new int[]{8593}, new int[]{8595}, new int[]{8592}, new int[]{8594}, new int[]{8864}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{915,1043}, null, new int[]{945}, new int[]{946}, new int[]{947}, new int[]{916,8710}, new int[]{948}, new int[]{949}, new int[]{950}, new int[]{958}, new int[]{952}, new int[]{920}, new int[]{953}, new int[]{954,1082}, null, new int[]{923}, new int[]{955}, null, new int[]{181,956}, new int[]{957}, new int[]{926}, null, new int[]{928,1055}, new int[]{960,1087}, new int[]{8719}, new int[]{961}, new int[]{8721}, new int[]{931}, new int[]{963}, new int[]{964}, new int[]{965}, new int[]{966,1092}, new int[]{934,1060}, new int[]{248,216,8709}, new int[]{936}, new int[]{968}, new int[]{937,8486}, new int[]{969}, new int[]{982}, new int[]{8544}, new int[]{8548}, new int[]{8553}, new int[]{8558}, new int[]{8557}, new int[]{8556}, new int[]{8559}, new int[]{8626,8629}, new int[]{8996}, new int[]{9099}, new int[]{63382}, new int[]{63383}, new int[]{63397}, new int[]{9788}, new int[]{9681}, new int[]{9652}, new int[]{9662}, new int[]{9666}, new int[]{9656}, new int[]{63416}, new int[]{63417}, new int[]{63249}, null, null, null, null, new int[]{63435}, new int[]{63436}, new int[]{8677}, new int[]{8676}, new int[]{9645}, new int[]{63419}, new int[]{9644}, new int[]{9679}, new int[]{9675}, new int[]{9632}, new int[]{9633}, new int[]{9712}, new int[]{9636}, new int[]{9641}, new int[]{9673}, new int[]{63415}, new int[]{9677}, new int[]{215}, new int[]{247}, new int[]{185}, new int[]{178,8306}, new int[]{179,8307}, new int[]{8308}, new int[]{8309}, new int[]{8310}, new int[]{8311}, new int[]{8312}, new int[]{8313}, new int[]{8304,63327}, new int[]{63313}, new int[]{63314}, new int[]{63317}, new int[]{63321}, new int[]{63326}, new int[]{63331}, new int[]{63332}, new int[]{10003}, new int[]{8730}, new int[]{8731}, new int[]{8319}, new int[]{8321}, new int[]{8322}, new int[]{8323}, new int[]{8324}, new int[]{8325}, new int[]{8326}, new int[]{8327}, new int[]{8328}, new int[]{8329}, new int[]{8320,63359}, new int[]{8725}, new int[]{8726}, new int[]{172}, new int[]{8747}, new int[]{402}, new int[]{63438}, null, null, null, null, new int[]{8865}, new int[]{8857}, new int[]{63422}, new int[]{9000}, new int[]{8682}, new int[]{8596}, new int[]{8597}, new int[]{63458}, new int[]{8598}, new int[]{8599}, new int[]{8601}, new int[]{8600}, new int[]{63457}, new int[]{63456}, new int[]{63459}, new int[]{196}, new int[]{197}, new int[]{199}, new int[]{201}, new int[]{209}, new int[]{214}, new int[]{220}, new int[]{225}, new int[]{224}, new int[]{226}, new int[]{227}, new int[]{229}, new int[]{231}, new int[]{233}, new int[]{232}, new int[]{234}, new int[]{235}, new int[]{237,205}, new int[]{236,204}, new int[]{238,206}, new int[]{239,207}, new int[]{241}, new int[]{243}, new int[]{242}, new int[]{244}, new int[]{246}, new int[]{245}, new int[]{250}, new int[]{249}, new int[]{251}, new int[]{252}, new int[]{228}, new int[]{8800}, new int[]{198}, new int[]{230}, new int[]{338}, new int[]{339}, new int[]{8734}, new int[]{177}, new int[]{8804}, new int[]{8805}, new int[]{167}, new int[]{182}, new int[]{223}, new int[]{8226}, new int[]{165}, new int[]{191}, new int[]{161}, new int[]{8776}, new int[]{170}, new int[]{186}, new int[]{8211}, new int[]{8220}, new int[]{8221}, new int[]{8216}, new int[]{8217}, new int[]{376}, new int[]{255}, new int[]{64258}, new int[]{64257}, new int[]{164}, new int[]{8225}, new int[]{8240}, new int[]{160}, new int[]{1041}, null, new int[]{1073}, new int[]{1074}, null, new int[]{1044}, new int[]{1076}, new int[]{1046}, new int[]{1078}, new int[]{1079}, new int[]{1048}, null, new int[]{1080}, null, new int[]{1051}, null, new int[]{1083}, null, new int[]{1059}, new int[]{1062}, new int[]{1094}, null, null, new int[]{1063}, null, new int[]{1095}, null, new int[]{1049,1081}, null, new int[]{1064}, new int[]{1065}, new int[]{1096}, new int[]{1097}, new int[]{1067}, null, new int[]{1069}, null, new int[]{1101}, new int[]{1070}, new int[]{1102}, null, null, new int[]{1071}, null, new int[]{9098}, new int[]{63386}, new int[]{63387}, new int[]{63388}, new int[]{171}, new int[]{187}, new int[]{63377}, null, null, null, null, null, new int[]{9786}, new int[]{9787}, new int[]{9829}, new int[]{9830,9670}, new int[]{9824}, new int[]{9827}, new int[]{9794}, new int[]{9792}, }; private static final int[][] MAP_SCRIPT_HI = new int[][] { new int[]{189,8529}, new int[]{8531}, new int[]{8532}, new int[]{188,8528}, new int[]{190,8530}, new int[]{8533}, new int[]{8534}, new int[]{8535}, new int[]{8536}, new int[]{8537}, new int[]{8538}, new int[]{8539}, new int[]{8540}, new int[]{8541}, new int[]{8542}, new int[]{63276}, new int[]{63277}, new int[]{63278}, new int[]{63279}, new int[]{63264}, new int[]{63265}, new int[]{63266}, new int[]{63267}, new int[]{63268}, new int[]{63269}, new int[]{63270}, new int[]{63271}, new int[]{63272}, new int[]{63273}, new int[]{63274}, new int[]{63275}, new int[]{63312}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{715}, new int[]{180,714}, new int[]{168}, new int[]{710}, new int[]{711,728}, new int[]{730}, new int[]{175,713}, new int[]{732}, new int[]{729}, new int[]{733}, new int[]{184}, new int[]{731}, new int[]{9601}, new int[]{9615}, new int[]{9620}, new int[]{9621}, new int[]{9472}, null, null, null, null, new int[]{9532}, new int[]{9496}, new int[]{9492}, new int[]{9488}, new int[]{9484}, null, null, null, null, new int[]{63440}, new int[]{63442}, new int[]{63446}, new int[]{63444}, new int[]{9565}, new int[]{9562}, new int[]{9559}, new int[]{9556}, new int[]{9552}, new int[]{9580}, new int[]{9553}, new int[]{9500}, new int[]{9508}, new int[]{9516}, new int[]{9524}, new int[]{9568}, new int[]{9571}, new int[]{9574}, new int[]{9577}, new int[]{9474}, new int[]{9499}, new int[]{9490}, new int[]{9493}, new int[]{9473}, new int[]{9475}, new int[]{63447}, new int[]{63443}, new int[]{63441}, new int[]{63445}, null, new int[]{63420}, new int[]{63421}, new int[]{9586}, new int[]{9585}, new int[]{193}, new int[]{192}, new int[]{194}, new int[]{195}, new int[]{200}, new int[]{202}, new int[]{203}, new int[]{211}, new int[]{210}, new int[]{212}, new int[]{213}, new int[]{218}, new int[]{217}, new int[]{219}, new int[]{208}, new int[]{240}, new int[]{222}, new int[]{254}, new int[]{221}, new int[]{253}, new int[]{183}, new int[]{166}, new int[]{63234}, new int[]{63235}, new int[]{477,601}, new int[]{9251}, null, null, null, null, null, null, new int[]{63281}, new int[]{63282}, new int[]{63283}, new int[]{63284}, new int[]{63285}, new int[]{63286}, new int[]{63287}, new int[]{63288,1085}, new int[]{63289}, new int[]{63290}, new int[]{63291}, new int[]{63292}, new int[]{63293,1084}, new int[]{63294}, new int[]{63295}, new int[]{63296}, new int[]{63297}, new int[]{63298}, new int[]{63299}, new int[]{63300,1090}, new int[]{63301}, new int[]{63302}, new int[]{63303}, new int[]{63304}, new int[]{63305}, new int[]{63306}, new int[]{63232}, new int[]{63233}, new int[]{63252}, new int[]{63250}, new int[]{63743,63507}, new int[]{63742,63506}, new int[]{69}, new int[]{71}, new int[]{74}, new int[]{89}, new int[]{97}, new int[]{98}, new int[]{99}, new int[]{100}, new int[]{101}, new int[]{102}, new int[]{103}, new int[]{104}, new int[]{105}, new int[]{106}, new int[]{107}, new int[]{108}, new int[]{109}, new int[]{110}, new int[]{111}, new int[]{112}, new int[]{113}, new int[]{114}, new int[]{115}, new int[]{116}, new int[]{117}, new int[]{118}, new int[]{119}, new int[]{120}, new int[]{121}, new int[]{122}, new int[]{83}, new int[]{38,63280}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new int[]{63263}, new int[]{63260}, new int[]{63262}, new int[]{63261}, new int[]{63347}, new int[]{63348}, new int[]{63350}, new int[]{63351}, new int[]{63352}, new int[]{63354}, new int[]{63355}, new int[]{63356}, new int[]{63357}, new int[]{63360}, new int[]{63361}, new int[]{63362}, new int[]{63365}, new int[]{63366}, new int[]{63367}, new int[]{63368}, new int[]{63369}, new int[]{63370}, new int[]{63315}, new int[]{63316}, new int[]{63318}, new int[]{63319}, new int[]{63320}, new int[]{63322}, new int[]{63323}, new int[]{63324}, new int[]{63325}, new int[]{63328}, new int[]{63329}, new int[]{63330}, new int[]{63333}, new int[]{63334}, new int[]{63335}, new int[]{63336}, new int[]{63337}, new int[]{63338}, new int[]{9581,63448}, new int[]{9582,63450}, new int[]{9584,63454}, new int[]{9583,63452}, new int[]{63449}, new int[]{63453}, new int[]{63455}, new int[]{63451}, new int[]{63472}, new int[]{63429}, new int[]{63428}, new int[]{63431}, new int[]{63430}, new int[]{63385}, new int[]{63384}, new int[]{9604}, new int[]{9612}, new int[]{8992}, new int[]{8993}, }; } SBFBitmapFontImporter.java000066400000000000000000000102651506470510200342070ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.unicode.data.GlyphList; public class SBFBitmapFontImporter implements BitmapFontImporter { private GlyphList encoding; public SBFBitmapFontImporter() { this.encoding = null; } public SBFBitmapFontImporter(GlyphList encoding) { this.encoding = encoding; } @Override public BitmapFont[] importFont(byte[] data) throws IOException { DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); if (in.readInt() != 0x10B17E5C) throw new IOException("bad magic number"); in.readUnsignedByte(); int height = in.readUnsignedByte(); int ascent = in.readUnsignedByte(); int descent = in.readUnsignedByte(); BitmapFont f = new BitmapFont(ascent, descent, ascent, descent, 0, 0, height - ascent - descent); int[] offset = new int[256]; int[] gwidth = new int[256]; int[] gheight = new int[256]; int[] goffset = new int[256]; int[] gascent = new int[256]; int[] advance = new int[256]; int[] overhang = new int[256]; for (int ch = 1; ch < 256; ch++) { offset[ch] = Short.reverseBytes(in.readShort()) & 0xFFFF; gwidth[ch] = in.readUnsignedByte(); gheight[ch] = in.readUnsignedByte(); goffset[ch] = in.readByte(); gascent[ch] = in.readByte(); advance[ch] = in.readUnsignedByte(); overhang[ch] = in.readUnsignedByte(); } for (int ch = 0; ch < 256; ch++) { if (offset[ch] > 0) { int w = gwidth[ch] * 8 - overhang[ch]; byte[][] gd = new byte[gheight[ch]][w]; for (int dy = offset[ch], gy = 0; dy < data.length && gy < gd.length; dy += gwidth[ch], gy++) { for (int dx = dy, gx = 0; dx < data.length && gx < w; dx++, gx += 8) { for (int dm = 0x80, gi = gx; dm != 0 && gi < w; dm >>= 1, gi++) { if ((data[dx] & dm) != 0) gd[gy][gi] = -1; } } } BitmapFontGlyph g = new BitmapFontGlyph(gd, goffset[ch], advance[ch], gascent[ch]); int cp = (encoding != null) ? encoding.get(ch) : fromSuperLatin(ch); if (cp >= 0) f.putCharacter(cp, g); } } in.close(); f.setXHeight(); f.setCapHeight(); return new BitmapFont[]{f}; } @Override public BitmapFont[] importFont(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); return importFont(out.toByteArray()); } @Override public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1048576]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); in.close(); BitmapFont[] f = importFont(out.toByteArray()); if (f.length > 0) { String name = file.getName(); if (name.toLowerCase().endsWith(".sbf")) { name = name.substring(0, name.length() - 4); } for (BitmapFont ff : f) { ff.setName(Font.NAME_FAMILY, name); } } return f; } private static final int[] C0 = { 0x0000, 0x02CB, 0x02DD, 0x02D9, 0x02DA, 0x02C7, 0x02D8, 0x02DB, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0xFB01, 0xFB02, 0xF8FF, 0x2044, 0x221A, 0x2211, 0x220F, 0x222B, 0x2206, 0x03A9, 0x03C0, 0x2202, 0x221E, 0x001B, 0x2264, 0x2260, 0x2265, 0x2248, }; private static final int[] C1 = { 0x20AC, 0x25CA, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0141, 0x017D, 0x0131, 0x2318, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0142, 0x017E, 0x0178, }; private static int fromSuperLatin(int ch) { ch &= 0xFF; if (ch < 0x20) { return C0[ch]; } else if (ch < 0x80) { return ch; } else if (ch < 0xA0) { return C1[ch & 0x1F]; } else { return ch; } } } SFDBitmapFontImporter.java000077500000000000000000000214221506470510200342110ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.*; import java.util.*; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; public class SFDBitmapFontImporter implements BitmapFontImporter { public BitmapFont[] importFont(byte[] data) throws IOException { return importFont(new Scanner(new ByteArrayInputStream(data), "UTF-8")); } public BitmapFont[] importFont(InputStream is) throws IOException { return importFont(new Scanner(is, "UTF-8")); } public BitmapFont[] importFont(File file) throws IOException { return importFont(new Scanner(new FileInputStream(file), "UTF-8")); } public BitmapFont[] importFont(Scanner scan) throws IOException { Map names = new HashMap(); String currentGlyphName = null; Map glyphNames = new HashMap(); Map codePoints = new HashMap(); Vector fonts = new Vector(); BitmapFont bm = null; String bitmapBuffer = null; int ch=0, cw=0, bbx=0, bbw=0, bby=0, bbh=0, bbs=0; while (scan.hasNextLine()) { String l = scan.nextLine(); if (bm == null) { if (l.startsWith("Copyright: ")) { names.put(BitmapFont.NAME_COPYRIGHT, decodeEscapes(l.split(":\\s*", 2)[1])); } else if (l.startsWith("FamilyName: ")) { names.put(BitmapFont.NAME_FAMILY, decodeEscapes(l.split(":\\s*", 2)[1])); } else if (l.startsWith("Weight: ")) { names.put(BitmapFont.NAME_STYLE, decodeEscapes(l.split(":\\s*", 2)[1])); } else if (l.startsWith("StartChar: ")) { currentGlyphName = decodeEscapes(l.split(":\\s*", 2)[1]); } else if (l.startsWith("Encoding: ")) { if (currentGlyphName != null) { l = l.split(":\\s*", 2)[1]; String[] nums = l.split("\\s"); int local = Integer.parseInt(nums[0]); int unicode = Integer.parseInt(nums[1]); if (unicode >= 0) codePoints.put(local, unicode); else glyphNames.put(local, currentGlyphName); } } else if (l.equals("EndChar")) { currentGlyphName = null; } else if (l.startsWith("BitmapFont: ")) { l = l.split(":\\s*", 2)[1]; String[] nums = l.split("\\s"); int a = Integer.parseInt(nums[2]); int d = Integer.parseInt(nums[3]); bm = new BitmapFont(a, d, a, d, 0, 0, 0); for (Map.Entry e : names.entrySet()) { bm.setName(e.getKey(), e.getValue()); } } } else { if (l.equals("EndBitmapFont")) { if (bitmapBuffer != null) { byte[] data; try { data = decodeASCII85(bitmapBuffer.getBytes("US-ASCII")); } catch (UnsupportedEncodingException e) { data = decodeASCII85(bitmapBuffer.getBytes()); } data = unpack(data); byte[][] glyph = new byte[bbh][bbw]; for (int k = 0, j = 0; k < data.length && j < bbh; k += bbs, j++) { for (int i = 0; i < bbw && i < bbs && k+i < data.length; i++) { glyph[j][i] = ((data[k+i] != 0) ? (byte)0xFF : 0); } } BitmapFontGlyph bc = new BitmapFontGlyph(glyph, bbx, cw, bby+bbh); if (codePoints.containsKey(ch)) bm.putCharacter(codePoints.get(ch), bc); if (glyphNames.containsKey(ch)) bm.putNamedGlyph(glyphNames.get(ch), bc); } bm.setXHeight(); bm.setCapHeight(); fonts.add(bm); bm = null; } else if (l.startsWith("Resolution: ")) { // ignore } else if (l.startsWith("BDFChar: ")) { if (bitmapBuffer != null) { byte[] data; try { data = decodeASCII85(bitmapBuffer.getBytes("US-ASCII")); } catch (UnsupportedEncodingException e) { data = decodeASCII85(bitmapBuffer.getBytes()); } data = unpack(data); byte[][] glyph = new byte[bbh][bbw]; for (int k = 0, j = 0; k < data.length && j < bbh; k += bbs, j++) { for (int i = 0; i < bbw && i < bbs && k+i < data.length; i++) { glyph[j][i] = ((data[k+i] != 0) ? (byte)0xFF : 0); } } BitmapFontGlyph bc = new BitmapFontGlyph(glyph, bbx, cw, bby+bbh); if (codePoints.containsKey(ch)) bm.putCharacter(codePoints.get(ch), bc); if (glyphNames.containsKey(ch)) bm.putNamedGlyph(glyphNames.get(ch), bc); } l = l.split(":\\s*", 2)[1]; String[] nums = l.split("\\s"); ch = Integer.parseInt(nums[1]); cw = Integer.parseInt(nums[2]); bbx = Integer.parseInt(nums[3]); bbw = Integer.parseInt(nums[4])-bbx+1; bby = Integer.parseInt(nums[5]); bbh = Integer.parseInt(nums[6])-bby+1; bbs = ((bbw & 0x7) == 0) ? bbw : ((bbw | 7)+1); bitmapBuffer = null; } else { if (bitmapBuffer == null) bitmapBuffer = l; else bitmapBuffer += l; } } } if (bm != null) { if (bitmapBuffer != null) { byte[] data; try { data = decodeASCII85(bitmapBuffer.getBytes("US-ASCII")); } catch (UnsupportedEncodingException e) { data = decodeASCII85(bitmapBuffer.getBytes()); } data = unpack(data); byte[][] glyph = new byte[bbh][bbw]; for (int k = 0, j = 0; k < data.length && j < bbh; k += bbs, j++) { for (int i = 0; i < bbw && i < bbs && k+i < data.length; i++) { glyph[j][i] = ((data[k+i] != 0) ? (byte)0xFF : 0); } } BitmapFontGlyph bc = new BitmapFontGlyph(glyph, bbx, cw, bby+bbh); if (codePoints.containsKey(ch)) bm.putCharacter(codePoints.get(ch), bc); if (glyphNames.containsKey(ch)) bm.putNamedGlyph(glyphNames.get(ch), bc); } bm.setXHeight(); bm.setCapHeight(); fonts.add(bm); bm = null; } return fonts.toArray(new BitmapFont[0]); } private static String decodeEscapes(String s) { if (!s.contains("\\")) return s; char[] och = s.toCharArray(); char[] nch = new char[och.length]; int oi = 0; int ni = 0; while (oi < och.length) { if (och[oi] == '\\') { oi++; if (oi < och.length) switch(och[oi]) { case 'a': nch[ni++] = '\u0007'; break; case 'b': nch[ni++] = '\u0008'; break; case 'd': nch[ni++] = '\u007F'; break; case 'e': nch[ni++] = '\u001B'; break; case 'f': nch[ni++] = '\u000C'; break; case 'i': nch[ni++] = '\u000F'; break; case 'n': nch[ni++] = '\n'; break; case 'o': nch[ni++] = '\u000E'; break; case 'r': nch[ni++] = '\r'; break; case 't': nch[ni++] = '\u0009'; break; case 'u': { int h1 = och[++oi]; h1 = ((h1>='a')?(10+h1-'a'):(h1>='A')?(10+h1-'A'):(h1>='0')?(h1-'0'):0); int h2 = och[++oi]; h2 = ((h2>='a')?(10+h2-'a'):(h2>='A')?(10+h2-'A'):(h2>='0')?(h2-'0'):0); int h3 = och[++oi]; h3 = ((h3>='a')?(10+h3-'a'):(h3>='A')?(10+h3-'A'):(h3>='0')?(h3-'0'):0); int h4 = och[++oi]; h4 = ((h4>='a')?(10+h4-'a'):(h4>='A')?(10+h4-'A'):(h4>='0')?(h4-'0'):0); nch[ni++] = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); } break; case 'v': nch[ni++] = '\u000B'; break; case 'x': { int h1 = och[++oi]; h1 = ((h1>='a')?(10+h1-'a'):(h1>='A')?(10+h1-'A'):(h1>='0')?(h1-'0'):0); int h2 = och[++oi]; h2 = ((h2>='a')?(10+h2-'a'):(h2>='A')?(10+h2-'A'):(h2>='0')?(h2-'0'):0); nch[ni++] = (char)((h1 << 4) | h2); } break; case ' ': nch[ni++] = ' '; break; case '\"': nch[ni++] = '\"'; break; case '\'': nch[ni++] = '\''; break; case '\\': nch[ni++] = '\\'; break; default: nch[ni++] = och[oi]; break; } oi++; } else { nch[ni++] = och[oi++]; } } return new String(nch, 0, ni); } private static byte[] decodeASCII85(byte[] b) { try { byte[] r = new byte[b.length*4]; int rp = 0; int bp = 0; while (b[bp]<33 || b[bp]>126) bp++; if (b[bp]=='<' && b[bp+1]=='~') bp+=2; int d=0; int n=0; for (; bp32 && b[bp]<127){ d *= 85; d += b[bp]-'!'; n++; if (n==5) { r[rp++] = (byte)(d >>> 24); r[rp++] = (byte)(d >>> 16); r[rp++] = (byte)(d >>> 8); r[rp++] = (byte)(d >>> 0); d=0; n=0; } } } if (n>0) { d*=85; d+=85; for (int m=n+1; m<5; m++) d*=85; if (n>1) r[rp++] = (byte)(d >>> 24); if (n>2) r[rp++] = (byte)(d >>> 16); if (n>3) r[rp++] = (byte)(d >>> 8); if (n>4) r[rp++] = (byte)(d >>> 0); } byte[] rr = new byte[rp]; while((rp--)>0) rr[rp]=r[rp]; return rr; } catch (ArrayIndexOutOfBoundsException e) { return b; } } private static byte[] unpack(byte[] data) { byte[] nd = new byte[data.length*8]; for (int s=0, d=0; s> 7) & 1); nd[d+1] = (byte)((data[s] >> 6) & 1); nd[d+2] = (byte)((data[s] >> 5) & 1); nd[d+3] = (byte)((data[s] >> 4) & 1); nd[d+4] = (byte)((data[s] >> 3) & 1); nd[d+5] = (byte)((data[s] >> 2) & 1); nd[d+6] = (byte)((data[s] >> 1) & 1); nd[d+7] = (byte)((data[s] >> 0) & 1); } return nd; } } SRFontBitmapFontImporter.java000077500000000000000000000260221506470510200347510ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.metadata.IIOMetadata; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; public class SRFontBitmapFontImporter implements BitmapFontImporter { public BitmapFont[] importFont(byte[] data) throws IOException { ByteArrayInputStream b = new ByteArrayInputStream(data); BitmapFont[] f = importFont(b); b.close(); return f; } public BitmapFont[] importFont(InputStream is) throws IOException { //BufferedImage bi = ImageIO.read(is); Iterator iterator = ImageIO.getImageReadersBySuffix("png"); ImageReader imagereader = iterator.next(); imagereader.setInput(ImageIO.createImageInputStream(is)); BufferedImage bi = imagereader.read(0); BitmapFont f = importFont(bi); if (f == null) return new BitmapFont[0]; IIOImage iioImage = imagereader.readAll(0, null); IIOMetadata metadata = iioImage.getMetadata(); String format = metadata.getNativeMetadataFormatName(); Node root = metadata.getAsTree(format); for (Node n = root.getFirstChild(); n != null; n = n.getNextSibling()) { if ("tEXt".equals(n.getNodeName())) { for (Node m = n.getFirstChild(); m != null; m = m.getNextSibling()) { if ("tEXtEntry".equals(m.getNodeName())) { NamedNodeMap attr = m.getAttributes(); String k = attr.getNamedItem("keyword").getNodeValue(); String v = attr.getNamedItem("value").getNodeValue(); if ("FontFamily".equals(k)) f.setName(Font.NAME_FAMILY, v); if ("FontStyle".equals(k)) f.setName(Font.NAME_STYLE, v); if ("Copyright".equals(k)) f.setName(Font.NAME_COPYRIGHT, v); } } } } return new BitmapFont[]{f}; } public BitmapFont[] importFont(File file) throws IOException { FileInputStream in = new FileInputStream(file); BitmapFont[] f = importFont(in); in.close(); return f; } public boolean canImportFont(BufferedImage bi) { return bi != null && decodeVM(bi, 0, 0, bi.getHeight()) != null; } public BitmapFont importFont(BufferedImage bi) { int[] mtx = decodeVM(bi, 0, 0, bi.getHeight()); if (mtx == null) return null; int bh = 1 + mtx[MAX_ASCENT] + mtx[MAX_DESCENT] + mtx[LINE_GAP]; int cp = decodeCC(bi, 1, 0, bh); if (cp < 0) { // SFont List runs = new ArrayList(); List widths = new ArrayList(); int x = 0; int width = bi.getWidth(); while (x < width) { int cr = 0; int cw = 0; while (x < width && decodeControlPixel(bi.getRGB(x, 0)) == MAGENTA) { x++; cr++; } while (x < width && decodeControlPixel(bi.getRGB(x, 0)) != MAGENTA) { x++; cw++; } runs.add(cr); widths.add(cw); } int[] l = new int[runs.size()-1]; int[] w = new int[runs.size()-1]; int[] r = new int[runs.size()-1]; byte[][][] g = new byte[runs.size()-1][][]; x = 0; int tw = 0; for (int i = 0; i < l.length; i++) { l[i] = (i == 0) ? runs.get(i) : ((runs.get(i)+1)/2); w[i] = widths.get(i); r[i] = (i == l.length-1) ? runs.get(i+1) : (runs.get(i+1)/2); int gw = l[i] + w[i] + r[i]; g[i] = new byte[bh-1][gw]; for (int gy = 0; gy < g[i].length; gy++) { for (int gx = 0; gx < gw; gx++) { g[i][gy][gx] = (byte)((bi.getRGB(x+gx, 1+gy) >> 24) & 0xFF); } } x += gw; tw += w[i]; } int Xi = 'X'-33; if (Xi < g.length) { byte[][] Xg = g[Xi]; for (int i = 0; i < Xg.length; i++) { if (arrayEmpty(Xg[i])) { mtx[EM_ASCENT]--; } else { break; } } } int xi = 'x'-33; if (xi < g.length) { byte[][] xg = g[xi]; for (int i = 0; i < xg.length; i++) { if (arrayEmpty(xg[i])) { mtx[X_HEIGHT]--; } else { break; } } for (int i = xg.length-1; i >= 0; i--) { if (arrayEmpty(xg[i])) { mtx[MAX_ASCENT]--; mtx[LINE_ASCENT]--; mtx[EM_ASCENT]--; mtx[X_HEIGHT]--; mtx[EM_DESCENT]++; mtx[LINE_DESCENT]++; mtx[MAX_DESCENT]++; } else { break; } } } int yi = 'y'-33; if (yi < g.length) { byte[][] yg = g[yi]; for (int i = yg.length-1; i >= 0; i--) { if (arrayEmpty(yg[i])) { mtx[EM_DESCENT]--; } else { break; } } } BitmapFont bm = new BitmapFont(mtx[EM_ASCENT], mtx[EM_DESCENT], mtx[LINE_ASCENT], mtx[LINE_DESCENT], mtx[X_HEIGHT], mtx[X_HEIGHT], mtx[LINE_GAP]); bm.putCharacter(32, new BitmapFontGlyph(new byte[bh-1][tw/g.length], 0, tw/g.length, mtx[MAX_ASCENT])); for (int i = 0; i < g.length; i++) { bm.putCharacter(i+33, new BitmapFontGlyph(g[i], -l[i], w[i], mtx[MAX_ASCENT])); } bm.setCapHeight(); return bm; } else { // RFont Map l = new HashMap(); Map w = new HashMap(); Map r = new HashMap(); Map g = new HashMap(); int height = bi.getHeight(); int width = bi.getWidth(); for (int y = 0; y+bh <= height; y += bh) { int x = 1; while (x < width) { int ch = decodeCC(bi, x, y, bh); if (ch < 0 || ch >= 0x110000) { break; } else { x++; int ox = x; int ll = 0; int lw = 0; int lr = 0; while (x < width && decodeControlPixel(bi.getRGB(x, y)) == RED) { x++; ll++; } while (x < width && decodeControlPixel(bi.getRGB(x, y)) == TRANSPARENT) { x++; lw++; } while (x < width && decodeControlPixel(bi.getRGB(x, y)) == BLUE) { x++; lr++; } int gw = ll+lw+lr; byte[][] lg = new byte[bh-1][gw]; for (int gy = 0; gy < lg.length; gy++) { for (int gx = 0; gx < gw; gx++) { lg[gy][gx] = (byte)((bi.getRGB(ox+gx, y+1+gy) >> 24) & 0xFF); } } l.put(ch, ll); w.put(ch, lw); r.put(ch, lr); g.put(ch, lg); } } } BitmapFont bm = new BitmapFont(mtx[EM_ASCENT], mtx[EM_DESCENT], mtx[LINE_ASCENT], mtx[LINE_DESCENT], mtx[X_HEIGHT], mtx[X_HEIGHT], mtx[LINE_GAP]); for (int ch : g.keySet()) { bm.putCharacter(ch, new BitmapFontGlyph(g.get(ch), -l.get(ch), w.get(ch), mtx[MAX_ASCENT])); } bm.setCapHeight(); return bm; } } private static final int TRANSPARENT = 0; private static final int RED = 02200; private static final int ORANGE = 02210; private static final int YELLOW = 02220; private static final int GREEN = 02020; private static final int CYAN = 02022; private static final int BLUE = 02002; private static final int VIOLET = 02102; private static final int MAGENTA = 02202; private int decodeControlPixel(int rgb) { int a = ((rgb >> 24) & 0xFF) / 86; if (a == 0) return 0; int r = ((rgb >> 16) & 0xFF) / 86; int g = ((rgb >> 8) & 0xFF) / 86; int b = ((rgb >> 0) & 0xFF) / 86; return (a<<9) | (r<<6) | (g<<3) | b; } private static final int MAX_ASCENT = 0; private static final int LINE_ASCENT = 1; private static final int EM_ASCENT = 2; private static final int X_HEIGHT = 3; private static final int EM_DESCENT = 4; private static final int LINE_DESCENT = 5; private static final int MAX_DESCENT = 6; private static final int LINE_GAP = 7; private int[] decodeVM(BufferedImage bi, int x, int y, int height) { if (decodeControlPixel(bi.getRGB(x, y)) != MAGENTA) { return null; } else { int[] mtx = new int[8]; y++; while (y < height) { switch (decodeControlPixel(bi.getRGB(x, y))) { case TRANSPARENT: mtx[X_HEIGHT]++; // continue; case YELLOW: mtx[EM_ASCENT]++; // continue; case ORANGE: mtx[LINE_ASCENT]++; // continue; case RED: mtx[MAX_ASCENT]++; break; case GREEN: mtx[EM_DESCENT]++; // continue; case CYAN: mtx[LINE_DESCENT]++; // continue; case BLUE: mtx[MAX_DESCENT]++; break; case VIOLET: mtx[LINE_GAP]++; break; case MAGENTA: return mtx; default: return null; } y++; } return mtx; } } private int decodeCC(BufferedImage bi, int x, int y, int bh) { int cp = bi.getRGB(x, y); if ( (((cp >> 24) & 0xFF) < 0xAA) || (((cp >> 16) & 0xFF) < 0xAA) || (((cp >> 8) & 0xFF) > 0x55) || (((cp >> 0) & 0xFF) < 0xAA) ) { return -1; } for (int i = 1; i < bh; i++) { int rgb = bi.getRGB(x, y+i); if (((rgb >> 24) & 0xFF) < 0xAA) { return -1; } } if (bh >= 22) { int p1 = bi.getRGB(x, y+16) & 0xFFFFFF; int p2 = bi.getRGB(x, y+17) & 0xFFFFFF; int p3 = bi.getRGB(x, y+18) & 0xFFFFFF; int p4 = bi.getRGB(x, y+19) & 0xFFFFFF; int p5 = bi.getRGB(x, y+20) & 0xFFFFFF; int p6 = bi.getRGB(x, y+21) & 0xFFFFFF; int a = (((p1 >> 20) & 0xF) + ((p1 >> 12) & 0xF) + ((p1 >> 4) & 0xF)) / 3; int b = (((p2 >> 20) & 0xF) + ((p2 >> 12) & 0xF) + ((p2 >> 4) & 0xF)) / 3; int c = (((p3 >> 20) & 0xF) + ((p3 >> 12) & 0xF) + ((p3 >> 4) & 0xF)) / 3; int d = (((p4 >> 20) & 0xF) + ((p4 >> 12) & 0xF) + ((p4 >> 4) & 0xF)) / 3; int e = (((p5 >> 20) & 0xF) + ((p5 >> 12) & 0xF) + ((p5 >> 4) & 0xF)) / 3; int f = (((p6 >> 20) & 0xF) + ((p6 >> 12) & 0xF) + ((p6 >> 4) & 0xF)) / 3; return (a<<20) | (b<<16) | (c<<12) | (d<<8) | (e<<4) | f; } else if (bh >= 11) { int p1 = bi.getRGB(x, y+7) & 0xFFFFFF; int p2 = bi.getRGB(x, y+8) & 0xFFFFFF; int p3 = bi.getRGB(x, y+9) & 0xFFFFFF; int p4 = bi.getRGB(x, y+10) & 0xFFFFFF; int a = (((p1 >> 20) & 0xF) + ((p1 >> 12) & 0xF)) / 2; int b = (((p1 >> 4) & 0xF) + ((p2 >> 20) & 0xF)) / 2; int c = (((p2 >> 12) & 0xF) + ((p2 >> 4) & 0xF)) / 2; int d = (((p3 >> 20) & 0xF) + ((p3 >> 12) & 0xF)) / 2; int e = (((p3 >> 4) & 0xF) + ((p4 >> 20) & 0xF)) / 2; int f = (((p4 >> 12) & 0xF) + ((p4 >> 4) & 0xF)) / 2; return (a<<20) | (b<<16) | (c<<12) | (d<<8) | (e<<4) | f; } else if (bh >= 7) { int p1 = bi.getRGB(x, y+4) & 0xFFFFFF; int p2 = bi.getRGB(x, y+5) & 0xFFFFFF; int p3 = bi.getRGB(x, y+6) & 0xFFFFFF; int a = (p1 >> 20) & 0xF; int b = (p1 >> 4) & 0xF; int c = (p2 >> 20) & 0xF; int d = (p2 >> 4) & 0xF; int e = (p3 >> 20) & 0xF; int f = (p3 >> 4) & 0xF; return (a<<20) | (b<<16) | (c<<12) | (d<<8) | (e<<4) | f; } else if (bh >= 4) { int p1 = bi.getRGB(x, y+2) & 0xFFFFFF; int p2 = bi.getRGB(x, y+3) & 0xFFFFFF; int a = (p1 >> 20) & 0xF; int b = (p1 >> 12) & 0xF; int c = (p1 >> 4) & 0xF; int d = (p2 >> 20) & 0xF; int e = (p2 >> 12) & 0xF; int f = (p2 >> 4) & 0xF; return (a<<20) | (b<<16) | (c<<12) | (d<<8) | (e<<4) | f; } else if (bh >= 2) { return bi.getRGB(x, y+1) & 0xFFFFFF; } else { return -1; } } private boolean arrayEmpty(byte[] a) { for (byte b : a) if (b != 0) return false; return true; } } U8MBitmapFontImporter.java000066400000000000000000000057651506470510200342170ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importerpackage com.kreative.bitsnpicas.importer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.Font; import com.kreative.bitsnpicas.u8m.U8MFile; import com.kreative.bitsnpicas.u8m.U8MGlyph; public class U8MBitmapFontImporter implements BitmapFontImporter { @Override public BitmapFont[] importFont(byte[] data) throws IOException { File file = File.createTempFile("u8m", ".u8m"); FileOutputStream out = new FileOutputStream(file); out.write(data); out.flush(); out.close(); BitmapFont[] fonts = importFont(file); file.delete(); return fonts; } @Override public BitmapFont[] importFont(InputStream is) throws IOException { File file = File.createTempFile("u8m", ".u8m"); FileOutputStream out = new FileOutputStream(file); int read; byte[] buf = new byte[65536]; while ((read = is.read(buf)) >= 0) out.write(buf, 0, read); out.flush(); out.close(); BitmapFont[] fonts = importFont(file); file.delete(); return fonts; } @Override public BitmapFont[] importFont(File file) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "r"); for (long base = 0; base <= 16; base++) { raf.seek(base); if (raf.readInt() == U8MFile.MAGIC_NUMBER) { raf.seek(base); U8MFile u = new U8MFile(); u.read(raf, base); raf.close(); return importFont(u); } } raf.close(); return new BitmapFont[0]; } private static BitmapFont[] importFont(U8MFile u) { BitmapFont b = new BitmapFont(); b.setName(Font.NAME_FAMILY, u.familyName); b.setName(Font.NAME_STYLE, fontStyleToString(u.style)); b.autoFillNames(); b.setLineAscent(u.lineAscent); b.setLineDescent(u.lineDescent); b.setLineGap(u.lineGap); double m = u.pointSize / (double)(u.lineAscent + u.lineDescent); b.setEmAscent2D(u.lineAscent * m); b.setEmDescent2D(u.lineDescent * m); for (int i = 0; i < 0x110000; i++) { int index = u.getUnicodeGlyphIndex(i); if (i == 0 || index != 0) { U8MGlyph ug = u.glyphs.get(index); BitmapFontGlyph g = new BitmapFontGlyph(); g.setCharacterWidth(ug.advanceWidth); g.setXY(ug.xOffset, -ug.yOffset); g.setGlyph(ug.to2DArray()); b.putCharacter(i, g); } } b.setXHeight(); b.setCapHeight(); return new BitmapFont[]{b}; } private static String fontStyleToString(int fontStyle) { StringBuffer sb = new StringBuffer(); if ((fontStyle & 0x01) != 0) sb.append(" Bold"); if ((fontStyle & 0x02) != 0) sb.append(" Italic"); if ((fontStyle & 0x04) != 0) sb.append(" Underline"); if ((fontStyle & 0x08) != 0) sb.append(" Outline"); if ((fontStyle & 0x10) != 0) sb.append(" Shadow"); if ((fontStyle & 0x20) != 0) sb.append(" Condensed"); if ((fontStyle & 0x40) != 0) sb.append(" Extended"); return (sb.length() > 0) ? sb.toString().trim() : "Normal"; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importer/kbitx.dtd000066400000000000000000000014501506470510200311150ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/importer/kpcax.dtd000066400000000000000000000014041506470510200311010ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/000077500000000000000000000000001506470510200263625ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/BitmapInputFormat.java000066400000000000000000000222751506470510200326420ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontImporter; import com.kreative.bitsnpicas.FileProxy; import com.kreative.bitsnpicas.importer.*; import com.kreative.unicode.data.EncodingList; public enum BitmapInputFormat { KBITX(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kbitx"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new KbitxBitmapFontImporter(); } }, KBITS(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".kbits"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new KbitsBitmapFontImporter(); } }, SFD(BitmapFont.NAME_POSTSCRIPT) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".sfd"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new SFDBitmapFontImporter(); } }, BDF(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".bdf"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new BDFBitmapFontImporter(); } }, PSF(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".psf", ".psfu"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new PSFBitmapFontImporter( o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfPuaBase, false ); } }, PSFGZ(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".psf.gz", ".psfu.gz"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new PSFBitmapFontImporter( o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfPuaBase, true ); } }, SUIT(BitmapFont.NAME_FAMILY_AND_STYLE, true) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".suit"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new NFNTBitmapFontImporter.ResourceFile(o.getEncoding()); } }, DFONT(BitmapFont.NAME_FAMILY_AND_STYLE, false) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".dfont"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new NFNTBitmapFontImporter.ResourceFile(o.getEncoding()); } }, NFNT(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".nfnt"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new NFNTBitmapFontImporter.FlatFile(o.getEncoding()); } }, SRFONT(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".png") && fp.isImage() && new SRFontBitmapFontImporter().canImportFont(fp.getImage()) ); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new SRFontBitmapFontImporter(); } }, HEX(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".hex"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new HexBitmapFontImporter(); } }, CVT(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".cvt"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new GEOSBitmapFontImporter(); } }, FZX(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".fzx"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new FZXBitmapFontImporter(o.getEncoding()); } }, U8M(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".u8m"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new U8MBitmapFontImporter(); } }, AMIGA(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".font") && (fp.startsWith(0x0F, 0x00) || fp.startsWith(0x0F, 0x02)) ); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new AmigaBitmapFontImporter.ContentsFile(o.getEncoding()); } }, FNT(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { if (!fp.hasExtension(".fnt")) return false; byte[] b = fp.getStartBytes(2); return b != null && b[0] == 0 && b[1] >= 1 && b[1] <= 3; } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new FNTBitmapFontImporter(o.getEncoding()); } }, FONTX(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".ftx", ".fnt") && fp.startsWith('F'); } public BitmapFontImporter createImporter(BitmapInputOptions o) { String sben = o.encodingName; if (sben == null || sben.length() == 0) sben = "CP437"; String dben = o.fontxDoubleByteEncoding; if (dben == null || dben.length() == 0) dben = "CP943"; return new FONTXBitmapFontImporter(EncodingList.instance().getGlyphList(sben), dben); } }, MGTK(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return ( fp.hasExtension(".mgf", ".mpf", ".fnt") && (fp.startsWith(0) || fp.startsWith(0x80)) ); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new MGTKBitmapFontImporter(o.getEncoding()); } }, ROCKBOX(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".rbf", ".rb11", ".rb12", ".fnt") && fp.startsWith('R'); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new RockboxBitmapFontImporter(); } }, CYBIKO(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".cyf", ".fntz", ".fnty", ".fnt") && fp.startsWith(1); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new CybikoBitmapFontImporter(o.getEncoding()); } }, PLAYDATE(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return PlaydateBitmapFontImporter.canImportFont(fp); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new PlaydateBitmapFontImporter(); } }, HRCG(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".set"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new HRCGBitmapFontImporter(); } }, HMZK(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".hmzk"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new HMZKBitmapFontImporter(); } }, // **** Add new formats above this line. **** DSF(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".dsf"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new DSFBitmapFontImporter(); } }, SBF(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".sbf"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new SBFBitmapFontImporter(o.getEncoding()); } }, S10(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.hasExtension(".s10"); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new S10BitmapFontImporter(); } }, DMOV(BitmapFont.NAME_FAMILY_AND_STYLE, true) { public boolean recognize(FileProxy fp) { return ( fp.hasMacCreator("DMOV") || fp.hasMacCreator("movr") || ( (fp.hasMacCreator("MACS") || fp.hasMacCreator("macs")) && (fp.hasMacType("ZSYS") || fp.hasMacType("zsys")) ) ); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new NFNTBitmapFontImporter.ResourceFile(o.getEncoding()); } }, NFNT_NOEXT(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.startsWith(0x90, 0x00); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new NFNTBitmapFontImporter.FlatFile(o.getEncoding()); } }, AMIGA_NOEXT(BitmapFont.NAME_FAMILY_AND_STYLE) { public boolean recognize(FileProxy fp) { return fp.startsWith(0x00, 0x00, 0x03, 0xF3); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new AmigaBitmapFontImporter.DescriptorFile(o.getEncoding()); } }, MGTK_NOEXT(BitmapFont.NAME_FAMILY) { public boolean recognize(FileProxy fp) { return fp.startsWith(0) || fp.startsWith(0x80); } public BitmapFontImporter createImporter(BitmapInputOptions o) { return new MGTKBitmapFontImporter(o.getEncoding()); } }; public final int nameType; public final boolean macResFork; private BitmapInputFormat(int nameType) { this.nameType = nameType; this.macResFork = false; } private BitmapInputFormat(int nameType, boolean macResFork) { this.nameType = nameType; this.macResFork = macResFork; } public abstract boolean recognize(FileProxy fp); public abstract BitmapFontImporter createImporter(BitmapInputOptions o); public static BitmapInputFormat forFile(File file) { FileProxy fp = new FileProxy(file); for (BitmapInputFormat f : values()) { if (f.recognize(fp)) { return f; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/BitmapInputOptions.java000066400000000000000000000014421506470510200330360ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapInputOptions { public String encodingName = null; public String fontxDoubleByteEncoding = null; public String psfLowEncoding = null; public String psfHighEncoding = null; public int psfPuaBase = -1; public GlyphList getEncoding() { if (encodingName == null) return null; return EncodingList.instance().getGlyphList(encodingName); } public GlyphList getPsfLowEncoding() { if (psfLowEncoding == null) return null; return EncodingList.instance().getGlyphList(psfLowEncoding); } public GlyphList getPsfHighEncoding() { if (psfHighEncoding == null) return null; return EncodingList.instance().getGlyphList(psfHighEncoding); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/BitmapOutputFormat.java000066400000000000000000000166001506470510200330360ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.IOException; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.exporter.*; import com.kreative.unicode.data.EncodingList; public enum BitmapOutputFormat { KBITX(".kbitx", "kbitx", "kbnp2") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new KbitxBitmapFontExporter(); } }, KBITS(".kbits", "kbits", "kbnp1") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new KbitsBitmapFontExporter(); } }, TTF(".ttf", "ttf", "truetype") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new TTFBitmapFontExporter(o.xSize, o.ySize, o.extendWinMetrics); } }, OTB(".otb", "otb") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new OTBBitmapFontExporter(o.extendWinMetrics); } }, BDF(".bdf", "bdf") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new BDFBitmapFontExporter(); } }, PSF2(".psf", "psf", "psf2") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PSFBitmapFontExporter( 2, o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfUseLowEncoding, o.psfUseHighEncoding, o.psfUseAllGlyphs, o.psfUnicodeTable, false ); } }, PSF1(".psf", "psf1") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PSFBitmapFontExporter( 1, o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfUseLowEncoding, o.psfUseHighEncoding, o.psfUseAllGlyphs, o.psfUnicodeTable, false ); } }, PSF2GZ(".psf.gz", "psfgz", "psf2gz") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PSFBitmapFontExporter( 2, o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfUseLowEncoding, o.psfUseHighEncoding, o.psfUseAllGlyphs, o.psfUnicodeTable, true ); } }, PSF1GZ(".psf.gz", "psf1gz") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PSFBitmapFontExporter( 1, o.getPsfLowEncoding(), o.getPsfHighEncoding(), o.psfUseLowEncoding, o.psfUseHighEncoding, o.psfUseAllGlyphs, o.psfUnicodeTable, true ); } }, SUIT(".suit", "suit", true) { public BitmapFontExporter createExporter(BitmapOutputOptions o) { o.idgen.setRange(128, 32768); o.sizegen.setRange(4, 127); o.sizegen.setPointSizes(9, 10, 12, 14, 18, 24, 36, 48, 72); return new NFNTBitmapFontExporter.ResourceFile(o.idgen, o.sizegen, o.getEncoding()); } public void postProcess(File file) throws IOException { MacUtility.setTypeAndCreator(file, "FFIL", "DMOV"); } }, DFONT(".dfont", "dfont", false) { public BitmapFontExporter createExporter(BitmapOutputOptions o) { o.idgen.setRange(128, 32768); o.sizegen.setRange(4, 127); o.sizegen.setPointSizes(9, 10, 12, 14, 18, 24, 36, 48, 72); return new NFNTBitmapFontExporter.ResourceFile(o.idgen, o.sizegen, o.getEncoding()); } }, NFNT(".nfnt", "nfnt") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new NFNTBitmapFontExporter.FlatFile(o.getEncoding()); } }, SFONT(".png", "png", "sfont") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new SFontBitmapFontExporter(); } }, RFONT(".png", "rfont") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new RFontBitmapFontExporter(); } }, HEX(".hex", "hex") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new HexBitmapFontExporter(); } }, CVT(".cvt", "cvt", "geos") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { o.idgen.setRange(128, 1024); o.sizegen.setRange(6, 63); o.sizegen.setPointSizes(9, 10, 12, 14, 18, 24, 36, 48, 60); return new GEOSBitmapFontExporter( o.idgen, o.sizegen, o.geosMega, o.geosKerning, o.geosUTF8 ); } }, FZX(".fzx", "fzx") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new FZXBitmapFontExporter(o.getEncoding()); } }, U8M(".u8m", "u8m") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new U8MBitmapFontExporter(o.u8mLoadAddress, o.getEncoding()); } }, AMIGA(".font", "font", "amiga") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new AmigaBitmapFontExporter.ContentsFile(o.amigaProportional, o.getEncoding()); } }, FNT3(".fnt", "fnt", "fnt3") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new FNTBitmapFontExporter(3, o.getEncoding()); } }, FNT2(".fnt", "fnt2") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new FNTBitmapFontExporter(2, o.getEncoding()); } }, FONTX(".fnt", "dosv", "fontx", "fontx2") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { if (o.fontxDoubleByte) { String en = o.fontxDoubleByteEncoding; if (en == null || en.length() == 0) en = "CP943"; return new FONTXBitmapFontExporter(en); } else { String en = o.encodingName; if (en == null || en.length() == 0) en = "CP437"; return new FONTXBitmapFontExporter(EncodingList.instance().getGlyphList(en)); } } }, MGTK(".fnt", "mgtk", "mgf", "mpf", "mousepaint") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new MGTKBitmapFontExporter(o.getEncoding()); } }, RB12(".fnt", "rb12") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new RockboxBitmapFontExporter(RockboxBitmapFontExporter.RB12); } }, RB11(".fnt", "rb11") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new RockboxBitmapFontExporter(RockboxBitmapFontExporter.RB11); } }, CYBIKO(".fnt", "cybiko") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new CybikoBitmapFontExporter(o.getEncoding()); } }, PLAYDATE_FNT(".fnt", "playdate", "playdate-allinone", "playdate-fnt") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PlaydateBitmapFontExporter(false); } }, PLAYDATE_FNT_PNG(".fnt", "playdate-separate", "playdate-fnt+png") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new PlaydateBitmapFontExporter(true); } }, HRCG(".set", "hrcg", "set") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new HRCGBitmapFontExporter(); } }, HMZK(".hmzk", "hmzk") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new HMZKBitmapFontExporter(); } }, // **** Add new formats above this line. **** SBF(".sbf", "sbf") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new SBFBitmapFontExporter(o.getEncoding()); } }, TOS(".ft", "tos", "ft") { public BitmapFontExporter createExporter(BitmapOutputOptions o) { return new TOSBitmapFontExporter(); } }; public final String[] ids; public final String suffix; public final boolean macResFork; private BitmapOutputFormat(String suffix, String... ids) { this.ids = ids; this.suffix = suffix; this.macResFork = false; } private BitmapOutputFormat(String suffix, String id, boolean macResFork) { this.ids = new String[]{id}; this.suffix = suffix; this.macResFork = macResFork; } public abstract BitmapFontExporter createExporter(BitmapOutputOptions o); public void postProcess(File file) throws IOException {} } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/BitmapOutputOptions.java000066400000000000000000000027171506470510200332450ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class BitmapOutputOptions { public int xSize = 100, ySize = 100; public boolean extendWinMetrics = false; public IDGenerator idgen = new IDGenerator.HashCode(128, 32768); public PointSizeGenerator sizegen = new PointSizeGenerator.Automatic(4, 127); public String encodingName = null; public Integer u8mLoadAddress = null; public Boolean amigaProportional = null; public boolean geosMega = false; public boolean geosKerning = false; public boolean geosUTF8 = false; public boolean fontxDoubleByte = false; public String fontxDoubleByteEncoding = null; public String psfLowEncoding = null; public String psfHighEncoding = null; public boolean psfUseLowEncoding = true; public boolean psfUseHighEncoding = false; public boolean psfUseAllGlyphs = true; public boolean psfUnicodeTable = true; public GlyphList getEncoding() { if (encodingName == null) return null; return EncodingList.instance().getGlyphList(encodingName); } public GlyphList getPsfLowEncoding() { if (psfLowEncoding == null) return null; return EncodingList.instance().getGlyphList(psfLowEncoding); } public GlyphList getPsfHighEncoding() { if (psfHighEncoding == null) return null; return EncodingList.instance().getGlyphList(psfHighEncoding); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ConvertBitmap.java000066400000000000000000000664351506470510200320200ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.BitmapFontExporter; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontGlyphTransformer; import com.kreative.bitsnpicas.GlyphPair; import com.kreative.bitsnpicas.IDGenerator; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.PointSizeGenerator; import com.kreative.bitsnpicas.edit.TimestampGlyphGenerator; import com.kreative.bitsnpicas.transformer.*; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class ConvertBitmap { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} if (args.length == 0) { printHelp(); } else { boolean processingOptions = true; Options o = new Options(); String sp = null; String rp = null; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingOptions && arg.startsWith("-")) { if (arg.equals("--")) { processingOptions = false; } else if (arg.equals("-s") && argi < args.length) { sp = args[argi++]; if (rp != null) { o.nameSearchReplace.add(new SearchReplacePattern(sp, rp)); sp = null; rp = null; } } else if (arg.equals("-r") && argi < args.length) { rp = args[argi++]; if (sp != null) { o.nameSearchReplace.add(new SearchReplacePattern(sp, rp)); sp = null; rp = null; } } else if (arg.equals("-t") && argi < args.length) { o.timestampCodepoint = parseInt16(args[argi++]); } else if (arg.equals("-sr") && argi < args.length) { File srFile = new File(args[argi++]); try { Scanner scan = new Scanner(new FileInputStream(srFile), "utf-8"); while (scan.hasNextLine()) { String line = scan.nextLine().trim(); int offset = line.indexOf('#'); if (offset >= 0) line = line.substring(0, offset).trim(); if (line.length() == 0) continue; GlyphPair gp = parseGlyphPair(line); if (gp == null) continue; o.subsetRemap.add(gp); } scan.close(); } catch (IOException e) { System.err.println("Failed to read subsetRemap: " + srFile.getName()); } } else if (arg.equals("-d") && argi < args.length) { String s = args[argi++]; String[] a = s.split("-", 2); Integer rs = (a.length > 0) ? parseInt16(a[0]) : null; Integer re = (a.length > 1) ? parseInt16(a[1]) : null; if (rs != null && re != null) o.codePointsToRemove.set(Math.min(rs,re), Math.max(rs,re)+1); else if (rs != null) o.codePointsToRemove.set(rs); else if (re != null) o.codePointsToRemove.set(re); else if (s.length() > 0) o.glyphNamesToRemove.add(s); } else if (arg.equals("-D") && argi < args.length) { String s = args[argi++]; String[] a = s.split("-", 2); Integer rs = (a.length > 0) ? parseInt16(a[0]) : null; Integer re = (a.length > 1) ? parseInt16(a[1]) : null; if (rs != null && re != null) o.codePointsToRemove.clear(Math.min(rs,re), Math.max(rs,re)+1); else if (rs != null) o.codePointsToRemove.clear(rs); else if (re != null) o.codePointsToRemove.clear(re); else if (s.length() > 0) o.glyphNamesToRemove.remove(s); } else if (arg.equals("-c")) { o.strictMonospace = true; } else if (arg.equals("-C")) { o.strictMonospace = false; } else if (arg.equals("-n")) { o.transform.clear(); } else if (arg.equals("-b")) { o.transform.add(new BoldBitmapFontGlyphTransformer(true)); } else if (arg.equals("-B")) { o.transform.add(new BoldBitmapFontGlyphTransformer(false)); } else if (arg.equals("-tx") && argi < args.length) { int tx = parseInt(args[argi++], 0); o.transform.add(new TranslateBitmapFontGlyphTransformer(tx, 0, 0)); } else if (arg.equals("-tw") && argi < args.length) { int tw = parseInt(args[argi++], 0); o.transform.add(new TranslateBitmapFontGlyphTransformer(0, tw, 0)); } else if ((arg.equals("-ta") || arg.equals("-ty")) && argi < args.length) { int ta = parseInt(args[argi++], 0); o.transform.add(new TranslateBitmapFontGlyphTransformer(0, 0, ta)); } else if (arg.equals("-o") && argi < args.length) { o.dest = new File(args[argi++]); } else if (arg.equals("-f") && argi < args.length) { o.format = args[argi++]; } else if ((arg.equals("-w") || arg.equals("-x")) && argi < args.length) { o.oo.xSize = parseInt(args[argi++], 100); } else if ((arg.equals("-h") || arg.equals("-y")) && argi < args.length) { o.oo.ySize = parseInt(args[argi++], 100); } else if (arg.equals("-T")) { o.oo.extendWinMetrics = false; } else if (arg.equals("-Y")) { o.oo.extendWinMetrics = true; } else if (arg.equals("-p") && argi < args.length) { String s = args[argi++]; boolean done = loadPreset(o, s); if (!done) System.err.println("Unknown preset: " + s); } else if (arg.equals("-i") && argi < args.length) { int id = parseInt(args[argi++], 0); o.oo.idgen = new IDGenerator.Sequential(id, 128, 32768); } else if (arg.equals("-R")) { o.oo.idgen = new IDGenerator.Random(128, 32768); } else if (arg.equals("-H")) { o.oo.idgen = new IDGenerator.HashCode(128, 32768); } else if (arg.equals("-z") && argi < args.length) { int size = parseInt(args[argi++], 0); o.oo.sizegen = new PointSizeGenerator.Fixed(size); } else if (arg.equals("-E")) { o.oo.sizegen = new PointSizeGenerator.Automatic(4, 127); } else if (arg.equals("-S")) { o.oo.sizegen = new PointSizeGenerator.Standard(9, 10, 12, 14, 18, 24, 36, 48, 72); } else if (arg.equals("-e") && argi < args.length) { o.io.encodingName = o.oo.encodingName = args[argi++]; o.oo.fontxDoubleByte = false; } else if (arg.equals("-ie") && argi < args.length) { o.io.encodingName = args[argi++]; } else if (arg.equals("-oe") && argi < args.length) { o.oo.encodingName = args[argi++]; o.oo.fontxDoubleByte = false; } else if (arg.equals("-ee") && argi < args.length) { o.io.fontxDoubleByteEncoding = o.oo.fontxDoubleByteEncoding = args[argi++]; o.oo.fontxDoubleByte = true; } else if (arg.equals("-iee") && argi < args.length) { o.io.fontxDoubleByteEncoding = args[argi++]; } else if (arg.equals("-oee") && argi < args.length) { o.oo.fontxDoubleByteEncoding = args[argi++]; o.oo.fontxDoubleByte = true; } else if (arg.equals("-le") && argi < args.length) { o.io.psfLowEncoding = o.oo.psfLowEncoding = args[argi++]; o.oo.psfUseLowEncoding = (o.oo.psfLowEncoding.length() > 0); } else if (arg.equals("-he") && argi < args.length) { o.io.psfHighEncoding = o.oo.psfHighEncoding = args[argi++]; o.oo.psfUseHighEncoding = (o.oo.psfHighEncoding.length() > 0); } else if (arg.equals("-ile") && argi < args.length) { o.io.psfLowEncoding = args[argi++]; } else if (arg.equals("-ihe") && argi < args.length) { o.io.psfHighEncoding = args[argi++]; } else if (arg.equals("-ole") && argi < args.length) { o.oo.psfLowEncoding = args[argi++]; o.oo.psfUseLowEncoding = (o.oo.psfLowEncoding.length() > 0); } else if (arg.equals("-ohe") && argi < args.length) { o.oo.psfHighEncoding = args[argi++]; o.oo.psfUseHighEncoding = (o.oo.psfHighEncoding.length() > 0); } else if (arg.equals("-pb") && argi < args.length) { o.io.psfPuaBase = parseInt16(args[argi++]); } else if (arg.equals("-a") && argi < args.length) { o.oo.u8mLoadAddress = parseInt16(args[argi++]); } else if (arg.equals("-P")) { o.oo.amigaProportional = true; } else if (arg.equals("-X")) { o.oo.amigaProportional = false; } else if (arg.equals("-A")) { o.oo.amigaProportional = null; } else if (arg.equals("-m")) { o.oo.geosMega = true; } else if (arg.equals("-M")) { o.oo.geosMega = false; } else if (arg.equals("-k")) { o.oo.geosKerning = true; } else if (arg.equals("-K")) { o.oo.geosKerning = false; } else if (arg.equals("-u")) { o.oo.geosUTF8 = true; } else if (arg.equals("-U")) { o.oo.geosUTF8 = false; } else if (arg.equals("-pa")) { o.oo.psfUseAllGlyphs = true; } else if (arg.equals("-PA")) { o.oo.psfUseAllGlyphs = false; } else if (arg.equals("-pu")) { o.oo.psfUnicodeTable = true; } else if (arg.equals("-PU")) { o.oo.psfUnicodeTable = false; } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { try { File file = new File(arg); System.out.print("Converting " + file.getName() + "..."); BitmapInputFormat format = BitmapInputFormat.forFile(file); if (format == null) { System.out.println(" FAILED: Unknown input format."); } else { if (format.macResFork) file = MacUtility.getResourceFork(file); BitmapFont[] fonts = format.createImporter(o.io).importFont(file); if (fonts == null || fonts.length == 0) { System.out.println(" FAILED: No fonts found."); } else { boolean anyDone = false; for (BitmapFont font : fonts) { transformFont(font, o); font.contractGlyphs(); font.autoFillNames(); String name = font.getName(format.nameType); boolean done = exportFont(font, name, o); if (done) anyDone = true; } if (anyDone) System.out.println(" DONE"); else System.out.println(" FAILED: Unknown output format."); } } } catch (IOException e) { System.out.println(" FAILED: " + e.getClass().getSimpleName() + ": " + e.getMessage()); } } } } } private static void printHelp() { System.out.println(); System.out.println("Usage:"); System.out.println(" java -jar BitsNPicas.jar convertbitmap "); System.out.println(); System.out.println("Options:"); System.out.println(" -s Regular expression to search for in the font name."); System.out.println(" -r Replacement text for in the font name."); System.out.println(" -t Generate a timestamp glyph at the specified code point."); System.out.println(" -sr Create a subset/remap glyphs according to a mapping file."); System.out.println(" -d Do not include characters in the specified range."); System.out.println(" -D Include characters in the specified range."); System.out.println(" -c Strict monospace: remove glyphs not the width of a space."); System.out.println(" -C Loose monospace or proportional; the opposite of -c."); System.out.println(" -n Do not transform the font (the default)."); System.out.println(" -b Transform the font using faux bold."); System.out.println(" -B Transform the font using faux bold without changing widths."); System.out.println(" -tx Nudge glyphs left or right."); System.out.println(" -tw Increase or decrease advance widths."); System.out.println(" -ta Nudge glyphs up or down."); System.out.println(" -o Write output to the specified file or directory."); System.out.println(" -f Set the output format. One of:"); List ids = new ArrayList(); for (BitmapOutputFormat f : BitmapOutputFormat.values()) { for (String id : f.ids) ids.add(id); } printHelpList(ids); System.out.println(" -w Pixel width in em units (for ttf). Default: 100."); System.out.println(" -h Pixel height in em units (for ttf). Default: 100."); System.out.println(" -T Use typo metrics for winAscent/winDescent (for ttf)."); System.out.println(" (Force line height; more compatible. The default.)"); System.out.println(" -Y Use yMin/yMax for winAscent/winDescent (for ttf)."); System.out.println(" (Prevent clipping; more conformant to the TT/OT spec.)"); System.out.println(" -p Use a preset for -s, -r, -w, and -h. One of:"); System.out.println(" none, apple2, apple2-40col, apple2-80col,"); System.out.println(" apple2-hgr, apple2-dhr, lisa, lisa-raw, lisa-2x3y,"); System.out.println(" iigs-320, iigs-640, iigs-320h, iigs-640h, atari,"); System.out.println(" atari-40col, atari-80col, commodore, commodore-20col,"); System.out.println(" commodore-40col, commodore-80col, trs80, trs80-64col,"); System.out.println(" trs80-32col, trs80-m1, trs80-m1-64col, trs80-m1-32col,"); System.out.println(" trs80-m2, trs80-m3, trs80-m3-64col, trs80-m3-32col,"); System.out.println(" trs80-m4, trs80-m4-64col, trs80-m4-32col,"); System.out.println(" trs80-m4-80col, trs80-m4-40col"); System.out.println(" -i Font ID number (for nfnt or geos)."); System.out.println(" -R Use random ID number (for nfnt or geos)."); System.out.println(" -H Use ID number derived from font name (for nfnt or geos)."); System.out.println(" -z Font point size (for nfnt or geos)."); System.out.println(" -E Use any point size (for nfnt or geos)."); System.out.println(" -S Use only standard point sizes (for nfnt or geos)."); System.out.println(" (9, 10, 12, 14, 18, 24, 36, 48, and 72 for nfnt,)"); System.out.println(" (9, 10, 12, 14, 18, 24, 36, 48, and 60 for geos.)"); System.out.println(" -m / -M Generate a MEGA / standard font (for geos)."); System.out.println(" -k / -K Generate / don't generate kerning tables (for geos)."); System.out.println(" -u / -U Generate / don't generate UTF-8 tables (for geos)."); System.out.println(" -a Add a loading address to the file (for u8m)."); System.out.println(" -P Always generate proportional font (for Amiga)."); System.out.println(" -X Always generate monospaced font (for Amiga)."); System.out.println(" -A Automatically detect proportional/mono (for Amiga)."); System.out.println(" -e Use the specified encoding (for nfnt, fzx, etc.). One of:"); System.out.println(" -ie Use the specified encoding for reading only. One of:"); System.out.println(" -oe Use the specified encoding for writing only. One of:"); List encs = new ArrayList(); for (GlyphList e : EncodingList.instance().glyphLists()) { encs.add(e.getName()); } printHelpList(encs); System.out.println(" -ee Use the specified double-byte encoding (for fontx)."); System.out.println(" -iee Use the specified double-byte encoding for reading only."); System.out.println(" -oee Use the specified double-byte encoding for writing only."); System.out.println(" -le Use the specified encoding for chars 000-0FF (for psf)."); System.out.println(" -he Use the specified encoding for chars 100-1FF (for psf)."); System.out.println(" -ile Use the specified encoding for chars 000-0FF for reading."); System.out.println(" -ihe Use the specified encoding for chars 100-1FF for reading."); System.out.println(" -ole Use the specified encoding for chars 000-0FF for writing."); System.out.println(" -ohe Use the specified encoding for chars 100-1FF for writing."); System.out.println(" -pb Read all glyphs in order starting at code point (for psf)."); System.out.println(" -pa / -PA Write / don't write other characters (for psf)."); System.out.println(" -pu / -PU Write / don't write Unicode mapping table (for psf)."); System.out.println(" -- Process remaining arguments as file names."); System.out.println(); } private static void printHelpList(List list) { int col = 0; for (int i = 0, n = list.size(); i < n; i++) { String item = " " + list.get(i); if (i < n - 1) item += ","; if (col + item.length() > 78) { System.out.println(); col = 0; } if (col == 0) { System.out.print(" "); col = 19; } System.out.print(item); col += item.length(); } System.out.println(); } private static class Options { public final BitmapInputOptions io = new BitmapInputOptions(); public final BitmapOutputOptions oo = new BitmapOutputOptions(); public List nameSearchReplace = new ArrayList(); public Integer timestampCodepoint = null; public Set subsetRemap = new HashSet(); public BitSet codePointsToRemove = new BitSet(); public Set glyphNamesToRemove = new HashSet(); public boolean strictMonospace = false; public List transform = new ArrayList(); public File dest = null; public String format = "ttf"; } private static class SearchReplacePattern { private final Pattern searchPattern; private final String replacePattern; public SearchReplacePattern(String s, String r) { Pattern sp; try { sp = Pattern.compile(s); } catch (PatternSyntaxException e) { sp = Pattern.compile(Pattern.quote(s)); } this.searchPattern = sp; this.replacePattern = r; } public String replaceAll(String s) { return searchPattern.matcher(s).replaceAll(replacePattern); } } private static int parseInt(String s, int def) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { return def; } } private static Integer parseInt16(String s) { try { if (s.startsWith("U+") || s.startsWith("u+")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("0x") || s.startsWith("0X")) return Integer.parseInt(s.substring(2), 16); if (s.startsWith("$")) return Integer.parseInt(s.substring(1), 16); return Integer.parseInt(s); } catch (NumberFormatException e) { return null; } } private static GlyphPair parseGlyphPair(String s) { String[] a = s.trim().split("\\s+"); Integer ocp = parseInt16(a[0]); if (ocp != null) { if (a.length > 1) { Integer ncp = parseInt16(a[1]); if (ncp != null) return new GlyphPair(ocp, ncp); if (a[1].length() > 0) return new GlyphPair(ocp, a[1]); } return new GlyphPair(ocp, ocp); } if (a[0].length() > 0) { if (a.length > 1) { Integer ncp = parseInt16(a[1]); if (ncp != null) return new GlyphPair(a[0], ncp); if (a[1].length() > 0) return new GlyphPair(a[0], a[1]); } return new GlyphPair(a[0], a[0]); } return null; } private static boolean loadPreset(Options o, String name) { name = name.toLowerCase(); if (name.equals("") || name.equals("none")) { o.nameSearchReplace.clear(); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("apple2") || name.equals("apple2-40col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Apple II", "Print Char 21")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("apple2-80col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Apple II", "PR Number 3")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("apple2-hgr")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("II", "II HGR")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("apple2-dhr")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("II", "II DHR")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("lisa") || name.equals("lisa-2x3y")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "2X3Y")); o.oo.xSize = 80; o.oo.ySize = 120; return true; } else if (name.equals("lisa-raw")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("2X3Y", "Raw")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("iigs-320")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Shaston", "Shaston 320")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("iigs-640")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Shaston", "Shaston 640")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("iigs-320h")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Shaston", "Shaston Hi 320")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("iigs-640h")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Shaston", "Shaston Hi 640")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("atari") || name.equals("atari-40col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Colleen", "Candy")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("atari-80col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Candy", "Colleen")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("commodore") || name.equals("commodore-40col")) { o.nameSearchReplace.clear(); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("commodore-20col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Pet.*$", "$0 2X")); o.oo.xSize = 200; o.oo.ySize = 100; return true; } else if (name.equals("commodore-80col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Pet.*$", "$0 2Y")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("trs80") || name.equals("trs80-64col") || name.equals("trs80-m1") || name.equals("trs80-m1-64col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "64C 2X3Y")); o.oo.xSize = 80; o.oo.ySize = 120; return true; } else if (name.equals("trs80-32col") || name.equals("trs80-m1-32col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "32C 4X3Y")); o.oo.xSize = 160; o.oo.ySize = 120; return true; } else if (name.equals("trs80-m2")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "2Y")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("trs80-m3") || name.equals("trs80-m3-64col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "64C")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("trs80-m3-32col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "32C")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else if (name.equals("trs80-m4") || name.equals("trs80-m4-64col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "64C")); o.oo.xSize = 100; o.oo.ySize = 160; return true; } else if (name.equals("trs80-m4-32col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "32C")); o.oo.xSize = 100; o.oo.ySize = 80; return true; } else if (name.equals("trs80-m4-80col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "80C")); o.oo.xSize = 100; o.oo.ySize = 200; return true; } else if (name.equals("trs80-m4-40col")) { o.nameSearchReplace.clear(); o.nameSearchReplace.add(new SearchReplacePattern("Raw", "40C")); o.oo.xSize = 100; o.oo.ySize = 100; return true; } else { return false; } } private static void transformFont(BitmapFont font, Options o) { if (!o.nameSearchReplace.isEmpty()) { for (Map.Entry e : font.names(true).entrySet()) { String s = e.getValue(); for (SearchReplacePattern p : o.nameSearchReplace) { s = p.replaceAll(s); } font.setName(e.getKey(), s); } } if (o.timestampCodepoint != null) { GregorianCalendar now = new GregorianCalendar(); BitmapFontGlyph[] glyphs = TimestampGlyphGenerator.getTimestampGlyphs(font, now); if (glyphs != null) { BitmapFontGlyph glyph = BitmapFontGlyph.compose(glyphs); font.putCharacter(o.timestampCodepoint, glyph); } } if (!o.subsetRemap.isEmpty()) { font.subsetRemap(o.subsetRemap); } if (!o.codePointsToRemove.isEmpty()) { for ( int i = o.codePointsToRemove.nextSetBit(0); i >= 0; i = o.codePointsToRemove.nextSetBit(i + 1) ) { font.removeCharacter(i); } } if (!o.glyphNamesToRemove.isEmpty()) { for (String name : o.glyphNamesToRemove) { font.removeNamedGlyph(name); } } if (o.strictMonospace) { BitmapFontGlyph space = font.getCharacter(32); int monoWidth = (space != null) ? space.getCharacterWidth() : 0; for (Map.Entry e : font.characters(true).entrySet()) { if (e.getValue().getCharacterWidth() != monoWidth) { font.removeCharacter(e.getKey()); } } for (Map.Entry e : font.namedGlyphs(true).entrySet()) { if (e.getValue().getCharacterWidth() != monoWidth) { font.removeNamedGlyph(e.getKey()); } } } for (BitmapFontGlyphTransformer tx : o.transform) { font.transform(tx); } } private static boolean exportFont(BitmapFont font, String name, Options o) throws IOException { String format = o.format.toLowerCase(); for (BitmapOutputFormat f : BitmapOutputFormat.values()) { for (String id : f.ids) { if (format.equals(id)) { File out = getOutputFile(o.dest, name, f.suffix); System.out.print(" to " + out.getName() + "..."); BitmapFontExporter exporter = f.createExporter(o.oo); if (f.macResFork) { out.createNewFile(); File rf = MacUtility.getResourceFork(out); exporter.exportFontToFile(font, rf); } else { exporter.exportFontToFile(font, out); } f.postProcess(out); return true; } } } return false; } private static File getOutputFile(File dest, String name, String ext) { if (dest == null || dest.isDirectory()) { ext = normalizeExtension(ext); } else { name = dest.getName(); int o = name.lastIndexOf('.'); if (o > 0) { ext = name.substring(o); name = name.substring(0, o); } else { ext = ""; } dest = dest.getParentFile(); } File f = new File(dest, name + ext); if (f.exists()) { int i = 2; do { f = new File(dest, name + "-" + (i++) + ext); } while (f.exists()); } return f; } private static String normalizeExtension(String ext) { if (ext == null) return ""; if (ext.equals("") || ext.startsWith(".")) return ext; return "." + ext; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/DebugCybiko.java000066400000000000000000000031101506470510200314070ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class DebugCybiko { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { FileInputStream in = new FileInputStream(new File(arg)); debugCybiko(new DataInputStream(in)); in.close(); } catch (IOException e) { System.out.println(" ERROR: " + e); } } } private static void debugCybiko(DataInputStream in) throws IOException { int mn = in.readUnsignedByte(); int cc = in.readUnsignedByte(); int mw = in.readUnsignedByte(); int mh = in.readUnsignedByte(); System.out.println("\tMN\tCC\tMW\tMH"); System.out.println("\t" + mn + "\t" + cc + "\t" + mw + "\t" + mh); System.out.println("\tC\tL\tT\tW\tH\tOK\tCHK"); for (int c = 0; c < cc; c++) { int l = in.readUnsignedByte(); int t = in.readUnsignedByte(); int w = in.readUnsignedByte(); int h = in.readUnsignedByte(); boolean ok = l > 0 || t > 0 || w > 1 || h > 1; List gd = new ArrayList(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = in.readUnsignedByte(); for (int m = 0x80, i = x; m != 0 && i < w; m >>= 1, i++) { if ((b & m) != 0) { ok = true; gd.add((l + i) | ((t + y) << 16)); } } } } System.out.println( "\t" + (c+32) + "\t" + l + "\t" + t + "\t" + w + "\t" + h + "\t" + ok + "\t" + gd.hashCode() ); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/DebugRockbox.java000066400000000000000000000113201506470510200316000ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class DebugRockbox { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { FileInputStream in = new FileInputStream(new File(arg)); debugRockbox(new DataInputStream(in)); in.close(); } catch (IOException e) { System.out.println(" ERROR: " + e); } } } private static void debugRockbox(DataInputStream in) throws IOException { byte[] magic = new byte[4]; in.readFully(magic); System.out.println("Magic:\t" + new String(magic)); if (magic[3] == '1') { byte[] name = new byte[64]; in.readFully(name); byte[] copyright = new byte[256]; in.readFully(copyright); System.out.println("Name:\t" + new String(name).trim()); System.out.println("Copyrt:\t" + new String(copyright).trim()); } int maxWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int height = Short.reverseBytes(in.readShort()) & 0xFFFF; int ascent = Short.reverseBytes(in.readShort()) & 0xFFFF; int depth = Short.reverseBytes(in.readShort()) & 0xFFFF; int firstChar = Integer.reverseBytes(in.readInt()); int defaultChar = Integer.reverseBytes(in.readInt()); int numChars = Integer.reverseBytes(in.readInt()); int numBits = Integer.reverseBytes(in.readInt()); int numOffsets = Integer.reverseBytes(in.readInt()); int numWidths = Integer.reverseBytes(in.readInt()); System.out.println("MaxWid:\t" + maxWidth); System.out.println("Height:\t" + height); System.out.println("Ascent:\t" + ascent); System.out.println("Depth:\t" + depth); System.out.println("FrstCh:\t" + firstChar); System.out.println("DfltCh:\t" + defaultChar); System.out.println("NChars:\t" + numChars); System.out.println("NBits:\t" + numBits); System.out.println("NOffst:\t" + numOffsets); System.out.println("NWidth:\t" + numWidths); byte[] bitmap; if (magic[3] == '1') { bitmap = new byte[(((numBits * 2) + 3) / 4) * 4]; } else { bitmap = new byte[((numBits + 1) / 2) * 2]; } in.readFully(bitmap); int[] offsets = new int[numOffsets]; int[] widths = new int[numWidths]; for (int i = 0; i < numOffsets; i++) { if (magic[3] == '1') { offsets[i] = Integer.reverseBytes(in.readInt()); } else { offsets[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; } } for (int i = 0; i < numWidths; i++) { widths[i] = in.readUnsignedByte(); } /* if (numOffsets > 0) { System.out.print("Offsts:\t"); for (int i : offsets) System.out.print(i + " "); System.out.println(); } if (numWidths > 0) { System.out.print("Widths:\t"); for (int i : widths) System.out.print(i + " "); System.out.println(); } */ for (int i = 0; i < numChars; i++) { System.out.println("Glyph " + i + ":"); int width = (i < widths.length) ? widths[i] : maxWidth; int rowBytes = ((width + 15) / 16) * 2; byte[] gb; if (magic[3] == '1') { int o = (i < offsets.length) ? (offsets[i] * 2) : (rowBytes * height * i); gb = swab(bitmap, o, width, height); } else { int o = (i < offsets.length) ? offsets[i] : (((height + 7) / 8) * maxWidth * i); gb = rotright(bitmap, o, width, height); } for (int y = 0; y < height; y++) { for (int x = 0; x < rowBytes; x++) { for (int m = 0x80; m != 0; m >>= 1) { if ((gb[y * rowBytes + x] & m) == 0) { System.out.print("."); } else { System.out.print("#"); } } } System.out.println(); } } } private static byte[] swab(byte[] fntData, int fntOffset, int width, int height) { int rowByteCount = ((width + 15) / 16) * 2; int bmpByteCount = rowByteCount * height; byte[] bmpBytes = new byte[bmpByteCount]; for (int i = 0; i < bmpByteCount; i++) { bmpBytes[i ^ 1] = fntData[fntOffset++]; } return bmpBytes; } private static byte[] rotright(byte[] fntData, int fntOffset, int width, int height) { int rowWordCount = (width + 15) / 16; int bmpWordCount = rowWordCount * height; int[] bmpWords = new int[bmpWordCount]; int fntMask = 1; for (int i = 0; i < height; i++) { int bmpOffset = i * rowWordCount; int bmpMask = 0x8000; for (int j = 0; j < width; j++) { if ((fntData[fntOffset + j] & fntMask) != 0) { bmpWords[bmpOffset] |= bmpMask; } bmpMask >>= 1; if (bmpMask == 0) { bmpMask = 0x8000; bmpOffset++; } } fntMask <<= 1; if (fntMask >= 256) { fntMask = 1; fntOffset += width; } } byte[] bmpBytes = new byte[bmpWordCount * 2]; for (int bi = 0, wi = 0; wi < bmpWordCount; wi++) { bmpBytes[bi++] = (byte)(bmpWords[wi] >> 8); bmpBytes[bi++] = (byte)(bmpWords[wi] >> 0); } return bmpBytes; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/DebugSound.java000066400000000000000000000050151506470510200312650ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileOutputStream; import com.kreative.bitsnpicas.mover.SoundResource; import com.kreative.bitsnpicas.mover.SoundResource.SampledSound; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; import com.kreative.unicode.ttflib.DfontResourceType; public class DebugSound { public static void main(String[] args) { for (String arg : args) { File file = new File(arg); try { DfontFile rsrc = new DfontFile(file); DfontResourceType rt = rsrc.getResourceType("snd "); if (rt != null) { for (DfontResource res : rt.getResources()) { String ns = file.getName() + " " + res.getId(); if (res.getName() != null) ns += " " + res.getName(); String fns = ns.replaceAll("[\\\\/:*?\"<>|]+", "_"); try { SoundResource sr = new SoundResource(res.getData()); SampledSound ss = sr.toSampledSound(); if (ss == null) continue; System.out.print(ns + ":"); System.out.print("\tsndFmt " + sr.format); System.out.print("\trate " + rateString(ss.std.sampleRate)); System.out.print("\tenc " + ss.std.encode); if (ss.ext != null) { System.out.print("\tch " + ss.ext.numChannels); System.out.print("\tsampSize " + ss.ext.sampleSize); } if (ss.cmp != null) { System.out.print("\tch " + ss.cmp.numChannels); System.out.print("\tfmt " + formatString(ss.cmp.format)); System.out.print("\tcompId " + ss.cmp.compressionId); System.out.print("\tpktSize " + ss.cmp.packetSize); System.out.print("\tsampSize " + ss.cmp.sampleSize); } System.out.println(); byte[] wav = sr.toWav(); if (wav != null) { FileOutputStream out = new FileOutputStream(new File(fns + ".wav")); out.write(wav); out.close(); } byte[] aiff = sr.toAiff(); if (aiff != null) { FileOutputStream out = new FileOutputStream(new File(fns + ".aiff")); out.write(aiff); out.close(); } } catch (Exception e) { System.err.println("Skipping " + ns + ": " + e); } } } } catch (Exception e) { System.err.println("Skipping " + file.getName() + ": " + e); } } } public static String rateString(int rate) { return Double.toString((rate & 0xFFFFFFFFL) / 65536.0); } public static String formatString(int format) { if (format == 0) return "0"; return DfontResourceType.toString(format); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/DebugTTF.java000066400000000000000000000323201506470510200306310ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.text.SimpleDateFormat; import com.kreative.bitsnpicas.truetype.ColrTable; import com.kreative.bitsnpicas.truetype.CpalTable; import com.kreative.bitsnpicas.truetype.HeadTable; import com.kreative.bitsnpicas.truetype.HheaTable; import com.kreative.bitsnpicas.truetype.MaxpTable; import com.kreative.bitsnpicas.truetype.NameTable; import com.kreative.bitsnpicas.truetype.NameTableEntry; import com.kreative.bitsnpicas.truetype.Os2Table; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class DebugTTF { public static void main(String[] args) { boolean parseOptions = true; boolean includeCOLR = false; for (String arg : args) { if (parseOptions && arg.startsWith("-")) { if (arg.equals("--")) { parseOptions = false; } else if (arg.equals("-c")) { includeCOLR = true; } else if (arg.equals("-C")) { includeCOLR = false; } else { System.err.println("Unknown option: " + arg); } continue; } System.out.println(arg); try { // Open file File file = new File(arg); FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); // Read file byte[] buf = new byte[1048576]; int len; while ((len = in.read(buf)) > 0) out.write(buf, 0, len); // Close file out.flush(); out.close(); in.close(); // Decompile TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(out.toByteArray()); // Print head System.out.println(" head"); HeadTable head = (HeadTable)ttf.getByTableName("head"); if (head == null) System.out.println(" Not present."); else { SimpleDateFormat df = new SimpleDateFormat(); System.out.println(" version: " + hex(head.version, 8)); System.out.println(" fontRevision: " + head.getFontRevisionDouble()); System.out.println(" checkSum: " + hex(head.checkSum, 8)); System.out.println(" magicNumber: " + hex(head.magicNumber, 8)); System.out.println(" flags: " + hex(head.flags, 4)); System.out.println(" unitsPerEm: " + head.unitsPerEm); System.out.println(" dateCreated: " + df.format(head.getDateCreatedCalendar().getTime())); System.out.println(" dateModified: " + df.format(head.getDateModifiedCalendar().getTime())); System.out.println(" xMin: " + head.xMin); System.out.println(" yMin: " + head.yMin); System.out.println(" xMax: " + head.xMax); System.out.println(" yMax: " + head.yMax); System.out.println(" macStyle: " + hex(head.macStyle, 2)); System.out.println(" lowestRecPPEM: " + head.lowestRecPPEM); System.out.println(" fontDirectionHint: " + head.fontDirectionHint); System.out.println(" indexToLocFormat: " + head.indexToLocFormat); System.out.println(" glyphDataFormat: " + head.glyphDataFormat); } // Print hhea System.out.println(" hhea"); HheaTable hhea = (HheaTable)ttf.getByTableName("hhea"); if (hhea == null) System.out.println(" Not present."); else { System.out.println(" version: " + hex(hhea.version, 8)); System.out.println(" ascent: " + hhea.ascent); System.out.println(" descent: " + hhea.descent); System.out.println(" lineGap: " + hhea.lineGap); System.out.println(" advanceWidthMax: " + hhea.advanceWidthMax); System.out.println(" minLSB: " + hhea.minLeftSideBearing); System.out.println(" minRSB: " + hhea.minRightSideBearing); System.out.println(" xMaxExtent: " + hhea.xMaxExtent); System.out.println(" caretSlopeRise: " + hhea.caretSlopeRise); System.out.println(" caretSlopeRun: " + hhea.caretSlopeRun); System.out.println(" caretOffset: " + hhea.caretOffset); System.out.println(" reserved1: " + hex(hhea.reserved1, 4)); System.out.println(" reserved2: " + hex(hhea.reserved2, 4)); System.out.println(" reserved3: " + hex(hhea.reserved3, 4)); System.out.println(" reserved4: " + hex(hhea.reserved4, 4)); System.out.println(" metricDataFormat: " + hhea.metricDataFormat); System.out.println(" numLongHorMetrics: " + hhea.numLongHorMetrics); } // Print maxp System.out.println(" maxp"); MaxpTable maxp = (MaxpTable)ttf.getByTableName("maxp"); if (maxp == null) System.out.println(" Not present."); else { System.out.println(" version: " + hex(maxp.version, 8)); System.out.println(" numGlyphs: " + maxp.numGlyphs); System.out.println(" maxPoints: " + maxp.maxPoints); System.out.println(" maxContours: " + maxp.maxContours); System.out.println(" maxComponentPoints: " + maxp.maxComponentPoints); System.out.println(" maxComponentContours: " + maxp.maxComponentContours); System.out.println(" maxZones: " + maxp.maxZones); System.out.println(" maxTwilightPoints: " + maxp.maxTwilightPoints); System.out.println(" maxStorage: " + maxp.maxStorage); System.out.println(" maxFunctionDefs: " + maxp.maxFunctionDefs); System.out.println(" maxInstructionDefs: " + maxp.maxInstructionDefs); System.out.println(" maxStackElements: " + maxp.maxStackElements); System.out.println(" maxSizeOfInstructions: " + maxp.maxSizeOfInstructions); System.out.println(" maxComponentElements: " + maxp.maxComponentElements); System.out.println(" maxComponentDepth: " + maxp.maxComponentDepth); } // Print name System.out.println(" name"); NameTable name = (NameTable)ttf.getByTableName("name"); if (name == null) System.out.println(" Not present."); else { System.out.println(" Plat Spec Lang Name Size String"); for (NameTableEntry e : name) { System.out.print(" "); System.out.print(pad(e.platformID, 6)); System.out.print(pad(e.platformSpecificID, 6)); System.out.print(pad(e.languageID, 6)); System.out.print(pad(e.nameID, 6)); System.out.print(pad(e.nameData.length, 6)); try { System.out.print("\"" + e.getNameString() + "\""); } catch (Exception x) { System.out.print("<" + e.nameData.length + ">"); } if (e.padding != 0) System.out.print(" [" + e.padding + "]"); System.out.println(); } } // Print OS/2 System.out.println(" OS/2"); Os2Table os2 = (Os2Table)ttf.getByTableName("OS/2"); if (os2 == null) System.out.println(" Not present."); else do { System.out.println(" length: " + os2.length); System.out.println(" version: " + os2.version); System.out.println(" avgCharWidth: " + os2.averageCharWidth); System.out.println(" weightClass: " + os2.weightClass); System.out.println(" widthClass: " + os2.widthClass); System.out.println(" flags: " + hex(os2.flags, 4)); System.out.println(" subscriptXSize: " + os2.subscriptXSize); System.out.println(" subscriptYSize: " + os2.subscriptYSize); System.out.println(" subscriptXOffset: " + os2.subscriptXOffset); System.out.println(" subscriptYOffset: " + os2.subscriptYOffset); System.out.println(" superscriptXSize: " + os2.superscriptXSize); System.out.println(" superscriptYSize: " + os2.superscriptYSize); System.out.println(" superscriptXOffset: " + os2.superscriptXOffset); System.out.println(" superscriptYOffset: " + os2.superscriptYOffset); System.out.println(" strikeoutWidth: " + os2.strikeoutWidth); System.out.println(" strikeoutPosition: " + os2.strikeoutPosition); System.out.println(" familyClass: " + os2.familyClass); System.out.println(" familySubClass: " + os2.familySubClass); System.out.println(" panoseFamilyType: " + os2.panoseFamilyType); System.out.println(" panoseSerifStyle: " + os2.panoseSerifStyle); System.out.println(" panoseWeight: " + os2.panoseWeight); System.out.println(" panoseProportion: " + os2.panoseProportion); System.out.println(" panoseContrast: " + os2.panoseContrast); System.out.println(" panoseStrokeVariation: " + os2.panoseStrokeVariation); System.out.println(" panoseArmStyle: " + os2.panoseArmStyle); System.out.println(" panoseLetterform: " + os2.panoseLetterform); System.out.println(" panoseMidline: " + os2.panoseMidline); System.out.println(" panoseXHeight: " + os2.panoseXHeight); System.out.println(" unicodeRanges: " + hex(os2.unicodeRanges, 8)); System.out.println(" vendorID: " + os2.getVendorIDString()); System.out.println(" fsSelection: " + hex(os2.fsSelection, 4)); System.out.println(" fsFirstCharIndex: " + hex(os2.fsFirstCharIndex, 4)); System.out.println(" fsLastCharIndex: " + hex(os2.fsLastCharIndex, 4)); if (os2.length < Os2Table.LENGTH_78) continue; System.out.println(" typoAscent: " + os2.typoAscent); System.out.println(" typoDescent: " + os2.typoDescent); System.out.println(" typoLineGap: " + os2.typoLineGap); System.out.println(" winAscent: " + os2.winAscent); System.out.println(" winDescent: " + os2.winDescent); if (os2.length < Os2Table.LENGTH_86) continue; System.out.println(" codePages: " + hex(os2.codePages, 8)); if (os2.length < Os2Table.LENGTH_96) continue; System.out.println(" xHeight: " + os2.xHeight); System.out.println(" capHeight: " + os2.capHeight); System.out.println(" defaultChar: " + hex(os2.defaultChar, 4)); System.out.println(" breakChar: " + hex(os2.breakChar, 4)); System.out.println(" maxContext: " + os2.maxContext); if (os2.length < Os2Table.LENGTH_100) continue; System.out.println(" lowerOpticalPointSize: " + os2.getLowerOpticalPointSizeDouble()); System.out.println(" upperOpticalPointSize: " + os2.getUpperOpticalPointSizeDouble()); } while (false); if (includeCOLR) { // Print CPAL System.out.println(" CPAL"); CpalTable cpal = (CpalTable)ttf.getByTableName("CPAL"); if (cpal == null) System.out.println(" Not present."); else { System.out.println(" version: " + cpal.version); System.out.println(" numPaletteEntries: " + cpal.numPaletteEntries); System.out.println(" numPalettes: " + cpal.colorRecordIndices.length); System.out.println(" numColorRecords: " + cpal.colorRecordsArray.length); System.out.println(" colorRecordsArray:"); for (int color : cpal.colorRecordsArray) System.out.print(color(color)); System.out.println(); for (int j = 0; j < cpal.colorRecordIndices.length; j++) { System.out.println(" palette #" + j + ":"); int offset = cpal.colorRecordIndices[j]; for (int i = 0; i < cpal.numPaletteEntries; i++) { System.out.print(color(cpal.colorRecordsArray[offset++])); } System.out.println(); } } // Print COLR System.out.println(" COLR"); ColrTable colr = (ColrTable)ttf.getByTableName("COLR"); if (colr == null) System.out.println(" Not present."); else { System.out.println(" version: " + colr.version); System.out.println(" numBaseGlyphRecords: " + colr.baseGlyphRecords.length); System.out.println(" numLayerRecords: " + colr.layerRecords.length); } } } catch (IOException e) { System.out.println(" Could not read."); } } } private static String color(int color) { int r = ((color >> 16) & 0xFF); int g = ((color >> 8) & 0xFF); int b = ((color >> 0) & 0xFF); int k = (r*30 + g*59 + b*11); StringBuffer sb = new StringBuffer(); sb.append("\u001B[48;2;" + r + ";" + g + ";" + b + "m"); sb.append((k < 12750) ? "\u001B[97m" : "\u001B[30m"); sb.append(" " + Integer.toHexString(color).toUpperCase() + " "); sb.append("\u001B[0m"); return sb.toString(); } private static String hex(int v, int len) { String h = Integer.toHexString(v).toUpperCase(); while (h.length() < len) h = "0" + h; return h; } private static String hex(int[] a, int len) { StringBuffer sb = new StringBuffer(); for (int v : a) sb.insert(0, hex(v, len)); return sb.toString(); } private static String pad(int i, int len) { StringBuffer sb = new StringBuffer(); sb.append(i); while (sb.length() < len) sb.append(" "); return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/DebugWinFNT.java000066400000000000000000000202321506470510200313000ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class DebugWinFNT { public static final int CHARSET_CP1252 = 0; public static final int CHARSET_DEFAULT = 1; public static final int CHARSET_SYMBOL = 2; public static final int CHARSET_MAC = 77; public static final int CHARSET_CP932 = 128; public static final int CHARSET_CP949 = 129; public static final int CHARSET_CP1361 = 130; public static final int CHARSET_CP936 = 134; public static final int CHARSET_CP950 = 136; public static final int CHARSET_CP1253 = 161; public static final int CHARSET_CP1254 = 162; public static final int CHARSET_CP1258 = 163; public static final int CHARSET_CP1255 = 177; public static final int CHARSET_CP1256 = 178; public static final int CHARSET_CP1257 = 186; public static final int CHARSET_CP1251 = 204; public static final int CHARSET_CP874 = 222; public static final int CHARSET_CP1250 = 238; public static final int CHARSET_OEM = 255; public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { FileInputStream in = new FileInputStream(new File(arg)); debugWinFNT(new DataInputStream(new BufferedInputStream(in))); in.close(); } catch (IOException e) { System.out.println(" ERROR: " + e); } } } private static void debugWinFNT(DataInputStream in) throws IOException { // READ HEADER int magic = in.readUnsignedShort(); if (magic < 1 || magic > 3) throw new IOException("bad magic number: " + magic); int size = Integer.reverseBytes(in.readInt()); if (size < 118) throw new IOException("bad size: " + size); byte[] data = new byte[size]; in.readFully(data, 6, size - 6); in = new DataInputStream(new ByteArrayInputStream(data, 6, size - 6)); byte[] copyrightBytes = new byte[60]; in.readFully(copyrightBytes); int copyrightLength = 0; while (copyrightLength < 60 && copyrightBytes[copyrightLength] != 0) copyrightLength++; String copyright = new String(copyrightBytes, 0, copyrightLength, "CP1252"); int type = Short.reverseBytes(in.readShort()) & 0xFFFF; if ((type & 1) != 0) throw new IOException("vector fonts are not supported"); int points = Short.reverseBytes(in.readShort()) & 0xFFFF; int vertRes = Short.reverseBytes(in.readShort()) & 0xFFFF; int horizRes = Short.reverseBytes(in.readShort()) & 0xFFFF; int ascent = Short.reverseBytes(in.readShort()) & 0xFFFF; int internalLeading = Short.reverseBytes(in.readShort()) & 0xFFFF; int externalLeading = Short.reverseBytes(in.readShort()) & 0xFFFF; int italic = in.readUnsignedByte(); int underline = in.readUnsignedByte(); int strikeOut = in.readUnsignedByte(); int weight = Short.reverseBytes(in.readShort()) & 0xFFFF; int charSet = in.readUnsignedByte(); int pixWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int pixHeight = Short.reverseBytes(in.readShort()) & 0xFFFF; int pitchAndFamily = in.readUnsignedByte(); int avgWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int maxWidth = Short.reverseBytes(in.readShort()) & 0xFFFF; int firstChar = in.readUnsignedByte(); int lastChar = in.readUnsignedByte(); int defaultChar = in.readUnsignedByte(); int breakChar = in.readUnsignedByte(); int widthBytes = Short.reverseBytes(in.readShort()) & 0xFFFF; int device = Integer.reverseBytes(in.readInt()); int face = Integer.reverseBytes(in.readInt()); int bitsPointer = Integer.reverseBytes(in.readInt()); int bitsOffset = Integer.reverseBytes(in.readInt()); int reserved = in.readUnsignedByte(); int flags = (magic >= 3) ? Integer.reverseBytes(in.readInt()) : 0; int aSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; int bSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; int cSpace = (magic >= 3) ? (Short.reverseBytes(in.readShort()) & 0xFFFF) : 0; int colorPointer = (magic >= 3) ? Integer.reverseBytes(in.readInt()) : 0; byte[] reserved1 = new byte[16]; if (magic >= 3) in.readFully(reserved1); int deviceEnd = device; while (deviceEnd < size && data[deviceEnd] != 0) deviceEnd++; String deviceName = new String(data, device, deviceEnd - device, "CP1252"); int faceEnd = face; while (faceEnd < size && data[faceEnd] != 0) faceEnd++; String faceName = new String(data, face, faceEnd - face, "CP1252"); // PRINT HEADER System.out.println("Magic:\t" + magic); System.out.println("Size:\t" + size); System.out.println("Copyrt:\t" + copyright); System.out.println("Type:\t" + type); System.out.println("Points:\t" + points); System.out.println("VrtRes:\t" + vertRes); System.out.println("HrzRes:\t" + horizRes); System.out.println("Ascent:\t" + ascent); System.out.println("IntLdg:\t" + internalLeading); System.out.println("ExtLdg:\t" + externalLeading); System.out.println("Italic:\t" + italic); System.out.println("Undrln:\t" + underline); System.out.println("Stkout:\t" + strikeOut); System.out.println("Weight:\t" + weight); System.out.println("Charst:\t" + charSet); System.out.println("PixWid:\t" + pixWidth); System.out.println("PixHgt:\t" + pixHeight); System.out.println("PchFam:\t" + pitchAndFamily); System.out.println("AvgWid:\t" + avgWidth); System.out.println("MaxWid:\t" + maxWidth); System.out.println("FrstCh:\t" + firstChar); System.out.println("LastCh:\t" + lastChar); System.out.println("DfltCh:\t" + defaultChar); System.out.println("BrkCh:\t" + breakChar); System.out.println("WidByt:\t" + widthBytes); System.out.println("Device:\t" + device + "\t" + deviceName); System.out.println("Face:\t" + face + "\t" + faceName); System.out.println("BitPtr:\t" + bitsPointer); System.out.println("BitOfs:\t" + bitsOffset); System.out.println("Rsrvd:\t" + reserved); System.out.println("Flags:\t" + flags); System.out.println("ASpace:\t" + aSpace); System.out.println("BSpace:\t" + bSpace); System.out.println("CSpace:\t" + cSpace); System.out.println("ClrPtr:\t" + colorPointer); System.out.print("Rsrvd1:\t"); for (byte b : reserved1) System.out.print(b + " "); System.out.println(); // READ CHARTABLE int n = lastChar - firstChar + 2; int[] geWidth = new int[n]; int[] geOffset = new int[n]; int[] geHeight = new int[n]; int[] geAspace = new int[n]; int[] geBspace = new int[n]; int[] geCspace = new int[n]; if (magic < 3) { for (int i = 0; i < n; i++) { geWidth[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geOffset[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geHeight[i] = pixHeight; } } else { for (int i = 0; i < n; i++) { geWidth[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; geOffset[i] = Integer.reverseBytes(in.readInt()); if ((flags & 0xF0) < 0x20) { geHeight[i] = pixHeight; } else { geHeight[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; } if ((flags & 0x0F) >= 0x04) { geAspace[i] = Integer.reverseBytes(in.readInt()); geBspace[i] = Integer.reverseBytes(in.readInt()); geCspace[i] = Integer.reverseBytes(in.readInt()); } } } // PRINT CHARTABLE System.out.println("CharTable:"); for (int i = 0; i < n; i++) { System.out.println( "\t" + geWidth[i] + "\t" + geOffset[i] + "\t" + geHeight[i] + "\t" + geAspace[i] + "\t" + geBspace[i] + "\t" + geCspace[i] ); } // READ BITMAPS byte[][][] bitmaps = new byte[n][][]; for (int i = 0; i < n; i++) { bitmaps[i] = new byte[geHeight[i]][geWidth[i]]; for (int dy = geOffset[i], by = 0; by < geHeight[i]; by++, dy++) { for (int dx = dy, bx = 0; bx < geWidth[i]; dx += geHeight[i]) { for (int m = 0x80; bx < geWidth[i] && m != 0; bx++, m >>= 1) { if ((data[dx] & m) != 0) { bitmaps[i][by][bx] = -1; } } } } } // PRINT BITMAPS System.out.println("Bitmaps:"); for (int i = 0; i < n; i++) { System.out.println("\t" + i + ":"); for (byte[] row : bitmaps[i]) { System.out.print("\t\t"); for (byte b : row) { System.out.print((b == 0) ? "." : "#"); } System.out.println(); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ExtractCbdt.java000066400000000000000000000311131506470510200314330ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import com.kreative.bitsnpicas.truetype.CbdtEntry; import com.kreative.bitsnpicas.truetype.CbdtEntryFormat17; import com.kreative.bitsnpicas.truetype.CbdtEntryFormat18; import com.kreative.bitsnpicas.truetype.CbdtEntryFormat19; import com.kreative.bitsnpicas.truetype.CmapSubtable; import com.kreative.bitsnpicas.truetype.CmapTable; import com.kreative.bitsnpicas.truetype.EbdtComponent; import com.kreative.bitsnpicas.truetype.EbdtEntry; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat1; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat2; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat5; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat6; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat7; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat8; import com.kreative.bitsnpicas.truetype.EbdtEntryFormat9; import com.kreative.bitsnpicas.truetype.EbdtTable; import com.kreative.bitsnpicas.truetype.EblcBitmapSize; import com.kreative.bitsnpicas.truetype.EblcGlyphIdOffsetPair; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable1; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable2; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable3; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable4; import com.kreative.bitsnpicas.truetype.EblcIndexSubtable5; import com.kreative.bitsnpicas.truetype.EblcTable; import com.kreative.bitsnpicas.truetype.HheaTable; import com.kreative.bitsnpicas.truetype.HmtxTable; import com.kreative.bitsnpicas.truetype.Os2Table; import com.kreative.bitsnpicas.truetype.SbitBigGlyphMetrics; import com.kreative.bitsnpicas.truetype.SbitLineMetrics; import com.kreative.bitsnpicas.truetype.SbitSmallGlyphMetrics; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class ExtractCbdt { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} for (String arg : args) { File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { byte[] data = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); EbdtTable cbdt = (EbdtTable)ttf.getByTableName("CBDT"); EblcTable cblc = (EblcTable)ttf.getByTableName("CBLC"); if (cbdt == null || cblc == null) { System.out.println("no CBDT/CBLC table found."); } else { File outputRoot = new File(file.getParent(), file.getName() + ".cbdt.d"); if (!outputRoot.exists()) outputRoot.mkdir(); File debug = new File(outputRoot, "fontinfo.txt"); FileOutputStream debugOS = new FileOutputStream(debug); OutputStreamWriter debugWR = new OutputStreamWriter(debugOS, "UTF-8"); PrintWriter debugPR = new PrintWriter(debugWR, true); HheaTable hhea = (HheaTable)ttf.getByTableName("hhea"); if (hhea != null) { debugPR.println("ascent: " + hhea.ascent); debugPR.println("descent: " + hhea.descent); debugPR.println("lineGap: " + hhea.lineGap); debugPR.println("advanceWidthMax: " + hhea.advanceWidthMax); } Os2Table os2 = (Os2Table)ttf.getByTableName("OS/2"); if (os2 != null) { debugPR.println("vendorID: " + os2.getVendorIDString()); debugPR.println("typoAscent: " + os2.typoAscent); debugPR.println("typoDescent: " + os2.typoDescent); debugPR.println("typoLineGap: " + os2.typoLineGap); debugPR.println("winAscent: " + os2.winAscent); debugPR.println("winDescent: " + os2.winDescent); debugPR.println("xHeight: " + os2.xHeight); debugPR.println("capHeight: " + os2.capHeight); } CmapTable cmap = (CmapTable)ttf.getByTableName("cmap"); if (cmap != null) { CmapSubtable cmapsub = cmap.getBestSubtable(); if (cmapsub != null) { int spg = cmapsub.getGlyphIndex(32); int nbspg = cmapsub.getGlyphIndex(160); if (spg != 0) debugPR.println("space.glyphId: " + spg); if (nbspg != 0) debugPR.println("nbsp.glyphId: " + nbspg); } } HmtxTable hmtx = (HmtxTable)ttf.getByTableName("hmtx"); if (hmtx != null) { for (int i = 0, n = hmtx.size(); i < n; i++) { debugPR.println("advanceWidth[" + i + "]: " + hmtx.get(i).advanceWidth); } } debugPR.flush(); debugPR.close(); for (int i = 0, n = cblc.size(); i < n; i++) { EblcBitmapSize ebs = cblc.get(i); String ebsName = "0000" + i; ebsName = ebsName.substring(ebsName.length() - 4); File ebsRoot = new File(outputRoot, ebsName); if (!ebsRoot.exists()) ebsRoot.mkdir(); File meta = new File(ebsRoot, "metadata.txt"); FileOutputStream metaOS = new FileOutputStream(meta); OutputStreamWriter metaWR = new OutputStreamWriter(metaOS, "UTF-8"); PrintWriter metaPR = new PrintWriter(metaWR, true); metaPR.println("indexSubTableArrayOffset: " + ebs.indexSubTableArrayOffset); metaPR.println("indexTablesSize: " + ebs.indexTablesSize); metaPR.println("numberOfIndexSubTables: " + ebs.numberOfIndexSubTables); metaPR.println("colorRef: " + ebs.colorRef); print(metaPR, "hori", ebs.hori); print(metaPR, "vert", ebs.vert); metaPR.println("startGlyphIndex: " + ebs.startGlyphIndex); metaPR.println("endGlyphIndex: " + ebs.endGlyphIndex); metaPR.println("ppemX: " + ebs.ppemX); metaPR.println("ppemY: " + ebs.ppemY); metaPR.println("bitDepth: " + ebs.bitDepth); metaPR.println("flags: " + ebs.flags); int index = 0; for (EblcIndexSubtable st : ebs) { metaPR.println(); metaPR.println("indexSubTable: " + index++); metaPR.println("firstGlyphIndex: " + st.header.firstGlyphIndex); metaPR.println("lastGlyphIndex: " + st.header.lastGlyphIndex); metaPR.println("additionalOffsetToIndexSubtable: " + st.header.additionalOffsetToIndexSubtable); metaPR.println("indexFormat: " + st.header.indexFormat); metaPR.println("imageFormat: " + st.header.imageFormat); metaPR.println("imageDataOffset: " + st.header.imageDataOffset); if (st instanceof EblcIndexSubtable1) { EblcIndexSubtable1 st1 = (EblcIndexSubtable1)st; StringBuffer sb = new StringBuffer("offsetArray:"); for (int offset : st1) { sb.append(" "); sb.append(offset); } metaPR.println(sb); } if (st instanceof EblcIndexSubtable2) { EblcIndexSubtable2 st2 = (EblcIndexSubtable2)st; metaPR.println("imageSize: " + st2.imageSize); print(metaPR, st2.bigMetrics); } if (st instanceof EblcIndexSubtable3) { EblcIndexSubtable3 st3 = (EblcIndexSubtable3)st; StringBuffer sb = new StringBuffer("offsetArray:"); for (int offset : st3) { sb.append(" "); sb.append(offset); } metaPR.println(sb); } if (st instanceof EblcIndexSubtable4) { EblcIndexSubtable4 st4 = (EblcIndexSubtable4)st; StringBuffer sb = new StringBuffer("glyphArray:"); for (EblcGlyphIdOffsetPair pair : st4) { sb.append(" "); sb.append(pair.glyphID); sb.append(","); sb.append(pair.offset); } metaPR.println(sb); } if (st instanceof EblcIndexSubtable5) { EblcIndexSubtable5 st5 = (EblcIndexSubtable5)st; metaPR.println("imageSize: " + st5.imageSize); print(metaPR, st5.bigMetrics); } EblcGlyphIdOffsetPair[] pairs = st.getGlyphIdOffsetPairs(); for (int j = 0, m = pairs.length - 1; j < m; j++) { EblcGlyphIdOffsetPair pair = pairs[j]; EbdtEntry e = cbdt.get(pair.offset); metaPR.println(); metaPR.println("glyph: " + pair.glyphID); metaPR.println("offset: " + pair.offset); if (e instanceof EbdtEntryFormat1) { EbdtEntryFormat1 e1 = (EbdtEntryFormat1)e; print(metaPR, e1.smallMetrics); metaPR.println("imageData: <" + e1.imageData.length + "b>"); } if (e instanceof EbdtEntryFormat2) { EbdtEntryFormat2 e2 = (EbdtEntryFormat2)e; print(metaPR, e2.smallMetrics); metaPR.println("imageData: <" + e2.imageData.length + "b>"); } if (e instanceof EbdtEntryFormat5) { EbdtEntryFormat5 e5 = (EbdtEntryFormat5)e; metaPR.println("imageData: <" + e5.imageData.length + "b>"); } if (e instanceof EbdtEntryFormat6) { EbdtEntryFormat6 e6 = (EbdtEntryFormat6)e; print(metaPR, e6.bigMetrics); metaPR.println("imageData: <" + e6.imageData.length + "b>"); } if (e instanceof EbdtEntryFormat7) { EbdtEntryFormat7 e7 = (EbdtEntryFormat7)e; print(metaPR, e7.bigMetrics); metaPR.println("imageData: <" + e7.imageData.length + "b>"); } if (e instanceof EbdtEntryFormat8) { EbdtEntryFormat8 e8 = (EbdtEntryFormat8)e; print(metaPR, e8.smallMetrics); StringBuffer sb = new StringBuffer("components:"); for (EbdtComponent c : e8) { sb.append(" "); sb.append(c.glyphID); sb.append(","); sb.append(c.xOffset); sb.append(","); sb.append(c.yOffset); } metaPR.println(sb); } if (e instanceof EbdtEntryFormat9) { EbdtEntryFormat9 e9 = (EbdtEntryFormat9)e; print(metaPR, e9.bigMetrics); StringBuffer sb = new StringBuffer("components:"); for (EbdtComponent c : e9) { sb.append(" "); sb.append(c.glyphID); sb.append(","); sb.append(c.xOffset); sb.append(","); sb.append(c.yOffset); } metaPR.println(sb); } if (e instanceof CbdtEntryFormat17) { CbdtEntryFormat17 e17 = (CbdtEntryFormat17)e; print(metaPR, e17.glyphMetrics); metaPR.println("imageData: <" + e17.imageData.length + "b>"); } if (e instanceof CbdtEntryFormat18) { CbdtEntryFormat18 e18 = (CbdtEntryFormat18)e; print(metaPR, e18.glyphMetrics); metaPR.println("imageData: <" + e18.imageData.length + "b>"); } if (e instanceof CbdtEntryFormat19) { CbdtEntryFormat19 e19 = (CbdtEntryFormat19)e; metaPR.println("imageData: <" + e19.imageData.length + "b>"); } metaPR.println("endGlyph"); if (e instanceof CbdtEntry) { File imageFile = new File(ebsRoot, "glyph_" + pair.glyphID + ".png"); FileOutputStream imageOS = new FileOutputStream(imageFile); imageOS.write(((CbdtEntry)e).imageData); imageOS.flush(); imageOS.close(); } } metaPR.println("endIndexSubTable"); } metaPR.flush(); metaPR.close(); } System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); } } } private static void print(PrintWriter pr, String prefix, SbitLineMetrics metrics) { pr.println(prefix + "Ascender: " + metrics.ascender); pr.println(prefix + "Descender: " + metrics.descender); pr.println(prefix + "WidthMax: " + metrics.widthMax); pr.println(prefix + "CaretSlopeNumerator: " + metrics.caretSlopeNumerator); pr.println(prefix + "CaretSlopeDenominator: " + metrics.caretSlopeDenominator); pr.println(prefix + "CaretOffset: " + metrics.caretOffset); pr.println(prefix + "MinOriginSB: " + metrics.minOriginSB); pr.println(prefix + "MinAdvanceSB: " + metrics.minAdvanceSB); pr.println(prefix + "MaxBeforeBL: " + metrics.maxBeforeBL); pr.println(prefix + "MinAfterBL: " + metrics.minAfterBL); } private static void print(PrintWriter pr, SbitSmallGlyphMetrics smallMetrics) { pr.println("height: " + smallMetrics.height); pr.println("width: " + smallMetrics.width); pr.println("bearingX: " + smallMetrics.bearingX); pr.println("bearingY: " + smallMetrics.bearingY); pr.println("advance: " + smallMetrics.advance); } private static void print(PrintWriter pr, SbitBigGlyphMetrics bigMetrics) { pr.println("height: " + bigMetrics.height); pr.println("width: " + bigMetrics.width); pr.println("horiBearingX: " + bigMetrics.horiBearingX); pr.println("horiBearingY: " + bigMetrics.horiBearingY); pr.println("horiAdvance: " + bigMetrics.horiAdvance); pr.println("vertBearingX: " + bigMetrics.vertBearingX); pr.println("vertBearingY: " + bigMetrics.vertBearingY); pr.println("vertAdvance: " + bigMetrics.vertAdvance); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ExtractSbix.java000077500000000000000000000036741506470510200315020ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import com.kreative.bitsnpicas.truetype.SbixEntry; import com.kreative.bitsnpicas.truetype.SbixSubtable; import com.kreative.bitsnpicas.truetype.SbixTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class ExtractSbix { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} for (String arg : args) { File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { byte[] data = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); SbixTable sbix = (SbixTable)ttf.getByTableName("sbix"); if (sbix == null) { System.out.println("no sbix table found."); } else { File outputRoot = new File(file.getParent(), file.getName() + ".sbix.d"); if (!outputRoot.exists()) outputRoot.mkdir(); for (SbixSubtable subtable : sbix) { File outputSubdir = new File(outputRoot, Integer.toString(subtable.ppem)); if (!outputSubdir.exists()) outputSubdir.mkdir(); for (int i = 0; i < subtable.size(); i++) { SbixEntry entry = subtable.get(i); if (entry.imageData != null && entry.imageData.length > 0) { String name = "glyph_" + Integer.toString(i); String extension = "." + entry.getImageTypeString().trim(); File outputFile = new File(outputSubdir, name + extension); FileOutputStream out = new FileOutputStream(outputFile); out.write(entry.imageData); out.flush(); out.close(); } } } System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ExtractSvg.java000066400000000000000000000057271506470510200313320ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.BitSet; import java.util.HashMap; import java.util.Map; import com.kreative.bitsnpicas.truetype.SvgTableEntry; import com.kreative.bitsnpicas.truetype.SvgTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class ExtractSvg { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} for (String arg : args) { File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { byte[] data = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); SvgTable svg = (SvgTable)ttf.getByTableName("SVG "); if (svg == null) { System.out.println("no svg table found."); } else { File outputRoot = new File(file.getParent(), file.getName() + ".svg.d"); if (!outputRoot.exists()) outputRoot.mkdir(); Map documents = new HashMap(); for (SvgTableEntry entry : svg) { if (entry.svgDocument.length > 0) { BitSet indices = documents.get(entry.svgDocument); if (indices == null) { indices = new BitSet(); documents.put(entry.svgDocument, indices); } int fromIndex = Math.min(entry.startGlyphID, entry.endGlyphID); int toIndex = Math.max(entry.startGlyphID, entry.endGlyphID) + 1; indices.set(fromIndex, toIndex); } } for (SvgTableEntry entry : svg) { if (documents.containsKey(entry.svgDocument)) { BitSet indices = documents.remove(entry.svgDocument); StringBuffer indexString = new StringBuffer(); int fromIndex = indices.nextSetBit(0); while (fromIndex >= 0) { int toIndex = indices.nextClearBit(fromIndex); if (indexString.length() > 0) { indexString.append("+"); } indexString.append(fromIndex); if (toIndex - 1 > fromIndex) { indexString.append("-"); indexString.append(toIndex - 1); } fromIndex = indices.nextSetBit(toIndex); } String name = "glyph_" + indexString.toString(); File outputFile = new File(outputRoot, name + ".svg"); copyAndClose(entry.getInputStream(), new FileOutputStream(outputFile)); } } System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); e.printStackTrace(); } } } private static void copyAndClose(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[65536]; int len; while ((len = in.read(buf)) >= 0) out.write(buf, 0, len); out.flush(); out.close(); in.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ImageToSvg.java000066400000000000000000000137721506470510200312440ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; public class ImageToSvg { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} boolean parsingOptions = true; int[] imageRect = new int[]{ 0, -700, 800, 800 }; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) { parsingOptions = false; } else if (arg.equals("-x") && argi < args.length) { imageRect[0] = parseInt(args[argi++]); } else if (arg.equals("-y") && argi < args.length) { imageRect[1] = parseInt(args[argi++]); } else if (arg.equals("-w") && argi < args.length) { imageRect[2] = parseInt(args[argi++]); } else if (arg.equals("-h") && argi < args.length) { imageRect[3] = parseInt(args[argi++]); } else if (arg.equals("-r") && (argi+4) <= args.length) { imageRect[0] = parseInt(args[argi++]); imageRect[1] = parseInt(args[argi++]); imageRect[2] = parseInt(args[argi++]); imageRect[3] = parseInt(args[argi++]); } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { File inputFile = new File(arg); String fileName = inputFile.getName(); int o = fileName.lastIndexOf('.'); if (o <= 0) continue; String extension = fileName.substring(o + 1); String mimeType = getMimeType(extension); if (mimeType == null) continue; String dataURI = createDataURI(inputFile, mimeType); if (dataURI == null) continue; File parentFile = inputFile.getParentFile(); String baseName = fileName.substring(0, o); String outputFileName = baseName + ".svg"; File outputFile = new File(parentFile, outputFileName); writeSVG(outputFile, dataURI, imageRect); } } } private static void printHelp() { System.out.println(); System.out.println("Usage:"); System.out.println(" java -jar BitsNPicas.jar imagetosvg "); System.out.println(); System.out.println("Options:"); System.out.println(" -x Set X origin of image."); System.out.println(" -y Set Y origin of image."); System.out.println(" -w Set width of image."); System.out.println(" -h Set height of image."); System.out.println(" -r Set image position and size."); System.out.println(" -- Treat remaining args as file names."); System.out.println(); } private static String createDataURI(File inputFile, String mimeType) { try { StringBuffer data = new StringBuffer("data:"); data.append(mimeType); data.append(";base64,"); OutputStream out = new Base64OutputStream(data); InputStream in = new FileInputStream(inputFile); byte[] buf = new byte[1048576]; int len; while ((len = in.read(buf)) >= 0) out.write(buf, 0, len); in.close(); out.flush(); out.close(); return data.toString(); } catch (IOException e) { System.err.println("Error reading " + inputFile.getAbsolutePath()); return null; } } private static void writeSVG(File outputFile, String dataURI, int[] rect) { try { FileOutputStream fos = new FileOutputStream(outputFile); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); PrintWriter pw = new PrintWriter(osw, true); pw.print(""); pw.print(""); pw.print(""); pw.flush(); pw.close(); } catch (IOException e) { System.err.println("Error writing " + outputFile.getAbsolutePath()); } } private static int parseInt(String s) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { return 0; } } private static String getMimeType(String ext) { if (ext.equalsIgnoreCase("bmp")) return "image/bmp"; if (ext.equalsIgnoreCase("gif")) return "image/gif"; if (ext.equalsIgnoreCase("jpe")) return "image/jpeg"; if (ext.equalsIgnoreCase("jpeg")) return "image/jpeg"; if (ext.equalsIgnoreCase("jpg")) return "image/jpeg"; if (ext.equalsIgnoreCase("png")) return "image/png"; if (ext.equalsIgnoreCase("tif")) return "image/tiff"; if (ext.equalsIgnoreCase("tiff")) return "image/tiff"; if (ext.equalsIgnoreCase("wbm")) return "image/vnd.wap.wbmp"; if (ext.equalsIgnoreCase("wbmp")) return "image/vnd.wap.wbmp"; if (ext.equalsIgnoreCase("webp")) return "image/webp"; return null; } private static class Base64OutputStream extends OutputStream { private final StringBuffer sb; public Base64OutputStream(StringBuffer sb) { this.sb = sb; } private int word = 0; private int count = 0; @Override public void write(int b) throws IOException { word <<= 8; word |= (b & 0xFF); count++; if (count >= 3) { writeWord(); word = 0; count = 0; } } @Override public void flush() throws IOException { if (count > 0) { for (int i = count; i < 3; i++) word <<= 8; writeWord(); } word = 0; count = 0; } @Override public void close() throws IOException { flush(); } private void writeWord() throws IOException { for (int m = 18, i = 0; i <= count; m -= 6, i++) { sb.append(b64e[(word >> m) & 0x3F]); } for (int i = count; i < 3; i++) { sb.append('='); } } private static final char[] b64e = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', }; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/InjectCbdt.java000066400000000000000000000412551506470510200312450ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.SortedMap; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.*; public class InjectCbdt { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} boolean removeGlyphs = true; for (String arg : args) { if (arg.equals("-g")) { removeGlyphs = false; continue; } if (arg.equals("-G")) { removeGlyphs = true; continue; } File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { File inputRoot = new File(file.getParent(), file.getName() + ".cbdt.d"); if (!(inputRoot.exists() && inputRoot.isDirectory())) { System.out.println("no cbdt directory found."); } else { byte[] data = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); CmapTable cmap = (CmapTable)ttf.getByTableName("cmap"); CmapSubtable cmapsub = (cmap == null) ? null : cmap.getBestSubtable(); PostTable post = (PostTable)ttf.getByTableName("post"); HheaTable hhea = (HheaTable)ttf.getByTableName("hhea"); EblcTable cblc = (EblcTable)ttf.getByTableName("CBLC"); if (cblc == null) { cblc = new EblcTable(SbitTableType.COLOR); ttf.add(cblc); } else { cblc.clear(); } EbdtTable cbdt = (EbdtTable)ttf.getByTableName("CBDT"); if (cbdt == null) { cbdt = new EbdtTable(SbitTableType.COLOR); ttf.add(cbdt); } else { cbdt.clear(); } for (File inputSubdir : inputRoot.listFiles()) { if (inputSubdir.isDirectory() && !inputSubdir.getName().startsWith(".")) { File meta = new File(inputSubdir, "metadata.txt"); EblcBitmapSize ebs = createBitmapSize(hhea); Map smallMetrics = new HashMap(); Map bigMetrics = new HashMap(); if (meta.isFile()) parseMetadata(meta, ebs, smallMetrics, bigMetrics, cmapsub, post); SortedMap entries = new TreeMap(); for (File inputFile : inputSubdir.listFiles()) { String name = inputFile.getName(); int o = name.lastIndexOf('.'); if (o > 0) { String extension = name.substring(o + 1); if ("png".equalsIgnoreCase(extension)) { name = name.substring(0, o); int glyphIndex = getGlyphIndex(name, cmapsub, post); if (glyphIndex > 0) { byte[] inputData = new byte[(int)inputFile.length()]; FileInputStream inIn = new FileInputStream(inputFile); inIn.read(inputData); inIn.close(); CbdtEntry entry = createCbdtEntry(smallMetrics, bigMetrics, glyphIndex); entry.imageData = inputData; entries.put(glyphIndex, entry); } } } } EblcIndexSubtable1 st = null; for (Map.Entry e : entries.entrySet()) { int gid = e.getKey(); if (ebs.startGlyphIndex <= 0 || gid < ebs.startGlyphIndex) ebs.startGlyphIndex = gid; if (ebs.endGlyphIndex <= 0 || gid > ebs.endGlyphIndex) ebs.endGlyphIndex = gid; CbdtEntry entry = e.getValue(); if (st != null && (st.header.lastGlyphIndex + 1) == gid && st.header.imageFormat == entry.format()) { st.header.lastGlyphIndex++; } else { ebs.add((st = new EblcIndexSubtable1())); st.header = new EblcIndexSubtableHeader(); st.header.firstGlyphIndex = gid; st.header.lastGlyphIndex = gid; st.header.indexFormat = 1; st.header.imageFormat = entry.format(); st.add(cbdt.getNextKey()); } int key = st.get(st.size() - 1); cbdt.put(key, entry); st.add(cbdt.getNextKey()); } cblc.add(ebs); } } cbdt.recalculate(cblc); if (removeGlyphs) { ttf.remove(ttf.getByTableName("loca")); ttf.remove(ttf.getByTableName("glyf")); ttf.remove(ttf.getByTableName("CFF ")); ttf.remove(ttf.getByTableName("CFF2")); } data = ttf.compile(); String ext = ttf.isOpenType() ? ".otf" : ".ttf"; File outputFile = new File(file.getParent(), file.getName() + ".cbdt" + ext); FileOutputStream out = new FileOutputStream(outputFile); out.write(data); out.flush(); out.close(); System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); } } } private static EblcBitmapSize createBitmapSize(HheaTable hhea) { EblcBitmapSize ebs = new EblcBitmapSize(); ebs.hori = new SbitLineMetrics(); ebs.vert = new SbitLineMetrics(); if (hhea != null) { ebs.hori.ascender = ebs.vert.ascender = hhea.ascent; ebs.hori.descender = ebs.vert.descender = hhea.descent; ebs.hori.widthMax = ebs.vert.widthMax = hhea.advanceWidthMax; ebs.ppemX = ebs.ppemY = hhea.ascent - hhea.descent; } else { ebs.hori.ascender = ebs.vert.ascender = 101; ebs.hori.descender = ebs.vert.descender = -27; ebs.hori.widthMax = ebs.vert.widthMax = 136; ebs.ppemX = ebs.ppemY = 109; } ebs.bitDepth = 32; ebs.flags = 1; return ebs; } private static void parseMetadata( File meta, EblcBitmapSize ebs, Map smallMetrics, Map bigMetrics, CmapSubtable cmap, PostTable post ) throws IOException { Scanner scan = new Scanner(new FileInputStream(meta), "UTF-8"); boolean inGlyph = false; int glyphId = 0; SbitSmallGlyphMetrics sgm = null; SbitBigGlyphMetrics bgm = null; boolean useBGM = false; while (scan.hasNextLine()) { String line = scan.nextLine().trim(); if (line.length() > 0 && !line.startsWith("#")) { String[] fields = line.split(":", 2); String key = fields[0].trim().toLowerCase(); String value = (fields.length > 1) ? fields[1].trim() : null; if (inGlyph) { if ("endglyph".equals(key)) { if (useBGM) bigMetrics.put(glyphId, bgm); else smallMetrics.put(glyphId, sgm); inGlyph = false; glyphId = 0; sgm = null; bgm = null; useBGM = false; } else if ("height".equals(key)) { try { sgm.height = bgm.height = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("width".equals(key)) { try { sgm.width = bgm.width = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("bearingx".equals(key)) { try { sgm.bearingX = Integer.parseInt(value); useBGM = false; } catch (NumberFormatException nfe) {} } else if ("bearingy".equals(key)) { try { sgm.bearingY = Integer.parseInt(value); useBGM = false; } catch (NumberFormatException nfe) {} } else if ("advance".equals(key)) { try { sgm.advance = Integer.parseInt(value); useBGM = false; } catch (NumberFormatException nfe) {} } else if ("horibearingx".equals(key)) { try { bgm.horiBearingX = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } else if ("horibearingy".equals(key)) { try { bgm.horiBearingY = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } else if ("horiadvance".equals(key)) { try { bgm.horiAdvance = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } else if ("vertbearingx".equals(key)) { try { bgm.vertBearingX = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } else if ("vertbearingy".equals(key)) { try { bgm.vertBearingY = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } else if ("vertadvance".equals(key)) { try { bgm.vertAdvance = Integer.parseInt(value); useBGM = true; } catch (NumberFormatException nfe) {} } } else { if ("glyph".equals(key)) { inGlyph = true; try { glyphId = Integer.parseInt(value); } catch (NumberFormatException nfe) { glyphId = getGlyphIndex(value, cmap, post); } sgm = new SbitSmallGlyphMetrics(); bgm = new SbitBigGlyphMetrics(); useBGM = false; } else if ("indexsubtablearrayoffset".equals(key)) { try { ebs.indexSubTableArrayOffset = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("indextablessize".equals(key)) { try { ebs.indexTablesSize = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("numberofindexsubtables".equals(key)) { try { ebs.numberOfIndexSubTables = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("colorref".equals(key)) { try { ebs.colorRef = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horiascender".equals(key)) { try { ebs.hori.ascender = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horidescender".equals(key)) { try { ebs.hori.descender = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horiwidthmax".equals(key)) { try { ebs.hori.widthMax = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horicaretslopenumerator".equals(key)) { try { ebs.hori.caretSlopeNumerator = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horicaretslopedenominator".equals(key)) { try { ebs.hori.caretSlopeDenominator = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horicaretoffset".equals(key)) { try { ebs.hori.caretOffset = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horiminoriginsb".equals(key)) { try { ebs.hori.minOriginSB = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horiminadvancesb".equals(key)) { try { ebs.hori.minAdvanceSB = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horimaxbeforebl".equals(key)) { try { ebs.hori.maxBeforeBL = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("horiminafterbl".equals(key)) { try { ebs.hori.minAfterBL = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertascender".equals(key)) { try { ebs.vert.ascender = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertdescender".equals(key)) { try { ebs.vert.descender = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertwidthmax".equals(key)) { try { ebs.vert.widthMax = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertcaretslopenumerator".equals(key)) { try { ebs.vert.caretSlopeNumerator = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertcaretslopedenominator".equals(key)) { try { ebs.vert.caretSlopeDenominator = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertcaretoffset".equals(key)) { try { ebs.vert.caretOffset = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertminoriginsb".equals(key)) { try { ebs.vert.minOriginSB = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertminadvancesb".equals(key)) { try { ebs.vert.minAdvanceSB = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertmaxbeforebl".equals(key)) { try { ebs.vert.maxBeforeBL = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("vertminafterbl".equals(key)) { try { ebs.vert.minAfterBL = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("startglyphindex".equals(key)) { try { ebs.startGlyphIndex = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("endglyphindex".equals(key)) { try { ebs.endGlyphIndex = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("ppemx".equals(key)) { try { ebs.ppemX = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("ppemy".equals(key)) { try { ebs.ppemY = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("bitdepth".equals(key)) { try { ebs.bitDepth = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } else if ("flags".equals(key)) { try { ebs.flags = Integer.parseInt(value); } catch (NumberFormatException nfe) {} } } } } scan.close(); } private static int getGlyphIndex(String s, CmapSubtable cmap, PostTable post) { if (s.startsWith("glyph_")) { try { return Integer.parseInt(s.substring(6)); } catch (NumberFormatException nfe) { return 0; } } if (s.startsWith("char_")) { if (cmap == null) { return 0; } else try { int ch = Integer.parseInt(s.substring(5), 16); return cmap.getGlyphIndex(ch); } catch (NumberFormatException nfe) { return 0; } } if (post == null) { return 0; } else { PostTableEntry pe = PostTableEntry.forCharacterName(unescape(s)); if (post.contains(pe)) { return post.indexOf(pe); } else { return 0; } } } private static String unescape(String s) { StringBuffer sb = new StringBuffer(); CharacterIterator i = new StringCharacterIterator(s); for (char ch = i.first(); ch != CharacterIterator.DONE; ch = i.next()) { switch (ch) { case '!': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('!'); else sb.append(Character.toLowerCase(ch)); break; case '^': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('^'); else sb.append(Character.toUpperCase(ch)); break; case '#': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('#'); else sb.append(Character.toTitleCase(ch)); break; case '=': ch = i.next(); switch (ch) { case CharacterIterator.DONE: sb.append('='); break; case 'A': case 'a': sb.append('\''); break; case 'B': case 'b': sb.append('\\'); break; case 'C': case 'c': sb.append(':'); break; case 'D': case 'd': sb.append('$'); break; case 'E': case 'e': sb.append('='); break; case 'F': case 'f': sb.append('/'); break; case 'G': case 'g': sb.append('>'); break; case 'H': case 'h': sb.append('?'); break; case 'I': case 'i': sb.append('['); break; case 'J': case 'j': sb.append(']'); break; case 'K': case 'k': sb.append(';'); break; case 'L': case 'l': sb.append('<'); break; case 'M': case 'm': sb.append('&'); break; case 'N': case 'n': sb.append('+'); break; case 'O': case 'o': sb.append('#'); break; case 'P': case 'p': sb.append('%'); break; case 'Q': case 'q': sb.append('"'); break; case 'R': case 'r': sb.append('^'); break; case 'S': case 's': sb.append('*'); break; case 'T': case 't': sb.append('~'); break; case 'U': case 'u': sb.append('_'); break; case 'V': case 'v': sb.append('|'); break; case 'W': case 'w': sb.append('`'); break; case 'X': case 'x': sb.append('!'); break; case 'Y': case 'y': sb.append('{'); break; case 'Z': case 'z': sb.append('}'); break; default: sb.append(ch); break; } break; default: sb.append(ch); break; } } return sb.toString(); } private static CbdtEntry createCbdtEntry( Map smallMetrics, Map bigMetrics, int glyphIndex ) { if (smallMetrics.containsKey(glyphIndex)) { CbdtEntryFormat17 e17 = new CbdtEntryFormat17(); e17.glyphMetrics = smallMetrics.get(glyphIndex); return e17; } else if (bigMetrics.containsKey(glyphIndex)) { CbdtEntryFormat18 e18 = new CbdtEntryFormat18(); e18.glyphMetrics = bigMetrics.get(glyphIndex); return e18; } else if (smallMetrics.containsKey(0)) { CbdtEntryFormat17 e17 = new CbdtEntryFormat17(); e17.glyphMetrics = smallMetrics.get(0); return e17; } else if (bigMetrics.containsKey(0)) { CbdtEntryFormat18 e18 = new CbdtEntryFormat18(); e18.glyphMetrics = bigMetrics.get(0); return e18; } else { return new CbdtEntryFormat19(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/InjectSbix.java000077500000000000000000000203501506470510200312720ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.HashMap; import java.util.Map; import com.kreative.bitsnpicas.truetype.CmapSubtable; import com.kreative.bitsnpicas.truetype.CmapTable; import com.kreative.bitsnpicas.truetype.GlyfTable; import com.kreative.bitsnpicas.truetype.HeadTable; import com.kreative.bitsnpicas.truetype.LocaTable; import com.kreative.bitsnpicas.truetype.MaxpTable; import com.kreative.bitsnpicas.truetype.PostTable; import com.kreative.bitsnpicas.truetype.PostTableEntry; import com.kreative.bitsnpicas.truetype.SbixEntry; import com.kreative.bitsnpicas.truetype.SbixSubtable; import com.kreative.bitsnpicas.truetype.SbixTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class InjectSbix { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} for (String arg : args) { File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { File inputRoot = new File(file.getParent(), file.getName() + ".sbix.d"); if (!(inputRoot.exists() && inputRoot.isDirectory())) { System.out.println("no sbix directory found."); } else { byte[] data = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); CmapTable cmap = (CmapTable)ttf.getByTableName("cmap"); CmapSubtable cmapsub = (cmap == null) ? null : cmap.getBestSubtable(); PostTable post = (PostTable)ttf.getByTableName("post"); MaxpTable maxp = (MaxpTable)ttf.getByTableName("maxp"); HeadTable head = (HeadTable)ttf.getByTableName("head"); GlyfTable glyf = (GlyfTable)ttf.getByTableName("glyf"); LocaTable loca = (LocaTable)ttf.getByTableName("loca"); SbixTable sbix = (SbixTable)ttf.getByTableName("sbix"); if (sbix == null) { sbix = new SbixTable(); ttf.add(sbix); } else { sbix.clear(); } for (File inputSubdir : inputRoot.listFiles()) { try { int ppem = Integer.parseInt(inputSubdir.getName()); SbixSubtable subtable = new SbixSubtable(); subtable.ppem = ppem; sbix.add(subtable); Map entries = new HashMap(); for (File inputFile : inputSubdir.listFiles()) { String name = inputFile.getName(); int o = name.lastIndexOf('.'); if (o > 0) { String extension = name.substring(o + 1); name = name.substring(0, o); int glyphIndex = getGlyphIndex(name, cmapsub, post); if (glyphIndex > 0) { byte[] inputData = new byte[(int)inputFile.length()]; FileInputStream inIn = new FileInputStream(inputFile); inIn.read(inputData); inIn.close(); SbixEntry e = new SbixEntry(); e.setImageTypeString(extension); e.imageData = inputData; entries.put(glyphIndex, e); } } } for (int i = 0; i < maxp.numGlyphs; i++) { if (entries.containsKey(i)) { SbixEntry e = entries.get(i); if (glyf != null) { GlyfInfo g = rewriteGlyf(glyf.get(i)); e.offsetX = g.xMin * ppem / head.unitsPerEm; e.offsetY = g.yMin * ppem / head.unitsPerEm; glyf.set(i, g.data); } subtable.add(e); } else { subtable.add(new SbixEntry()); } } } catch (NumberFormatException nfe) { continue; } } if (glyf != null && loca != null) { loca.clear(); int currentLocation = 0; for (int i = 0; i < maxp.numGlyphs; i++) { loca.add(currentLocation); currentLocation += glyf.get(i).length; } loca.add(currentLocation); } data = ttf.compile(); String ext = ttf.isOpenType() ? ".otf" : ".ttf"; File outputFile = new File(file.getParent(), file.getName() + ".sbix" + ext); FileOutputStream out = new FileOutputStream(outputFile); out.write(data); out.flush(); out.close(); System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); } } } private static class GlyfInfo { public int xMin, yMin, xMax, yMax; public byte[] data; } private static GlyfInfo rewriteGlyf(byte[] data) { GlyfInfo info = new GlyfInfo(); try { ByteArrayInputStream in = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(in); din.readShort(); info.xMin = din.readShort(); info.yMin = din.readShort(); info.xMax = din.readShort(); info.yMax = din.readShort(); din.close(); in.close(); ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(out); dout.writeShort(0); dout.writeShort(info.xMin); dout.writeShort(info.yMin); dout.writeShort(info.xMax); dout.writeShort(info.yMax); dout.writeShort(0); dout.flush(); out.flush(); dout.close(); out.close(); info.data = out.toByteArray(); } catch (IOException ioe) { info.data = data; } return info; } private static int getGlyphIndex(String s, CmapSubtable cmap, PostTable post) { if (s.startsWith("glyph_")) { try { return Integer.parseInt(s.substring(6)); } catch (NumberFormatException nfe) { return 0; } } if (s.startsWith("char_")) { if (cmap == null) { return 0; } else try { int ch = Integer.parseInt(s.substring(5), 16); return cmap.getGlyphIndex(ch); } catch (NumberFormatException nfe) { return 0; } } if (post == null) { return 0; } else { PostTableEntry pe = PostTableEntry.forCharacterName(unescape(s)); if (post.contains(pe)) { return post.indexOf(pe); } else { return 0; } } } private static String unescape(String s) { StringBuffer sb = new StringBuffer(); CharacterIterator i = new StringCharacterIterator(s); for (char ch = i.first(); ch != CharacterIterator.DONE; ch = i.next()) { switch (ch) { case '!': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('!'); else sb.append(Character.toLowerCase(ch)); break; case '^': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('^'); else sb.append(Character.toUpperCase(ch)); break; case '#': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('#'); else sb.append(Character.toTitleCase(ch)); break; case '=': ch = i.next(); switch (ch) { case CharacterIterator.DONE: sb.append('='); break; case 'A': case 'a': sb.append('\''); break; case 'B': case 'b': sb.append('\\'); break; case 'C': case 'c': sb.append(':'); break; case 'D': case 'd': sb.append('$'); break; case 'E': case 'e': sb.append('='); break; case 'F': case 'f': sb.append('/'); break; case 'G': case 'g': sb.append('>'); break; case 'H': case 'h': sb.append('?'); break; case 'I': case 'i': sb.append('['); break; case 'J': case 'j': sb.append(']'); break; case 'K': case 'k': sb.append(';'); break; case 'L': case 'l': sb.append('<'); break; case 'M': case 'm': sb.append('&'); break; case 'N': case 'n': sb.append('+'); break; case 'O': case 'o': sb.append('#'); break; case 'P': case 'p': sb.append('%'); break; case 'Q': case 'q': sb.append('"'); break; case 'R': case 'r': sb.append('^'); break; case 'S': case 's': sb.append('*'); break; case 'T': case 't': sb.append('~'); break; case 'U': case 'u': sb.append('_'); break; case 'V': case 'v': sb.append('|'); break; case 'W': case 'w': sb.append('`'); break; case 'X': case 'x': sb.append('!'); break; case 'Y': case 'y': sb.append('{'); break; case 'Z': case 'z': sb.append('}'); break; default: sb.append(ch); break; } break; default: sb.append(ch); break; } } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/InjectSvg.java000066400000000000000000000241551506470510200311300ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.BitSet; import java.util.Collections; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.kreative.bitsnpicas.truetype.CmapSubtable; import com.kreative.bitsnpicas.truetype.CmapTable; import com.kreative.bitsnpicas.truetype.PostTable; import com.kreative.bitsnpicas.truetype.PostTableEntry; import com.kreative.bitsnpicas.truetype.SvgTable; import com.kreative.bitsnpicas.truetype.SvgTableEntry; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class InjectSvg { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} // Note: Microsoft claims the SVG-in-OpenType specification supports // gzip-compressed SVG glyphs, and the availability of a version of // EmojiOne with gzip-compressed SVG glyphs appears to back this up. // However, I could not find any mention of gzip support in the W3C // specification, and I was unable to get fonts with gzip-compressed // SVG glyphs to work even in the latest version of Firefox (50.1.0). boolean compressed = false; for (String arg : args) { if (arg.equals("-z")) { compressed = true; continue; } if (arg.equals("-Z")) { compressed = false; continue; } File file = new File(arg); System.out.print("Processing " + file.getAbsolutePath() + "... "); try { File inputRoot = new File(file.getParent(), file.getName() + ".svg.d"); if (!(inputRoot.exists() && inputRoot.isDirectory())) { System.out.println("no svg directory found."); } else { ByteArrayOutputStream inData = new ByteArrayOutputStream(); copyAndClose(new FileInputStream(file), inData); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(inData.toByteArray()); CmapTable cmap = (CmapTable)ttf.getByTableName("cmap"); CmapSubtable cmapsub = (cmap == null) ? null : cmap.getBestSubtable(); PostTable post = (PostTable)ttf.getByTableName("post"); SvgTable svg = (SvgTable)ttf.getByTableName("SVG "); if (svg == null) { svg = new SvgTable(); ttf.add(svg); } else { svg.clear(); } for (File inputFile : inputRoot.listFiles()) { String name = inputFile.getName(); int o = name.lastIndexOf('.'); if (o <= 0) continue; String extension = name.substring(o + 1); if (!extension.equalsIgnoreCase("svg")) continue; name = name.substring(0, o); BitSet indices = getGlyphIndices(name, cmapsub, post); if (indices.isEmpty()) continue; ByteArrayOutputStream svgData = new ByteArrayOutputStream(); copyAndClose(new FileInputStream(inputFile), svgData); byte[] document = null; int fromIndex = indices.nextSetBit(0); while (fromIndex >= 0) { int toIndex = indices.nextClearBit(fromIndex); SvgTableEntry e = new SvgTableEntry(); e.startGlyphID = fromIndex; e.endGlyphID = toIndex - 1; if (document == null) { OutputStream out = e.getOutputStream(compressed); out.write(rewriteEntryData(svgData.toByteArray(), indices, cmapsub, post)); out.flush(); out.close(); document = e.svgDocument; } else { e.svgDocument = document; } svg.add(e); fromIndex = indices.nextSetBit(toIndex); } } Collections.sort(svg); byte[] outData = ttf.compile(); String ext = ttf.isOpenType() ? ".otf" : ".ttf"; File outputFile = new File(file.getParent(), file.getName() + ".svg" + ext); FileOutputStream out = new FileOutputStream(outputFile); out.write(outData); out.flush(); out.close(); System.out.println("done."); } } catch (Exception e) { System.out.println("failed (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")."); } } } private static final Pattern GLYPH_ID_PATTERN = Pattern.compile("([\"']glyph)\\{\\{\\{([A-Za-z0-9_.:+-]+)\\}\\}\\}([\"'])"); private static byte[] rewriteEntryData(byte[] data, BitSet indices, CmapSubtable cmap, PostTable post) { try { StringBuffer rs = new StringBuffer(); String ss = new String(data, "UTF-8"); Matcher m = GLYPH_ID_PATTERN.matcher(ss); while (m.find()) { int n = getGlyphIndex(m.group(2), indices, cmap, post); String r = (n > 0) ? (m.group(1) + n + m.group(3)) : m.group(); m.appendReplacement(rs, r); } m.appendTail(rs); return rs.toString().getBytes("UTF-8"); } catch (IOException e) { return data; } } private static final Pattern G_PATTERN = Pattern.compile("^[Gg][:+]"); private static final Pattern C_PATTERN = Pattern.compile("^[CcUu][:+]"); private static final Pattern N_PATTERN = Pattern.compile("^[NnPp][:+]"); private static int getGlyphIndex(String s, BitSet indices, CmapSubtable cmap, PostTable post) { if (s.startsWith("glyph_")) { try { return Integer.parseInt(s.substring(6)); } catch (NumberFormatException nfe) { return 0; } } if (s.startsWith("char_")) { if (cmap == null) return 0; try { return cmap.getGlyphIndex(Integer.parseInt(s.substring(5), 16)); } catch (NumberFormatException nfe) { return 0; } } if (G_PATTERN.matcher(s).find()) { try { return Integer.parseInt(s.substring(2)); } catch (NumberFormatException nfe) { return 0; } } if (C_PATTERN.matcher(s).find()) { if (cmap == null) return 0; try { return cmap.getGlyphIndex(Integer.parseInt(s.substring(2), 16)); } catch (NumberFormatException nfe) { return 0; } } if (N_PATTERN.matcher(s).find()) { if (post == null) return 0; PostTableEntry pe = PostTableEntry.forCharacterName(s.substring(2)); return post.contains(pe) ? post.indexOf(pe) : 0; } try { int i = Integer.parseInt(s); if (i < 0) return 0; int fromIndex = indices.nextSetBit(0); while (fromIndex >= 0) { int toIndex = indices.nextClearBit(fromIndex); int length = toIndex - fromIndex; if (i < length) return fromIndex + i; else i -= length; fromIndex = indices.nextSetBit(toIndex); } return 0; } catch (NumberFormatException nfe) { if (post == null) return 0; PostTableEntry pe = PostTableEntry.forCharacterName(s); return post.contains(pe) ? post.indexOf(pe) : 0; } } private static BitSet getGlyphIndices(String s, CmapSubtable cmap, PostTable post) { if (s.startsWith("glyph_")) { BitSet indices = new BitSet(); String[] ranges = s.substring(6).split("[+]"); for (String range : ranges) { try { String[] r = range.split("[-_]", 2); int a = Integer.parseInt(r[0]); int b = (r.length > 1) ? Integer.parseInt(r[1]) : a; int fromIndex = Math.min(a, b); int toIndex = Math.max(a, b) + 1; indices.set(fromIndex, toIndex); } catch (NumberFormatException nfe) { continue; } } return indices; } if (s.startsWith("char_")) { BitSet indices = new BitSet(); if (cmap != null) { String[] ranges = s.substring(5).split("[+]"); for (String range : ranges) { try { String[] r = range.split("[-_]", 2); int a = Integer.parseInt(r[0], 16); int b = (r.length > 1) ? Integer.parseInt(r[1], 16) : a; int fromIndex = Math.min(a, b); int toIndex = Math.max(a, b) + 1; for (int i = fromIndex; i < toIndex; i++) { indices.set(cmap.getGlyphIndex(i)); } } catch (NumberFormatException nfe) { continue; } } } return indices; } BitSet indices = new BitSet(); if (post != null) { PostTableEntry pe = PostTableEntry.forCharacterName(unescape(s)); if (post.contains(pe)) indices.set(post.indexOf(pe)); } return indices; } private static String unescape(String s) { StringBuffer sb = new StringBuffer(); CharacterIterator i = new StringCharacterIterator(s); for (char ch = i.first(); ch != CharacterIterator.DONE; ch = i.next()) { switch (ch) { case '!': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('!'); else sb.append(Character.toLowerCase(ch)); break; case '^': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('^'); else sb.append(Character.toUpperCase(ch)); break; case '#': ch = i.next(); if (ch == CharacterIterator.DONE) sb.append('#'); else sb.append(Character.toTitleCase(ch)); break; case '=': ch = i.next(); switch (ch) { case CharacterIterator.DONE: sb.append('='); break; case 'A': case 'a': sb.append('\''); break; case 'B': case 'b': sb.append('\\'); break; case 'C': case 'c': sb.append(':'); break; case 'D': case 'd': sb.append('$'); break; case 'E': case 'e': sb.append('='); break; case 'F': case 'f': sb.append('/'); break; case 'G': case 'g': sb.append('>'); break; case 'H': case 'h': sb.append('?'); break; case 'I': case 'i': sb.append('['); break; case 'J': case 'j': sb.append(']'); break; case 'K': case 'k': sb.append(';'); break; case 'L': case 'l': sb.append('<'); break; case 'M': case 'm': sb.append('&'); break; case 'N': case 'n': sb.append('+'); break; case 'O': case 'o': sb.append('#'); break; case 'P': case 'p': sb.append('%'); break; case 'Q': case 'q': sb.append('"'); break; case 'R': case 'r': sb.append('^'); break; case 'S': case 's': sb.append('*'); break; case 'T': case 't': sb.append('~'); break; case 'U': case 'u': sb.append('_'); break; case 'V': case 'v': sb.append('|'); break; case 'W': case 'w': sb.append('`'); break; case 'X': case 'x': sb.append('!'); break; case 'Y': case 'y': sb.append('{'); break; case 'Z': case 'z': sb.append('}'); break; default: sb.append(ch); break; } break; default: sb.append(ch); break; } } return sb.toString(); } private static void copyAndClose(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[65536]; int len; while ((len = in.read(buf)) >= 0) out.write(buf, 0, len); out.flush(); out.close(); in.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/Main.java000066400000000000000000000064321506470510200301160ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.util.Arrays; import java.util.List; import com.kreative.bitsnpicas.puaa.PuaaCompiler; import com.kreative.bitsnpicas.puaa.PuaaDecompiler; import com.kreative.bitsnpicas.puaa.PuaaLookup; public class Main { public static void main(String[] args) { if (args.length == 0) { com.kreative.bitsnpicas.edit.Main.main(args); } else { String arg0 = args[0].toLowerCase(); List arga = Arrays.asList(args); arga = arga.subList(1, arga.size()); args = arga.toArray(new String[arga.size()]); if (arg0.equals("edit")) { com.kreative.bitsnpicas.edit.Main.main(args); } else if (arg0.equals("convertbitmap")) { ConvertBitmap.main(args); } else if (arg0.equals("viewbitmap")) { ViewFont.main(args); } else if (arg0.equals("extractcbdt")) { ExtractCbdt.main(args); } else if (arg0.equals("injectcbdt")) { InjectCbdt.main(args); } else if (arg0.equals("extractsbix")) { ExtractSbix.main(args); } else if (arg0.equals("injectsbix")) { InjectSbix.main(args); } else if (arg0.equals("extractsvg")) { ExtractSvg.main(args); } else if (arg0.equals("injectsvg")) { InjectSvg.main(args); } else if (arg0.equals("imagetosvg")) { ImageToSvg.main(args); } else if (arg0.equals("splitsuit")) { SplitSuit.main(args); } else if (arg0.equals("mergesuit")) { MergeSuit.main(args); } else if (arg0.equals("splitgeos")) { SplitGEOS.main(args); } else if (arg0.equals("mergegeos")) { MergeGEOS.main(args); } else if (arg0.equals("injectpuaa")) { PuaaCompiler.main(args); } else if (arg0.equals("extractpuaa")) { PuaaDecompiler.main(args); } else if (arg0.equals("lookuppuaa")) { PuaaLookup.main(args); } else if (arg0.equals("debugttf")) { DebugTTF.main(args); } else { printHelp(); } } } private static void printHelp() { System.out.println(); System.out.println("Usage:"); System.out.println(" java -jar BitsNPicas.jar edit "); System.out.println(" java -jar BitsNPicas.jar convertbitmap "); System.out.println(" java -jar BitsNPicas.jar viewbitmap "); System.out.println(" java -jar BitsNPicas.jar extractcbdt "); System.out.println(" java -jar BitsNPicas.jar injectcbdt "); System.out.println(" java -jar BitsNPicas.jar extractsbix "); System.out.println(" java -jar BitsNPicas.jar injectsbix "); System.out.println(" java -jar BitsNPicas.jar extractsvg "); System.out.println(" java -jar BitsNPicas.jar injectsvg "); System.out.println(" java -jar BitsNPicas.jar imagetosvg "); System.out.println(" java -jar BitsNPicas.jar splitsuit "); System.out.println(" java -jar BitsNPicas.jar mergesuit "); System.out.println(" java -jar BitsNPicas.jar splitgeos "); System.out.println(" java -jar BitsNPicas.jar mergegeos "); System.out.println(" java -jar BitsNPicas.jar extractpuaa "); System.out.println(" java -jar BitsNPicas.jar injectpuaa "); System.out.println(" java -jar BitsNPicas.jar lookuppuaa "); System.out.println(" java -jar BitsNPicas.jar debugttf "); System.out.println(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/MergeGEOS.java000066400000000000000000000052011506470510200307400ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class MergeGEOS { public static void main(String[] args) { if (args.length == 0) { printHelp(); } else { boolean processingOptions = true; Map families = new HashMap(); File outputDir = new File("."); int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingOptions && arg.startsWith("-")) { if (arg.equals("--")) { processingOptions = false; } else if (arg.equals("-d") && argi < args.length) { outputDir = new File(args[argi++]); } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { try { System.out.print(arg + "..."); File file = new File(arg); DataInputStream in = new DataInputStream(new FileInputStream(file)); GEOSFontFile inFont = new GEOSFontFile(in); in.close(); if (inFont.isValid()) { String family = inFont.getFontName(); if (families.containsKey(family)) { GEOSFontFile outFont = families.get(family); for (int pointSize : inFont.getFontPointSizes()) { outFont.setFontPointSize(pointSize, inFont.getFontPointSize(pointSize)); } } else { families.put(family, inFont); } System.out.println(" READ"); } else { System.out.println(" ERROR: Not a GEOS font file."); } } catch (IOException e) { System.out.println(" ERROR: " + e.getClass().getSimpleName() + ": " + e.getMessage()); } } } for (Map.Entry e : families.entrySet()) { try { System.out.print(e.getKey() + "..."); GEOSFontFile outFont = e.getValue(); outFont.recalculate(); File outfile = new File(outputDir, e.getKey() + ".cvt"); DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile)); outFont.write(out); out.flush(); out.close(); System.out.println(" DONE"); } catch (IOException ioe) { System.out.println(" ERROR: " + ioe.getClass().getSimpleName() + ": " + ioe.getMessage()); } } } } private static void printHelp() { System.out.println("MergeGEOS - Merge GEOS font files of the same family into a single file."); System.out.println(" -d Specify directory for output files."); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/MergeSuit.java000066400000000000000000000063511506470510200311360ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.IOException; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.mover.MoverFile; import com.kreative.unicode.ttflib.DfontFile; public class MergeSuit { public static void main(String[] args) { if (args.length == 0) { printHelp(); } else { boolean processingOptions = true; File outputFile = null; boolean inRes; try { inRes = System.getProperty("os.name").toUpperCase().contains("MAC OS"); } catch (Exception e) { inRes = false; } DfontFile outrp = new DfontFile(); MoverFile outmf; try { outmf = new MoverFile(outrp); } catch (IOException e) { e.printStackTrace(); return; } int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingOptions && arg.startsWith("-")) { if (arg.equals("--")) { processingOptions = false; } else if (arg.equals("-o") && argi < args.length) { outputFile = new File(args[argi++]); } else if (arg.equals("-D")) { inRes = false; } else if (arg.equals("-R")) { inRes = true; } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { try { System.out.print(arg + "..."); File file = new File(arg); File rsrc = new File(new File(file, "..namedfork"), "rsrc"); DfontFile inrp; int count = 0; if ((inrp = open(file)) != null) count += process(outmf, inrp); if ((inrp = open(rsrc)) != null) count += process(outmf, inrp); System.out.println((count > 0) ? " READ" : " ERROR: No items found."); } catch (IOException e) { System.out.println(" ERROR: " + e); } } } if (outmf.isEmpty()) { System.out.println("No items found."); return; } if (outputFile == null) { if (outmf.size() == 1) { String name = outmf.get(0).name; outputFile = new File(inRes ? name : (name + ".dfont")); } else { String name = "Untitled Suitcase"; outputFile = new File(inRes ? name : (name + ".dfont")); } } try { System.out.print(outputFile.getName() + "..."); if (inRes) { outputFile.createNewFile(); outrp.write(new File(new File(outputFile, "..namedfork"), "rsrc")); MacUtility.setTypeAndCreator(outputFile, "FFIL", "DMOV"); } else { outrp.write(outputFile); } System.out.println(" DONE"); } catch (IOException ioe) { System.out.println(" ERROR: " + ioe); } } } private static DfontFile open(File file) { try { return new DfontFile(file); } catch (IOException ioe) { return null; } } private static int process(MoverFile outmf, DfontFile inrp) throws IOException { MoverFile inmf = new MoverFile(inrp); for (int i = 0, n = inmf.size(); i < n; i++) { outmf.add(inmf.get(i)); } return inmf.size(); } private static void printHelp() { System.out.println("MergeSuit - Merge Macintosh suitcase and mover files into a single suitcase."); System.out.println(" -o Specify output file."); System.out.println(" -D Write to data fork. (Default on non-Mac OS systems.)"); System.out.println(" -R Write to resource fork. (Default on Mac OS systems.)"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/SplitGEOS.java000066400000000000000000000045571506470510200310110ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import com.kreative.bitsnpicas.geos.GEOSFontFile; public class SplitGEOS { public static void main(String[] args) { if (args.length == 0) { printHelp(); } else { boolean processingOptions = true; File outputDir = null; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingOptions && arg.startsWith("-")) { if (arg.equals("--")) { processingOptions = false; } else if (arg.equals("-d") && argi < args.length) { outputDir = new File(args[argi++]); } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { try { System.out.print(arg + "..."); File file = new File(arg); DataInputStream in = new DataInputStream(new FileInputStream(file)); GEOSFontFile inFont = new GEOSFontFile(in); in.close(); if (inFont.isValid()) { for (int pointSize : inFont.getFontPointSizes()) { GEOSFontFile outFont = new GEOSFontFile(); outFont.setFontName(inFont.getFontName()); outFont.setClassTextString(inFont.getClassTextString()); outFont.setDescriptionString(inFont.getDescriptionString()); outFont.setFontID(inFont.getFontID()); outFont.setFontPointSize(pointSize, inFont.getFontPointSize(pointSize)); outFont.recalculate(); File outfile = new File( ((outputDir != null) ? outputDir : file.getParentFile()), (inFont.getFontName() + "." + pointSize + ".cvt") ); DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile)); outFont.write(out); out.flush(); out.close(); } System.out.println(" DONE"); } else { System.out.println(" ERROR: Not a GEOS font file."); } } catch (IOException e) { System.out.println(" ERROR: " + e.getClass().getSimpleName() + ": " + e.getMessage()); } } } } } private static void printHelp() { System.out.println("SplitGEOS - Split GEOS font files into individual point sizes."); System.out.println(" -d Specify directory for output files."); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/SplitSuit.java000066400000000000000000000056361506470510200311770ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.IOException; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.mover.MoverFile; import com.kreative.bitsnpicas.mover.ResourceBundle; import com.kreative.unicode.ttflib.DfontFile; public class SplitSuit { public static void main(String[] args) { if (args.length == 0) { printHelp(); } else { boolean processingOptions = true; File outputDir = null; boolean inRes; try { inRes = System.getProperty("os.name").toUpperCase().contains("MAC OS"); } catch (Exception e) { inRes = false; } int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingOptions && arg.startsWith("-")) { if (arg.equals("--")) { processingOptions = false; } else if (arg.equals("-d") && argi < args.length) { outputDir = new File(args[argi++]); } else if (arg.equals("-D")) { inRes = false; } else if (arg.equals("-R")) { inRes = true; } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { try { System.out.print(arg + "..."); File file = new File(arg); File rsrc = new File(new File(file, "..namedfork"), "rsrc"); File parent = ((outputDir != null) ? outputDir : file.getParentFile()); DfontFile rp; int count = 0; if ((rp = open(file)) != null) count += process(parent, inRes, rp); if ((rp = open(rsrc)) != null) count += process(parent, inRes, rp); System.out.println((count > 0) ? " DONE" : " ERROR: No items found."); } catch (IOException e) { System.out.println(" ERROR: " + e); } } } } } private static DfontFile open(File file) { try { return new DfontFile(file); } catch (IOException ioe) { return null; } } private static int process(File parent, boolean inRes, DfontFile rp) throws IOException { MoverFile mf = new MoverFile(rp); for (int i = 0, n = mf.size(); i < n; i++) { export(parent, inRes, mf.get(i)); } return mf.size(); } private static void export(File parent, boolean inRes, ResourceBundle rb) throws IOException { DfontFile rp = new DfontFile(); MoverFile mf = new MoverFile(rp); mf.add(rb); if (inRes) { File file = new File(parent, rb.name); file.createNewFile(); rp.write(new File(new File(file, "..namedfork"), "rsrc")); MacUtility.setTypeAndCreator(file, rb.moverType, "movr"); } else { rp.write(new File(parent, rb.name + ".dfont")); } } private static void printHelp() { System.out.println("SplitSuit - Split Macintosh suitcase files into separate mover files."); System.out.println(" -d Specify directory for output files."); System.out.println(" -D Write to data fork. (Default on non-Mac OS systems.)"); System.out.println(" -R Write to resource fork. (Default on Mac OS systems.)"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/TTFRewriteTest.java000066400000000000000000000037301506470510200320670ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class TTFRewriteTest { public static void main(String[] args) { boolean interpret = true; boolean writeDiff = false; boolean parseOptions = true; for (String arg : args) { if (parseOptions && arg.startsWith("-")) { if (arg.equals("--")) { parseOptions = false; } else if (arg.equals("-i")) { interpret = true; } else if (arg.equals("-n")) { interpret = false; } else if (arg.equals("-w")) { writeDiff = true; } else if (arg.equals("-q")) { writeDiff = false; } else { System.err.println("Unknown option: " + arg); } } else { File file = new File(arg); System.out.print("Testing " + file.getName() + "..."); try { if (rewriteTest(file, interpret, writeDiff)) { System.out.println(" SAME"); } else { System.out.println(" DIFF"); } } catch (IOException e) { System.out.println(" ERROR: " + e); } } } } public static boolean rewriteTest(File file, boolean interpret, boolean writeDiff) throws IOException { long length = file.length(); if (length < 12) throw new IOException("file too small"); if (length > Integer.MAX_VALUE) throw new IOException("file too large"); byte[] originalData = new byte[(int)length]; FileInputStream in = new FileInputStream(file); in.read(originalData); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.interpret = interpret; ttf.decompile(originalData); byte[] rewrittenData = ttf.compile(); if (Arrays.equals(originalData, rewrittenData)) return true; if (writeDiff) { File diff = new File(file.getName() + ".diff"); FileOutputStream out = new FileOutputStream(diff); out.write(rewrittenData); out.flush(); out.close(); } return false; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/main/ViewFont.java000077500000000000000000000100161506470510200307670ustar00rootroot00000000000000package com.kreative.bitsnpicas.main; import java.awt.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; import com.kreative.bitsnpicas.*; public class ViewFont extends JFrame { private static final long serialVersionUID = 1; public static void main(String[] args) { BitmapInputOptions o = new BitmapInputOptions(); for (String arg : args) { try { File file = new File(arg); BitmapInputFormat format = BitmapInputFormat.forFile(file); if (format == null) { System.err.println("Unknown type: " + arg); } else { if (format.macResFork) { file = new File(new File(file, "..namedfork"), "rsrc"); } BitmapFont[] fonts = format.createImporter(o).importFont(file); if (fonts == null || fonts.length == 0) { System.err.println("No fonts found: " + arg); } else { for (BitmapFont font : fonts) new ViewFont(font); } } } catch (IOException e) { System.err.println("Could not load " + arg); } } } private final BitmapFont myFont; private final SpinnerNumberModel scale; private final JComponent alphaPanel; private final JTextArea textArea; private final JComponent textPanel; public ViewFont(BitmapFont bm) { myFont = bm; if (bm.getName(BitmapFont.NAME_FAMILY_AND_STYLE) != null) { setTitle(bm.getName(BitmapFont.NAME_FAMILY_AND_STYLE)); } else if (bm.getName(BitmapFont.NAME_FAMILY) != null) { setTitle(bm.getName(BitmapFont.NAME_FAMILY)); } scale = new SpinnerNumberModel(1, 1, 16, 1); scale.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { alphaPanel.repaint(); textPanel.repaint(); } }); alphaPanel = new JComponent() { private static final long serialVersionUID = 1L; protected void paintComponent(Graphics g) { Insets i = getInsets(); int x = i.left; int y = i.top; int w = getWidth()-i.left-i.right; int h = getHeight()-i.top-i.bottom; int s = scale.getNumber().intValue(); g.setColor(Color.white); g.fillRect(x, y, w, h); g.setColor(Color.black); myFont.drawAlphabet(g, x, y + myFont.getLineAscent() * s, s, w); } }; textArea = new JTextArea("The quick brown fox jumped over the lazy dogs with a razorback-jumping frog that could level six piqued gymnasts who speak Latin: Lorem ipsum dolor sit amet..."); textArea.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { textPanel.repaint(); } public void insertUpdate(DocumentEvent e) { textPanel.repaint(); } public void removeUpdate(DocumentEvent e) { textPanel.repaint(); } }); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textPanel = new JComponent() { private static final long serialVersionUID = 1L; protected void paintComponent(Graphics g) { Insets i = getInsets(); int x = i.left; int y = i.top; int w = getWidth()-i.left-i.right; int h = getHeight()-i.top-i.bottom; int s = scale.getNumber().intValue(); g.setColor(Color.white); g.fillRect(x, y, w, h); g.setColor(Color.black); myFont.draw(g, textArea.getText(), x, y + myFont.getLineAscent() * s, s, w); } }; JPanel top = new JPanel(new BorderLayout(4,4)); top.add(new JLabel("Scale:"), BorderLayout.LINE_START); top.add(new JSpinner(scale), BorderLayout.CENTER); JPanel top2 = new JPanel(new BorderLayout()); top2.add(top, BorderLayout.LINE_END); JPanel main = new JPanel(new GridLayout(3,1,10,10)); main.add(alphaPanel); main.add(new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)); main.add(textPanel); JPanel main2 = new JPanel(new BorderLayout(10,10)); main2.add(main, BorderLayout.CENTER); main2.add(top2, BorderLayout.PAGE_END); main2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setContentPane(main2); setSize(512, 456); setLocationRelativeTo(null); setVisible(true); } public void fontChanged() { alphaPanel.repaint(); textPanel.repaint(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/000077500000000000000000000000001506470510200265665ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/DA.16.png000066400000000000000000000027051506470510200300110ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}MHq ۆ[c˦iXΞe,% :C<ة[D{c޼D2[xICө[ΒMcZtɴ|?]>EQd%mFGGݪ2Y7lrkx`hhQ}MWmDo){v~yLKKKF$+(h>/)tXiG8pپ/jpvʼ|Ʈ7$uV2Vy%zM`bWOAXl/P*f_f*"KTVS\kC?wdb*9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXŖ[lTs^{65kc'NڻBH҄T/UJF8PKE(B* D}!jӔTFN |ٻòbtso?#R?+ZWP٠kw߈G`P*JbvbDgggk]/yJ{D /e7&B)ţ5j(UEп΍*O)EGGGmU_]PYTWW B*ϩjݺuj}СêKuttc."o;Xmchӓydcx?~b=Xctww=DBa>h1jkjyX~=N +i}ofma͉uSj3aӃ/vFy{.<~__맦9U(ʭF2IÒ:nرc746H)4jexp}sM%6ռ=AMS9 lс,VDV!Dh)$R -N &~g9?4Ǟ? I鼛Kc䃽Ʊf"rFϛO2Ε+O/'[^m?o]}gc_4.y|T[|zώr8NbSVf%6T{BB\dӧ7߿`{{<|. 6=XRF|NPcr7 _'0)[R& խL !sRJQQQHA 'i3D'Q d94<ͥ@qΆ=6I.1-`+C@AN**+"Ayzn]Sch4d@& D89=h`srosA>CLMcGֺ1W-^y.uuumԓ8l MJt&,6;5V}#̪ 4N݆Iwhs2v(FXy _'Bܾ'dA8&M%эF4D:n)[}ivɌel3(]^ǚf Yh_ %"gˎ;p:٬i΍c7ح9Aiy38u|t"I &Ř%91:F)gb|ꖯIɇ@P$p #z6 ;%%63s*MF|\ bD#1$h'sxn[#}}j hF_?/"\myݳH"q4NPµb҂QĎn' xW ܙp555y66/r@FaV1zv].@tttUwGGG7tw?T:lA_*_[0|'޽ӹ 0\zHKx<Ȥ34J)  `4 d22p8^=?/q $e^sMMM{^xaPM*EVBqSKMr'n hGb8d3J. RH4)1 ],z"*ĦMfus_|u[_W`4!w`404<Ȯ[u/ǒ%3L&'O7޸e ̗]^bߴ@Dwo|K%@tG { public final int size; public final int style; public final int id; public FONDEntry(int size, int style, int id) { this.size = size; this.style = style; this.id = id; } public FONDEntry(DataInput in) throws IOException { this.size = in.readShort(); this.style = in.readShort(); this.id = in.readShort(); } public void write(DataOutput out) throws IOException { out.writeShort(size); out.writeShort(style); out.writeShort(id); } @Override public int compareTo(FONDEntry that) { if (this.size != that.size) return this.size - that.size; if (this.style != that.style) return this.style - that.style; return this.id - that.id; } @Override public boolean equals(Object o) { if (o instanceof FONDEntry) { FONDEntry that = (FONDEntry)o; return ( this.size == that.size && this.style == that.style && this.id == that.id ); } return false; } @Override public int hashCode() { return (id << 16) ^ (style << 8) ^ size; } @Override public String toString() { return "[" + toString("FONDEntry") + " -> " + id + "]"; } public String toString(String fontName) { if (style != 0) fontName += " (" + styleString(style) + ")"; if (size != 0) fontName += " " + size; return fontName; } private static String styleString(int style) { StringBuffer sb = new StringBuffer(); if ((style & 0x01) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("bold" ); } if ((style & 0x02) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("italic" ); } if ((style & 0x04) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("underline"); } if ((style & 0x08) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("outline" ); } if ((style & 0x10) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("shadow" ); } if ((style & 0x20) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("condensed"); } if ((style & 0x40) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("extended" ); } if ((style & 0x80) != 0) { if (sb.length() > 0) sb.append(", "); sb.append("group" ); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/FONDResource.java000066400000000000000000000132151506470510200316710ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.util.SortedSet; import java.util.TreeSet; public class FONDResource { public String name; public int flags; public int id; public int firstChar; public int lastChar; public int maxAscent; public int maxDescent; public int maxLeading; public int maxCharWidth; public int offsetToGlyphWidthTable; public int offsetToKerningTable; public int offsetToStyleMappingTable; public int extraWidthForPlain; public int extraWidthForBold; public int extraWidthForItalic; public int extraWidthForUnderline; public int extraWidthForOutline; public int extraWidthForShadow; public int extraWidthForCondensed; public int extraWidthForExtended; public int extraWidthForGroup; public int internationalInfo; public int version; public final SortedSet entries = new TreeSet(); public byte[] optionalTables; public FONDResource(String name, int id) { this.name = name; this.flags = 0x6000; this.id = id; this.version = 1; } public FONDResource(FONDResource src, Iterable ee) { this.name = src.name; this.flags = src.flags; this.id = src.id; this.firstChar = src.firstChar; this.lastChar = src.lastChar; this.maxAscent = src.maxAscent; this.maxDescent = src.maxDescent; this.maxLeading = src.maxLeading; this.maxCharWidth = src.maxCharWidth; this.offsetToGlyphWidthTable = src.offsetToGlyphWidthTable; this.offsetToKerningTable = src.offsetToKerningTable; this.offsetToStyleMappingTable = src.offsetToStyleMappingTable; this.extraWidthForPlain = src.extraWidthForPlain; this.extraWidthForBold = src.extraWidthForBold; this.extraWidthForItalic = src.extraWidthForItalic; this.extraWidthForUnderline = src.extraWidthForUnderline; this.extraWidthForOutline = src.extraWidthForOutline; this.extraWidthForShadow = src.extraWidthForShadow; this.extraWidthForCondensed = src.extraWidthForCondensed; this.extraWidthForExtended = src.extraWidthForExtended; this.extraWidthForGroup = src.extraWidthForGroup; this.internationalInfo = src.internationalInfo; this.version = src.version; for (FONDEntry e : ee) this.entries.add(e); this.optionalTables = src.optionalTables; } public FONDResource(String name, DataInput in, int length) throws IOException { this.name = name; this.flags = in.readUnsignedShort(); this.id = in.readShort(); this.firstChar = in.readUnsignedShort(); this.lastChar = in.readUnsignedShort(); this.maxAscent = in.readUnsignedShort(); this.maxDescent = in.readUnsignedShort(); this.maxLeading = in.readUnsignedShort(); this.maxCharWidth = in.readUnsignedShort(); this.offsetToGlyphWidthTable = in.readInt(); this.offsetToKerningTable = in.readInt(); this.offsetToStyleMappingTable = in.readInt(); this.extraWidthForPlain = in.readUnsignedShort(); this.extraWidthForBold = in.readUnsignedShort(); this.extraWidthForItalic = in.readUnsignedShort(); this.extraWidthForUnderline = in.readUnsignedShort(); this.extraWidthForOutline = in.readUnsignedShort(); this.extraWidthForShadow = in.readUnsignedShort(); this.extraWidthForCondensed = in.readUnsignedShort(); this.extraWidthForExtended = in.readUnsignedShort(); this.extraWidthForGroup = in.readUnsignedShort(); this.internationalInfo = in.readInt(); this.version = in.readUnsignedShort(); int count = in.readShort() + 1; for (int i = 0; i < count; i++) entries.add(new FONDEntry(in)); int end = 54 + 6 * count; if (offsetToGlyphWidthTable != 0) offsetToGlyphWidthTable -= end; if (offsetToKerningTable != 0) offsetToKerningTable -= end; if (offsetToStyleMappingTable != 0) offsetToStyleMappingTable -= end; if (length > end) in.readFully(optionalTables = new byte[length - end]); } public FONDResource(String name, byte[] data) throws IOException { this(name, new DataInputStream(new ByteArrayInputStream(data)), data.length); } public void write(DataOutput out) throws IOException { out.writeShort(flags); out.writeShort(id); out.writeShort(firstChar); out.writeShort(lastChar); out.writeShort(maxAscent); out.writeShort(maxDescent); out.writeShort(maxLeading); out.writeShort(maxCharWidth); int end = 54 + 6 * entries.size(); out.writeInt((offsetToGlyphWidthTable == 0) ? 0 : (offsetToGlyphWidthTable + end)); out.writeInt((offsetToKerningTable == 0) ? 0 : (offsetToKerningTable + end)); out.writeInt((offsetToStyleMappingTable == 0) ? 0 : (offsetToStyleMappingTable + end)); out.writeShort(extraWidthForPlain); out.writeShort(extraWidthForBold); out.writeShort(extraWidthForItalic); out.writeShort(extraWidthForUnderline); out.writeShort(extraWidthForOutline); out.writeShort(extraWidthForShadow); out.writeShort(extraWidthForExtended); out.writeShort(extraWidthForCondensed); out.writeShort(extraWidthForGroup); out.writeInt(internationalInfo); out.writeShort(version); out.writeShort(entries.size() - 1); for (FONDEntry e : entries) e.write(out); if (optionalTables != null) out.write(optionalTables); } public byte[] toByteArray() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); write(new DataOutputStream(out)); out.flush(); out.close(); return out.toByteArray(); } public int length() { int length = 54 + 6 * entries.size(); if (optionalTables != null) length += optionalTables.length; return length; } @Override public String toString() { if (entries.size() == 1) { return entries.first().toString(name); } else { return name; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Blank.16.png000066400000000000000000000025021506470510200314250ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp UR>IDATx|SOPW0tdőNL4q#QVϐAW7 Hؾ;)R/׾5Da֪8c@Dh/4nk th:R' -KZ,G4i2yz$Gp08?fX EE$e3?`o\<;e")HZh4?C"&$ݢoiEbY lmo k32*+Nђ D tFS"ls \8ЀDe"V$zA\/ L` H9؟ r1D&JD{`%G)-T*PK,~@0p,9"q2կ+ˉ4UaYZOgQf])q)n۩IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Blank.32.png000066400000000000000000000036071506470510200314320ustar00rootroot00000000000000PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp "X0IDATxڬWOoG HE!%"9rM@TI|Zn "%3x{Xpfvo7wvNec 2!foYxQ`h$5=M_GnDtM{D%: @ښc"L0,T U,7 s.lnlJ=7 B Ѭ K&X<}/xRћlӦ(LSv9J"M ~zdV&gݑ-"0|DZn|f= \͈Dh)n,#{M$ =`%6'Q1 P1C08)F;V[@4Po y8tu* |])r裼4wh^NڡYk<@¨ mZ},&V^fywS`Jj`ۅ`Tc԰8kh̝?unYP\=wN f\tFEAn셷-ԥ,lEI~f,h"C& t..vcÖhO]4XUρ<6AaJOTU=(Da9F+e1 p4;6,ǃ&u.9sÁcL_.TH}wE,lTg),W3~n3L@dܐH:*^Х&5UNX-Е[γ2AVӰi&um1Թ}ZL φGLVիTۯ܈K.[ET˚ Lט.2V`o]GK|y4 ksE{agzg~B*EVIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.FKEY.16.png000066400000000000000000000025141506470510200311370ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp IDATxڌS=OA]0h P`ŠKHԄVlID F;z'71;N"hMSZ(@ӚQ+W^Q(vNNObASdGo#<p7A4NZG홂}wanGupV.0>#nBn ul6Rdl6-&I&zL-Zz<[[jӉlJ j$|7/GR@-,|㷺'~` ?&J[V0RK# \葙4"m4_jf(_n!A7.\]6@Y ]{p؞hWj5jZkF+5[L,!>牚2V g w_lN͇E|IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.FKEY.32.png000066400000000000000000000034501506470510200311350ustar00rootroot00000000000000PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp %&IDATxڴWOSS1Oʌ77z+ڑGPW:g@uwy+K[1M^/'[^tvvZ(=868P .K=\*kԇ-511/'J=)\AHrϗWj*k^j۪Z{02BN5N+*ղn+eVXJ4h@kBD"_//Wǣ%:@zpߒ<ҫ%BMMNXa{^ kGJkM !@ɩ +M:BvC4 X}[]t؍ 魂7L`$*hmm]]_{1X7O7h#” OpqKh Q˘g w->&>@XedSTP  ,TC1ItL{FaFcրb?J VaIsBemS@% EW}6??_x>::tZ7P7>?H8aTҝG$RNA:aԮ{H:!Y|0h5PDqa((>OefHY2l6]3ڥT>u/N< 9=c_~C: A3Z-xRim3)0Q.2W95mpQL, #W ʲށ\7wNNzKgQ@G<dsǤ6_?U'w!/U!Au)X. C~φ *9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8u?OQ P,,ppU%ʧ`t+/5&,2A7ܴb{qmi)>s&˲bxj$BF! B`}ppЏr*9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXnUUrC/8M4 C ud G*H}bQsi C: MdF"5eTMd9~wr9guL;WY_;x;w=wB{ ׭I\Ȁ7] ! w! #@(IÇa$K5@r"īpx\|'GQ+?ݽ;9@k's93C$ &vzқ!3;@b~fn&Haf̬`,PWVcȑ7, &/[150%U,jj@څ{~ WV2DibV=[u__ a}.?bjjӱ0txr$'іŋloo !TVACʑ܅aLOO*chZwFrv-4kt FGBKu)Oa֭[}JP#;QOrg]x[:bKil.hI`_NveYcֹVt N|w(HL#@7B[pԩK-hoIe:[tt NύKG|؊p_E0wk:݂gԴVe|H5d{Td E=vr9ŠeTSlQCVWWwHӤG߼ٯ@[.h5Jt'rwCB|l6#yQY?7nxےD+ǖBPkL ƉS'!,seY(˲rM`JCHEfiJ*6<伏X pA!~YDje49^W5 dզḩޏ y}<<惿ml ARƓ y9 3 x̕g.4z{Ki7҄4Ҧ4dkkO'3+?XY7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Keyboard.16.png000066400000000000000000000024011506470510200321340ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}OSQ?(#  LčDMX ] Nbdc%.*$nk3}ᵵœ{>s΍l$\X<Ͳ IH"lR  ν;h8k}yy鋋 ~l6}~mggO?{#,n t܆'nJWZjupاk(%dY__`aaq°H(oJ4_}Rټ5v{ QLۉiR.yC-fffHt DQ<ȴG^`B`(zIT( 2ڭ &$82K&/mNE$OKLMM#Q`|@y$ f$ V/sP,<ι2y>{Q{P$IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Keyboard.32.png000066400000000000000000000035121506470510200321360ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXnGp9f+pY) 8G;1[Gj9Yp27KMaCb'dKϡgzw] ntU]UIbu}˗w@p  !yڲ!!uN~}?! v[x4{GGGLLL 9rR.\!=K(Yח/G ߺyo CɊ`%͐{",|iq9&.^,X+̔Y Y^ds7\b…>ҾQ!,;"(dh L]O66xQԓibg-+'Dnz1==jy N<ۿ c@t$ΝBt EǕ# Ø1ShZE\jzK:|>:*7B| 9AjwR:ge>`vv61Vە<}˹z=X{LG`Ud0f MZBcu6=QnwDNf#CuuH~ŚcP/Y]}E!ݼq{lnn׳< >PDA1,--4'A.l$1K(8˱QXq 2)>ײ |LdC~.Y~!U0J#SND@DͱD՞k:rAU`O33mbʂ7 w, *'<%z]k_?NE'&!,Wu]QuSuNiEH4Y.Ҷ*2͔ri KwȸYUUhX@i(#Ta3pqwf ƂTy;W8p x,ߧ\H○д&Bm.JCQVT$_@x?h10fIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Script.16.png000066400000000000000000000026221506470510200316450ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  gIDAT8e?kY3$EbӨdTradә(aw %a):/lHa#FrwOAj}9^ $In.,,  3{Iyi08o>zX/_k4i0L𰫟nߖ$&pQT`002{qqz>mo9A0 ]ϩ=Q{P_qttDVc~~իL'BD뤩#J3TUZ/]ɉslJs$9ٹ b'^<C*-r2򵌨&Fr?>͛6.//M٣4mDMbRuYM"™{ʚ$30 c<'D4rV\Y4)Çgm40"˪orSQ,[(aRThZiU:)yeHHF$w̘$pαIU|9ǵy>.p%I.Y2~2'O0 n!* @$H3MsE-y 8~c,IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Script.32.png000066400000000000000000000041041506470510200316400ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXoG?s9 %BF4B=)vKDdܟ0+ N pIAE4NDI¼bf>?ivggΛ7QUi4]=ANj "xDD#xѣGfFHa¯\o̙3xQUDUEEP@UAj3F~ l%{@%M{PT"}?4j M u>_Y0)H `AAdxP 5VVVX8}baF0@05F~ Ue>J/ENl/0(2^ Z@ųg^ﷷ~{oonGxM,Ea3qcRA UW7xp5Zz(Z ?b0,//#*ǫEio)MӺ-GID~D6pαX %lmm)ZqMH}4">MӐX\q+]zk-YfEibܹs!@n0IQCݭl mw:7 UD5 2'J}D `2¹a'-4T (FCL0ư`0}%KE`0`iiuޕF#F?>|Jb$&/^… ܾ};(\*EZg=Mgh4x!j0*d**hLL is4 װq+mƀJHʀ[5v'Xli8|Uz|+A "h)RQT~ |/;@µQKpE*ժ"4VEozDx?]IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Sound.16.png000066400000000000000000000025021506470510200314660ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8mOSQ>:ܤ8&:K QhWY@B G,uF4nDpbgLK+å ͹9sIDQ4;f$9Yje5 z=u]TmZ-iIb{/:n^9~ʞ4$*TnWdn)J!|fL7&EwvʥF$8@Aqjug0 `&ϿNؗ8fmm 5H 3B-z;;(.-!h@YdJ[))D h4jC`^fssA GENREѳ(S_ؘ:33yjzLTL%8cIz5v2GΣt.^$YEr)~{[r8r^hKPIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.Sound.32.png000066400000000000000000000040551506470510200314710ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXoTUgPI4a.؊`@XTvڝa,&=aG"5UE>._3Lo2sy{uh(: y70ox 33{Iy}=r7##Gll7ok.HLHBf qիՅ7awH/]o!>̈́ɇg 7 ^ÞvgHppr7frJ bbvuqSs $+*Y 8 ;vƠ%s 6ua$ʒq^C9K1 n;H]P2d'p8Ͼ}w/{a  :?o;,,.t5n&큒Iiޅ9gϞ15uy@N(,h .DOh0Zs+++@$`f Gqqqɓ)hD^gvv&mP jAI*6aǏwX^^6Wj\%."{}}[TU:W^EyP2 ;J-._ޠR*W\`iqN²dSOړ@jAt:ZV} "h4n]"/=9U24b%T ,+ Q>NjdqaZ- %(CQEQG!TD);[!vX (ss guCɚ v"eQJE%)B(r.)Ycbs r>r,QS6 W qNY&+ɀs <`/wͲrկ[(DӂTc)+RQNV ~+h2BJJo"4I!Z>W*@_ρ_߀9n7+=IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.TTC.16.png000066400000000000000000000023461506470510200310360ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8nQ?,.qheP@B<@p$;]q?#eDJGY/19hܙ9st \*F3pafl)f񱮮>h<kZiXh6i:*O4Lt{KϏ$޾yWH{kzx>!] &,K:q1Q (\. L<(6dHrv/0;; rf;- 7 wvdI','6's+n'*p m>Y~9+?v{g3cHF x/)TU &I‡w?g~M$Ir}MB&Lك!) xEjH3m6p& m | !$:FAT7IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.TTC.32.png000066400000000000000000000034321506470510200310310ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXjW3v-F^7](CҸ eр!E`4^ؤ/ ?@+t.Uh^o@Je';ӤT$Bs+KH3s`ѝ{s"I$I~t!pf g3a53s99ݍF@T/[9$̄$dI &~׾:{@_wrtt4!̈́g;VyDp$e>]XR"E+C }(lԽ L:5E`1(B'!d*g9wfUڢZ~$2JXR{:t-MrZy2ɰ+^ߤ+gZFi_A$$Hƕ+Wɽ{߰Y 4O:{df oA@Ĺ D>֝7&~fLek"IbP&03x{ f%$+傒&@nO6΅|t^Ϯ4MRC֐(<bA84v^ׇ\q=2A(4 vvI.hoiiS| UA·O0%"&3pv?IDq!ɂyKHfA(/ۤ@8Zkkk<@l 5>Wt,1I*2A|7;?B$Y y5L@"_Da}L)G3`x$̈ ?B۷ Y\q䟟%I;"K8oÄcqq% sve0Gv19x Ǔ_ Lg~Y/!!;^+/`H.0zP :`13#~/ƃo?( uUIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.TTF.16.png000066400000000000000000000023451506470510200310400ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}1o`8PaH.EqLT$KԵ]ߑWDde Hle`C) |2|qcI>ssMQ5Yfs00s8g2ȭ]]_k<85ϵnfVZ,zxD~秧m4%2vno2̱5~>>2a8<su+T& l6.//h E3SUL HӓzÃ$0*I )%p*ȌWN*7AAd@V C_ I ]<=WnX~K+A O* 3#( ryB2(z |˾7dF^?2vїyW(za2%q3F>y^4d 9tp& u?fQE*9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXnEjF1@E ͂lMZDA K#!ҒgA ~odH6`!4EUPROOUW9S:I,(n}r)!f o3aØ{L¼㽕hӋS# 3! !@(I[ {@}Ϟ1Y[[C2dǻ0"LW^z ->ǍI!F.Zr$a<vzm"(8\$8_d/rlnlvZü!\)$mln~+Ϗx~tT[N 7B߅fq+l,=ڪ٨FxT {H$G\^WϐCJ r(Ape|73plooc2|m3}L*œ>/<3 dҮɬ\h4l6l^JP QkAo.ȔT;<ϫtF?(pA<xGD: cZ<@<\ٌ `2ѻd&\ -͂y7B1DԷ6Y,@2ӽ)ɊOA7QE]X_I" VCE(sJpnO1/)Hx?m2J-=@=,_ VJuanZHjͨEQ`=deVcޖvZdl5&vy)Eq xw||I@"[؏y$k?/hɌ, eXrB<[S %Ž@7kN ^/۰ Nn)N@J'Q%23.d@hUU S`LHEȪ?>3p db \l謮T9>͹(5 #?gk|IIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.TrueType.16.png000066400000000000000000000025371506470510200321670ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  4IDAT8mOaGcC 88` $$J` wt4,&5?8,DXULd08mmؾ8mE%7wy@ILd2faf80 s3s֏zģmo‚ժtzzƯ$LOljh8:G.[Vccsǫ &H 4rbS4`~7 \lv]K5l HՑ #/#E)b$!I< 2A̐(@27G.Q(w $aH_{k 1Jx%Rl6 d 159IK5rWzܿ R2#9*o!j *AHHg"&!hȈmۢd$IrP.NR2chh a]0O1w8.p-I?LF`3+#!2͔L nw>΄oT?ƙ>IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/File.TrueType.32.png000066400000000000000000000042041506470510200321560ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  YIDATXOlE,[9Xd#Ha?@nbj4Odĭ͛RcҦEԁC4xH9!-JWԥK(֭O\Mi4VsW90s͓a-2ݝ&zrdWrWggXh#8!~eϐC ji,\ȑua sC!pe|{fd!cjZ>YN6ͪWe/o\t5=k5n&oIY5|qȈ|6rCC3 [ >2M1܅ejM/{[[ijKp‰>Vf>3p//ިg^"À %e[ٺtz(W.ʲqV*1(J#K@hfk12НС&''sr2$Mde$-$JL |1Ŝd_rT='\$N>}30Wl "(6Ķm۲ޖȷl=G$k! Kjs9́,XJp PK0yb,ff̕ _/p!xW~IEg \,nu&cgRWp!Wo+|S9>6M/pa--)A1p0jIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/KeyboardFrame.java000066400000000000000000000012151506470510200321430ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import javax.swing.JFrame; import com.kreative.unicode.data.GlyphList; import com.kreative.unicode.ttflib.DfontResource; public class KeyboardFrame extends JFrame { private static final long serialVersionUID = 1L; private KeyboardPanel panel; public KeyboardFrame(DfontResource res, GlyphList encoding) { super(res.getName()); this.panel = new KeyboardPanel(res.getData(), encoding); setJMenuBar(new KeyboardMenuBar(this)); setContentPane(panel); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); addKeyListener(panel); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/KeyboardMenuBar.java000066400000000000000000000013701506470510200324440ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Window; import javax.swing.JMenu; import javax.swing.JMenuBar; import com.kreative.bitsnpicas.edit.CommonMenuItems; public class KeyboardMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public KeyboardMenuBar(final Window window) { add(new FileMenu(window)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Window window) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(window)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/KeyboardPanel.java000066400000000000000000000103771506470510200321610ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.unicode.data.GlyphList; public class KeyboardPanel extends JPanel implements KeyListener { private static final long serialVersionUID = 1L; private final byte[] kchr; private final JLabel[][] labels; private final GlyphList encoding; public KeyboardPanel(byte[] kchr, GlyphList encoding) { this.kchr = kchr; this.labels = new JLabel[4][]; this.encoding = encoding; JPanel keyboard = new JPanel(); keyboard.setLayout(new BoxLayout(keyboard, BoxLayout.PAGE_AXIS)); for (int y = 0; y < keyWidths.length; y++) { labels[y] = new JLabel[keyWidths[y].length]; JPanel row = new JPanel(); row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS)); for (int x = 0; x < keyWidths[y].length; x++) { int w = keyWidths[y][x] * 6 + ((x == 0) ? 2 : 1); int h = 4 * 6 + ((y == 0) ? 2 : 1); if (y >= 2 && x == 0) w++; // hack JLabel label = new JLabel(" "); label.setBorder(BorderFactory.createMatteBorder( ((y == 0) ? 1 : 0), ((x == 0) ? 1 : 0), 1, 1, Color.gray )); label.setBackground(Color.white); label.setOpaque(true); label.setHorizontalAlignment(JLabel.CENTER); label.setVerticalAlignment(JLabel.CENTER); Dimension d = new Dimension(w, h); label.setMinimumSize(d); label.setPreferredSize(d); label.setMaximumSize(d); labels[y][x] = label; row.add(label); } keyboard.add(row); } keyboard.setBorder(BorderFactory.createEmptyBorder(12,12,12,12)); setLayout(new GridLayout()); add(keyboard); refresh(null); } public void refresh(KeyEvent e) { int mods = getModifiers(e); int table = kchr[mods + 2] & 0xFF; int base = table * 128 + 260; int numTables = ((kchr[258] & 0xFF) << 8) | (kchr[259] & 0xFF); int deadBase = numTables * 128 + 262; int numDead = ((kchr[deadBase-2] & 0xFF) << 8) | (kchr[deadBase-1] & 0xFF); for (int y = 0; y < labels.length; y++) { for (int x = 0; x < labels[y].length; x++) { int code = keyCodes[y][x]; boolean dead = false; int ch = kchr[base + code] & 0xFF; if (ch == 0) { for (int b = deadBase, i = 0; i < numDead; i++) { int numRec = ((kchr[b+2] & 0xFF) << 8) | (kchr[b+3] & 0xFF); int recLen = numRec * 2 + 6; if ((kchr[b+0] & 0xFF) == table) { if ((kchr[b+1] & 0xFF) == code) { dead = true; ch = kchr[b + recLen - 1] & 0xFF; break; } } b += recLen; } } Integer uch = encoding.get(ch); if (uch == null || uch < 32) { labels[y][x].setText(" "); } else { labels[y][x].setText(new String(Character.toChars(uch))); } labels[y][x].setBackground(dead ? deadKeyColor : Color.white); } } } public void keyPressed(KeyEvent e) { refresh(e); } public void keyReleased(KeyEvent e) { refresh(e); } public void keyTyped(KeyEvent e) { refresh(e); } private static final Color deadKeyColor = new Color(0xFFDD55); private static final int[][] keyWidths = new int[][] { { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8 }, { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6 }, { 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9 }, { 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 11 }, }; private static final int[][] keyCodes = new int[][] { { 50, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51 }, { 48, 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 42 }, { 57, 0, 1, 2, 3, 5, 4, 38, 40, 37, 41, 39, 36 }, { 56, 10, 6, 7, 8, 9, 11, 45, 46, 43, 47, 44, 56 }, }; private static boolean isCapsLockDown = false; private static int getModifiers(KeyEvent e) { if (e == null) return 0; if (e.getKeyCode() == KeyEvent.VK_CAPS_LOCK) { switch (e.getID()) { case KeyEvent.KEY_PRESSED: isCapsLockDown = true; break; case KeyEvent.KEY_RELEASED: isCapsLockDown = false; break; } } int mods = 0; if (e.isMetaDown()) mods |= 0x01; if (e.isShiftDown()) mods |= 0x02; if (isCapsLockDown) mods |= 0x04; if (e.isAltDown()) mods |= 0x08; if (e.isControlDown()) mods |= 0x10; return mods; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MACEDecoder.java000066400000000000000000000364551506470510200314410ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; public class MACEDecoder { private static final int[] MAJOR_INDEX_DELTA = { -13, 8, 76, 222, 222, 76, 8, -13 }; private static final int[][] MAJOR_LEVEL_DELTA = { { 37, 116, 206, 330, -331, -207, -117, -38 }, { 39, 121, 216, 346, -347, -217, -122, -40 }, { 41, 127, 225, 361, -362, -226, -128, -42 }, { 42, 132, 235, 377, -378, -236, -133, -43 }, { 44, 137, 245, 392, -393, -246, -138, -45 }, { 46, 144, 256, 410, -411, -257, -145, -47 }, { 48, 150, 267, 428, -429, -268, -151, -49 }, { 51, 157, 280, 449, -450, -281, -158, -52 }, { 53, 165, 293, 470, -471, -294, -166, -54 }, { 55, 172, 306, 490, -491, -307, -173, -56 }, { 58, 179, 319, 511, -512, -320, -180, -59 }, { 60, 187, 333, 534, -535, -334, -188, -61 }, { 63, 195, 348, 557, -558, -349, -196, -64 }, { 66, 205, 364, 583, -584, -365, -206, -67 }, { 69, 214, 380, 609, -610, -381, -215, -70 }, { 72, 223, 396, 635, -636, -397, -224, -73 }, { 75, 233, 414, 663, -664, -415, -234, -76 }, { 79, 244, 433, 694, -695, -434, -245, -80 }, { 82, 254, 453, 725, -726, -454, -255, -83 }, { 86, 265, 472, 756, -757, -473, -266, -87 }, { 90, 278, 495, 792, -793, -496, -279, -91 }, { 94, 290, 516, 826, -827, -517, -291, -95 }, { 98, 303, 538, 862, -863, -539, -304, -99 }, { 102, 316, 562, 901, -902, -563, -317, -103 }, { 107, 331, 588, 942, -943, -589, -332, -108 }, { 112, 345, 614, 983, -984, -615, -346, -113 }, { 117, 361, 641, 1027, -1028, -642, -362, -118 }, { 122, 377, 670, 1074, -1075, -671, -378, -123 }, { 127, 394, 701, 1123, -1124, -702, -395, -128 }, { 133, 411, 732, 1172, -1173, -733, -412, -134 }, { 139, 430, 764, 1224, -1225, -765, -431, -140 }, { 145, 449, 799, 1280, -1281, -800, -450, -146 }, { 152, 469, 835, 1337, -1338, -836, -470, -153 }, { 159, 490, 872, 1397, -1398, -873, -491, -160 }, { 166, 512, 911, 1459, -1460, -912, -513, -167 }, { 173, 535, 951, 1523, -1524, -952, -536, -174 }, { 181, 558, 993, 1590, -1591, -994, -559, -182 }, { 189, 584, 1038, 1663, -1664, -1039, -585, -190 }, { 197, 610, 1085, 1738, -1739, -1086, -611, -198 }, { 206, 637, 1133, 1815, -1816, -1134, -638, -207 }, { 215, 665, 1183, 1895, -1896, -1184, -666, -216 }, { 225, 695, 1237, 1980, -1981, -1238, -696, -226 }, { 235, 726, 1291, 2068, -2069, -1292, -727, -236 }, { 246, 759, 1349, 2161, -2162, -1350, -760, -247 }, { 257, 792, 1409, 2257, -2258, -1410, -793, -258 }, { 268, 828, 1472, 2357, -2358, -1473, -829, -269 }, { 280, 865, 1538, 2463, -2464, -1539, -866, -281 }, { 293, 903, 1606, 2572, -2573, -1607, -904, -294 }, { 306, 944, 1678, 2688, -2689, -1679, -945, -307 }, { 319, 986, 1753, 2807, -2808, -1754, -987, -320 }, { 334, 1030, 1832, 2933, -2934, -1833, -1031, -335 }, { 349, 1076, 1914, 3065, -3066, -1915, -1077, -350 }, { 364, 1124, 1999, 3202, -3203, -2000, -1125, -365 }, { 380, 1174, 2088, 3344, -3345, -2089, -1175, -381 }, { 398, 1227, 2182, 3494, -3495, -2183, -1228, -399 }, { 415, 1281, 2278, 3649, -3650, -2279, -1282, -416 }, { 434, 1339, 2380, 3811, -3812, -2381, -1340, -435 }, { 453, 1398, 2486, 3982, -3983, -2487, -1399, -454 }, { 473, 1461, 2598, 4160, -4161, -2599, -1462, -474 }, { 495, 1526, 2714, 4346, -4347, -2715, -1527, -496 }, { 517, 1594, 2835, 4540, -4541, -2836, -1595, -518 }, { 540, 1665, 2961, 4741, -4742, -2962, -1666, -541 }, { 564, 1740, 3093, 4953, -4954, -3094, -1741, -565 }, { 589, 1818, 3232, 5175, -5176, -3233, -1819, -590 }, { 615, 1898, 3375, 5405, -5406, -3376, -1899, -616 }, { 643, 1984, 3527, 5647, -5648, -3528, -1985, -644 }, { 671, 2072, 3683, 5898, -5899, -3684, -2073, -672 }, { 701, 2164, 3848, 6161, -6162, -3849, -2165, -702 }, { 733, 2261, 4020, 6438, -6439, -4021, -2262, -734 }, { 766, 2362, 4199, 6724, -6725, -4200, -2363, -767 }, { 800, 2467, 4386, 7024, -7025, -4387, -2468, -801 }, { 836, 2578, 4583, 7339, -7340, -4584, -2579, -837 }, { 873, 2692, 4786, 7664, -7665, -4787, -2693, -874 }, { 912, 2813, 5001, 8008, -8009, -5002, -2814, -913 }, { 952, 2938, 5223, 8364, -8365, -5224, -2939, -953 }, { 995, 3070, 5457, 8739, -8740, -5458, -3071, -996 }, { 1039, 3207, 5701, 9129, -9130, -5702, -3208, -1040 }, { 1086, 3350, 5956, 9537, -9538, -5957, -3351, -1087 }, { 1134, 3499, 6220, 9960, -9961, -6221, -3500, -1135 }, { 1185, 3655, 6497, 10404, -10405, -6498, -3656, -1186 }, { 1238, 3818, 6788, 10869, -10870, -6789, -3819, -1239 }, { 1293, 3989, 7091, 11355, -11356, -7092, -3990, -1294 }, { 1351, 4166, 7407, 11861, -11862, -7408, -4167, -1352 }, { 1411, 4352, 7738, 12390, -12391, -7739, -4353, -1412 }, { 1474, 4547, 8084, 12946, -12947, -8085, -4548, -1475 }, { 1540, 4750, 8444, 13522, -13523, -8445, -4751, -1541 }, { 1609, 4962, 8821, 14126, -14127, -8822, -4963, -1610 }, { 1680, 5183, 9215, 14756, -14757, -9216, -5184, -1681 }, { 1756, 5415, 9626, 15415, -15416, -9627, -5416, -1757 }, { 1834, 5657, 10057, 16104, -16105, -10058, -5658, -1835 }, { 1916, 5909, 10505, 16822, -16823, -10506, -5910, -1917 }, { 2001, 6173, 10975, 17574, -17575, -10976, -6174, -2002 }, { 2091, 6448, 11463, 18356, -18357, -11464, -6449, -2092 }, { 2184, 6736, 11974, 19175, -19176, -11975, -6737, -2185 }, { 2282, 7037, 12510, 20032, -20033, -12511, -7038, -2283 }, { 2383, 7351, 13068, 20926, -20927, -13069, -7352, -2384 }, { 2490, 7679, 13652, 21861, -21862, -13653, -7680, -2491 }, { 2601, 8021, 14260, 22834, -22835, -14261, -8022, -2602 }, { 2717, 8380, 14897, 23854, -23855, -14898, -8381, -2718 }, { 2838, 8753, 15561, 24918, -24919, -15562, -8754, -2839 }, { 2965, 9144, 16256, 26031, -26032, -16257, -9145, -2966 }, { 3097, 9553, 16982, 27193, -27194, -16983, -9554, -3098 }, { 3236, 9979, 17740, 28407, -28408, -17741, -9980, -3237 }, { 3380, 10424, 18532, 29675, -29676, -18533, -10425, -3381 }, { 3531, 10890, 19359, 31000, -31001, -19360, -10891, -3532 }, { 3688, 11375, 20222, 32382, -32383, -20223, -11376, -3689 }, { 3853, 11883, 21125, 32767, -32768, -21126, -11884, -3854 }, { 4025, 12414, 22069, 32767, -32768, -22070, -12415, -4026 }, { 4205, 12967, 23053, 32767, -32768, -23054, -12968, -4206 }, { 4392, 13546, 24082, 32767, -32768, -24083, -13547, -4393 }, { 4589, 14151, 25157, 32767, -32768, -25158, -14152, -4590 }, { 4793, 14783, 26280, 32767, -32768, -26281, -14784, -4794 }, { 5007, 15442, 27452, 32767, -32768, -27453, -15443, -5008 }, { 5231, 16132, 28678, 32767, -32768, -28679, -16133, -5232 }, { 5464, 16851, 29957, 32767, -32768, -29958, -16852, -5465 }, { 5708, 17603, 31294, 32767, -32768, -31295, -17604, -5709 }, { 5963, 18389, 32691, 32767, -32768, -32692, -18390, -5964 }, { 6229, 19210, 32767, 32767, -32768, -32768, -19211, -6230 }, { 6507, 20067, 32767, 32767, -32768, -32768, -20068, -6508 }, { 6797, 20963, 32767, 32767, -32768, -32768, -20964, -6798 }, { 7101, 21899, 32767, 32767, -32768, -32768, -21900, -7102 }, { 7418, 22876, 32767, 32767, -32768, -32768, -22877, -7419 }, { 7749, 23897, 32767, 32767, -32768, -32768, -23898, -7750 }, { 8095, 24964, 32767, 32767, -32768, -32768, -24965, -8096 }, { 8456, 26078, 32767, 32767, -32768, -32768, -26079, -8457 }, { 8833, 27242, 32767, 32767, -32768, -32768, -27243, -8834 }, { 9228, 28457, 32767, 32767, -32768, -32768, -28458, -9229 }, { 9639, 29727, 32767, 32767, -32768, -32768, -29728, -9640 }, }; private static final int[] MINOR_INDEX_DELTA = { -18, 140, 140, -18 }; private static final int[][] MINOR_LEVEL_DELTA = { { 64, 216, -217, -65 }, { 67, 226, -227, -68 }, { 70, 236, -237, -71 }, { 74, 246, -247, -75 }, { 77, 257, -258, -78 }, { 80, 268, -269, -81 }, { 84, 280, -281, -85 }, { 88, 294, -295, -89 }, { 92, 307, -308, -93 }, { 96, 321, -322, -97 }, { 100, 334, -335, -101 }, { 104, 350, -351, -105 }, { 109, 365, -366, -110 }, { 114, 382, -383, -115 }, { 119, 399, -400, -120 }, { 124, 416, -417, -125 }, { 130, 434, -435, -131 }, { 136, 454, -455, -137 }, { 142, 475, -476, -143 }, { 148, 495, -496, -149 }, { 155, 519, -520, -156 }, { 162, 541, -542, -163 }, { 169, 564, -565, -170 }, { 176, 590, -591, -177 }, { 185, 617, -618, -186 }, { 193, 644, -645, -194 }, { 201, 673, -674, -202 }, { 210, 703, -704, -211 }, { 220, 735, -736, -221 }, { 230, 767, -768, -231 }, { 240, 801, -802, -241 }, { 251, 838, -839, -252 }, { 262, 876, -877, -263 }, { 274, 914, -915, -275 }, { 286, 955, -956, -287 }, { 299, 997, -998, -300 }, { 312, 1041, -1042, -313 }, { 326, 1089, -1090, -327 }, { 341, 1138, -1139, -342 }, { 356, 1188, -1189, -357 }, { 372, 1241, -1242, -373 }, { 388, 1297, -1298, -389 }, { 406, 1354, -1355, -407 }, { 424, 1415, -1416, -425 }, { 443, 1478, -1479, -444 }, { 462, 1544, -1545, -463 }, { 483, 1613, -1614, -484 }, { 505, 1684, -1685, -506 }, { 527, 1760, -1761, -528 }, { 551, 1838, -1839, -552 }, { 576, 1921, -1922, -577 }, { 601, 2007, -2008, -602 }, { 628, 2097, -2098, -629 }, { 656, 2190, -2191, -657 }, { 686, 2288, -2289, -687 }, { 716, 2389, -2390, -717 }, { 748, 2496, -2497, -749 }, { 781, 2607, -2608, -782 }, { 816, 2724, -2725, -817 }, { 853, 2846, -2847, -854 }, { 891, 2973, -2974, -892 }, { 930, 3104, -3105, -931 }, { 972, 3243, -3244, -973 }, { 1016, 3389, -3390, -1017 }, { 1061, 3539, -3540, -1062 }, { 1108, 3698, -3699, -1109 }, { 1158, 3862, -3863, -1159 }, { 1209, 4035, -4036, -1210 }, { 1264, 4216, -4217, -1265 }, { 1320, 4403, -4404, -1321 }, { 1379, 4599, -4600, -1380 }, { 1441, 4806, -4807, -1442 }, { 1505, 5019, -5020, -1506 }, { 1572, 5244, -5245, -1573 }, { 1642, 5477, -5478, -1643 }, { 1715, 5722, -5723, -1716 }, { 1792, 5978, -5979, -1793 }, { 1872, 6245, -6246, -1873 }, { 1955, 6522, -6523, -1956 }, { 2043, 6813, -6814, -2044 }, { 2134, 7118, -7119, -2135 }, { 2229, 7436, -7437, -2230 }, { 2329, 7767, -7768, -2330 }, { 2432, 8114, -8115, -2433 }, { 2541, 8477, -8478, -2542 }, { 2655, 8854, -8855, -2656 }, { 2773, 9250, -9251, -2774 }, { 2897, 9663, -9664, -2898 }, { 3026, 10094, -10095, -3027 }, { 3162, 10546, -10547, -3163 }, { 3303, 11016, -11017, -3304 }, { 3450, 11508, -11509, -3451 }, { 3604, 12020, -12021, -3605 }, { 3765, 12556, -12557, -3766 }, { 3933, 13118, -13119, -3934 }, { 4108, 13703, -13704, -4109 }, { 4292, 14315, -14316, -4293 }, { 4483, 14953, -14954, -4484 }, { 4683, 15621, -15622, -4684 }, { 4892, 16318, -16319, -4893 }, { 5111, 17046, -17047, -5112 }, { 5339, 17807, -17808, -5340 }, { 5577, 18602, -18603, -5578 }, { 5826, 19433, -19434, -5827 }, { 6086, 20300, -20301, -6087 }, { 6358, 21205, -21206, -6359 }, { 6642, 22152, -22153, -6643 }, { 6938, 23141, -23142, -6939 }, { 7248, 24173, -24174, -7249 }, { 7571, 25252, -25253, -7572 }, { 7909, 26380, -26381, -7910 }, { 8262, 27557, -27558, -8263 }, { 8631, 28786, -28787, -8632 }, { 9016, 30072, -30073, -9017 }, { 9419, 31413, -31414, -9420 }, { 9839, 32767, -32768, -9840 }, { 10278, 32767, -32768, -10279 }, { 10737, 32767, -32768, -10738 }, { 11216, 32767, -32768, -11217 }, { 11717, 32767, -32768, -11718 }, { 12240, 32767, -32768, -12241 }, { 12786, 32767, -32768, -12787 }, { 13356, 32767, -32768, -13357 }, { 13953, 32767, -32768, -13954 }, { 14576, 32767, -32768, -14577 }, { 15226, 32767, -32768, -15227 }, { 15906, 32767, -32768, -15907 }, { 16615, 32767, -32768, -16616 }, }; private static class MACEState { int index; int factor; int prev2; int prev1; int level; int inOffset; int outOffset; } private static void decompressBits3(MACEState state, int b, short[] out, int[] indexDelta, int[][] levelDelta, int channels) { int curr = levelDelta[(state.index & 0x7F0) >> 4][b] + state.level; if (curr > 32767) curr = 32767; if (curr < -32768) curr = -32767; state.level = curr - (curr >> 3); out[state.outOffset] = (short)curr; state.outOffset += channels; state.index += indexDelta[b] - (state.index >> 5); if (state.index < 0) state.index = 0; } private static void decompressBits6(MACEState state, int b, short[] out, int[] indexDelta, int[][] levelDelta, int channels) { int curr = levelDelta[(state.index & 0x7F0) >> 4][b]; if ((state.prev1 ^ curr) >= 0) { state.factor += 506; if (state.factor > 32767) state.factor = 32767; } else { state.factor -= 314; if (state.factor < -32768) state.factor = -32767; } curr += state.level; if (curr > 32767) curr = 32767; if (curr < -32768) curr = -32767; state.level = (curr * state.factor) >> 15; curr >>= 1; out[state.outOffset] = (short)(state.prev1 + state.prev2 - ((state.prev2 - curr) >> 2)); state.outOffset += channels; out[state.outOffset] = (short)(state.prev1 + curr + ((state.prev2 - curr) >> 2)); state.outOffset += channels; state.prev2 = state.prev1; state.prev1 = curr; state.index += indexDelta[b] - (state.index >> 5); if (state.index < 0) state.index = 0; } private static void decompressStream3(byte[] in, short[] out, int channels) { MACEState state = new MACEState(); for (int channel = 0; channel < channels; channel++) { state.index = 0; state.factor = 0; state.prev2 = 0; state.prev1 = 0; state.level = 0; state.inOffset = channel * 2; state.outOffset = channel; while (state.inOffset < in.length && state.outOffset < out.length) { int b = in[state.inOffset]; decompressBits3(state, (b >> 0) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); decompressBits3(state, (b >> 3) & 3, out, MINOR_INDEX_DELTA, MINOR_LEVEL_DELTA, channels); decompressBits3(state, (b >> 5) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); b = in[state.inOffset+1]; decompressBits3(state, (b >> 0) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); decompressBits3(state, (b >> 3) & 3, out, MINOR_INDEX_DELTA, MINOR_LEVEL_DELTA, channels); decompressBits3(state, (b >> 5) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); state.inOffset += channels * 2; } } } private static void decompressStream6(byte[] in, short[] out, int channels) { MACEState state = new MACEState(); for (int channel = 0; channel < channels; channel++) { state.index = 0; state.factor = 0; state.prev2 = 0; state.prev1 = 0; state.level = 0; state.inOffset = channel; state.outOffset = channel; while (state.inOffset < in.length && state.outOffset < out.length) { int b = in[state.inOffset]; decompressBits6(state, (b >> 5) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); decompressBits6(state, (b >> 3) & 3, out, MINOR_INDEX_DELTA, MINOR_LEVEL_DELTA, channels); decompressBits6(state, (b >> 0) & 7, out, MAJOR_INDEX_DELTA, MAJOR_LEVEL_DELTA, channels); state.inOffset += channels; } } } public static byte[] decompressMACE3(byte[] compressedData, int channels) { short[] decompressedData = new short[compressedData.length*3]; decompressStream3(compressedData, decompressedData, channels); byte[] ret = new byte[decompressedData.length]; for (int i = 0; i < decompressedData.length; i++) ret[i] = (byte)(decompressedData[i] >> 8); return ret; } public static byte[] decompressMACE6(byte[] compressedData, int channels) { short[] decompressedData = new short[compressedData.length*6]; decompressStream6(compressedData, decompressedData, channels); byte[] ret = new byte[decompressedData.length]; for (int i = 0; i < decompressedData.length; i++) ret[i] = (byte)(decompressedData[i] >> 8); return ret; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverFile.java000066400000000000000000000321451506470510200313260ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import javax.swing.ImageIcon; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; import com.kreative.unicode.ttflib.DfontResourceType; public class MoverFile { private static final Random random = new Random(); private final DfontFile rsrc; private final List items; public MoverFile(DfontFile rsrc) throws IOException { this.rsrc = rsrc; this.items = new ArrayList(); // Fonts DfontResourceType fonds = rsrc.getResourceType("FOND"); if (fonds != null) for (DfontResource res : fonds.getResources()) { FONDResource fond = new FONDResource(res.getName(), res.getData()); for (FONDEntry e : fond.entries) { ImageIcon icon; String moverType; DfontResource font; if (e.size == 0) { icon = MoverIcons.FILE_TRUETYPE_16; moverType = "tfil"; font = rsrc.getResource("sfnt", e.id); } else { icon = MoverIcons.FILE_FONT_16; moverType = "ffil"; font = rsrc.getResource("NFNT", e.id); if (font == null) font = rsrc.getResource("FONT", e.id); } if (font != null) { FONDResource fr = new FONDResource(fond, Arrays.asList(e)); ResourceBundle rb = new ResourceBundle(icon, moverType, fr); rb.resources.add(font); items.add(rb); } } } if (items.isEmpty()) { DfontResourceType fonts = rsrc.getResourceType("FONT"); if (fonts != null) for (DfontResource res : fonts.getResources()) { int fontSize = res.getId() & 0x7F; if (fontSize != 0) { int fontId = res.getId() >> 7; int fontNameId = res.getId() &~ 0x7F; DfontResource fontNameRes = fonts.getResource(fontNameId); String fontName = (fontNameRes != null) ? fontNameRes.getName() : null; FONDResource fr = new FONDResource(fontName, fontId); fr.entries.add(new FONDEntry(fontSize, 0, res.getId())); ResourceBundle rb = new ResourceBundle(MoverIcons.FILE_FONT_16, "ffil", fr); rb.resources.add(res); items.add(rb); } } } // Desk Accessories DfontResourceType drvrs = rsrc.getResourceType("DRVR"); if (drvrs != null) for (DfontResource drvr : drvrs.getResources()) { String name = drvr.getName(); if (name != null && name.length() > 0 && !name.startsWith(".")) { ResourceBundle rb = new ResourceBundle( MoverIcons.DA_16, "dfil", name.trim(), drvr.getId() ); rb.resources.add(drvr); items.add(rb); for (DfontResourceType type : rsrc.getResourceTypes()) { for (DfontResource res : type.getResources()) { if (res.getOwnerType() == DfontResource.OWNER_TYPE_DRVR) { if (res.getOwnerId() == drvr.getId()) { rb.resources.add(res); } } } } } } // Script Systems DfontResourceType itlbs = rsrc.getResourceType("itlb"); if (itlbs != null) for (DfontResource itlb : itlbs.getResources()) { ResourceBundle rb = new ResourceBundle( MoverIcons.FILE_SCRIPT_16, "ifil", itlb.getName(), itlb.getId() ); rb.resources.add(itlb); items.add(rb); for (DfontResourceType type : rsrc.getResourceTypes()) { if (isScriptType(type.getType())) { for (DfontResource res : type.getResources()) { if (scriptCode(res.getId()) == itlb.getId()) { rb.resources.add(res); } } } } } // Keyboard Layouts for (int id : getIds("KCHR", "uchr")) { ResourceBundle rb = getAll( MoverIcons.FILE_KEYBOARD_16, "kfil", "" + id, id, "KCHR", "uchr", "itlk", "kcs#", "kcs4", "kcs8", "KCN#", "kcl4", "kcl8", "kscn", "ksc4", "ksc8", "kcns" ); if (rb != null) items.add(rb); } // FKEYs for (int id : getIds("FKEY", "fkey")) { ResourceBundle rb = getAll( MoverIcons.FILE_FKEY_16, "fkey", "\u2318-Shift-" + id, id, "FKEY", "fkey" ); if (rb != null) items.add(rb); } // Sounds DfontResourceType snds = rsrc.getResourceType("snd "); if (snds != null) for (DfontResource snd : snds.getResources()) { String name = snd.getName(); if (name != null && name.length() > 0) { ResourceBundle rb = new ResourceBundle( MoverIcons.FILE_SOUND_16, "sfil", name, snd.getId() ); rb.resources.add(snd); items.add(rb); } } Collections.sort(items); } private static final int itl0 = 0x69746C30; private static final int itl9 = 0x69746C39; private static final int trsl = 0x7472736C; private boolean isScriptType(int type) { return (type >= itl0 && type <= itl9) || type == trsl; } private int scriptCode(int id) { id &= 0xFFFF; if (id < 16384) return 0; return ((id - 16384) / 512) + 1; } private Set getIds(String... types) { Set ids = new HashSet(); for (String type : types) { DfontResourceType t = rsrc.getResourceType(type); if (t != null) ids.addAll(t.getResourceIds()); } return ids; } private ResourceBundle getAll(ImageIcon icon, String moverType, String name, int id, String... types) { ResourceBundle rb = null; for (String type : types) { DfontResource res = rsrc.getResource(type, id); if (res != null) { if (rb == null) { String n = res.getName(); if (n == null || n.length() == 0) n = name; rb = new ResourceBundle(icon, moverType, n, id); } rb.resources.add(res); } } return rb; } public void add(ResourceBundle e) { if (!items.contains(e)) { if (e.fond != null) { if ((e = addFont(e)) == null) return; } else if (e.moverType.equals("dfil")) { if ((e = addDeskAccessory(e)) == null) return; } else if (e.moverType.equals("kfil")) { if ((e = addKeyboardLayout(e)) == null) return; } else if (e.moverType.equals("sfil")) { if ((e = addSound(e)) == null) return; } else { if ((e = addGeneric(e)) == null) return; } items.add(e); Collections.sort(items); } } private ResourceBundle addFont(ResourceBundle e) { // Remove existing resource if it exists. for (ResourceBundle ee : items) { if (ee.moverType.equals(e.moverType) && ee.name.equals(e.name)) { remove(ee); break; } } // Build list of font resources to add, renumbering if necessary. Map resmap = new HashMap(); for (DfontResource res : e.resources) { String type = res.getTypeString(); if (type.equals("FONT")) type = "NFNT"; String key = type + res.getId(); int id = res.getId(); while (rsrc.getResource(type, id) != null) { id = random.nextInt(32768 - 256) + 256; } resmap.put(key, new DfontResource( type, id, res.getAttributes(), res.getName(), res.getData(), 0, res.getData().length )); } // Build list of FOND entries to add, renumbered if necessary. List entries = new ArrayList(); for (FONDEntry entry : e.fond.entries) { String type = ((entry.size == 0) ? "sfnt" : "NFNT"); String key = type + entry.id; int id = resmap.get(key).getId(); entries.add(new FONDEntry(entry.size, entry.style, id)); } // Update or create the FOND resource. FONDResource fond; DfontResource fondRes = rsrc.getResource("FOND", e.fond.name); if (fondRes == null) { fond = new FONDResource(e.fond, entries); while (rsrc.getResource("FOND", fond.id) != null) { fond.id = randomScriptId(fond.id); } try { byte[] data = fond.toByteArray(); fondRes = new DfontResource( "FOND", fond.id, 0x60, fond.name, data, 0, data.length ); if (!rsrc.addResource(fondRes)) return null; if (!addAllResources(resmap.values())) return null; } catch (IOException ioe) { ioe.printStackTrace(); return null; } } else { try { fond = new FONDResource(fondRes.getName(), fondRes.getData()); fond.entries.addAll(entries); byte[] data = fond.toByteArray(); fond.entries.retainAll(entries); fondRes.setData(data, 0, data.length); if (!addAllResources(resmap.values())) return null; } catch (IOException ioe) { ioe.printStackTrace(); return null; } } e = new ResourceBundle(e.icon, e.moverType, fond); e.resources.addAll(resmap.values()); return e; } private ResourceBundle addDeskAccessory(ResourceBundle e) { // Remove existing resource if it exists. for (ResourceBundle ee : items) { if (ee.moverType.equals(e.moverType) && ee.name.equals(e.name)) { remove(ee); break; } } // Renumber if necessary. e = e.clone(); while (containsAny(e.resources)) { int newOwnerId = random.nextInt(64); List newRes = new ArrayList(); for (DfontResource res : e.resources) { int newId; if (res.getId() == e.id) { newId = newOwnerId; } else if (res.getOwnerType() == DfontResource.OWNER_TYPE_DRVR && res.getOwnerId() == e.id) { newId = DfontResource.ownedId(DfontResource.OWNER_TYPE_DRVR, newOwnerId, res.getSubId()); } else { newId = res.getId(); } newRes.add(new DfontResource( res.getType(), newId, res.getAttributes(), res.getName(), res.getData(), 0, res.getData().length )); } e = new ResourceBundle(e.icon, e.moverType, e.name, newOwnerId); e.resources.addAll(newRes); } return addAllResources(e.resources) ? e : null; } private ResourceBundle addKeyboardLayout(ResourceBundle e) { // Remove existing resource if it exists. for (ResourceBundle ee : items) { if (ee.moverType.equals(e.moverType) && ee.name.equals(e.name)) { remove(ee); break; } } // Renumber if necessary. e = e.clone(); while (containsAny(e.resources)) { int newId = randomScriptId(e.id); List newRes = new ArrayList(); for (DfontResource res : e.resources) { newRes.add(new DfontResource( res.getType(), newId, res.getAttributes(), res.getName(), res.getData(), 0, res.getData().length )); } e = new ResourceBundle(e.icon, e.moverType, e.name, newId); e.resources.addAll(newRes); } return addAllResources(e.resources) ? e : null; } private ResourceBundle addSound(ResourceBundle e) { // Remove existing resource if it exists. for (ResourceBundle ee : items) { if (ee.moverType.equals(e.moverType) && ee.name.equals(e.name)) { remove(ee); break; } } // Renumber if necessary. e = e.clone(); while (containsAny(e.resources)) { int newId = random.nextInt(32768 - 256) + 256; List newRes = new ArrayList(); for (DfontResource res : e.resources) { newRes.add(new DfontResource( res.getType(), newId, res.getAttributes(), res.getName(), res.getData(), 0, res.getData().length )); } e = new ResourceBundle(e.icon, e.moverType, e.name, newId); e.resources.addAll(newRes); } return addAllResources(e.resources) ? e : null; } private ResourceBundle addGeneric(ResourceBundle e) { // Remove existing resource if it exists. for (ResourceBundle ee : items) { if (ee.moverType.equals(e.moverType) && ee.id == e.id) { remove(ee); break; } } // Don't renumber, just clobber anything with the same id. // (Should be done by the above but just in case.) e = e.clone(); for (DfontResource res : e.resources) rsrc.removeResource(res.getType(), res.getId()); return addAllResources(e.resources) ? e : null; } private int randomScriptId(int id) { if (id >= 0 && id < 16384) return random.nextInt(16383 - 256) + 256; return (id &~ 0x1FF) + random.nextInt(511 - 256) + 256; } private boolean containsAny(Iterable resources) { for (DfontResource res : resources) { if (rsrc.getResource(res.getType(), res.getId()) != null) { return true; } } return false; } private boolean addAllResources(Iterable resources) { for (DfontResource res : resources) { if (!rsrc.addResource(res)) { return false; } } return true; } public boolean contains(ResourceBundle e) { return items.contains(e); } public ResourceBundle get(int i) { return items.get(i); } public boolean isEmpty() { return items.isEmpty(); } public void remove(ResourceBundle e) { if (items.remove(e)) { for (DfontResource res : e.resources) { rsrc.removeResource(res); } if (e.fond != null) { // Update or remove FOND resource. DfontResource res = rsrc.getResource("FOND", e.fond.id); if (res != null) { try { FONDResource fond = new FONDResource(res.getName(), res.getData()); fond.entries.removeAll(e.fond.entries); if (fond.entries.isEmpty()) { rsrc.removeResource(res); } else { byte[] data = fond.toByteArray(); res.setData(data, 0, data.length); } } catch (IOException ioe) { ioe.printStackTrace(); } } // Remove base FONT resource if no other FONT resources are left. int base = e.fond.id << 7; res = rsrc.getResource("FONT", base); if (res != null) { for (int i = 1; i < 128; i++) { if (rsrc.getResource("FONT", base + i) != null) { return; } } rsrc.removeResource(res); } } } } public int size() { return items.size(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverFrame.java000066400000000000000000000023651506470510200315020ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.io.File; import java.io.IOException; import javax.swing.JFrame; import com.kreative.bitsnpicas.MacUtility; import com.kreative.unicode.ttflib.DfontFile; public class MoverFrame extends JFrame { private static final long serialVersionUID = 1L; private final SaveManager sm; private final MoverPanel panel; private final MoverMenuBar mb; public MoverFrame(File fork, DfontFile rsrc, MoverFile mf) { File file = (fork == null) ? null : MacUtility.getDataFork(fork); this.sm = new SaveManager(this, file, fork, rsrc); this.panel = new MoverPanel(this, file, mf, sm); this.mb = new MoverMenuBar(this, sm, panel.getTable()); setTitle((file == null) ? "Untitled Suitcase" : file.getName()); setJMenuBar(mb); setContentPane(panel); setSize(600, 400); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(sm); } public static MoverFrame forNewFile() throws IOException { DfontFile rsrc = new DfontFile(); return new MoverFrame(null, rsrc, new MoverFile(rsrc)); } public static MoverFrame forFile(File file) throws IOException { DfontFile rsrc = new DfontFile(file); return new MoverFrame(file, rsrc, new MoverFile(rsrc)); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverIcons.java000066400000000000000000000102451506470510200315170ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.io.File; import javax.swing.ImageIcon; import com.kreative.bitsnpicas.MacUtility; public class MoverIcons { public static final ImageIcon DA_16 = icon("DA.16.png", "desk accessory"); public static final ImageIcon DA_32 = icon("DA.32.png", "desk accessory"); public static final ImageIcon FILE_BLANK_16 = icon("File.Blank.16.png", "file"); public static final ImageIcon FILE_BLANK_32 = icon("File.Blank.32.png", "file"); public static final ImageIcon FILE_FKEY_16 = icon("File.FKEY.16.png", "function key"); public static final ImageIcon FILE_FKEY_32 = icon("File.FKEY.32.png", "function key"); public static final ImageIcon FILE_FONT_16 = icon("File.Font.16.png", "font"); public static final ImageIcon FILE_FONT_32 = icon("File.Font.32.png", "font"); public static final ImageIcon FILE_KEYBOARD_16 = icon("File.Keyboard.16.png", "keyboard layout"); public static final ImageIcon FILE_KEYBOARD_32 = icon("File.Keyboard.32.png", "keyboard layout"); public static final ImageIcon FILE_SCRIPT_16 = icon("File.Script.16.png", "script"); public static final ImageIcon FILE_SCRIPT_32 = icon("File.Script.32.png", "script"); public static final ImageIcon FILE_SOUND_16 = icon("File.Sound.16.png", "sound"); public static final ImageIcon FILE_SOUND_32 = icon("File.Sound.32.png", "sound"); public static final ImageIcon FILE_TRUETYPE_16 = icon("File.TrueType.16.png", "TrueType font"); public static final ImageIcon FILE_TRUETYPE_32 = icon("File.TrueType.32.png", "TrueType font"); public static final ImageIcon FILE_TTC_16 = icon("File.TTC.16.png", "TrueType collection"); public static final ImageIcon FILE_TTC_32 = icon("File.TTC.32.png", "TrueType collection"); public static final ImageIcon FILE_TTF_16 = icon("File.TTF.16.png", "TrueType flat font"); public static final ImageIcon FILE_TTF_32 = icon("File.TTF.32.png", "TrueType flat font"); public static final ImageIcon SUITCASE_BLANK_16 = icon("Suitcase.Blank.16.png", "suitcase"); public static final ImageIcon SUITCASE_BLANK_32 = icon("Suitcase.Blank.32.png", "suitcase"); public static final ImageIcon SUITCASE_DA_16 = icon("Suitcase.DA.16.png", "desk accessory suitcase"); public static final ImageIcon SUITCASE_DA_32 = icon("Suitcase.DA.32.png", "desk accessory suitcase"); public static final ImageIcon SUITCASE_FONT_16 = icon("Suitcase.Font.16.png", "font suitcase"); public static final ImageIcon SUITCASE_FONT_32 = icon("Suitcase.Font.32.png", "font suitcase"); public static final ImageIcon SUITCASE_SYSTEM_16 = icon("Suitcase.System.16.png", "system suitcase"); public static final ImageIcon SUITCASE_SYSTEM_32 = icon("Suitcase.System.32.png", "system suitcase"); private static ImageIcon icon(String name, String description) { return new ImageIcon(MoverIcons.class.getResource(name), description); } public static ImageIcon getFileIcon(File file) { String type = MacUtility.getType(file); String creator = MacUtility.getCreator(file); if (creator != null) { if (creator.equals("MACS") || creator.equals("macs")) { if (type != null) { if (type.equals("ZSYS") || type.equals("zsys")) { return SUITCASE_SYSTEM_32; } } } if (creator.equals("DMOV")) { if (type != null) { if (type.equals("DFIL")) return SUITCASE_DA_32; if (type.equals("FFIL")) return SUITCASE_FONT_32; } return SUITCASE_BLANK_32; } if (creator.equals("movr")) { if (type != null) { if (type.equals("dfil")) return DA_32; if (type.equals("ffil")) return FILE_FONT_32; if (type.equals("fkey")) return FILE_FKEY_32; if (type.equals("ifil")) return FILE_SCRIPT_32; if (type.equals("kfil")) return FILE_KEYBOARD_32; if (type.equals("sfil")) return FILE_SOUND_32; if (type.equals("tfil")) return FILE_TRUETYPE_32; } return FILE_BLANK_32; } } String name = file.getName(); int o = name.lastIndexOf("."); if (o > 0) { String ext = name.substring(o); if (ext.equalsIgnoreCase(".dfont")) return SUITCASE_FONT_32; if (ext.equalsIgnoreCase(".suit")) return SUITCASE_FONT_32; if (ext.equalsIgnoreCase(".ttc")) return FILE_TTC_32; if (ext.equalsIgnoreCase(".ttf")) return FILE_TTF_32; } return FILE_BLANK_32; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverInfoPanel.java000066400000000000000000000057131506470510200323230ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.BorderLayout; import java.awt.Font; import java.awt.GridLayout; import java.io.File; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.bitsnpicas.edit.glmlicon.GLMLListCellRenderer; import com.kreative.unicode.data.EncodingList; import com.kreative.unicode.data.GlyphList; public class MoverInfoPanel extends JPanel { private static final long serialVersionUID = 1L; private final JLabel iconLabel; private final JLabel fileNameLabel; private final JLabel kindLabel; private final JComboBox encoding; public MoverInfoPanel(File file) { ImageIcon icon; String fileName; if (file == null) { icon = MoverIcons.SUITCASE_FONT_32; fileName = "Untitled Suitcase"; } else { icon = MoverIcons.getFileIcon(file); fileName = file.getName(); } this.iconLabel = new JLabel(icon); this.fileNameLabel = new JLabel(fileName); this.kindLabel = new JLabel(icon.getDescription()); this.encoding = new JComboBox(EncodingList.instance().glyphLists().toArray()); encoding.setEditable(false); new GLMLListCellRenderer("encoding").apply(encoding); encoding.setSelectedItem(EncodingList.instance().getGlyphList("MacRoman")); kindLabel.setFont(kindLabel.getFont().deriveFont(Font.PLAIN)); fileNameLabel.setFont(fileNameLabel.getFont().deriveFont(Font.BOLD)); JPanel encodingPanel = new JPanel(new BorderLayout(8,8)); encodingPanel.add(new JLabel("Encoding:"), BorderLayout.LINE_START); encodingPanel.add(encoding, BorderLayout.CENTER); JPanel encodingOuterPanel = new JPanel(); encodingOuterPanel.setLayout(new BoxLayout(encodingOuterPanel, BoxLayout.PAGE_AXIS)); encodingOuterPanel.add(Box.createVerticalGlue()); encodingOuterPanel.add(encodingPanel); encodingOuterPanel.add(Box.createVerticalGlue()); JPanel labelPanel = new JPanel(new GridLayout(0,1,4,4)); labelPanel.add(fileNameLabel); labelPanel.add(kindLabel); JPanel mainPanel = new JPanel(new BorderLayout(12,12)); mainPanel.add(iconLabel, BorderLayout.LINE_START); mainPanel.add(labelPanel, BorderLayout.CENTER); mainPanel.add(encodingOuterPanel, BorderLayout.LINE_END); setLayout(new GridLayout()); add(mainPanel); } public void setFile(File file) { ImageIcon icon; String fileName; if (file == null) { icon = MoverIcons.SUITCASE_FONT_32; fileName = "Untitled Suitcase"; } else { icon = MoverIcons.getFileIcon(file); fileName = file.getName(); } iconLabel.setIcon(icon); fileNameLabel.setText(fileName); kindLabel.setText(icon.getDescription()); } public GlyphList getSelectedEncoding() { return (GlyphList)(encoding.getSelectedItem()); } public void setSelectedEncoding(GlyphList enc) { encoding.setSelectedItem(enc); } public boolean readOnly() { return !((ImageIcon)iconLabel.getIcon()).getDescription().contains("suitcase"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverMenuBar.java000066400000000000000000000041021506470510200317700ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.datatransfer.ClearMenuItem; import com.kreative.bitsnpicas.datatransfer.CopyMenuItem; import com.kreative.bitsnpicas.datatransfer.CutMenuItem; import com.kreative.bitsnpicas.datatransfer.PasteMenuItem; import com.kreative.bitsnpicas.edit.CommonMenuItems; public class MoverMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public MoverMenuBar(final Window window, final SaveManager sm, final MoverTable table) { add(new FileMenu(window, sm)); add(new EditMenu(table)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Window window, final SaveManager sm) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(window)); addSeparator(); add(new CommonMenuItems.SaveMenuItem(sm)); add(new CommonMenuItems.SaveAsMenuItem(sm)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(final MoverTable table) { super("Edit"); add(new CutMenuItem()); add(new CopyMenuItem()); add(new PasteMenuItem()); add(new ClearMenuItem()); addSeparator(); add(new OpenItemsMenuItem(table)); } } public static class OpenItemsMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenItemsMenuItem(final MoverTable table) { super("Open Items"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { table.doOpen(); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverPanel.java000066400000000000000000000033221506470510200315010ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; public class MoverPanel extends JPanel { private static final long serialVersionUID = 1L; private final MoverInfoPanel infoPanel; private final MoverTableModel tableModel; private final MoverTable table; private final JScrollPane tablePane; public MoverPanel(JFrame parent, File file, MoverFile mf, final SaveManager sm) { this.infoPanel = new MoverInfoPanel(file); this.tableModel = new MoverTableModel(mf); this.table = new MoverTable(tableModel, infoPanel); this.tablePane = new JScrollPane( table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ); sm.setInfoPanel(infoPanel); table.createDropTarget(tablePane); JPanel mainPanel = new JPanel(new BorderLayout()); infoPanel.setBorder(BorderFactory.createEmptyBorder(12, 16, 12, 16)); mainPanel.add(infoPanel, BorderLayout.PAGE_START); mainPanel.add(tablePane); setLayout(new BorderLayout()); add(mainPanel, BorderLayout.CENTER); tableModel.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { sm.setChanged(); } }); parent.addWindowListener(new WindowAdapter() { public void windowOpened(WindowEvent e) { table.requestFocusInWindow(); } }); } public MoverTableModel getTableModel() { return tableModel; } public MoverTable getTable() { return table; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverTable.java000066400000000000000000000234511506470510200314760ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Component; import java.awt.Dimension; import java.awt.FontFormatException; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.border.Border; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import com.kreative.bitsnpicas.BitmapFont; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.importer.NFNTBitmapFontImporter; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; public class MoverTable extends JTable { private static final long serialVersionUID = 1L; private final MoverInfoPanel ip; public MoverTable(MoverTableModel model, MoverInfoPanel ip) { super(model); setColumnWidth(0, 40); setColumnWidth(2, 100); setColumnWidth(4, 100); setDefaultRenderer(ImageIcon.class, new MyIconRenderer()); setDefaultRenderer(Integer.class, new MyCellRenderer()); setDefaultRenderer(String.class, new MyCellRenderer()); setIntercellSpacing(new Dimension(0,1)); setShowGrid(false); setRowHeight(19); this.ip = ip; this.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() >= 2) { doOpen(); } } }); InputMap im = getInputMap(); int skm = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, skm), "Cut"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, skm), "Copy"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, skm), "Paste"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, skm), "Clear"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, skm), "Clear"); ActionMap am = getActionMap(); am.put("Cut", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCut(); } }); am.put("Copy", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doCopy(); } }); am.put("Paste", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doPaste(); } }); am.put("Clear", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { doClear(); } }); DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY, new DragGestureListener() { public void dragGestureRecognized(DragGestureEvent e) { if (e.getDragOrigin().x < 40) { List rb = getSelectedItems(); if (rb.isEmpty()) return; e.startDrag(null, new ResourceSelection(rb)); } } } ); } public void createDropTarget(JComponent c) { new DropTarget(c, new DropTargetListener() { public void dragEnter(DropTargetDragEvent e) {} public void dragExit(DropTargetEvent e) {} public void dragOver(DropTargetDragEvent e) {} public void dropActionChanged(DropTargetDragEvent e) {} public void drop(DropTargetDropEvent e) { if (ip.readOnly()) return; try { e.acceptDrop(e.getDropAction()); Transferable t = e.getTransferable(); DataFlavor fl = ResourceSelection.resourceFlavor; if (t.isDataFlavorSupported(fl)) { List list = (List)t.getTransferData(fl); if (list != null && !list.isEmpty()) { MoverTableModel model = getMoverModel(); MoverFile mf = model.getMoverFile(); for (Object o : list) mf.add((ResourceBundle)o); model.refresh(); e.dropComplete(true); } else { e.dropComplete(false); } } else if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { List list = (List)t.getTransferData(DataFlavor.javaFileListFlavor); if (list != null && !list.isEmpty()) { for (Object o : list) { try { addFromFile(MacUtility.getResourceFork((File)o)); } catch (Exception ex2) { /* ignored */ } try { addFromFile((File)o); } catch (Exception ex2) { /* ignored */ } } e.dropComplete(true); } else { e.dropComplete(false); } } else { e.dropComplete(false); } } catch (Exception ex) { e.dropComplete(false); } } }); } public MoverTableModel getMoverModel() { return (MoverTableModel)getModel(); } public List getSelectedItems() { List list = new ArrayList(); MoverFile mf = getMoverModel().getMoverFile(); for (int i : getSelectedRows()) list.add(mf.get(i)); return list; } public void addFromFile(File f) throws IOException { if (ip.readOnly()) return; MoverTableModel model = getMoverModel(); MoverFile outmf = model.getMoverFile(); DfontFile rsrc = new DfontFile(f); MoverFile inmf = new MoverFile(rsrc); for (int i = 0, n = inmf.size(); i < n; i++) outmf.add(inmf.get(i)); model.refresh(); } public void doOpen() { List list = getSelectedItems(); if (list.isEmpty()) return; for (ResourceBundle rb : list) { if (rb.moverType.equals("ffil")) { try { BitmapFont[] fonts = new NFNTBitmapFontImporter.ResourceFile( ip.getSelectedEncoding()).importFont(rb); Main.openFonts(null, null, fonts); } catch (IOException ioe) { ioe.printStackTrace(); } } if (rb.moverType.equals("tfil")) { for (DfontResource res : rb.resources) { try { new TrueTypeFrame(res.getData()).setVisible(true); } catch (IOException e) { e.printStackTrace(); } catch (FontFormatException e) { e.printStackTrace(); } } } if (rb.moverType.equals("sfil")) { for (DfontResource res : rb.resources) { new SoundFrame(res).setVisible(true); } } if (rb.moverType.equals("kfil")) { for (DfontResource res : rb.resources) { if (res.getTypeString().equals("KCHR")) { new KeyboardFrame(res, ip.getSelectedEncoding()).setVisible(true); } } } } } public void doCut() { if (ip.readOnly()) return; doCopy(); doClear(); } public void doCopy() { List list = getSelectedItems(); if (list.isEmpty()) return; Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new ResourceSelection(list), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); } public void doPaste() { if (ip.readOnly()) return; Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); DataFlavor flavor = ResourceSelection.resourceFlavor; if (cb.isDataFlavorAvailable(flavor)) { try { List list = (List)cb.getData(flavor); if (list == null || list.isEmpty()) return; MoverTableModel model = getMoverModel(); MoverFile mf = model.getMoverFile(); for (Object o : list) mf.add((ResourceBundle)o); model.refresh(); } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void doClear() { if (ip.readOnly()) return; MoverTableModel model = getMoverModel(); MoverFile mf = model.getMoverFile(); for (ResourceBundle rb : getSelectedItems()) mf.remove(rb); model.refresh(); } private void setColumnWidth(int i, int width) { TableColumn col = getColumnModel().getColumn(i); col.setWidth(width); col.setMinWidth(width); col.setMaxWidth(width); } private static class MyIconRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private static final Border padding = BorderFactory.createEmptyBorder(0, 12, 0, 0); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JComponent c = (JComponent)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); c.setBorder(BorderFactory.createCompoundBorder(c.getBorder(), padding)); if (c instanceof JLabel) { JLabel label = (JLabel)c; label.setHorizontalAlignment(JLabel.CENTER); label.setIcon((Icon)value); label.setText(null); } return c; } } private static class MyCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private static final Border padding = BorderFactory.createEmptyBorder(0, 4, 0, 4); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JComponent c = (JComponent)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (c instanceof JLabel) ((JLabel)c).setHorizontalAlignment((column == 2) ? JLabel.RIGHT : JLabel.LEFT); c.setBorder(BorderFactory.createCompoundBorder(c.getBorder(), padding)); return c; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/MoverTableModel.java000066400000000000000000000025321506470510200324540ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import javax.swing.ImageIcon; import javax.swing.table.AbstractTableModel; public class MoverTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private MoverFile mf; public MoverTableModel(MoverFile mf) { this.mf = mf; } public MoverFile getMoverFile() { return mf; } public void refresh() { fireTableDataChanged(); } @Override public Class getColumnClass(int col) { switch (col) { case 0: return ImageIcon.class; case 1: return String.class; case 2: return String.class; case 3: return String.class; case 4: return Integer.class; default: return null; } } @Override public int getColumnCount() { return 5; } @Override public String getColumnName(int col) { switch (col) { case 0: return ""; case 1: return "Name"; case 2: return "Size"; case 3: return "Kind"; case 4: return "ID"; default: return null; } } @Override public int getRowCount() { return mf.size(); } @Override public Object getValueAt(int row, int col) { switch (col) { case 0: return mf.get(row).icon; case 1: return mf.get(row).name; case 2: return ((mf.get(row).length() + 1023) / 1024) + "K"; case 3: return mf.get(row).icon.getDescription(); case 4: return mf.get(row).id; default: return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/ResourceBundle.java000066400000000000000000000057031506470510200323570ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.ImageIcon; import com.kreative.unicode.ttflib.DfontResource; public class ResourceBundle implements Cloneable, Comparable { public final ImageIcon icon; public final String moverType; public final String name; public final int id; public final FONDResource fond; public final Set resources; public ResourceBundle(ImageIcon icon, String moverType, String name, int id) { this.icon = icon; this.moverType = moverType; this.name = name; this.id = id; this.fond = null; this.resources = new HashSet(); } public ResourceBundle(ImageIcon icon, String moverType, FONDResource fond) { this.icon = icon; this.moverType = moverType; this.name = fond.toString(); this.id = fond.id; this.fond = fond; this.resources = new HashSet(); } public int length() { int length = ((fond != null) ? fond.length() : 0); for (DfontResource res : resources) length += res.getData().length; return length; } @Override public ResourceBundle clone() { ResourceBundle copy; if (fond != null) { FONDResource newFOND = new FONDResource(fond, fond.entries); copy = new ResourceBundle(icon, moverType, newFOND); } else { copy = new ResourceBundle(icon, moverType, name, id); } for (DfontResource res : resources) { copy.resources.add(new DfontResource( res.getType(), res.getId(), res.getAttributes(), res.getName(), res.getData(), 0, res.getData().length )); } return copy; } @Override public int compareTo(ResourceBundle that) { return compare(this, that); } public static int compare(ResourceBundle a, ResourceBundle b) { List na = tokenize(a.name.trim()); List nb = tokenize(b.name.trim()); for (int i = 0; i < na.size() && i < nb.size(); i++) { try { double va = Double.parseDouble(na.get(i)); double vb = Double.parseDouble(nb.get(i)); int cmp = Double.compare(va, vb); if (cmp != 0) return cmp; } catch (NumberFormatException e) { int cmp = na.get(i).compareToIgnoreCase(nb.get(i)); if (cmp != 0) return cmp; } } return na.size() - nb.size(); } private static List tokenize(String s) { List tokens = new ArrayList(); StringBuffer token = new StringBuffer(); int tokenType = 0; CharacterIterator iter = new StringCharacterIterator(s); for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter.next()) { int tt = Character.isDigit(ch) ? 1 : Character.isLetter(ch) ? 2 : 3; if (tt != tokenType) { if (token.length() > 0) { tokens.add(token.toString()); token = new StringBuffer(); } tokenType = tt; } token.append(ch); } if (token.length() > 0) tokens.add(token.toString()); return tokens; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/ResourceSelection.java000066400000000000000000000051541506470510200330730ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.MacUtility; import com.kreative.unicode.ttflib.DfontFile; public class ResourceSelection implements ClipboardOwner, Transferable { // I has a flavor. public static final DataFlavor resourceFlavor = new DataFlavor(ResourceBundle.class, "Resource"); private List resources; public ResourceSelection(ResourceBundle res) { this.resources = new ArrayList(); this.resources.add(res.clone()); } public ResourceSelection(ResourceBundle[] ra) { this.resources = new ArrayList(); for (ResourceBundle res : ra) this.resources.add(res.clone()); } public ResourceSelection(List rl) { this.resources = new ArrayList(); for (ResourceBundle res : rl) this.resources.add(res.clone()); } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (resourceFlavor.equals(flavor)) { return resources; } else if (DataFlavor.javaFileListFlavor.equals(flavor)) { File tempLock = File.createTempFile("kbnptemp", ".tmp"); File tempRoot = new File(tempLock.getAbsolutePath() + "d"); tempLock.delete(); tempRoot.mkdir(); tempRoot.deleteOnExit(); List fileList = new ArrayList(); for (ResourceBundle res : resources) { DfontFile rsrc = new DfontFile(); MoverFile mf = new MoverFile(rsrc); mf.add(res); try { File tmp = new File(tempRoot, res.name); tmp.deleteOnExit(); tmp.createNewFile(); rsrc.write(MacUtility.getResourceFork(tmp)); MacUtility.setTypeAndCreator(tmp, res.moverType, "movr"); fileList.add(tmp); } catch (IOException e) { File tmp = new File(tempRoot, res.name + ".dfont"); tmp.deleteOnExit(); rsrc.write(tmp); fileList.add(tmp); } } return fileList; } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{ resourceFlavor, DataFlavor.javaFileListFlavor }; } public boolean isDataFlavorSupported(DataFlavor flavor) { return ( resourceFlavor.equals(flavor) || DataFlavor.javaFileListFlavor.equals(flavor) ); } public void lostOwnership(Clipboard clipboard, Transferable contents) { // nothing } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/SaveManager.java000066400000000000000000000056151506470510200316310ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import javax.swing.JFrame; import com.kreative.bitsnpicas.MacUtility; import com.kreative.bitsnpicas.edit.CommonMenuItems; import com.kreative.bitsnpicas.edit.Main; import com.kreative.bitsnpicas.edit.SaveChangesDialog; import com.kreative.bitsnpicas.edit.SaveInterface; import com.kreative.unicode.ttflib.DfontFile; public class SaveManager extends WindowAdapter implements SaveInterface { private JFrame frame; private File file; private File fork; private String type; private String creator; private DfontFile rsrc; private MoverInfoPanel ip; private boolean changed; public SaveManager(JFrame frame, File file, File fork, DfontFile rsrc) { this.frame = frame; this.file = file; this.fork = fork; if (file != null) { this.type = MacUtility.getType(file); this.creator = MacUtility.getCreator(file); if (type == null || type.equals("\0\0\0\0")) type = "FFIL"; if (creator == null || creator.equals("\0\0\0\0")) creator = "DMOV"; } else { this.type = "FFIL"; this.creator = "DMOV"; } this.rsrc = rsrc; this.changed = false; updateWindow(); } public void setInfoPanel(MoverInfoPanel ip) { this.ip = ip; } public void setChanged() { this.changed = true; updateWindow(); } public boolean save() { if (file == null || fork == null) return saveAs(); boolean succeeded = write(); if (succeeded) changed = false; updateWindow(); return succeeded; } public boolean saveAs() { File newFile = Main.getSaveFile(""); if (newFile == null) return false; file = newFile; if (newFile.getName().toLowerCase().endsWith(".dfont")) { fork = newFile; } else { try { newFile.createNewFile(); } catch (IOException e) {} MacUtility.setTypeAndCreator(newFile, type, creator); fork = MacUtility.getResourceFork(newFile); } boolean succeeded = write(); if (succeeded) changed = false; updateWindow(); return succeeded; } private boolean write() { try { rsrc.write(fork); return true; } catch (IOException e) { return false; } } public void windowClosing(WindowEvent e) { Window w = e.getWindow(); if (!changed) w.dispose(); else switch (new SaveChangesDialog(w, file.getName()).showDialog()) { case SAVE: if (save()) w.dispose(); break; case DONT_SAVE: w.dispose(); break; case CANCEL: break; } } private void updateWindow() { String fileName = (file == null) ? "Untitled Suitcase" : file.getName(); if (CommonMenuItems.IS_MAC_OS) { frame.getRootPane().putClientProperty("Window.documentFile", file); frame.getRootPane().putClientProperty("Window.documentModified", changed); frame.setTitle(fileName); } else { frame.setTitle(changed ? (fileName + " \u2022") : fileName); } if (ip != null) ip.setFile(file); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Sound.png000066400000000000000000000004431506470510200303650ustar00rootroot00000000000000PNG  IHDR DgAMAOX2tEXtSoftwareAdobe ImageReadyqe<PLTEfff@WtRNSރY}IDATxܓ9 El1$ሁnHLM2Pztjg:Rd0KR Ь0JZwL- 1bL,W?sǹ%GIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/SoundFrame.java000066400000000000000000000007401506470510200314750ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import javax.swing.JFrame; import com.kreative.unicode.ttflib.DfontResource; public class SoundFrame extends JFrame { private static final long serialVersionUID = 1L; public SoundFrame(DfontResource snd) { super(snd.getName()); setJMenuBar(new SoundMenuBar(this, snd)); setContentPane(new SoundPanel(snd)); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/SoundMenuBar.java000066400000000000000000000065001506470510200317740ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.edit.CommonMenuItems; import com.kreative.bitsnpicas.edit.Main; import com.kreative.unicode.ttflib.DfontResource; public class SoundMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public SoundMenuBar(final Window window, final DfontResource snd) { add(new FileMenu(window, snd)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Window window, final DfontResource snd) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(window)); addSeparator(); add(new SaveWavMenuItem(snd)); add(new SaveAiffMenuItem(snd)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static class SaveWavMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveWavMenuItem(final DfontResource snd) { super("Save as WAV..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, CommonMenuItems.SHORTCUT_KEY)); try { SoundResource sr = new SoundResource(snd.getData()); final byte[] wavData = sr.toWav(); if (wavData != null) { addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { File file = Main.getSaveFile(".wav"); if (file == null) return; try { FileOutputStream out = new FileOutputStream(file); out.write(wavData); out.flush(); out.close(); } catch (Exception ex) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); } } }); } else { setEnabled(false); } } catch (IOException ioe) { setEnabled(false); } } } public static class SaveAiffMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveAiffMenuItem(final DfontResource snd) { super("Save as AIFF..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, CommonMenuItems.SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); try { SoundResource sr = new SoundResource(snd.getData()); final byte[] aiffData = sr.toAiff(); if (aiffData != null) { addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { File file = Main.getSaveFile(".aiff"); if (file == null) return; try { FileOutputStream out = new FileOutputStream(file); out.write(aiffData); out.flush(); out.close(); } catch (Exception ex) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); } } }); } else { setEnabled(false); } } catch (IOException ioe) { setEnabled(false); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/SoundPanel.java000066400000000000000000000057631506470510200315140ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.ByteArrayInputStream; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import com.kreative.unicode.ttflib.DfontResource; public class SoundPanel extends JPanel { private static final long serialVersionUID = 1L; public SoundPanel(final DfontResource snd) { JLabel iconLabel = new JLabel(new ImageIcon(SoundPanel.class.getResource("Sound.png"))); iconLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT); JButton playButton = new JButton("Play Sound"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(playButton); buttonPanel.setAlignmentX(JPanel.CENTER_ALIGNMENT); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS)); mainPanel.add(Box.createGlue()); mainPanel.add(iconLabel); mainPanel.add(buttonPanel); mainPanel.add(Box.createGlue()); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setLayout(new GridLayout()); add(mainPanel); try { SoundResource sr = new SoundResource(snd.getData()); final byte[] aiffData = sr.toAiff(); final byte[] wavData = sr.toWav(); if (aiffData != null || wavData != null) { playButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (aiffData != null) { try { playSound(aiffData); return; } catch (UnsupportedAudioFileException ex) {} } if (wavData != null) { try { playSound(wavData); return; } catch (UnsupportedAudioFileException ex) {} } JOptionPane.showMessageDialog( null, "Could not produce audio in a supported format.", "Play Sound", JOptionPane.ERROR_MESSAGE ); } }); } else { playButton.setEnabled(false); } } catch (IOException e) { playButton.setEnabled(false); } } private static void playSound(byte[] stuff) throws UnsupportedAudioFileException { try { AudioInputStream st = AudioSystem.getAudioInputStream(new ByteArrayInputStream(stuff)); AudioFormat fm = st.getFormat(); DataLine.Info inf = new DataLine.Info(Clip.class, fm, ((int)st.getFrameLength()*fm.getFrameSize())); Clip c = (Clip)AudioSystem.getLine(inf); c.open(st); c.start(); c.drain(); c.close(); } catch (IOException e) { e.printStackTrace(); } catch (LineUnavailableException e) { e.printStackTrace(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/SoundResource.java000066400000000000000000000472421506470510200322420ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; public class SoundResource { public static final int SQUAREWAVESYNTH = 0x0001; public static final int WAVETABLESYNTH = 0x0003; public static final int SAMPLEDSYNTH = 0x0005; public static final int INITCHANLEFT = 0x0002; public static final int INITCHANRIGHT = 0x0003; public static final int WAVECHANNEL0 = 0x0004; public static final int WAVECHANNEL1 = 0x0005; public static final int WAVECHANNEL2 = 0x0006; public static final int WAVECHANNEL3 = 0x0007; public static final int INITMONO = 0x0080; public static final int INITSTEREO = 0x00C0; public static final int INITMACE3 = 0x0300; public static final int INITMACE6 = 0x0400; public static final int INITNOINTERP = 0x0004; public static final int INITNODROP = 0x0008; public static final int INITPANMASK = 0x0003; public static final int INITSRATEMASK = 0x0030; public static final int INITSTEREOMASK = 0x00C0; public static final int INITCOMPMASK = 0xFF00; public static final int NULLCMD = 0x0000; public static final int QUIETCMD = 0x0003; public static final int FLUSHCMD = 0x0004; public static final int REINITCMD = 0x0005; public static final int WAITCMD = 0x000A; public static final int PAUSECMD = 0x000B; public static final int RESUMECMD = 0x000C; public static final int CALLBACKCMD = 0x000D; public static final int SYNCCMD = 0x000E; public static final int AVAILABLECMD = 0x0018; public static final int VERSIONCMD = 0x0019; public static final int TOTALLOADCMD = 0x001A; public static final int LOADCMD = 0x001B; public static final int FREQDURATIONCMD = 0x0028; public static final int RESTCMD = 0x0029; public static final int FREQCMD = 0x002A; public static final int AMPCMD = 0x002B; public static final int TIMBRECMD = 0x002C; public static final int GETAMPCMD = 0x002D; public static final int VOLUMECMD = 0x002E; public static final int GETVOLUMECMD = 0x002F; public static final int WAVETABLECMD = 0x003C; public static final int SOUNDCMD = 0x0050; public static final int BUFFERCMD = 0x0051; public static final int RATECMD = 0x0052; public static final int GETRATECMD = 0x0055; public static final int COMMANDMASK = 0x7FFF; public static final int DATAOFFSETFLAG = 0x8000; public static final int RATE_44KHZ = 0xAC440000; public static final int RATE_22KHZ = 0x56EE8BA3; public static final int RATE_22050 = 0x56220000; public static final int RATE_11KHZ = 0x2B7745D1; public static final int RATE_11025 = 0x2B110000; public static final int ENCODE_STANDARD = 0; public static final int ENCODE_EXTENDED = -1; public static final int ENCODE_COMPRESSED = -2; public static final short EXPONENT_44KHZ = 0x400E; public static final long MANTISSA_44KHZ = 0xAC44000000000000L; public static final short EXPONENT_22KHZ = 0x400D; public static final long MANTISSA_22KHZ = 0xADDD1745D145826BL; public static final short EXPONENT_22050 = 0x400D; public static final long MANTISSA_22050 = 0xAC44000000000000L; public static final short EXPONENT_11KHZ = 0x400C; public static final long MANTISSA_11KHZ = 0xADDD1745D145826BL; public static final short EXPONENT_11025 = 0x400C; public static final long MANTISSA_11025 = 0xAC44000000000000L; public static final int FORMAT_NONE = 0x4E4F4E45; // NONE public static final int FORMAT_ACE_2TO1 = 0x41434532; // ACE2 public static final int FORMAT_ACE_8TO3 = 0x41434538; // ACE8 public static final int FORMAT_MACE_3TO1 = 0x4D414333; // MAC3 public static final int FORMAT_MACE_6TO1 = 0x4D414336; // MAC6 public static final int COMPID_NONE = 0; public static final int COMPID_ACE_2TO1 = 1; public static final int COMPID_ACE_8TO3 = 2; public static final int COMPID_MACE_3TO1 = 3; public static final int COMPID_MACE_6TO1 = 4; public static final int COMPID_USE_FORMAT = -1; private static final int RIFF = 0x52494646; // RIFF private static final int WAVE = 0x57415645; // WAVE private static final int FMT = 0x666D7420; // fmt private static final int DATA = 0x64617461; // data private static final int CYNH = 0x43796E68; // Cynh private static final int FORM = 0x464F524D; // FORM private static final int AIFC = 0x41494643; // AIFC private static final int FVER = 0x46564552; // FVER private static final int COMM = 0x434F4D4D; // COMM private static final int SSND = 0x53534E44; // SSND private static final byte[] COMPNAME_NONE = {0x0E,'n','o','t',' ','c','o','m','p','r','e','s','s','e','d',0}; private static final byte[] COMPNAME_ACE_2TO1 = {0x0A,'A','C','E',' ','2','-','t','o','-','1', 0 , 0 , 0 , 0 ,0}; private static final byte[] COMPNAME_ACE_8TO3 = {0x0A,'A','C','E',' ','8','-','t','o','-','3', 0 , 0 , 0 , 0 ,0}; private static final byte[] COMPNAME_MACE_3TO1 = {0x0B,'M','A','C','E',' ','3','-','t','o','-','1', 0 , 0 , 0 ,0}; private static final byte[] COMPNAME_MACE_6TO1 = {0x0B,'M','A','C','E',' ','6','-','t','o','-','1', 0 , 0 , 0 ,0}; public static final class DataFormat { public final int synthId; public final int initOption; private DataFormat(DataInputStream in) throws IOException { synthId = in.readShort(); initOption = in.readInt(); } } public static final class SoundCommand { public final int cmd; public final int param1; public final int param2; private SoundCommand(DataInputStream in) throws IOException { cmd = in.readShort(); param1 = in.readShort(); param2 = in.readInt(); } } public static final class SampledSoundHeader { public final int samplePtr; public final int length; public final int sampleRate; public final int loopStart; public final int loopEnd; public final int encode; public final int baseFrequency; private SampledSoundHeader(DataInputStream in) throws IOException { samplePtr = in.readInt(); length = in.readInt(); sampleRate = in.readInt(); loopStart = in.readInt(); loopEnd = in.readInt(); encode = in.readByte(); baseFrequency = in.readByte(); } } public static final class ExtendedSoundHeader { public final int samplePtr; public final int numChannels; public final int sampleRate; public final int loopStart; public final int loopEnd; public final int encode; public final int baseFrequency; public final int numFrames; public final short sampleRateExponent; public final long sampleRateMantissa; public final int markerChunk; public final int instrumentChunks; public final int aesRecording; public final int sampleSize; public final int futureUse1; public final int futureUse2; public final int futureUse3; public final int futureUse4; private ExtendedSoundHeader(SampledSoundHeader sh, DataInputStream in) throws IOException { samplePtr = sh.samplePtr; numChannels = sh.length; sampleRate = sh.sampleRate; loopStart = sh.loopStart; loopEnd = sh.loopEnd; encode = sh.encode; baseFrequency = sh.baseFrequency; numFrames = in.readInt(); sampleRateExponent = in.readShort(); sampleRateMantissa = in.readLong(); markerChunk = in.readInt(); instrumentChunks = in.readInt(); aesRecording = in.readInt(); sampleSize = in.readShort(); futureUse1 = in.readShort(); futureUse2 = in.readInt(); futureUse3 = in.readInt(); futureUse4 = in.readInt(); } } public static final class CompressedSoundHeader { public final int samplePtr; public final int numChannels; public final int sampleRate; public final int loopStart; public final int loopEnd; public final int encode; public final int baseFrequency; public final int numFrames; public final short sampleRateExponent; public final long sampleRateMantissa; public final int markerChunk; public final int format; public final int futureUse2; public final int stateVars; public final int leftOverSamples; public final int compressionId; public final int packetSize; public final int snthId; public final int sampleSize; private CompressedSoundHeader(SampledSoundHeader sh, DataInputStream in) throws IOException { samplePtr = sh.samplePtr; numChannels = sh.length; sampleRate = sh.sampleRate; loopStart = sh.loopStart; loopEnd = sh.loopEnd; encode = sh.encode; baseFrequency = sh.baseFrequency; numFrames = in.readInt(); sampleRateExponent = in.readShort(); sampleRateMantissa = in.readLong(); markerChunk = in.readInt(); format = in.readInt(); futureUse2 = in.readInt(); stateVars = in.readInt(); leftOverSamples = in.readInt(); compressionId = in.readShort(); packetSize = in.readShort(); snthId = in.readShort(); sampleSize = in.readShort(); } private byte[] decompress(byte[] data) { switch (compressionId) { case COMPID_USE_FORMAT: switch (format) { case FORMAT_NONE: return data; case FORMAT_MACE_3TO1: return MACEDecoder.decompressMACE3(data, numChannels); case FORMAT_MACE_6TO1: return MACEDecoder.decompressMACE6(data, numChannels); default: return null; } case COMPID_NONE: return data; case COMPID_MACE_3TO1: return MACEDecoder.decompressMACE3(data, numChannels); case COMPID_MACE_6TO1: return MACEDecoder.decompressMACE6(data, numChannels); default: return null; } } } public static final class SampledSound { public final SampledSoundHeader std; public final ExtendedSoundHeader ext; public final CompressedSoundHeader cmp; public final int dataLength; public final byte[] data; public SampledSound(byte[] data) throws IOException { this(new DataInputStream(new ByteArrayInputStream(data))); } private SampledSound(DataInputStream in) throws IOException { std = new SampledSoundHeader(in); switch (std.encode) { case ENCODE_STANDARD: ext = null; cmp = null; dataLength = std.length; data = new byte[dataLength]; in.readFully(data); break; case ENCODE_EXTENDED: ext = new ExtendedSoundHeader(std, in); cmp = null; dataLength = ext.numChannels * ext.numFrames * ((ext.sampleSize + 7) / 8); data = new byte[dataLength]; in.readFully(data); break; case ENCODE_COMPRESSED: ext = null; cmp = new CompressedSoundHeader(std, in); dataLength = cmp.numChannels * cmp.numFrames * ((cmp.packetSize + 7) / 8); data = new byte[dataLength]; in.readFully(data); break; default: ext = null; cmp = null; dataLength = 0; data = null; break; } } } public final int format; public final int refCon; public final List dataFormats; public final List soundCommands; public final Map soundData; public SoundResource(byte[] data) throws IOException { this(new DataInputStream(new ByteArrayInputStream(data)), data.length); } private SoundResource(DataInputStream in, int length) throws IOException { this.format = in.readShort(); this.refCon = in.readShort(); if (this.format == 1) { List dataFormats = new ArrayList(refCon); for (int i = 0; i < refCon; i++) dataFormats.add(new DataFormat(in)); this.dataFormats = Collections.unmodifiableList(dataFormats); } else { this.dataFormats = null; } int numCommands = in.readShort(); List soundCommands = new ArrayList(numCommands); for (int i = 0; i < numCommands; i++) soundCommands.add(new SoundCommand(in)); this.soundCommands = Collections.unmodifiableList(soundCommands); TreeSet dataOffsets = new TreeSet(); for (SoundCommand sc : soundCommands) { if ((sc.cmd & DATAOFFSETFLAG) != 0) { dataOffsets.add(sc.param2); } } dataOffsets.add(length); Map soundData = new HashMap(); for (SoundCommand sc : soundCommands) { if ((sc.cmd & DATAOFFSETFLAG) != 0) { in.reset(); in.skipBytes(sc.param2); int len = dataOffsets.higher(sc.param2) - sc.param2; byte[] data = new byte[len]; in.readFully(data); soundData.put(sc.param2, data); } } this.soundData = Collections.unmodifiableMap(soundData); } public SampledSound toSampledSound() { if (format == 1 || format == 2) { for (SoundCommand sc : soundCommands) { if ((sc.cmd & DATAOFFSETFLAG) != 0) { int cmd = sc.cmd & COMMANDMASK; if (cmd == SOUNDCMD || cmd == BUFFERCMD) { try { return new SampledSound(soundData.get(sc.param2)); } catch (IOException e) { return null; } } } } } return null; } public byte[] toWav() { SampledSound snd = toSampledSound(); if (snd == null) return null; byte[] data = snd.data; if (data == null || data.length == 0) return null; int numChannels; int bitsPerSample; int bytesPerSample; switch (snd.std.encode) { case ENCODE_STANDARD: numChannels = 1; bitsPerSample = 8; bytesPerSample = 1; break; case ENCODE_EXTENDED: numChannels = snd.ext.numChannels; bitsPerSample = snd.ext.sampleSize; bytesPerSample = ((snd.ext.sampleSize + 7) / 8); break; case ENCODE_COMPRESSED: numChannels = snd.cmp.numChannels; bitsPerSample = snd.cmp.sampleSize; bytesPerSample = ((snd.cmp.sampleSize + 7) / 8); data = snd.cmp.decompress(data); if (data == null) return null; break; default: return null; } // If *compressed* 8-bit audio, flip signedness. if (data != snd.data && bytesPerSample == 1) { for (int i = 0; i < data.length; i++) data[i] ^= 0x80; } // If 16-bit audio, swap endianness (as WAV is a little-endian format). if (bytesPerSample > 1) { for (int i = 0; i < data.length; i += bytesPerSample) { for (int j = 0, k = bytesPerSample - 1; j < k; j++, k--) { byte t = data[i+j]; data[i+j] = data[i+k]; data[i+k] = t; } } } int padding = 0; while (((data.length + padding) & 3) != 0) padding++; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream out2 = new DataOutputStream(out); // RIFF header out2.writeInt(RIFF); out2.writeInt(Integer.reverseBytes(56 + data.length + padding)); out2.writeInt(WAVE); // FMT chunk out2.writeInt(FMT); out2.writeInt(Integer.reverseBytes(16)); out2.writeShort(Short.reverseBytes((short)1)); out2.writeShort(Short.reverseBytes((short)numChannels)); out2.writeInt(Integer.reverseBytes(snd.std.sampleRate >>> 16)); out2.writeInt(Integer.reverseBytes((snd.std.sampleRate >>> 16) * bytesPerSample * numChannels)); out2.writeShort(Short.reverseBytes((short)(bytesPerSample * numChannels))); out2.writeShort(Short.reverseBytes((short)bitsPerSample)); // DATA chunk out2.writeInt(DATA); out2.writeInt(Integer.reverseBytes(data.length + padding)); out2.write(data); out2.write(new byte[padding]); // CYNTH chunk out2.writeInt(CYNH); out2.writeInt(Integer.reverseBytes(12)); out2.writeInt(Integer.reverseBytes(snd.std.loopStart)); out2.writeInt(Integer.reverseBytes(snd.std.loopEnd)); out2.writeInt(Integer.reverseBytes(snd.std.baseFrequency)); // done out2.close(); out.close(); return out.toByteArray(); } catch (IOException ioe) { return null; } } public byte[] toAiff() { SampledSound snd = toSampledSound(); if (snd == null) return null; byte[] data = snd.data; if (data == null || data.length == 0) return null; int numChannels; int numFrames; int bitsPerSample; short sampleRateExponent; long sampleRateMantissa; int format; byte[] compName; switch (snd.std.encode) { case ENCODE_STANDARD: numChannels = 1; numFrames = snd.std.length; bitsPerSample = 8; switch (snd.std.sampleRate) { case RATE_44KHZ: sampleRateExponent = EXPONENT_44KHZ; sampleRateMantissa = MANTISSA_44KHZ; break; case RATE_22KHZ: sampleRateExponent = EXPONENT_22KHZ; sampleRateMantissa = MANTISSA_22KHZ; break; case RATE_22050: sampleRateExponent = EXPONENT_22050; sampleRateMantissa = MANTISSA_22050; break; case RATE_11KHZ: sampleRateExponent = EXPONENT_11KHZ; sampleRateMantissa = MANTISSA_11KHZ; break; case RATE_11025: sampleRateExponent = EXPONENT_11025; sampleRateMantissa = MANTISSA_11025; break; default: double sampleRateFP = snd.std.sampleRate & 0xFFFFFFFFL; long sampleRateBits = Double.doubleToLongBits(sampleRateFP); sampleRateExponent = (short)((sampleRateBits >> 52) + 15344); sampleRateMantissa = (((1L << 52) | sampleRateBits) << 11); break; } format = FORMAT_NONE; compName = COMPNAME_NONE; break; case ENCODE_EXTENDED: numChannels = snd.ext.numChannels; numFrames = snd.ext.numFrames; bitsPerSample = snd.ext.sampleSize; sampleRateExponent = snd.ext.sampleRateExponent; sampleRateMantissa = snd.ext.sampleRateMantissa; format = FORMAT_NONE; compName = COMPNAME_NONE; break; case ENCODE_COMPRESSED: numChannels = snd.cmp.numChannels; numFrames = snd.cmp.numFrames; bitsPerSample = snd.cmp.sampleSize; sampleRateExponent = snd.cmp.sampleRateExponent; sampleRateMantissa = snd.cmp.sampleRateMantissa; switch (snd.cmp.compressionId) { case COMPID_USE_FORMAT: switch (snd.cmp.format) { case FORMAT_NONE: format = FORMAT_NONE; compName = COMPNAME_NONE; break; case FORMAT_ACE_2TO1: format = FORMAT_ACE_2TO1; compName = COMPNAME_ACE_2TO1; break; case FORMAT_ACE_8TO3: format = FORMAT_ACE_8TO3; compName = COMPNAME_ACE_8TO3; break; case FORMAT_MACE_3TO1: format = FORMAT_MACE_3TO1; compName = COMPNAME_MACE_3TO1; break; case FORMAT_MACE_6TO1: format = FORMAT_MACE_6TO1; compName = COMPNAME_MACE_6TO1; break; default: format = snd.cmp.format; compName = new byte[16]; break; } break; case COMPID_NONE: format = FORMAT_NONE; compName = COMPNAME_NONE; break; case COMPID_ACE_2TO1: format = FORMAT_ACE_2TO1; compName = COMPNAME_ACE_2TO1; break; case COMPID_ACE_8TO3: format = FORMAT_ACE_8TO3; compName = COMPNAME_ACE_8TO3; break; case COMPID_MACE_3TO1: format = FORMAT_MACE_3TO1; compName = COMPNAME_MACE_3TO1; break; case COMPID_MACE_6TO1: format = FORMAT_MACE_6TO1; compName = COMPNAME_MACE_6TO1; break; default: return null; } break; default: return null; } // If *uncompressed* 8-bit audio, flip signedness. if (format == FORMAT_NONE && bitsPerSample <= 8) { for (int i = 0; i < data.length; i++) data[i] ^= 0x80; } int padding = 0; while (((data.length + padding) & 3) != 0) padding++; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream out2 = new DataOutputStream(out); // form chunk out2.writeInt(FORM); out2.writeInt(98 + data.length + padding); out2.writeInt(AIFC); // format version chunk out2.writeInt(FVER); out2.writeInt(4); out2.writeInt(0xA2805140); // common chunk out2.writeInt(COMM); out2.writeInt(38); out2.writeShort(numChannels); out2.writeInt(numFrames); out2.writeShort(bitsPerSample); out2.writeShort(sampleRateExponent); out2.writeLong(sampleRateMantissa); out2.writeInt(format); out2.write(compName); // cynth chunk out2.writeInt(CYNH); out2.writeInt(12); out2.writeInt(snd.std.loopStart); out2.writeInt(snd.std.loopEnd); out2.writeInt(snd.std.baseFrequency); // sound data chunk out2.writeInt(SSND); out2.writeInt(8 + data.length); out2.writeInt(0); out2.writeInt(0); out2.write(data); out2.write(new byte[padding]); // done out2.close(); out.close(); return out.toByteArray(); } catch (IOException ioe) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Suitcase.Blank.16.png000066400000000000000000000024541506470510200323340ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}JQ]EESBƅyeo0\YftƊbq*.f2Ppr=.lEHO+ZqAIӔpnG8{srFxxR>^*yo6.""~z,] tIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Suitcase.Blank.32.png000066400000000000000000000037711506470510200323350ustar00rootroot00000000000000PNG  IHDR szziCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXŗnW?'YvC"hPRGTU`O@1ĢP1j(,"BbEJxIڐJ\ihUmZ Ќbx6 CY"Z}_o޼ jTՁX%p U0>~80Ƥjjтz-l/A%ѣ} y \.Ss[0 rZUj=ebbbH\VqqDuL?ĂUJ?55gow$ӂx+U=*JvQU8FUP -f7$/qR(ЧªbUv @|O襫w`h֠+ 31NI;nl{wHOҬ$3ϒX#Q@vc!ަzڗ$~gJS-T@}Lm[Fw=,--oHg$mƉ2]5dŋt3Ky嫍Ą/2Wg<=bcc3lmn1990X@{UN<[σ i4w8<6ƱcǾ~p}WIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Suitcase.DA.16.png000066400000000000000000000024331506470510200315660ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8NQE.v ۸Ha–e$*#"?&U$(Z|n)_@HΕߛH)ӝGz*AAtOgVƘNy'MS0 aQHGD4m (fS$p[[[DDUU4գ#nk$ AMk-j`@QE@級M v,,v2ZOZ&I1QPY_1q?rc`b-ZsXkF4 D((~rsxpZ߱Z Q-lNs8&t0͝V,8*9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  ZIDATXŗMoW'YvHH"WTU^¦XD*,+Š2.oڨPGJU[ 9]ܙ8Hҝ<==3SSUeLE`#MS8 &AEk:61Z-&&'7:/]+j6vԌ1s(X]]%1Aunn2痖0)R3ht:49Gi Wlm~z_h *2QQױrqyϯ\!˲QDϞrsDQD MS:V I4t>9XS ǿP*$ AB#L 6gΜ!"0yi sa%ݯ3&juVVVh4C iri/-EѾ,Z3[@L= ^ r_*8rp +hە}Ekͼ>O ֪'cC U f4nwĦ 2O@~=ԩSc@v0 t:%LJ/_͝+׿`nnn$ C6'N@|ݻ? "-7dNO^Q\jVU.((I#JGUɲ U(o~~xLrs2`=fYް+H3dRw%@1|  iEkZwc7+-*j2+ڣU ]]]0`~JP̓h|dx8j-sA@фW >>A>N cG ,+hs1[1 :h f%.#=whV(^O+ ?DrQ1/' VKP/:yiv?{q?xU^yӎ$5o|GϟM8 fEq&`Z88G`Ŀa~~~mwrx H¹.B PɓjoZ$337 "\IENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Suitcase.Font.16.png000066400000000000000000000024751506470510200322160ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}NQ3P6Jlkb0l֥># /Ψ#̵re F&j=Ņ}^ThE*"Y;d\Ƙv^ yu5ƴD-"EZ-fheueeESj皦j42tyys%zeYR%ZI£EfQ!*s\\LȲnKyO۝2Ny9s8q1 X__GD㘲,9889_Q9G*1Y]]eww'i:!,qvv1|k|P.`$}8>=oZ*9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  >IDATXŗ?c6Ik*` v{tC{3hi$qDrF8ѡB7,][J[=i4cSg4驥uEg(Zy,7Ǐ-,6A׎RQDQڡ1n˱ɓ'ӻז2ƬCk-Itc A6Z^]kc(?ޑic424%sq|H# ?DwTL9iIh4w;w ~Dž jTmXk988@d[יŷCtF h-"v*Ƿ Rj~i~2sQeo4]DAE >GUǨ*eY*QLe^Yt^q@)yڈ >z0۫?2.Rg+Rg ^ytTǥo3Onb8&8ݻwwܺP(?zDQtfW;10 9s,~<8 7փ WhCh4O>]E_lZicueYvVC6SO njx@Rot|k?gYhUV&n?<>دL߁#|Φ/dIMO9 ~$#bB rj˧NʩS;w}3jkG2gIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/Suitcase.System.16.png000066400000000000000000000024341506470510200325670ustar00rootroot00000000000000PNG  IHDRaiCCPICC Profile(Kaǿ(A`f{CHLeD宿شmY컻"^:f=**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDAT8}=n@]  qJ" A  t OӤ@uqI^ 1NJ"-;7o*Ot20 UDF7=`mQQc~:9!2NG#^2aPtkZm}"Yi$ p84MU#"e9eIY, >ovv\8zV8績`'MS8ϗ38ntY+69s8qqyyt:^GYf3~]]pY8 Cb4h#"L8Wq) %#VxߜŢqěk**9R,"t%1)fm-%*t̩vOvSA\\zN=/EN1I pHYs  IDATXŗMoV'#unB ) VH T 5b_@1$QTXbEv xU!2j)kZj+aӅ?pf<$Hi$<=9D5;< H0 Y__$Iu?޻֚4M b0Fѣ9ydHض I۶+0cR1 "z=N8Am$ Zk1,;'vD@AA`D*E~ܜ mHǏ@c7o"RJP䥂}VZJNؾkQK)%7Q OnL8Xm Mk6.]bjj6MT$kǎ<ayyG28|' Lf*1UI\%z9rt:fff0[(`@ٝ}QM!QӯMmEH3Smt ?GQ5'k]L]y☩)0<{Z| >vqaY%JJSav>Y""d&x |9Д۰9pֻ읞׀rk| [oIENDB`bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/TrueTypeFrame.java000066400000000000000000000013011506470510200321600ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Font; import java.awt.FontFormatException; import java.io.ByteArrayInputStream; import java.io.IOException; import javax.swing.JFrame; public class TrueTypeFrame extends JFrame { private static final long serialVersionUID = 1L; public TrueTypeFrame(byte[] fontData) throws IOException, FontFormatException { Font font = Font.createFont(Font.TRUETYPE_FONT, new ByteArrayInputStream(fontData)); setTitle(font.getFontName()); setJMenuBar(new TrueTypeMenuBar(this, fontData)); setContentPane(new TrueTypePanel(font)); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/TrueTypeMenuBar.java000066400000000000000000000036571506470510200324770ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import com.kreative.bitsnpicas.edit.CommonMenuItems; import com.kreative.bitsnpicas.edit.Main; public class TrueTypeMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public TrueTypeMenuBar(final Window window, final byte[] fontData) { add(new FileMenu(window, fontData)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(final Window window, final byte[] fontData) { super("File"); add(new CommonMenuItems.NewMenu()); add(new CommonMenuItems.OpenMenuItem()); add(new CommonMenuItems.CloseMenuItem(window)); addSeparator(); add(new SaveMenuItem(fontData)); if (!CommonMenuItems.IS_MAC_OS) { addSeparator(); add(new CommonMenuItems.ExitMenuItem()); } } } public static class SaveMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveMenuItem(final byte[] fontData) { super("Save as TTF..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, CommonMenuItems.SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { File file = Main.getSaveFile(".ttf"); if (file == null) return; try { FileOutputStream out = new FileOutputStream(file); out.write(fontData); out.flush(); out.close(); } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); } } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/mover/TrueTypePanel.java000066400000000000000000000034531506470510200321770ustar00rootroot00000000000000package com.kreative.bitsnpicas.mover; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.JTextArea; public class TrueTypePanel extends JPanel { private static final long serialVersionUID = 1L; public TrueTypePanel(Font font) { JTextArea l1 = make("How razorback-jumping frogs can level six piqued gymnasts!"); JTextArea l2 = make("Cozy lummox gives smart squid who asks for job pen."); JTextArea l3 = make("The quick brown fox jumps over the lazy dog."); l1.setFont(font.deriveFont(9f)); l2.setFont(font.deriveFont(12f)); l3.setFont(font.deriveFont(18f)); l1.setBorder(BorderFactory.createTitledBorder("9 point")); l2.setBorder(BorderFactory.createTitledBorder("12 point")); l3.setBorder(BorderFactory.createTitledBorder("18 point")); l1.setMinimumSize(new Dimension(288,72)); l2.setMinimumSize(new Dimension(288,108)); l3.setMinimumSize(new Dimension(288,144)); l1.setPreferredSize(new Dimension(288,72)); l2.setPreferredSize(new Dimension(288,108)); l3.setPreferredSize(new Dimension(288,144)); l1.setMaximumSize(new Dimension(288,72)); l2.setMaximumSize(new Dimension(288,108)); l3.setMaximumSize(new Dimension(288,144)); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS)); mainPanel.add(l1); mainPanel.add(l2); mainPanel.add(l3); mainPanel.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); setLayout(new GridLayout()); add(mainPanel); } private static JTextArea make(String s) { JTextArea a = new JTextArea(s); a.setWrapStyleWord(true); a.setLineWrap(true); a.setOpaque(false); a.setEditable(false); a.setFocusable(false); a.setBackground(null); return a; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/000077500000000000000000000000001506470510200263645ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/AbstractCategoryCodec.java000066400000000000000000000047521506470510200334360ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public abstract class AbstractCategoryCodec extends PuaaCodec { protected final String fileName; protected final String propName; protected final List propValues; protected AbstractCategoryCodec(String fileName, String propName, List propValues) { this.fileName = fileName; this.propName = propName; this.propValues = propValues; } @Override public String getFileName() { return fileName; } @Override public String[] getPropertyNames() { return new String[]{propName}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable(propName); st.addAll(PuaaUtility.createEntriesFromStringMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable(propName); if (values == null || values.isEmpty()) return; List runs = PuaaUtility.createRunsFromEntries(values); Collections.sort(runs, new Comparator() { @Override public int compare(PuaaSubtableEntry.Single a, PuaaSubtableEntry.Single b) { int va = propValues.indexOf(a.value); int vb = propValues.indexOf(b.value); if (va != vb) return va - vb; int cmp = a.value.compareTo(b.value); if (cmp != 0) return cmp; if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }); for (PuaaSubtableEntry.Single e : runs) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/AbstractPropListCodec.java000066400000000000000000000043551506470510200334340ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public abstract class AbstractPropListCodec extends PuaaCodec { protected final String fileName; protected final List propNames; protected AbstractPropListCodec(String fileName, List propNames) { this.fileName = fileName; this.propNames = propNames; } @Override public String getFileName() { return fileName; } @Override public String[] getPropertyNames() { return propNames.toArray(new String[propNames.size()]); } @Override public void compile(PuaaTable puaa, Scanner in) { Map> props = new HashMap>(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String prop = fields[1].trim(); if (props.containsKey(prop)) { Map p = props.get(prop); for (int cp = r[0]; cp <= r[1]; cp++) p.put(cp, true); } else { Map p = new HashMap(); for (int cp = r[0]; cp <= r[1]; cp++) p.put(cp, true); props.put(prop, p); } } catch (NumberFormatException nfe) {} } for (Map.Entry> e : props.entrySet()) { PuaaSubtable st = puaa.getOrCreateSubtable(e.getKey()); st.addAll(PuaaUtility.createEntriesFromBooleanMap(e.getValue())); } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { for (String prop : propNames) { PuaaSubtable props = puaa.getSubtable(prop); if (props == null || props.isEmpty()) continue; for (PuaaSubtableEntry.Single e : PuaaUtility.createRunsFromEntries(props)) { if ("Y".equalsIgnoreCase(e.value)) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(prop); out.println(sb.toString()); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/AbstractStringCodec.java000066400000000000000000000032101506470510200331130ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public abstract class AbstractStringCodec extends PuaaCodec { protected final String fileName; protected final String propName; protected AbstractStringCodec(String fileName, String propName) { this.fileName = fileName; this.propName = propName; } @Override public String getFileName() { return fileName; } @Override public String[] getPropertyNames() { return new String[]{propName}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable(propName); st.addAll(PuaaUtility.createEntriesFromStringMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable(propName); if (values == null || values.isEmpty()) return; for (PuaaSubtableEntry.Single e : PuaaUtility.createRunsFromEntries(values)) { out.println(format(PuaaUtility.joinRange(e), e.value)); } } protected abstract String format(String range, String value); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/AbstractUnihanCodec.java000066400000000000000000000076341506470510200331050ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public abstract class AbstractUnihanCodec extends PuaaCodec { protected final String fileName; protected final List propNames; protected AbstractUnihanCodec(String fileName, List propNames) { this.fileName = fileName; this.propNames = propNames; } @Override public String getFileName() { return fileName; } @Override public String[] getPropertyNames() { return propNames.toArray(new String[propNames.size()]); } @Override public void compile(PuaaTable puaa, Scanner in) { Map> props = new HashMap>(); while (in.hasNextLine()) { String line = in.nextLine().trim(); if (line.length() == 0 || line.startsWith("#")) continue; String[] fields = line.split("\\s+", 3); if (fields.length < 3) continue; try { int cp = Integer.parseInt(fields[0].replaceAll("^([Uu][+]|[0][Xx])", ""), 16); String prop = fields[1]; String value = fields[2]; if (props.containsKey(prop)) { Map p = props.get(prop); p.put(cp, value); } else { Map p = new HashMap(); p.put(cp, value); props.put(prop, p); } } catch (NumberFormatException nfe) {} } List elist; for (Map.Entry> e : props.entrySet()) { PuaaSubtable st = puaa.getOrCreateSubtable(e.getKey()); if ((elist = toDecimalEntries(e.getValue())) != null) st.addAll(elist); else if ((elist = toHexadecimalEntries(e.getValue())) != null) st.addAll(elist); else st.addAll(PuaaUtility.createEntriesFromNameMap(e.getValue())); } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { Map> props = new TreeMap>(); for (String prop : propNames) { PuaaSubtable st = puaa.getSubtable(prop); if (st == null || st.isEmpty()) continue; for (Map.Entry e : PuaaUtility.createMapFromEntries(st).entrySet()) { if (props.containsKey(e.getKey())) { Map p = props.get(e.getKey()); p.put(prop, e.getValue()); } else { Map p = new TreeMap(); p.put(prop, e.getValue()); props.put(e.getKey(), p); } } } for (Map.Entry> e : props.entrySet()) { String cps = "U+" + PuaaUtility.toHexString(e.getKey()); for (String prop : propNames) { String value = e.getValue().get(prop); if (value == null || value.length() == 0) continue; out.println(cps + "\t" + prop + "\t" + value); } } } private static List toDecimalEntries(Map smap) { Map dmap = new HashMap(); for (Map.Entry e : smap.entrySet()) { try { int iv = Integer.parseInt(e.getValue(), 10); if (Integer.toString(iv).equals(e.getValue())) { dmap.put(e.getKey(), iv); } else { return null; } } catch (NumberFormatException nfe) { return null; } } return PuaaUtility.createEntriesFromDecimalMap(dmap); } private static List toHexadecimalEntries(Map smap) { Map dmap = new HashMap(); for (Map.Entry e : smap.entrySet()) { try { int iv = Integer.parseInt(e.getValue(), 16); if (PuaaUtility.toHexString(iv).equals(e.getValue())) { dmap.put(e.getKey(), iv); } else { return null; } } catch (NumberFormatException nfe) { return null; } } return PuaaUtility.createEntriesFromHexadecimalMap(dmap); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/ArabicShapingCodec.java000066400000000000000000000050271506470510200326640ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Scanner; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class ArabicShapingCodec extends PuaaCodec { @Override public String getFileName() { return "ArabicShaping.txt"; } @Override public String[] getPropertyNames() { return new String[]{ "Joining_Type", "Joining_Group", }; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap types = new HashMap(); HashMap groups = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 4) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String t = fields[2].trim(); String g = fields[3].trim(); for (int cp = r[0]; cp <= r[1]; cp++) { types.put(cp, t); groups.put(cp, g); } } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Joining_Type"); st.addAll(PuaaUtility.createEntriesFromStringMap(types)); st = puaa.getOrCreateSubtable("Joining_Group"); st.addAll(PuaaUtility.createEntriesFromNameMap(groups)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable names = puaa.getSubtable("Name"); PuaaSubtable types = puaa.getSubtable("Joining_Type"); PuaaSubtable groups = puaa.getSubtable("Joining_Group"); TreeMap lines = new TreeMap(); if (types != null) for (PuaaSubtableEntry e : types) addLine(names, lines, e, 2); if (groups != null) for (PuaaSubtableEntry e : groups) addLine(names, lines, e, 3); for (String[] line : lines.values()) out.println(PuaaUtility.joinLine(line, "; ")); } private static void addLine(PuaaSubtable names, TreeMap lines, PuaaSubtableEntry e, int i) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { String value = e.getPropertyValue(cp); if (value == null || value.length() == 0) continue; if (lines.containsKey(cp)) { String[] line = lines.get(cp); if (line[i] == null) line[i] = value; else line[i] += value; } else { String[] line = new String[4]; line[0] = PuaaUtility.toHexString(cp); if (names != null) line[1] = names.getPropertyValue(cp); line[i] = value; lines.put(cp, line); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/BidiBracketsCodec.java000066400000000000000000000047271506470510200325250ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Scanner; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class BidiBracketsCodec extends PuaaCodec { @Override public String getFileName() { return "BidiBrackets.txt"; } @Override public String[] getPropertyNames() { return new String[]{ "Bidi_Paired_Bracket", "Bidi_Paired_Bracket_Type", }; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); HashMap types = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 3) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); int v = Integer.parseInt(fields[1].trim(), 16); String t = fields[2].trim(); for (int cp = r[0]; cp <= r[1]; cp++) { values.put(cp, v); types.put(cp, t); } } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Bidi_Paired_Bracket"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(values)); st = puaa.getOrCreateSubtable("Bidi_Paired_Bracket_Type"); st.addAll(PuaaUtility.createEntriesFromStringMap(types)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Bidi_Paired_Bracket"); PuaaSubtable types = puaa.getSubtable("Bidi_Paired_Bracket_Type"); TreeMap lines = new TreeMap(); if (values != null) for (PuaaSubtableEntry e : values) addLine(lines, e, 1); if (types != null) for (PuaaSubtableEntry e : types) addLine(lines, e, 2); for (String[] line : lines.values()) out.println(PuaaUtility.joinLine(line, "; ")); } private static void addLine(TreeMap lines, PuaaSubtableEntry e, int i) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { String value = e.getPropertyValue(cp); if (value == null || value.length() == 0) continue; if (lines.containsKey(cp)) { String[] line = lines.get(cp); if (line[i] == null) line[i] = value; else line[i] += value; } else { String[] line = new String[3]; line[0] = PuaaUtility.toHexString(cp); line[i] = value; lines.put(cp, line); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/BidiMirroringCodec.java000066400000000000000000000026741506470510200327360ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaTable; public class BidiMirroringCodec extends PuaaCodec { @Override public String getFileName() { return "BidiMirroring.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Bidi_Mirroring_Glyph"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); int v = Integer.parseInt(fields[1].trim(), 16); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Bidi_Mirroring_Glyph"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Bidi_Mirroring_Glyph"); if (values == null || values.isEmpty()) return; for (Map.Entry e : PuaaUtility.createMapFromEntries(values).entrySet()) { out.println(PuaaUtility.toHexString(e.getKey()) + "; " + e.getValue()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/BlocksCodec.java000066400000000000000000000025221506470510200314030ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class BlocksCodec extends PuaaCodec { @Override public String getFileName() { return "Blocks.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Block"}; } @Override public void compile(PuaaTable puaa, Scanner in) { PuaaSubtable blocks = puaa.getOrCreateSubtable("Block"); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); PuaaSubtableEntry.Single e = new PuaaSubtableEntry.Single(); e.firstCodePoint = r[0]; e.lastCodePoint = r[1]; e.value = v; blocks.add(e); } catch (NumberFormatException nfe) {} } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable blocks = puaa.getSubtable("Block"); if (blocks == null || blocks.isEmpty()) return; for (PuaaSubtableEntry e : blocks) { String r = PuaaUtility.joinRange(e); String v = e.getPropertyValue(e.firstCodePoint); out.println(r + "; " + v); } } } CompositionExclusionsCodec.java000066400000000000000000000026671506470510200345010ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaTable; public class CompositionExclusionsCodec extends PuaaCodec { @Override public String getFileName() { return "CompositionExclusions.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Composition_Exclusion"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 1) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, true); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Composition_Exclusion"); st.addAll(PuaaUtility.createEntriesFromBooleanMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Composition_Exclusion"); if (values == null || values.isEmpty()) return; for (Map.Entry e : PuaaUtility.createMapFromEntries(values).entrySet()) { if ("Y".equalsIgnoreCase(e.getValue())) { out.println(PuaaUtility.toHexString(e.getKey())); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/DerivedAgeCodec.java000066400000000000000000000042071506470510200321670ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class DerivedAgeCodec extends PuaaCodec { @Override public String getFileName() { return "DerivedAge.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Age"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Age"); st.addAll(PuaaUtility.createEntriesFromStringMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Age"); if (values == null || values.isEmpty()) return; List runs = PuaaUtility.createRunsFromEntries(values); Collections.sort(runs, BY_AGE); for (PuaaSubtableEntry.Single e : runs) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } private static final Comparator BY_AGE = new Comparator() { @Override public int compare(PuaaSubtableEntry.Single a, PuaaSubtableEntry.Single b) { int cmp = PuaaUtility.naturalCompare(a.value, b.value); if (cmp != 0) return cmp; if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/EastAsianWidthCodec.java000066400000000000000000000004431506470510200330360ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; public class EastAsianWidthCodec extends AbstractStringCodec { public EastAsianWidthCodec() { super("EastAsianWidth.txt", "East_Asian_Width"); } @Override protected String format(String range, String value) { return range + ";" + value; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/EmojiDataCodec.java000066400000000000000000000005421506470510200320230ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class EmojiDataCodec extends AbstractPropListCodec { public EmojiDataCodec() { super( "emoji-data.txt", Arrays.asList( "Emoji", "Emoji_Presentation", "Emoji_Modifier", "Emoji_Modifier_Base", "Emoji_Component", "Extended_Pictographic" ) ); } } EquivalentUnifiedIdeographCodec.java000066400000000000000000000032041506470510200353510ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.HashMap; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class EquivalentUnifiedIdeographCodec extends PuaaCodec { @Override public String getFileName() { return "EquivalentUnifiedIdeograph.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Equivalent_Unified_Ideograph"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); int v = Integer.parseInt(fields[1].trim(), 16); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Equivalent_Unified_Ideograph"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Equivalent_Unified_Ideograph"); if (values == null || values.isEmpty()) return; for (PuaaSubtableEntry.Single e : PuaaUtility.createRunsFromEntries(values)) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 11) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } } GraphemeBreakPropertyCodec.java000066400000000000000000000006771506470510200343620ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class GraphemeBreakPropertyCodec extends AbstractCategoryCodec { public GraphemeBreakPropertyCodec() { super( "GraphemeBreakProperty.txt", "Grapheme_Cluster_Break", Arrays.asList( "Prepend", "CR", "LF", "Control", "Extend", "Regional_Indicator", "SpacingMark", "L", "V", "T", "LV", "LVT", "ZWJ" ) ); }; } HangulSyllableTypeCodec.java000066400000000000000000000051711506470510200336620ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class HangulSyllableTypeCodec extends PuaaCodec { @Override public String getFileName() { return "HangulSyllableType.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Hangul_Syllable_Type"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Hangul_Syllable_Type"); st.addAll(PuaaUtility.createEntriesFromStringMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Hangul_Syllable_Type"); if (values == null || values.isEmpty()) return; List runs = PuaaUtility.createRunsFromEntries(values); // Find the first code point of each type. final HashMap firstOfType = new HashMap(); for (PuaaSubtableEntry.Single e : runs) { if (firstOfType.containsKey(e.value)) { if (firstOfType.get(e.value) < e.firstCodePoint) { continue; } } firstOfType.put(e.value, e.firstCodePoint); } // Sort by the first code point of the type. Collections.sort(runs, new Comparator() { @Override public int compare(PuaaSubtableEntry.Single a, PuaaSubtableEntry.Single b) { int foa = firstOfType.get(a.value); int fob = firstOfType.get(b.value); if (foa != fob) return foa - fob; int cmp = a.value.compareTo(b.value); if (cmp != 0) return cmp; if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }); for (PuaaSubtableEntry.Single e : runs) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } } IndicPositionalCategoryCodec.java000066400000000000000000000011351506470510200346740ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class IndicPositionalCategoryCodec extends AbstractCategoryCodec { public IndicPositionalCategoryCodec() { super( "IndicPositionalCategory.txt", "Indic_Positional_Category", Arrays.asList( "Right", "Left", "Visual_Order_Left", "Left_And_Right", "Top", "Bottom", "Top_And_Bottom", "Top_And_Right", "Top_And_Left", "Top_And_Left_And_Right", "Bottom_And_Right", "Bottom_And_Left", "Top_And_Bottom_And_Right", "Top_And_Bottom_And_Left", "Overstruck" ) ); } } IndicSyllabicCategoryCodec.java000066400000000000000000000020451506470510200343160ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class IndicSyllabicCategoryCodec extends AbstractCategoryCodec { public IndicSyllabicCategoryCodec() { super( "IndicSyllabicCategory.txt", "Indic_Syllabic_Category", Arrays.asList( "Bindu", "Visarga", "Avagraha", "Nukta", "Virama", "Pure_Killer", "Invisible_Stacker", "Vowel_Independent", "Vowel_Dependent", "Vowel", "Consonant_Placeholder", "Consonant", "Consonant_Dead", "Consonant_With_Stacker", "Consonant_Prefixed", "Consonant_Preceding_Repha", "Consonant_Initial_Postfixed", "Consonant_Succeeding_Repha", "Consonant_Subjoined", "Consonant_Medial", "Consonant_Final", "Consonant_Head_Letter", "Modifying_Letter", "Tone_Letter", "Tone_Mark", "Gemination_Mark", "Cantillation_Mark", "Register_Shifter", "Syllable_Modifier", "Consonant_Killer", "Non_Joiner", "Joiner", "Number_Joiner", "Number", "Brahmi_Joining_Number" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/JamoCodec.java000066400000000000000000000026571506470510200310650ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class JamoCodec extends PuaaCodec { @Override public String getFileName() { return "Jamo.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Jamo_Short_Name"}; } @Override public void compile(PuaaTable puaa, Scanner in) { PuaaSubtable jamo = puaa.getOrCreateSubtable("Jamo_Short_Name"); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 1) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = (fields.length > 1) ? fields[1].trim() : ""; // U+110B is actually "" PuaaSubtableEntry.Single e = new PuaaSubtableEntry.Single(); e.firstCodePoint = r[0]; e.lastCodePoint = r[1]; e.value = v; jamo.add(e); } catch (NumberFormatException nfe) {} } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable jamo = puaa.getSubtable("Jamo_Short_Name"); if (jamo == null || jamo.isEmpty()) return; for (PuaaSubtableEntry e : jamo) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { out.println(PuaaUtility.toHexString(cp) + "; " + e.getPropertyValue(cp)); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/LineBreakCodec.java000066400000000000000000000004161506470510200320220ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; public class LineBreakCodec extends AbstractStringCodec { public LineBreakCodec() { super("LineBreak.txt", "Line_Break"); } @Override protected String format(String range, String value) { return range + ";" + value; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/NameAliasesCodec.java000066400000000000000000000026661506470510200323610ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class NameAliasesCodec extends PuaaCodec { @Override public String getFileName() { return "NameAliases.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Name_Alias"}; } @Override public void compile(PuaaTable puaa, Scanner in) { PuaaSubtable names = puaa.getOrCreateSubtable("Name_Alias"); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 3) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String n = fields[1].trim(); String t = fields[2].trim(); PuaaSubtableEntry.NameAlias e = new PuaaSubtableEntry.NameAlias(); e.firstCodePoint = r[0]; e.lastCodePoint = r[1]; e.alias = n; e.type = t; names.add(e); } catch (NumberFormatException nfe) {} } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable names = puaa.getSubtable("Name_Alias"); if (names == null || names.isEmpty()) return; for (PuaaSubtableEntry e : names) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { out.println(PuaaUtility.toHexString(cp) + ";" + e.getPropertyValue(cp)); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/NushuSourcesCodec.java000066400000000000000000000004031506470510200326300ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class NushuSourcesCodec extends AbstractUnihanCodec { public NushuSourcesCodec() { super( "NushuSources.txt", Arrays.asList( "kSrc_NushuDuben", "kReading" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PropListCodec.java000066400000000000000000000020741506470510200317440ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class PropListCodec extends AbstractPropListCodec { public PropListCodec() { super( "PropList.txt", Arrays.asList( "White_Space", "Bidi_Control", "Join_Control", "Dash", "Hyphen", "Quotation_Mark", "Terminal_Punctuation", "Other_Math", "Hex_Digit", "ASCII_Hex_Digit", "Other_Alphabetic", "Ideographic", "Diacritic", "Extender", "Other_Lowercase", "Other_Uppercase", "Noncharacter_Code_Point", "Other_Grapheme_Extend", "IDS_Binary_Operator", "IDS_Trinary_Operator", "IDS_Unary_Operator", "Radical", "Unified_Ideograph", "Other_Default_Ignorable_Code_Point", "Deprecated", "Soft_Dotted", "Logical_Order_Exception", "Other_ID_Start", "Other_ID_Continue", "ID_Compat_Math_Continue", "ID_Compat_Math_Start", "Sentence_Terminal", "Variation_Selector", "Pattern_White_Space", "Pattern_Syntax", "Prepended_Concatenation_Mark", "Regional_Indicator" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaCodec.java000066400000000000000000000010411506470510200310470ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaTable; public abstract class PuaaCodec implements Comparable { public abstract String getFileName(); public abstract String[] getPropertyNames(); public abstract void compile(PuaaTable puaa, Scanner in); public abstract void decompile(PuaaTable puaa, PrintWriter out); @Override public final int compareTo(PuaaCodec that) { return this.getFileName().compareTo(that.getFileName()); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaCodecRegistry.java000066400000000000000000000054761506470510200326200ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; public class PuaaCodecRegistry { public static final PuaaCodecRegistry instance = new PuaaCodecRegistry(); private final SortedMap codecs = new TreeMap(); private PuaaCodecRegistry() { addCodec(new ArabicShapingCodec()); addCodec(new BidiBracketsCodec()); addCodec(new BidiMirroringCodec()); addCodec(new BlocksCodec()); addCodec(new CompositionExclusionsCodec()); addCodec(new DerivedAgeCodec()); addCodec(new EastAsianWidthCodec()); addCodec(new EmojiDataCodec()); addCodec(new EquivalentUnifiedIdeographCodec()); addCodec(new GraphemeBreakPropertyCodec()); addCodec(new HangulSyllableTypeCodec()); addCodec(new IndicPositionalCategoryCodec()); addCodec(new IndicSyllabicCategoryCodec()); addCodec(new JamoCodec()); addCodec(new LineBreakCodec()); addCodec(new NameAliasesCodec()); addCodec(new NushuSourcesCodec()); addCodec(new PropListCodec()); addCodec(new ScriptsCodec()); addCodec(new ScriptExtensionsCodec()); addCodec(new SentenceBreakPropertyCodec()); addCodec(new SpecialCasingCodec()); addCodec(new TangutSourcesCodec()); addCodec(new UnicodeDataCodec()); addCodec(new UnihanDictionaryIndicesCodec()); addCodec(new UnihanDictionaryLikeDataCodec()); addCodec(new UnihanIRGSourcesCodec()); addCodec(new UnihanNumericValuesCodec()); addCodec(new UnihanOtherMappingsCodec()); addCodec(new UnihanRadicalStrokeCountsCodec()); addCodec(new UnihanReadingsCodec()); addCodec(new UnihanVariantsCodec()); addCodec(new VerticalOrientationCodec()); addCodec(new WordBreakPropertyCodec()); } public void addCodec(PuaaCodec codec) { this.codecs.put(codec.getFileName().toLowerCase(), codec); } public PuaaCodec getCodec(String fileName) { return this.codecs.get(fileName.toLowerCase()); } public Collection getCodecs() { return this.codecs.values(); } public void printFileNames() { List fileNames = new ArrayList(); int longestFileName = 0; for (PuaaCodec codec : this.codecs.values()) { String fileName = codec.getFileName(); fileNames.add(fileName); if (fileName.length() > longestFileName) { longestFileName = fileName.length(); } } int columns = 80 / (longestFileName + 2); if (columns < 1) { columns = 1; longestFileName = 0; } int rows = (fileNames.size() + columns - 1) / columns; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { int k = j * rows + i; if (k < fileNames.size()) { String fileName = fileNames.get(k); while (fileName.length() < longestFileName) fileName += " "; System.out.print(" " + fileName); } } System.out.println(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaCodecTest.java000066400000000000000000000040231506470510200317120ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaTable; public class PuaaCodecTest { private static final PuaaCodecRegistry registry = PuaaCodecRegistry.instance; public static void main(String[] args) { for (String arg : args) { File src = new File(arg); testDir(src); } } private static void testDir(File src) { if (src.isDirectory()) { for (File child : src.listFiles()) { if (!child.getName().startsWith(".")) { testDir(child); } } } else { PuaaCodec codec = registry.getCodec(src.getName()); if (codec != null) { testFile(src, codec); } } } private static void testFile(File src, PuaaCodec codec) { System.out.print(src.getName()); System.out.print("\t"); System.out.print(src.length()); System.out.print("\t"); try { // File -> PuaaTable PuaaTable puaa = new PuaaTable(); Scanner in = new Scanner(new FileInputStream(src), "UTF-8"); codec.compile(puaa, in); in.close(); // PuaaTable -> byte[] byte[] data = puaa.compile(null); System.out.print(data.length); System.out.print("\t"); // byte[] -> PuaaTable puaa = new PuaaTable(); puaa.decompile(data, null); // PuaaTable -> File ByteArrayOutputStream bos = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(bos, "UTF-8"); PrintWriter pw = new PrintWriter(osw, true); codec.decompile(puaa, pw); pw.flush(); pw.close(); byte[] dst = bos.toByteArray(); System.out.print(dst.length); System.out.print("\t"); // round trip test byte[] data2 = puaa.compile(null); if (Arrays.equals(data, data2)) { System.out.println("PASS"); } else { System.out.println("FAIL"); } } catch (IOException e) { System.out.println("ERROR: " + e); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaCompiler.java000066400000000000000000000123041506470510200316100ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class PuaaCompiler { private static final PuaaCodecRegistry registry = PuaaCodecRegistry.instance; public static void main(String[] args) { if (args.length == 0) { printHelp(); return; } List dataFiles = new ArrayList(); List inputFiles = new ArrayList(); List outputFiles = new ArrayList(); List defaultList = dataFiles; boolean parsingOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) { parsingOptions = false; } else if (arg.equals("-d") && argi < args.length) { dataFiles.add(new File(args[argi++])); } else if (arg.equals("-i") && argi < args.length) { inputFiles.add(new File(args[argi++])); } else if (arg.equals("-o") && argi < args.length) { outputFiles.add(new File(args[argi++])); } else if (arg.equals("-D")) { defaultList = dataFiles; } else if (arg.equals("-I")) { defaultList = inputFiles; } else if (arg.equals("-O")) { defaultList = outputFiles; } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { defaultList.add(new File(arg)); } } if (dataFiles.isEmpty()) return; PuaaTable puaa = read(dataFiles); if (inputFiles.isEmpty() && outputFiles.isEmpty()) { File file = new File("puaa.out"); write(puaa, file, file); return; } if (inputFiles.isEmpty() || outputFiles.isEmpty()) { for (File file : inputFiles) write(puaa, file, file); for (File file : outputFiles) write(puaa, file, file); return; } if (inputFiles.size() == 1 && outputFiles.size() == 1) { write(puaa, inputFiles.get(0), outputFiles.get(0)); return; } if (inputFiles.size() > 1) System.err.println("Too many input files."); if (outputFiles.size() > 1) System.err.println("Too many output files."); } private static PuaaTable read(List dataFiles) { PuaaTable puaa = new PuaaTable(); for (File dataFile : dataFiles) { System.out.print("Reading " + dataFile.getName() + "..."); try { compile(puaa, dataFile); System.out.println(" DONE"); } catch (IOException e) { System.out.println(" ERROR: " + e); } } return puaa; } private static void write(PuaaTable puaa, File inputFile, File outputFile) { System.out.print("Writing " + outputFile.getName() + "..."); try { inject(puaa, inputFile, outputFile); System.out.println(" DONE"); } catch (IOException e) { System.out.println(" ERROR: " + e); } } private static void printHelp() { System.out.println(); System.out.println("PuaaCompiler - Add Unicode Character Database properties to TrueType files."); System.out.println(); System.out.println(" -d Specify UCD data file or directory."); System.out.println(" -i Specify source TrueType file."); System.out.println(" -o Specify destination TrueType file."); System.out.println(" -D Process arguments as UCD data files."); System.out.println(" -I Process arguments as source files."); System.out.println(" -O Process arguments as destination files."); System.out.println(" -- Process remaining arguments as file names."); System.out.println(); System.out.println("Source and destination may be the same file."); System.out.println("Other files specified must be in the format of the"); System.out.println("Unicode Character Database and be named accordingly:"); System.out.println(); registry.printFileNames(); System.out.println(); System.out.println("Files other than those listed above will be ignored."); System.out.println(); } public static void compile(PuaaTable puaa, File src) throws IOException { if (src.isDirectory()) { for (File child : src.listFiles()) { if (!child.getName().startsWith(".")) { compile(puaa, child); } } } else { PuaaCodec codec = registry.getCodec(src.getName()); if (codec != null) { Scanner in = new Scanner(new FileInputStream(src), "UTF-8"); codec.compile(puaa, in); in.close(); } } } public static void inject(PuaaTable puaa, File src, File dst) throws IOException { TrueTypeFile ttf = new TrueTypeFile(); long length = src.length(); if (length > 0) { if (length < 12) throw new IOException("file too small"); if (length > Integer.MAX_VALUE) throw new IOException("file too large"); byte[] data = new byte[(int)length]; FileInputStream in = new FileInputStream(src); in.read(data); in.close(); ttf.interpret = false; ttf.decompile(data); ttf.remove(ttf.getByTableName("PUAA")); } else { ttf.scaler = 0x50554141; } ttf.add(puaa); byte[] data = ttf.compile(); FileOutputStream out = new FileOutputStream(dst); out.write(data); out.flush(); out.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaDecompiler.java000066400000000000000000000112511506470510200321210ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.truetype.PuaaTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class PuaaDecompiler { private static final PuaaCodecRegistry registry = PuaaCodecRegistry.instance; public static void main(String[] args) { if (args.length == 0) { printHelp(); return; } List inputFiles = new ArrayList(); List outputFiles = new ArrayList(); List defaultList = inputFiles; boolean parsingOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) { parsingOptions = false; } else if (arg.equals("-i") && argi < args.length) { inputFiles.add(new File(args[argi++])); } else if (arg.equals("-o") && argi < args.length) { outputFiles.add(new File(args[argi++])); } else if (arg.equals("-I")) { defaultList = inputFiles; } else if (arg.equals("-O")) { defaultList = outputFiles; } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { defaultList.add(new File(arg)); } } if (inputFiles.isEmpty()) return; if (outputFiles.isEmpty()) outputFiles.add(new File("puaa.d")); if (inputFiles.size() == 1) { PuaaTable puaa = read(inputFiles.get(0)); if (puaa != null) { for (File outputFile : outputFiles) { write(puaa, outputFile); } } return; } if (outputFiles.size() == 1) { for (File inputFile : inputFiles) { PuaaTable puaa = read(inputFile); if (puaa != null) { write(puaa, outputFiles.get(0)); } } return; } if (inputFiles.size() > 1) System.err.println("Too many input files."); if (outputFiles.size() > 1) System.err.println("Too many output files."); } private static PuaaTable read(File src) { System.out.print("Reading " + src.getName() + "..."); try { PuaaTable puaa = extract(src); if (puaa == null) { System.out.println(" ERROR: table not found"); } else { System.out.println(" DONE"); } return puaa; } catch (IOException e) { System.out.println(" ERROR: " + e); return null; } } private static void write(PuaaTable puaa, File dst) { System.out.print("Writing " + dst.getName() + "..."); try { dst.mkdirs(); decompile(puaa, dst); System.out.println(" DONE"); } catch (IOException e) { System.out.println(" ERROR: " + e); } } private static void printHelp() { System.out.println(); System.out.println("PuaaDecompiler - Create UCD files from character properties in TrueType files."); System.out.println(); System.out.println(" -i Specify source TrueType file."); System.out.println(" -o Specify destination directory."); System.out.println(" -I Process arguments as source files."); System.out.println(" -O Process arguments as destination files."); System.out.println(" -- Process remaining arguments as file names."); System.out.println(); System.out.println("Output files will be in the format of the Unicode Character Database"); System.out.println("(although without any comments) and will be named accordingly:"); System.out.println(); registry.printFileNames(); System.out.println(); System.out.println("Only files for properties present in the source files will be generated."); System.out.println(); } public static void decompile(PuaaTable puaa, File dst) throws IOException { for (PuaaCodec codec : registry.getCodecs()) { for (String property : codec.getPropertyNames()) { if (puaa.getSubtable(property) != null) { File dstFile = new File(dst, codec.getFileName()); FileOutputStream fos = new FileOutputStream(dstFile); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); PrintWriter pw = new PrintWriter(osw, true); codec.decompile(puaa, pw); pw.flush(); pw.close(); break; } } } } public static PuaaTable extract(File src) throws IOException { long length = src.length(); if (length < 12) throw new IOException("file too small"); if (length > Integer.MAX_VALUE) throw new IOException("file too large"); byte[] data = new byte[(int)length]; FileInputStream in = new FileInputStream(src); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); return (PuaaTable)ttf.getByTableName("PUAA"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaLookup.java000066400000000000000000000115531506470510200313140ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; import com.kreative.bitsnpicas.truetype.TrueTypeFile; public class PuaaLookup { public static void main(String[] args) { if (args.length == 0) { printHelp(); return; } List tables = new ArrayList(); List properties = new ArrayList(); List codePoints = new ArrayList(); boolean parsingOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) { parsingOptions = false; } else if (arg.equals("-i") && argi < args.length) { PuaaTable puaa = read(new File(args[argi++])); if (puaa != null) tables.addAll(puaa); } else if (arg.equals("-p") && argi < args.length) { String p = args[argi++].trim().toLowerCase(); if (p.length() > 0) properties.add(p); } else if (arg.equals("-c") && argi < args.length) { int cp = parseCodePoint(args[argi++]); if (cp >= 0) codePoints.add(cp); } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else { int cp = parseCodePoint(arg); if (cp >= 0) codePoints.add(cp); } } if (tables.isEmpty()) return; if (codePoints.isEmpty()) { if (properties.isEmpty()) { System.out.println("Properties:"); for (PuaaSubtable table : tables) { System.out.println(" " + table.property); } return; } for (PuaaSubtable table : tables) { if (properties.contains(table.property.toLowerCase())) { System.out.println(table.property + ":"); for (PuaaSubtableEntry.Single e : PuaaUtility.createRunsFromEntries(table)) { String range = PuaaUtility.joinRange(e); StringBuffer sb = new StringBuffer(); sb.append(" "); sb.append(range); sb.append(": "); for (int i = range.length(); i < 14; i++) sb.append(" "); sb.append(e.value); System.out.println(sb.toString()); } } } return; } int nameWidth = 0; for (PuaaSubtable table : tables) { int w = table.property.length(); if (w > nameWidth) nameWidth = w; } for (int cp : codePoints) { System.out.println("U+" + PuaaUtility.toHexString(cp) + ":"); for (PuaaSubtable table : tables) { if (properties.isEmpty() || properties.contains(table.property.toLowerCase())) { String value = table.getPropertyValue(cp); if (value == null) continue; String prop = table.property; StringBuffer sb = new StringBuffer(); sb.append(" "); sb.append(prop); sb.append(": "); for (int i = prop.length(); i < nameWidth; i++) sb.append(" "); sb.append(value); System.out.println(sb.toString()); } } } } private static PuaaTable read(File src) { System.out.print("Reading " + src.getName() + "..."); try { PuaaTable puaa = extract(src); if (puaa == null) { System.out.println(" ERROR: table not found"); } else { System.out.println(" DONE"); } return puaa; } catch (IOException e) { System.out.println(" ERROR: " + e); return null; } } private static int parseCodePoint(String s) { if (s.codePointCount(0, s.length()) == 1) { return s.codePointAt(0); } else try { s = s.replaceAll("[Uu][+]|[0][Xx]|\\s", ""); int cp = Integer.parseInt(s, 16); if (Character.isValidCodePoint(cp)) return cp; s = Integer.toHexString(cp).toUpperCase(); System.err.println("Invalid code point: " + s); return -1; } catch (NumberFormatException nfe) { System.err.println("Invalid code point: " + s); return -1; } } private static void printHelp() { System.out.println(); System.out.println("PuaaLookup - Look up Unicode Character Database properties in TrueType files."); System.out.println(); System.out.println(" -i Specify source TrueType file."); System.out.println(" -p Specify properties to look up."); System.out.println(" -c Specify code points to look up."); System.out.println(" -- Process remaining arguments as code points."); System.out.println(); } public static PuaaTable extract(File src) throws IOException { long length = src.length(); if (length < 12) throw new IOException("file too small"); if (length > Integer.MAX_VALUE) throw new IOException("file too large"); byte[] data = new byte[(int)length]; FileInputStream in = new FileInputStream(src); in.read(data); in.close(); TrueTypeFile ttf = new TrueTypeFile(); ttf.decompile(data); return (PuaaTable)ttf.getByTableName("PUAA"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/PuaaUtility.java000066400000000000000000000432501506470510200315050ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.UnsupportedEncodingException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; public class PuaaUtility { public static String[] splitLine(String line) { int o = line.indexOf("#"); if (o >= 0) line = line.substring(0, o); line = line.trim(); if (line.length() == 0) return null; return line.split(";"); } public static int[] splitRange(String range) { String[] ep = range.split("[.]+"); int start = Integer.parseInt(ep[0].trim(), 16); if (ep.length < 2) return new int[]{start, start}; int end = Integer.parseInt(ep[1].trim(), 16); return new int[]{start, end}; } public static String toHexString(int value) { String s = Integer.toHexString(value).toUpperCase(); while (s.length() < 4) s = "0" + s; return s; } public static String joinRange(PuaaSubtableEntry e) { if (e.firstCodePoint == e.lastCodePoint) { return toHexString(e.firstCodePoint); } else { StringBuffer sb = new StringBuffer(); sb.append(toHexString(e.firstCodePoint)); sb.append(".."); sb.append(toHexString(e.lastCodePoint)); return sb.toString(); } } public static String joinLine(String[] line, String delimiter) { StringBuffer sb = new StringBuffer(line[0]); for (int i = 1; i < line.length; i++) { sb.append(delimiter); if (line[i] != null) sb.append(line[i]); } return sb.toString(); } public static boolean equals(Object a, Object b) { if (a == null) return (b == null); if (b == null) return (a == null); return a.equals(b); } public static boolean appendToEntry(PuaaSubtableEntry.Single e, int cp, String value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; if (!equals(e.value, value)) return false; e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.Multiple e, int cp, String value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; List list = new ArrayList(); list.addAll(Arrays.asList(e.values)); list.add(value); e.values = list.toArray(new String[list.size()]); e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.Boolean e, int cp, boolean value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; if (e.value != value) return false; e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.Decimal e, int cp, int value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; if (e.value != value) return false; e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.Hexadecimal e, int cp, int value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; if (e.value != value) return false; e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.HexMultiple e, int cp, int value) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; int n = e.values.length; int[] newValues = new int[n + 1]; for (int i = 0; i < n; i++) newValues[i] = e.values[i]; newValues[n] = value; e.values = newValues; e.lastCodePoint++; return true; } public static boolean appendToEntry(PuaaSubtableEntry.HexSequence e, int cp, int[] values) { if (e == null) return false; if ((short)e.lastCodePoint == -1) return false; if (e.lastCodePoint+1 != cp) return false; if (!Arrays.equals(e.values, values)) return false; e.lastCodePoint++; return true; } private static final class CEFMItem implements Comparable> { public final int cp; public final T value; public CEFMItem(int cp, T value) { this.cp = cp; this.value = value; } @Override public int compareTo(CEFMItem that) { return this.cp - that.cp; } } private static List> sorted(Map map) { List> items = new ArrayList>(); for (Map.Entry e : map.entrySet()) { T v = e.getValue(); if (v == null) continue; if (v instanceof String && v.toString().length() == 0) continue; items.add(new CEFMItem(e.getKey(), v)); } Collections.sort(items); return items; } public static List createEntriesFromStringMap(Map map) { // Sort map entries by code point. List> items = sorted(map); // Create entries, collapsing runs of the same value into a single entry. List runs = new ArrayList(); PuaaSubtableEntry.Single currentRun = null; for (CEFMItem item : items) { if (!appendToEntry(currentRun, item.cp, item.value)) { currentRun = new PuaaSubtableEntry.Single(); currentRun.firstCodePoint = item.cp; currentRun.lastCodePoint = item.cp; currentRun.value = item.value; runs.add(currentRun); } } // Create entries, collapsing runs of length 1 into a single entry. List entries = new ArrayList(); PuaaSubtableEntry.Multiple currentEntry = null; for (PuaaSubtableEntry.Single run : runs) { if (run.firstCodePoint != run.lastCodePoint) { currentEntry = null; entries.add(run); } else if (!appendToEntry(currentEntry, run.firstCodePoint, run.value)) { currentEntry = new PuaaSubtableEntry.Multiple(); currentEntry.firstCodePoint = run.firstCodePoint; currentEntry.lastCodePoint = run.lastCodePoint; currentEntry.values = new String[]{run.value}; entries.add(currentEntry); } } // Replace Multiples of a single value with a Single. for (int i = 0, n = entries.size(); i < n; i++) { PuaaSubtableEntry e = entries.get(i); if (e.firstCodePoint == e.lastCodePoint) { currentRun = new PuaaSubtableEntry.Single(); currentRun.firstCodePoint = e.firstCodePoint; currentRun.lastCodePoint = e.lastCodePoint; currentRun.value = e.getPropertyValue(e.firstCodePoint); entries.set(i, currentRun); } } return entries; } public static List createEntriesFromBooleanMap(Map map) { List> items = sorted(map); List entries = new ArrayList(); PuaaSubtableEntry.Boolean currentEntry = null; for (CEFMItem item : items) { if (!appendToEntry(currentEntry, item.cp, item.value)) { currentEntry = new PuaaSubtableEntry.Boolean(); currentEntry.firstCodePoint = item.cp; currentEntry.lastCodePoint = item.cp; currentEntry.value = item.value; entries.add(currentEntry); } } return entries; } public static List createEntriesFromDecimalMap(Map map) { List> items = sorted(map); List entries = new ArrayList(); PuaaSubtableEntry.Decimal currentEntry = null; for (CEFMItem item : items) { if (!appendToEntry(currentEntry, item.cp, item.value)) { currentEntry = new PuaaSubtableEntry.Decimal(); currentEntry.firstCodePoint = item.cp; currentEntry.lastCodePoint = item.cp; currentEntry.value = item.value; entries.add(currentEntry); } } return entries; } public static List createEntriesFromHexadecimalMap(Map map) { // Sort map entries by code point. List> items = sorted(map); // Create entries, collapsing runs of the same value into a single entry. List runs = new ArrayList(); PuaaSubtableEntry.Hexadecimal currentRun = null; for (CEFMItem item : items) { if (!appendToEntry(currentRun, item.cp, item.value)) { currentRun = new PuaaSubtableEntry.Hexadecimal(); currentRun.firstCodePoint = item.cp; currentRun.lastCodePoint = item.cp; currentRun.value = item.value; runs.add(currentRun); } } // Create entries, collapsing runs of length 1 into a single entry. List entries = new ArrayList(); PuaaSubtableEntry.HexMultiple currentEntry = null; for (PuaaSubtableEntry.Hexadecimal run : runs) { if (run.firstCodePoint != run.lastCodePoint) { currentEntry = null; entries.add(run); } else if (!appendToEntry(currentEntry, run.firstCodePoint, run.value)) { currentEntry = new PuaaSubtableEntry.HexMultiple(); currentEntry.firstCodePoint = run.firstCodePoint; currentEntry.lastCodePoint = run.lastCodePoint; currentEntry.values = new int[]{run.value}; entries.add(currentEntry); } } // Replace HexMultiples of a single value with a Hexadecimal. for (int i = 0, n = entries.size(); i < n; i++) { PuaaSubtableEntry e = entries.get(i); if (e.firstCodePoint == e.lastCodePoint) { currentRun = new PuaaSubtableEntry.Hexadecimal(); currentRun.firstCodePoint = e.firstCodePoint; currentRun.lastCodePoint = e.lastCodePoint; currentRun.value = Integer.parseInt(e.getPropertyValue(e.firstCodePoint), 16); entries.set(i, currentRun); } } return entries; } public static List createEntriesFromHexSequenceMap(Map map) { List> items = sorted(map); List entries = new ArrayList(); PuaaSubtableEntry.HexSequence currentEntry = null; for (CEFMItem item : items) { if (!appendToEntry(currentEntry, item.cp, item.value)) { currentEntry = new PuaaSubtableEntry.HexSequence(); currentEntry.firstCodePoint = item.cp; currentEntry.lastCodePoint = item.cp; currentEntry.values = item.value; entries.add(currentEntry); } } return entries; } private static boolean isChunky(char ch) { return ( Character.isLetterOrDigit(ch) || Character.isSurrogate(ch) || (ch >= '"' && ch <= '*') || ch == '<' || ch == '>' || ch == '@' || ch == '[' || ch == ']' || ch == '_' || ch == '{' || ch == '}' ); } private static List splitName(String name) { List pieces = new ArrayList(); char[] ch = name.toCharArray(); for (int o = 0, i = 0; o < ch.length; o = i) { while (i < ch.length && isChunky(ch[i])) i++; while (i < ch.length && !isChunky(ch[i]) && !Character.isWhitespace(ch[i])) i++; while (i < ch.length && Character.isWhitespace(ch[i])) i++; pieces.add(name.substring(o, i)); } return pieces; } private static String joinName(List pieces) { StringBuffer sb = new StringBuffer(); for (String piece : pieces) sb.append(piece); return sb.toString(); } private static final class CEFNMItem implements Comparable { public final int cp; public final List pieces; public CEFNMItem(int cp, String value) { this.cp = cp; this.pieces = splitName(value); } @Override public int compareTo(CEFNMItem that) { return this.cp - that.cp; } public String getPrefix() { return pieces.isEmpty() ? null : pieces.get(0); } public String removePrefix() { return pieces.isEmpty() ? null : pieces.remove(0); } public String getSuffix() { return pieces.isEmpty() ? null : pieces.get(pieces.size()-1); } public String removeSuffix() { return pieces.isEmpty() ? null : pieces.remove(pieces.size()-1); } public String getValue() { return joinName(pieces); } } private static int utf8Length(String s) { try { return s.getBytes("UTF-8").length; } catch (UnsupportedEncodingException e) { return 0; } } public static List createEntriesFromNameMap(Map map) { // Sort map entries by code point. List items = new ArrayList(); for (Map.Entry e : map.entrySet()) { if (e.getValue() == null || e.getValue().length() == 0) continue; items.add(new CEFNMItem(e.getKey(), e.getValue())); } Collections.sort(items); // Create entries for runs of common prefixes. List prefixes = new ArrayList(); while (true) { List newPrefixes = new ArrayList(); for (int o = 0, i = 0, n = items.size(); o < n; o = i) { CEFNMItem firstItem = items.get(i); i++; if (firstItem.pieces.isEmpty()) continue; // Create an entry for the first item's prefix. PuaaSubtableEntry.Single entry = new PuaaSubtableEntry.Single(); entry.firstCodePoint = firstItem.cp; entry.lastCodePoint = firstItem.cp; entry.value = firstItem.getPrefix(); // Extend the entry for subsequent items with the same prefix. while (i < n) { CEFNMItem item = items.get(i); if (appendToEntry(entry, item.cp, item.getPrefix())) i++; else break; } // If there were subsequent items, add an entry and remove the prefix. if (entry.firstCodePoint != entry.lastCodePoint) { newPrefixes.add(entry); while (o < i) { items.get(o).removePrefix(); o++; } } } if (newPrefixes.isEmpty()) break; prefixes.addAll(newPrefixes); } // Create entries for runs of common suffixes. List suffixes = new ArrayList(); while (true) { List newSuffixes = new ArrayList(); for (int o = 0, i = 0, n = items.size(); o < n; o = i) { CEFNMItem firstItem = items.get(i); i++; if (firstItem.pieces.isEmpty()) continue; // Create an entry for the first item's suffix. PuaaSubtableEntry.Single entry = new PuaaSubtableEntry.Single(); entry.firstCodePoint = firstItem.cp; entry.lastCodePoint = firstItem.cp; entry.value = firstItem.getSuffix(); // Extend the entry for subsequent items with the same suffix. while (i < n) { CEFNMItem item = items.get(i); if (appendToEntry(entry, item.cp, item.getSuffix())) i++; else break; } // If there were subsequent items, add an entry and remove the suffix. if (entry.firstCodePoint != entry.lastCodePoint) { newSuffixes.add(entry); while (o < i) { items.get(o).removeSuffix(); o++; } } } if (newSuffixes.isEmpty()) break; suffixes.addAll(0, newSuffixes); } // Add remaining name fragments. // There are two maps here because some values of the kDefinition // property in the Unihan database are longer than 255 bytes. Map remainder1 = new HashMap(); Map remainder2 = new HashMap(); for (CEFNMItem item : items) { if (item.pieces.isEmpty()) continue; String value = item.getValue(); if (utf8Length(value) > 255) { int h = value.length() / 2; if (Character.isLowSurrogate(value.charAt(h))) h++; remainder1.put(item.cp, value.substring(0, h)); remainder2.put(item.cp, value.substring(h)); } else { remainder1.put(item.cp, value); } } List entries = new ArrayList(); entries.addAll(prefixes); entries.addAll(createEntriesFromStringMap(remainder1)); entries.addAll(createEntriesFromStringMap(remainder2)); entries.addAll(suffixes); return entries; } public static SortedMap createMapFromEntries(List entries) { SortedMap map = new TreeMap(); for (PuaaSubtableEntry e : entries) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { String value = e.getPropertyValue(cp); if (value == null) continue; if (map.containsKey(cp)) { map.put(cp, map.get(cp) + value); } else { map.put(cp, value); } } } return map; } public static List createRunsFromEntries(List entries) { List> items = sorted(createMapFromEntries(entries)); List runs = new ArrayList(); PuaaSubtableEntry.Single currentRun = null; for (CEFMItem item : items) { if (!appendToEntry(currentRun, item.cp, item.value)) { currentRun = new PuaaSubtableEntry.Single(); currentRun.firstCodePoint = item.cp; currentRun.lastCodePoint = item.cp; currentRun.value = item.value; runs.add(currentRun); } } return runs; } public static int naturalCompare(String a, String b) { List na = naturalTokenize(a.trim()); List nb = naturalTokenize(b.trim()); for (int i = 0; i < na.size() && i < nb.size(); i++) { try { double va = Double.parseDouble(na.get(i)); double vb = Double.parseDouble(nb.get(i)); int cmp = Double.compare(va, vb); if (cmp != 0) return cmp; } catch (NumberFormatException e) { int cmp = na.get(i).compareToIgnoreCase(nb.get(i)); if (cmp != 0) return cmp; } } return na.size() - nb.size(); } private static List naturalTokenize(String s) { List tokens = new ArrayList(); StringBuffer token = new StringBuffer(); int tokenType = 0; CharacterIterator iter = new StringCharacterIterator(s); for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter.next()) { int tt = Character.isDigit(ch) ? 1 : Character.isLetter(ch) ? 2 : 3; if (tt != tokenType) { if (token.length() > 0) { tokens.add(token.toString()); token = new StringBuffer(); } tokenType = tt; } token.append(ch); } if (token.length() > 0) tokens.add(token.toString()); return tokens; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/ScriptExtensionsCodec.java000066400000000000000000000072351506470510200335200ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class ScriptExtensionsCodec extends PuaaCodec { @Override public String getFileName() { return "ScriptExtensions.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Script_Extensions"}; } @Override public void compile(PuaaTable puaa, Scanner in) { Map> values = new TreeMap>(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); for (String s : fields[1].trim().split("\\s+")) { if (values.containsKey(s)) { Map m = values.get(s); for (int cp = r[0]; cp <= r[1]; cp++) m.put(cp, s); } else { Map m = new TreeMap(); for (int cp = r[0]; cp <= r[1]; cp++) m.put(cp, s); values.put(s, m); } } } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Script_Extensions"); for (Map m : values.values()) { st.addAll(PuaaUtility.createEntriesFromStringMap(m)); } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable entries = puaa.getSubtable("Script_Extensions"); if (entries == null || entries.isEmpty()) return; Map> scripts = new TreeMap>(); for (PuaaSubtableEntry e : entries) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { if (scripts.containsKey(cp)) { Set scr = scripts.get(cp); for (String s : e.getPropertyValue(cp).trim().split("\\s+")) scr.add(s); } else { Set scr = new TreeSet(); for (String s : e.getPropertyValue(cp).trim().split("\\s+")) scr.add(s); scripts.put(cp, scr); } } } List runs = new ArrayList(); for (Map.Entry> e : scripts.entrySet()) { StringBuffer sb = new StringBuffer(); boolean first = true; for (String s : e.getValue()) { if (first) first = false; else sb.append(" "); sb.append(s); } PuaaSubtableEntry.Single s = new PuaaSubtableEntry.Single(); s.firstCodePoint = s.lastCodePoint = e.getKey(); s.value = sb.toString(); runs.add(s); } runs = PuaaUtility.createRunsFromEntries(runs); Collections.sort(runs, BY_SCRIPTS); for (PuaaSubtableEntry.Single e : runs) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } private static final Comparator BY_SCRIPTS = new Comparator() { @Override public int compare(PuaaSubtableEntry.Single a, PuaaSubtableEntry.Single b) { if (a.value.length() != b.value.length()) return a.value.length() - b.value.length(); int cmp = a.value.compareToIgnoreCase(b.value); if (cmp != 0) return cmp; if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/ScriptsCodec.java000066400000000000000000000051111506470510200316120ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class ScriptsCodec extends PuaaCodec { @Override public String getFileName() { return "Scripts.txt"; } @Override public String[] getPropertyNames() { return new String[]{"Script"}; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap values = new HashMap(); while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 2) continue; try { int[] r = PuaaUtility.splitRange(fields[0]); String v = fields[1].trim(); for (int cp = r[0]; cp <= r[1]; cp++) values.put(cp, v); } catch (NumberFormatException nfe) {} } PuaaSubtable st = puaa.getOrCreateSubtable("Script"); st.addAll(PuaaUtility.createEntriesFromStringMap(values)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable values = puaa.getSubtable("Script"); if (values == null || values.isEmpty()) return; List runs = PuaaUtility.createRunsFromEntries(values); // Find the first code point in each script. final HashMap firstOfScript = new HashMap(); for (PuaaSubtableEntry.Single e : runs) { if (firstOfScript.containsKey(e.value)) { if (firstOfScript.get(e.value) < e.firstCodePoint) { continue; } } firstOfScript.put(e.value, e.firstCodePoint); } // Sort by the first code point of the script. Collections.sort(runs, new Comparator() { @Override public int compare(PuaaSubtableEntry.Single a, PuaaSubtableEntry.Single b) { int foa = firstOfScript.get(a.value); int fob = firstOfScript.get(b.value); if (foa != fob) return foa - fob; int cmp = a.value.compareTo(b.value); if (cmp != 0) return cmp; if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }); for (PuaaSubtableEntry.Single e : runs) { StringBuffer sb = new StringBuffer(); sb.append(PuaaUtility.joinRange(e)); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(e.value); out.println(sb.toString()); } } } SentenceBreakPropertyCodec.java000066400000000000000000000007031506470510200343640ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class SentenceBreakPropertyCodec extends AbstractCategoryCodec { public SentenceBreakPropertyCodec() { super( "SentenceBreakProperty.txt", "Sentence_Break", Arrays.asList( "CR", "LF", "Extend", "Sep", "Format", "Sp", "Lower", "Upper", "OLetter", "Numeric", "ATerm", "STerm", "Close", "SContinue" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/SpecialCasingCodec.java000066400000000000000000000071671506470510200327050ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Scanner; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class SpecialCasingCodec extends PuaaCodec { @Override public String getFileName() { return "SpecialCasing.txt"; } @Override public String[] getPropertyNames() { return new String[]{ "Lowercase_Mapping", "Titlecase_Mapping", "Uppercase_Mapping", }; } @Override public void compile(PuaaTable puaa, Scanner in) { PuaaSubtable lower = puaa.getOrCreateSubtable("Lowercase_Mapping"); PuaaSubtable title = puaa.getOrCreateSubtable("Titlecase_Mapping"); PuaaSubtable upper = puaa.getOrCreateSubtable("Uppercase_Mapping"); PuaaSubtableEntry.CaseMapping e; while (in.hasNextLine()) { String[] fields = PuaaUtility.splitLine(in.nextLine()); if (fields == null || fields.length < 4) continue; if ((e = createEntry(fields, 1)) != null) lower.add(e); if ((e = createEntry(fields, 2)) != null) title.add(e); if ((e = createEntry(fields, 3)) != null) upper.add(e); } } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable lower = puaa.getSubtable("Lowercase_Mapping"); PuaaSubtable title = puaa.getSubtable("Titlecase_Mapping"); PuaaSubtable upper = puaa.getSubtable("Uppercase_Mapping"); LinkedHashMap lines = new LinkedHashMap(); if (lower != null) for (PuaaSubtableEntry e : lower) addLine(lines, e, 1); if (title != null) for (PuaaSubtableEntry e : title) addLine(lines, e, 2); if (upper != null) for (PuaaSubtableEntry e : upper) addLine(lines, e, 3); for (String[] line : lines.values()) out.println(joinLine(line)); } private static PuaaSubtableEntry.CaseMapping createEntry(String[] fields, int i) { try { PuaaSubtableEntry.CaseMapping e = new PuaaSubtableEntry.CaseMapping(); int[] r = PuaaUtility.splitRange(fields[0]); e.firstCodePoint = r[0]; e.lastCodePoint = r[1]; String[] words = fields[i].trim().split("\\s+"); e.values = new int[words.length]; for (i = 0; i < words.length; i++) { e.values[i] = Integer.parseInt(words[i], 16); } if (fields.length > 4) { String c = fields[4].trim(); if (c.length() > 0) e.condition = c; } return e; } catch (NumberFormatException nfe) { return null; } } private static void addLine(LinkedHashMap lines, PuaaSubtableEntry e, int i) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { String key = Integer.toHexString(0xC0000000 + cp); String value = e.getPropertyValue(cp); String condition = null; int o = value.indexOf(";"); if (o >= 0) { condition = value.substring(o + 1).trim(); value = value.substring(0, o).trim(); key += condition; } if (lines.containsKey(key)) { String[] line = lines.get(key); line[i] = value; } else { String[] line = new String[5]; line[0] = PuaaUtility.toHexString(cp); line[i] = value; line[4] = condition; lines.put(key, line); } } } private static String joinLine(String[] line) { StringBuffer sb = new StringBuffer(); if (line[0] != null) sb.append(line[0]); sb.append("; "); if (line[1] != null) sb.append(line[1]); sb.append("; "); if (line[2] != null) sb.append(line[2]); sb.append("; "); if (line[3] != null) sb.append(line[3]); sb.append(";"); if (line[4] != null && line[4].length() > 0) { sb.append(" "); sb.append(line[4]); sb.append(";"); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/TangutSourcesCodec.java000066400000000000000000000004101506470510200327660ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class TangutSourcesCodec extends AbstractUnihanCodec { public TangutSourcesCodec() { super( "TangutSources.txt", Arrays.asList( "kTGT_MergedSrc", "kRSTUnicode" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/UnicodeDataCodec.java000066400000000000000000000240331506470510200323470ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Scanner; import java.util.TreeMap; import com.kreative.bitsnpicas.truetype.PuaaSubtable; import com.kreative.bitsnpicas.truetype.PuaaSubtableEntry; import com.kreative.bitsnpicas.truetype.PuaaTable; public class UnicodeDataCodec extends PuaaCodec { @Override public String getFileName() { return "UnicodeData.txt"; } @Override public String[] getPropertyNames() { return new String[]{ "Name", "General_Category", "Canonical_Combining_Class", "Bidi_Class", "Decomposition_Type", "Decomposition_Mapping", "Numeric_Type", "Numeric_Value", "Bidi_Mirrored", "Unicode_1_Name", "ISO_Comment", "Simple_Uppercase_Mapping", "Simple_Lowercase_Mapping", "Simple_Titlecase_Mapping", }; } @Override public void compile(PuaaTable puaa, Scanner in) { HashMap names = new HashMap(); HashMap categories = new HashMap(); HashMap combClasses = new HashMap(); HashMap bidiClasses = new HashMap(); HashMap decompTypes = new HashMap(); HashMap decompMappings = new HashMap(); HashMap numericTypes = new HashMap(); HashMap numericValues = new HashMap(); HashMap bidiMirrored = new HashMap(); HashMap uni1Names = new HashMap(); HashMap comments = new HashMap(); HashMap uppercase = new HashMap(); HashMap lowercase = new HashMap(); HashMap titlecase = new HashMap(); String[] fields; Integer cp; Boolean b; Integer i; String s; String[] words; while (in.hasNextLine()) { if ((fields = PuaaUtility.splitLine(in.nextLine())) == null) continue; if ((cp = parseHex(fields, 0)) == null) continue; if ((s = parseString(fields, 1)) != null) names.put(cp, s); if ((s = parseString(fields, 2)) != null) categories.put(cp, s); if ((i = parseInt(fields, 3)) != null) combClasses.put(cp, i); if ((s = parseString(fields, 4)) != null) bidiClasses.put(cp, s); if ((words = parseWords(fields, 5)) != null) { List types = new ArrayList(); List mappings = new ArrayList(); for (String word : words) { try { mappings.add(Integer.parseInt(word, 16)); } catch (NumberFormatException e) { types.add(word); } } if (!types.isEmpty()) decompTypes.put(cp, joinWords(types)); if (!mappings.isEmpty()) decompMappings.put(cp, toIntArray(mappings)); } if ((s = parseString(fields, 6)) != null) { numericTypes.put(cp, "Decimal"); numericValues.put(cp, s); } else if ((s = parseString(fields, 7)) != null) { numericTypes.put(cp, "Digit"); numericValues.put(cp, s); } else if ((s = parseString(fields, 8)) != null) { numericTypes.put(cp, "Numeric"); numericValues.put(cp, s); } if ((b = parseBoolean(fields, 9)) != null) bidiMirrored.put(cp, b); if ((s = parseString(fields, 10)) != null) uni1Names.put(cp, s); if ((s = parseString(fields, 11)) != null) comments.put(cp, s); if ((i = parseHex(fields, 12)) != null) uppercase.put(cp, i); if ((i = parseHex(fields, 13)) != null) lowercase.put(cp, i); if ((i = parseHex(fields, 14)) != null) titlecase.put(cp, i); } PuaaSubtable st = puaa.getOrCreateSubtable("Name"); st.addAll(PuaaUtility.createEntriesFromNameMap(names)); st = puaa.getOrCreateSubtable("General_Category"); st.addAll(PuaaUtility.createEntriesFromStringMap(categories)); st = puaa.getOrCreateSubtable("Canonical_Combining_Class"); st.addAll(PuaaUtility.createEntriesFromDecimalMap(combClasses)); st = puaa.getOrCreateSubtable("Bidi_Class"); st.addAll(PuaaUtility.createEntriesFromStringMap(bidiClasses)); st = puaa.getOrCreateSubtable("Decomposition_Type"); st.addAll(PuaaUtility.createEntriesFromStringMap(decompTypes)); st = puaa.getOrCreateSubtable("Decomposition_Mapping"); st.addAll(PuaaUtility.createEntriesFromHexSequenceMap(decompMappings)); st = puaa.getOrCreateSubtable("Numeric_Type"); st.addAll(PuaaUtility.createEntriesFromStringMap(numericTypes)); st = puaa.getOrCreateSubtable("Numeric_Value"); st.addAll(PuaaUtility.createEntriesFromStringMap(numericValues)); st = puaa.getOrCreateSubtable("Bidi_Mirrored"); st.addAll(PuaaUtility.createEntriesFromBooleanMap(bidiMirrored)); st = puaa.getOrCreateSubtable("Unicode_1_Name"); st.addAll(PuaaUtility.createEntriesFromNameMap(uni1Names)); st = puaa.getOrCreateSubtable("ISO_Comment"); st.addAll(PuaaUtility.createEntriesFromStringMap(comments)); st = puaa.getOrCreateSubtable("Simple_Uppercase_Mapping"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(uppercase)); st = puaa.getOrCreateSubtable("Simple_Lowercase_Mapping"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(lowercase)); st = puaa.getOrCreateSubtable("Simple_Titlecase_Mapping"); st.addAll(PuaaUtility.createEntriesFromHexadecimalMap(titlecase)); } @Override public void decompile(PuaaTable puaa, PrintWriter out) { PuaaSubtable names = puaa.getSubtable("Name"); PuaaSubtable categories = puaa.getSubtable("General_Category"); PuaaSubtable combClasses = puaa.getSubtable("Canonical_Combining_Class"); PuaaSubtable bidiClasses = puaa.getSubtable("Bidi_Class"); PuaaSubtable decompTypes = puaa.getSubtable("Decomposition_Type"); PuaaSubtable decompMappings = puaa.getSubtable("Decomposition_Mapping"); PuaaSubtable numericTypes = puaa.getSubtable("Numeric_Type"); PuaaSubtable numericValues = puaa.getSubtable("Numeric_Value"); PuaaSubtable bidiMirrored = puaa.getSubtable("Bidi_Mirrored"); PuaaSubtable uni1Names = puaa.getSubtable("Unicode_1_Name"); PuaaSubtable comments = puaa.getSubtable("ISO_Comment"); PuaaSubtable uppercase = puaa.getSubtable("Simple_Uppercase_Mapping"); PuaaSubtable lowercase = puaa.getSubtable("Simple_Lowercase_Mapping"); PuaaSubtable titlecase = puaa.getSubtable("Simple_Titlecase_Mapping"); TreeMap lines = new TreeMap(); if (names != null) for (PuaaSubtableEntry e : names) addLine(lines, e, 1); if (categories != null) for (PuaaSubtableEntry e : categories) addLine(lines, e, 2); if (combClasses != null) for (PuaaSubtableEntry e : combClasses) addLine(lines, e, 3); if (bidiClasses != null) for (PuaaSubtableEntry e : bidiClasses) addLine(lines, e, 4); if (decompTypes != null) for (PuaaSubtableEntry e : decompTypes) addLine(lines, e, 5); if (decompMappings != null) for (PuaaSubtableEntry e : decompMappings) addLine(lines, e, 5); if (numericTypes != null) for (PuaaSubtableEntry e : numericTypes) addLine(lines, e, 8); if (numericValues != null) for (PuaaSubtableEntry e : numericValues) addLine(lines, e, 8); if (bidiMirrored != null) for (PuaaSubtableEntry e : bidiMirrored) addLine(lines, e, 9); if (uni1Names != null) for (PuaaSubtableEntry e : uni1Names) addLine(lines, e, 10); if (comments != null) for (PuaaSubtableEntry e : comments) addLine(lines, e, 11); if (uppercase != null) for (PuaaSubtableEntry e : uppercase) addLine(lines, e, 12); if (lowercase != null) for (PuaaSubtableEntry e : lowercase) addLine(lines, e, 13); if (titlecase != null) for (PuaaSubtableEntry e : titlecase) addLine(lines, e, 14); for (String[] line : lines.values()) out.println(PuaaUtility.joinLine(line, ";")); } private static Integer parseInt(String[] fields, int i) { if (fields == null || i < 0 || i >= fields.length) return null; try { return Integer.parseInt(fields[i].trim(), 10); } catch (NumberFormatException e) { return null; } } private static Integer parseHex(String[] fields, int i) { if (fields == null || i < 0 || i >= fields.length) return null; try { return Integer.parseInt(fields[i].trim(), 16); } catch (NumberFormatException e) { return null; } } private static String parseString(String[] fields, int i) { if (fields == null || i < 0 || i >= fields.length) return null; String s = fields[i].trim(); if (s.length() == 0) return null; return s; } private static String[] parseWords(String[] fields, int i) { if (fields == null || i < 0 || i >= fields.length) return null; String s = fields[i].trim(); if (s.length() == 0) return null; return s.split("\\s+"); } private static Boolean parseBoolean(String[] fields, int i) { if (fields == null || i < 0 || i >= fields.length) return null; String s = fields[i].trim(); if (s.length() == 0) return null; return s.equalsIgnoreCase("Y"); } private static int[] toIntArray(Collection c) { Integer[] a = c.toArray(new Integer[c.size()]); int[] b = new int[a.length]; for (int i = 0; i < a.length; i++) b[i] = a[i]; return b; } private static String joinWords(List strings) { StringBuffer sb = new StringBuffer(); boolean first = true; for (String s : strings) { if (s != null && s.length() > 0) { if (first) first = false; else sb.append(" "); sb.append(s); } } return sb.toString(); } private static void addLine(TreeMap lines, PuaaSubtableEntry e, int i) { for (int cp = e.firstCodePoint; cp <= e.lastCodePoint; cp++) { String value = e.getPropertyValue(cp); if (value == null || value.length() == 0) continue; if (lines.containsKey(cp)) { String[] line = lines.get(cp); if (line[i] == null) { line[i] = value; } else if (i == 8) { if (line[i].equals("Decimal")) line[6] = line[7] = line[8] = value; if (line[i].equals("Digit")) line[7] = line[8] = value; if (line[i].equals("Numeric")) line[8] = value; } else { if (i == 5) line[i] += " "; line[i] += value; } } else { String[] line = new String[15]; line[0] = PuaaUtility.toHexString(cp); line[i] = value; lines.put(cp, line); } } } } UnihanDictionaryIndicesCodec.java000066400000000000000000000016421506470510200346600ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanDictionaryIndicesCodec extends AbstractUnihanCodec { public UnihanDictionaryIndicesCodec() { super( "Unihan_DictionaryIndices.txt", Arrays.asList( "kCheungBauerIndex", // added in Unicode 5.0 "kCihaiT", // moved in Unicode 15.0 (from DictionaryLikeData) "kCowles", // "kDaeJaweon", // "kFennIndex", // "kGSR", // "kHanYu", // "kIRGDaeJaweon", // "kIRGDaiKanwaZiten", // removed in Unicode 15.1 "kIRGHanyuDaZidian", // "kIRGKangXi", // "kKangXi", // "kKarlgren", // "kLau", // "kMatthews", // "kMeyerWempe", // "kMorohashi", // "kNelson", // "kSBGY", // "kSMSZD2003Index" // added in Unicode 15.1 ) ); } } UnihanDictionaryLikeDataCodec.java000066400000000000000000000014611506470510200347570ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanDictionaryLikeDataCodec extends AbstractUnihanCodec { public UnihanDictionaryLikeDataCodec() { super( "Unihan_DictionaryLikeData.txt", Arrays.asList( "kAlternateTotalStrokes", // added in Unicode 15.0 "kCangjie", // "kCheungBauer", // added in Unicode 5.0 "kFenn", // "kFourCornerCode", // added in Unicode 5.0 "kFrequency", // "kGradeLevel", // "kHDZRadBreak", // "kHKGlyph", // "kMojiJoho", // added in Unicode 15.1 "kPhonetic", // "kStrange", // added in Unicode 14.0 "kUnihanCore2020" // added in Unicode 13.0 ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/UnihanIRGSourcesCodec.java000066400000000000000000000014131506470510200333140ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanIRGSourcesCodec extends AbstractUnihanCodec { public UnihanIRGSourcesCodec() { super( "Unihan_IRGSources.txt", Arrays.asList( "kCompatibilityVariant", // "kIICore", // "kIRG_GSource", // "kIRG_HSource", // "kIRG_JSource", // "kIRG_KPSource", // "kIRG_KSource", // "kIRG_MSource", // added in Unicode 5.2 "kIRG_SSource", // added in Unicode 13.0 "kIRG_TSource", // "kIRG_UKSource", // added in Unicode 13.0 "kIRG_USource", // "kIRG_VSource", // "kRSUnicode", // "kTotalStrokes" // ) ); } } UnihanNumericValuesCodec.java000066400000000000000000000006601506470510200340350ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanNumericValuesCodec extends AbstractUnihanCodec { public UnihanNumericValuesCodec() { super( "Unihan_NumericValues.txt", Arrays.asList( "kAccountingNumeric", // "kOtherNumeric", // "kPrimaryNumeric", // "kVietnameseNumeric", // added in Unicode 15.1 "kZhuangNumeric" // added in Unicode 15.1 ) ); } } UnihanOtherMappingsCodec.java000066400000000000000000000026561506470510200340420ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanOtherMappingsCodec extends AbstractUnihanCodec { public UnihanOtherMappingsCodec() { super( "Unihan_OtherMappings.txt", Arrays.asList( "kBigFive", // "kCCCII", // "kCNS1986", // "kCNS1992", // "kEACC", // "kGB0", // "kGB1", // "kGB3", // "kGB5", // "kGB7", // "kGB8", // "kHKSCS", // removed in Unicode 15.1 "kIBMJapan", // "kJa", // added in Unicode 8.0 "kJinmeiyoKanji", // added in Unicode 11.0 "kJis0", // "kJis1", // "kJIS0213", // "kJoyoKanji", // added in Unicode 11.0 "kKPS0", // removed in Unicode 15.1 "kKPS1", // removed in Unicode 15.1 "kKSC0", // removed in Unicode 15.1 "kKSC1", // removed in Unicode 15.1 "kKoreanEducationHanja", // added in Unicode 11.0 "kKoreanName", // added in Unicode 11.0 "kMainlandTelegraph", // "kPseudoGB1", // "kTaiwanTelegraph", // "kTGH", // added in Unicode 11.0 "kXerox" // ) ); } } UnihanRadicalStrokeCountsCodec.java000066400000000000000000000007611506470510200352000ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanRadicalStrokeCountsCodec extends AbstractUnihanCodec { public UnihanRadicalStrokeCountsCodec() { super( "Unihan_RadicalStrokeCounts.txt", Arrays.asList( "kRSAdobe_Japan1_6", // "kRSJapanese", // removed in Unicode 13.0 "kRSKangXi", // removed in Unicode 15.1 "kRSKanWa", // removed in Unicode 13.0 "kRSKorean" // removed in Unicode 13.0 ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/UnihanReadingsCodec.java000066400000000000000000000014301506470510200330620ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanReadingsCodec extends AbstractUnihanCodec { public UnihanReadingsCodec() { super( "Unihan_Readings.txt", Arrays.asList( "kCantonese", // "kDefinition", // "kHangul", // added in Unicode 5.0 "kHanyuPinlu", // "kHanyuPinyin", // added in Unicode 5.2 "kJapanese", // added in Unicode 15.1 "kJapaneseKun", // "kJapaneseOn", // "kKorean", // "kMandarin", // "kSMSZD2003Readings", // added in Unicode 15.1 "kTang", // "kTGHZ2013", // added in Unicode 13.0 "kVietnamese", // "kXHC1983" // added in Unicode 5.1 ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaa/UnihanVariantsCodec.java000066400000000000000000000007361506470510200331250ustar00rootroot00000000000000package com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class UnihanVariantsCodec extends AbstractUnihanCodec { public UnihanVariantsCodec() { super( "Unihan_Variants.txt", Arrays.asList( "kSemanticVariant", // "kSimplifiedVariant", // "kSpecializedSemanticVariant", // "kSpoofingVariant", // added in Unicode 13.0 "kTraditionalVariant", // "kZVariant" // ) ); } } VerticalOrientationCodec.java000066400000000000000000000006761506470510200341040ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; public class VerticalOrientationCodec extends AbstractStringCodec { public VerticalOrientationCodec() { super("VerticalOrientation.txt", "Vertical_Orientation"); } @Override protected String format(String range, String value) { StringBuffer sb = new StringBuffer(); sb.append(range); while (sb.length() < 14) sb.append(" "); sb.append("; "); sb.append(value); return sb.toString(); } } WordBreakPropertyCodec.java000066400000000000000000000010421506470510200335300ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/puaapackage com.kreative.bitsnpicas.puaa; import java.util.Arrays; public class WordBreakPropertyCodec extends AbstractCategoryCodec { public WordBreakPropertyCodec() { super( "WordBreakProperty.txt", "Word_Break", Arrays.asList( "Double_Quote", "Single_Quote", "Hebrew_Letter", "CR", "LF", "Newline", "Extend", "Regional_Indicator", "Format", "Katakana", "ALetter", "MidLetter", "MidNum", "MidNumLet", "Numeric", "ExtendNumLet", "ZWJ", "WSegSpace" ) ); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/transformer/000077500000000000000000000000001506470510200300005ustar00rootroot00000000000000BoldBitmapFontGlyphTransformer.java000077500000000000000000000021431506470510200366620ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/transformerpackage com.kreative.bitsnpicas.transformer; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontGlyphTransformer; public class BoldBitmapFontGlyphTransformer implements BitmapFontGlyphTransformer { private final boolean extraWidth; public BoldBitmapFontGlyphTransformer(boolean extraWidth) { this.extraWidth = extraWidth; } public BitmapFontGlyph transformGlyph(BitmapFontGlyph glyph) { int x = glyph.getGlyphOffset(); int w = glyph.getCharacterWidth(); int a = glyph.getGlyphAscent(); byte[][] oldg = glyph.getGlyph(); byte[][] newg = new byte[oldg.length][]; for (int j = 0; j < oldg.length; j++) { newg[j] = new byte[oldg[j].length+1]; for (int i = 0; i < oldg[j].length; i++) { newg[j][i] = (byte)((newg[j][i] & 0xFF) + (255 - (newg[j][i] & 0xFF)) * (oldg[j][i] & 0xFF) / 255); newg[j][i+1] = (byte)((newg[j][i+1] & 0xFF) + (255 - (newg[j][i+1] & 0xFF)) * (oldg[j][i] & 0xFF) / 255); } } if (extraWidth) { if (w == 0) { if (x < 0) { x--; } } else { w++; } } return new BitmapFontGlyph(newg, x, w, a); } } TranslateBitmapFontGlyphTransformer.java000066400000000000000000000012531506470510200377350ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/transformerpackage com.kreative.bitsnpicas.transformer; import com.kreative.bitsnpicas.BitmapFontGlyph; import com.kreative.bitsnpicas.BitmapFontGlyphTransformer; public class TranslateBitmapFontGlyphTransformer implements BitmapFontGlyphTransformer { private final int x, w, a; public TranslateBitmapFontGlyphTransformer(int x, int w, int a) { this.x = x; this.w = w; this.a = a; } public BitmapFontGlyph transformGlyph(BitmapFontGlyph glyph) { int x = glyph.getGlyphOffset() + this.x; int w = glyph.getCharacterWidth() + this.w; int a = glyph.getGlyphAscent() + this.a; byte[][] g = glyph.getGlyph(); if (w < 0) w = 0; return new BitmapFontGlyph(g, x, w, a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/000077500000000000000000000000001506470510200273175ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CbdtEntry.java000066400000000000000000000013601506470510200320600ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.imageio.ImageIO; public abstract class CbdtEntry extends EbdtEntry { public byte[] imageData; public BufferedImage getImage() throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(imageData); BufferedImage image = ImageIO.read(in); in.close(); return image; } public void setImage(RenderedImage image) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageIO.write(image, "png", out); out.flush(); out.close(); imageData = out.toByteArray(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CbdtEntryFormat17.java000066400000000000000000000015051506470510200334020ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CbdtEntryFormat17 extends CbdtEntry { public SbitSmallGlyphMetrics glyphMetrics; @Override public int format() { return 17; } @Override protected void read(DataInputStream in, int length) throws IOException { glyphMetrics = new SbitSmallGlyphMetrics(); glyphMetrics.read(in); int imageSize = in.readInt(); imageData = new byte[imageSize]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((glyphMetrics != null) ? glyphMetrics : new SbitSmallGlyphMetrics()).write(out); out.writeInt(imageData.length); out.write(imageData); } @Override protected int length() { return 9 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CbdtEntryFormat18.java000066400000000000000000000015001506470510200333760ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CbdtEntryFormat18 extends CbdtEntry { public SbitBigGlyphMetrics glyphMetrics; @Override public int format() { return 18; } @Override protected void read(DataInputStream in, int length) throws IOException { glyphMetrics = new SbitBigGlyphMetrics(); glyphMetrics.read(in); int imageSize = in.readInt(); imageData = new byte[imageSize]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((glyphMetrics != null) ? glyphMetrics : new SbitBigGlyphMetrics()).write(out); out.writeInt(imageData.length); out.write(imageData); } @Override protected int length() { return 12 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CbdtEntryFormat19.java000066400000000000000000000011741506470510200334060ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CbdtEntryFormat19 extends CbdtEntry { @Override public int format() { return 19; } @Override protected void read(DataInputStream in, int length) throws IOException { int imageSize = in.readInt(); imageData = new byte[imageSize]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { out.writeInt(imageData.length); out.write(imageData); } @Override protected int length() { return 4 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CmapSubtable.java000077500000000000000000000020021506470510200325210ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public abstract class CmapSubtable { public abstract int format(); public abstract int getGlyphIndex(int charCode); protected abstract void compile(DataOutputStream out) throws IOException; public byte[] compile() throws IOException { ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); compile(out); out.flush(); byteout.flush(); out.close(); byteout.close(); return byteout.toByteArray(); } protected abstract void decompile(DataInputStream in, int length) throws IOException; public void decompile(byte[] data) throws IOException { ByteArrayInputStream bytein = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bytein); decompile(in, data.length); in.close(); bytein.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CmapSubtableEntry.java000077500000000000000000000004661506470510200335570ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public abstract class CmapSubtableEntry { public int startCharCode = 0; public int endCharCode = 0; public boolean contains(int charCode) { return (charCode >= startCharCode && charCode <= endCharCode); } public abstract int getGlyphIndex(int charCode); } CmapSubtableFormat0.java000077500000000000000000000017661506470510200337130ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CmapSubtableFormat0 extends CmapSubtable { public int languageID = 0; public final int[] glyphIndex = new int[256]; @Override public int format() { return 0; } @Override public int getGlyphIndex(int charCode) { if (charCode >= 0 && charCode < 256) { return glyphIndex[charCode]; } else { return 0; } } @Override protected void compile(DataOutputStream out) throws IOException { out.writeShort(0); // format out.writeShort(262); // length out.writeShort(languageID); for (int i = 0; i < 256; i++) { out.writeByte(glyphIndex[i]); } } @Override protected void decompile(DataInputStream in, int length) throws IOException { in.readUnsignedShort(); // format in.readUnsignedShort(); // length languageID = in.readUnsignedShort(); for (int i = 0; i < 256; i++) { glyphIndex[i] = in.readUnsignedByte(); } } } CmapSubtableFormat10.java000077500000000000000000000024261506470510200337660ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CmapSubtableFormat10 extends CmapSubtable { public int languageID = 0; public int firstChar = 0; public int glyphIndex[] = new int[0]; @Override public int format() { return 10; } @Override public int getGlyphIndex(int charCode) { if (charCode >= firstChar && charCode < firstChar + glyphIndex.length) { return glyphIndex[charCode - firstChar]; } else { return 0; } } @Override protected void compile(DataOutputStream out) throws IOException { out.writeShort(10); // format out.writeShort(0); // subformat out.writeInt(20 + glyphIndex.length * 2); out.writeInt(languageID); out.writeInt(firstChar); out.writeInt(glyphIndex.length); for (int i = 0; i < glyphIndex.length; i++) { out.writeShort(glyphIndex[i]); } } @Override protected void decompile(DataInputStream in, int length) throws IOException { in.readUnsignedShort(); // format in.readUnsignedShort(); // subformat in.readInt(); // length languageID = in.readInt(); firstChar = in.readInt(); glyphIndex = new int[in.readInt()]; for (int i = 0; i < glyphIndex.length; i++) { glyphIndex[i] = in.readUnsignedShort(); } } } CmapSubtableFormat12.java000077500000000000000000000025651506470510200337740ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CmapSubtableFormat12 extends ListBasedCmapSubtable { public int languageID = 0; @Override public int format() { return 12; } @Override public int getGlyphIndex(int charCode) { for (CmapSubtableSequentialEntry e : this) { if (e.contains(charCode)) { return e.getGlyphIndex(charCode); } } return 0; } @Override protected void compile(DataOutputStream out) throws IOException { out.writeShort(12); // format out.writeShort(0); // subformat out.writeInt(16 + this.size() * 12); out.writeInt(languageID); out.writeInt(this.size()); for (CmapSubtableSequentialEntry e : this) { out.writeInt(e.startCharCode); out.writeInt(e.endCharCode); out.writeInt(e.glyphIndex); } } @Override protected void decompile(DataInputStream in, int length) throws IOException { in.readUnsignedShort(); // format in.readUnsignedShort(); // subformat in.readInt(); // length languageID = in.readInt(); int count = in.readInt(); this.clear(); for (int i = 0; i < count; i++) { CmapSubtableSequentialEntry e = new CmapSubtableSequentialEntry(); e.startCharCode = in.readInt(); e.endCharCode = in.readInt(); e.glyphIndex = in.readInt(); this.add(e); } } } CmapSubtableFormat4.java000077500000000000000000000072551506470510200337160ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CmapSubtableFormat4 extends ListBasedCmapSubtable { public int languageID = 0; @Override public int format() { return 4; } @Override public int getGlyphIndex(int charCode) { for (CmapSubtableEntry e : this) { if (e.contains(charCode)) { return e.getGlyphIndex(charCode); } } return 0; } @Override protected void compile(DataOutputStream out) throws IOException { int segCnt = this.size(); int searchRange = (1 << 30); while (searchRange > segCnt) { searchRange >>>= 1; } int entrySelector = Integer.numberOfTrailingZeros(searchRange); searchRange <<= 1; int rangeShift = (segCnt << 1) - searchRange; int fmt4len = 16 + segCnt * 8; for (CmapSubtableEntry e : this) { if (e instanceof CmapSubtableRandomEntry) { fmt4len += ((CmapSubtableRandomEntry)e).glyphIndex.length * 2; } } out.writeShort(4); // format out.writeShort(fmt4len); out.writeShort(languageID); out.writeShort(segCnt * 2); out.writeShort(searchRange); out.writeShort(entrySelector); out.writeShort(rangeShift); for (CmapSubtableEntry e : this) { out.writeShort(e.endCharCode); } out.writeShort(0); // reservedPad for (CmapSubtableEntry e : this) { out.writeShort(e.startCharCode); } for (CmapSubtableEntry e : this) { if (e instanceof CmapSubtableSequentialEntry) { out.writeShort(((CmapSubtableSequentialEntry)e).glyphIndex - e.startCharCode); } else { out.writeShort(0); } } int idRangeOffset = this.size(); for (CmapSubtableEntry e : this) { if (e instanceof CmapSubtableRandomEntry) { out.writeShort(idRangeOffset * 2); idRangeOffset += ((CmapSubtableRandomEntry)e).glyphIndex.length; } else { out.writeShort(0); } idRangeOffset--; } for (CmapSubtableEntry e : this) { if (e instanceof CmapSubtableRandomEntry) { for (int glyphIndex : ((CmapSubtableRandomEntry)e).glyphIndex) { out.writeShort(glyphIndex); } } } } @Override protected void decompile(DataInputStream in, int length) throws IOException { in.readUnsignedShort(); // format in.readUnsignedShort(); // length languageID = in.readUnsignedShort(); int segCnt = in.readUnsignedShort() / 2; in.readUnsignedShort(); // searchRange in.readUnsignedShort(); // entrySelector in.readUnsignedShort(); // rangeShift int[] endCodes = new int[segCnt]; for (int i = 0; i < segCnt; i++) { endCodes[i] = in.readUnsignedShort(); } in.readUnsignedShort(); // reservedPad int[] startCodes = new int[segCnt]; for (int i = 0; i < segCnt; i++) { startCodes[i] = in.readUnsignedShort(); } int[] idDeltas = new int[segCnt]; for (int i = 0; i < segCnt; i++) { idDeltas[i] = in.readUnsignedShort(); } in.mark(length); int[] idRangeOffsets = new int[segCnt]; for (int i = 0; i < segCnt; i++) { idRangeOffsets[i] = in.readUnsignedShort(); } this.clear(); for (int i = 0; i < segCnt; i++) { if (idRangeOffsets[i] == 0) { CmapSubtableSequentialEntry e = new CmapSubtableSequentialEntry(); e.startCharCode = startCodes[i]; e.endCharCode = endCodes[i]; e.glyphIndex = (startCodes[i] + idDeltas[i]) & 0xFFFF; this.add(e); } else { CmapSubtableRandomEntry e = new CmapSubtableRandomEntry(); e.startCharCode = startCodes[i]; e.endCharCode = endCodes[i]; e.glyphIndex = new int[e.endCharCode - e.startCharCode + 1]; in.reset(); in.skipBytes(i + i + idRangeOffsets[i]); for (int j = 0; j < e.glyphIndex.length; j++) { e.glyphIndex[j] = in.readUnsignedShort(); } this.add(e); } } } } CmapSubtableFormat6.java000077500000000000000000000023721506470510200337130ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CmapSubtableFormat6 extends CmapSubtable { public int languageID = 0; public int firstChar = 0; public int glyphIndex[] = new int[0]; @Override public int format() { return 6; } @Override public int getGlyphIndex(int charCode) { if (charCode >= firstChar && charCode < firstChar + glyphIndex.length) { return glyphIndex[charCode - firstChar]; } else { return 0; } } @Override protected void compile(DataOutputStream out) throws IOException { out.writeShort(6); // format out.writeShort(10 + glyphIndex.length * 2); out.writeShort(languageID); out.writeShort(firstChar); out.writeShort(glyphIndex.length); for (int i = 0; i < glyphIndex.length; i++) { out.writeShort(glyphIndex[i]); } } @Override protected void decompile(DataInputStream in, int length) throws IOException { in.readUnsignedShort(); // format in.readUnsignedShort(); // length languageID = in.readUnsignedShort(); firstChar = in.readUnsignedShort(); glyphIndex = new int[in.readUnsignedShort()]; for (int i = 0; i < glyphIndex.length; i++) { glyphIndex[i] = in.readUnsignedShort(); } } } CmapSubtableRandomEntry.java000077500000000000000000000003761506470510200346410ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; public class CmapSubtableRandomEntry extends CmapSubtableEntry { public int[] glyphIndex = new int[0]; @Override public int getGlyphIndex(int charCode) { return glyphIndex[charCode - startCharCode]; } } CmapSubtableSequentialEntry.java000077500000000000000000000003721506470510200355270ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; public class CmapSubtableSequentialEntry extends CmapSubtableEntry { public int glyphIndex = 0; @Override public int getGlyphIndex(int charCode) { return glyphIndex + (charCode - startCharCode); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CmapTable.java000077500000000000000000000135341506470510200320230ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class CmapTable extends TrueTypeTable { public static final int VERSION_DEFAULT = 0; public static final int VERSION_CONTAINS_TYPE_8_OR_HIGHER = 1; public int version = VERSION_DEFAULT; public final List entries = new ArrayList(); public final List subtables = new ArrayList(); private static final CmapSubtable createSubtable(int format) { switch (format) { case 0: return new CmapSubtableFormat0(); case 4: return new CmapSubtableFormat4(); case 6: return new CmapSubtableFormat6(); case 10: return new CmapSubtableFormat10(); case 12: return new CmapSubtableFormat12(); default: return new UnknownCmapSubtable(format); } } @Override public String tableName() { return "cmap"; } @Override public String[] dependencyNames() { return new String[]{}; } public CmapSubtable getSubtable(int platformID, int platformSpecificID) { for (CmapTableEntry e : entries) { if (e.platformID == platformID && e.platformSpecificID == platformSpecificID) { return e.subtable; } } return null; } public CmapSubtable getBestSubtable() { CmapSubtable s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_FONTFORGE)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_FULL)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_2_0_NON_BMP)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_2_0)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_1_1)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_DEFAULT)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_WINDOWS_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_WINDOWS_UNICODE, PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_WINDOWS, PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32)) != null) return s; if ((s = getSubtable(PlatformConstants.PLATFORM_ID_WINDOWS, PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16)) != null) return s; return null; } public int getGlyphIndex(int charCode) { CmapSubtable s = getBestSubtable(); if (s != null) return s.getGlyphIndex(charCode); return 0; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeShort(version); out.writeShort(entries.size()); int currentOffset = 4 + entries.size() * 8; Map subtableData = new HashMap(); Map subtableOffset = new HashMap(); for (CmapSubtable subtable : subtables) { byte[] data = subtable.compile(); subtableData.put(subtable, data); subtableOffset.put(subtable, currentOffset); currentOffset += data.length; } for (CmapTableEntry e : entries) { out.writeShort(e.platformID); out.writeShort(e.platformSpecificID); out.writeInt(subtableOffset.get(e.subtable)); } for (CmapSubtable subtable : subtables) { out.write(subtableData.get(subtable)); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readUnsignedShort(); int numSubtables = in.readUnsignedShort(); // Read headers. List subtableInfo = new ArrayList(); List subtableOffsets = new ArrayList(); subtableOffsets.add(length); for (int i = 0; i < numSubtables; i++) { CmapSubtableInfo info = new CmapSubtableInfo(); info.platformID = in.readUnsignedShort(); info.platformSpecificID = in.readUnsignedShort(); info.offset = in.readInt(); subtableInfo.add(info); if (!subtableOffsets.contains(info.offset)) { subtableOffsets.add(info.offset); } } Collections.sort(subtableOffsets); // Read data. Map offsetToData = new HashMap(); int s = subtableOffsets.get(0); for (int i = 1; i < subtableOffsets.size(); i++) { int e = subtableOffsets.get(i); byte[] data = new byte[e - s]; in.reset(); in.skipBytes(s); in.readFully(data); offsetToData.put(s, data); s = e; } // Decompile. Map offsetToSubtable = new HashMap(); for (Map.Entry e : offsetToData.entrySet()) { int offset = e.getKey(); byte[] data = e.getValue(); int format = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF); CmapSubtable subtable = createSubtable(format); subtable.decompile(data); offsetToSubtable.put(offset, subtable); } // Gather tables. entries.clear(); for (CmapSubtableInfo info : subtableInfo) { CmapTableEntry e = new CmapTableEntry(); e.platformID = info.platformID; e.platformSpecificID = info.platformSpecificID; e.subtable = offsetToSubtable.get(info.offset); entries.add(e); } subtables.clear(); for (int i = 0; i < subtableOffsets.size() - 1; i++) { int offset = subtableOffsets.get(i); subtables.add(offsetToSubtable.get(offset)); } } private static final class CmapSubtableInfo { private int platformID; private int platformSpecificID; private int offset; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CmapTableEntry.java000077500000000000000000000031661506470510200330450ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public class CmapTableEntry implements Comparable { public int platformID; public int platformSpecificID; public CmapSubtable subtable; public static CmapTableEntry forUnicode(CmapSubtable subtable) { CmapTableEntry e = new CmapTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_UNICODE; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_2_0; e.subtable = subtable; return e; } public static CmapTableEntry forMacintosh(CmapSubtable subtable) { CmapTableEntry e = new CmapTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_MACINTOSH; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_MACINTOSH_ROMAN; e.subtable = subtable; return e; } public static CmapTableEntry forWindowsUnicode16(CmapSubtable subtable) { CmapTableEntry e = new CmapTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_WINDOWS; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16; e.subtable = subtable; return e; } public static CmapTableEntry forWindowsUnicode32(CmapSubtable subtable) { CmapTableEntry e = new CmapTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_WINDOWS; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32; e.subtable = subtable; return e; } @Override public int compareTo(CmapTableEntry other) { if (this.platformID != other.platformID) return this.platformID - other.platformID; if (this.platformSpecificID != other.platformSpecificID) return this.platformSpecificID - other.platformSpecificID; return 0; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/ColrTable.java000066400000000000000000000074521506470510200320410ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class ColrTable extends TrueTypeTable { public int version = 0; public BaseGlyph[] baseGlyphRecords = new BaseGlyph[0]; public Layer[] layerRecords = new Layer[0]; @Override public String tableName() { return "COLR"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { int offset = (version < 1) ? 14 : 34; out.writeShort(version); if (baseGlyphRecords != null) { out.writeShort(baseGlyphRecords.length); out.writeInt(offset); offset += baseGlyphRecords.length * 6; } else { out.writeShort(0); out.writeInt(0); } if (layerRecords != null) { out.writeInt(offset); offset += layerRecords.length * 4; out.writeShort(layerRecords.length); } else { out.writeInt(0); out.writeShort(0); } if (version >= 1) { out.writeInt(0); // TODO baseGlyphListOffset out.writeInt(0); // TODO layerListOffset out.writeInt(0); // TODO clipListOffset out.writeInt(0); // TODO varIndexMapOffset out.writeInt(0); // TODO itemVariationStoreOffset } if (baseGlyphRecords != null) { for (BaseGlyph record : baseGlyphRecords) { record.write(out); } } if (layerRecords != null) { for (Layer record : layerRecords) { record.write(out); } } if (version >= 1) { // TODO BaseGlyphList // TODO LayerList // TODO ClipList // TODO DeltaSetIndexMap // TODO ItemVariationStore } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readUnsignedShort(); int numBaseGlyphRecords = in.readUnsignedShort(); int baseGlyphRecordsOffset = in.readInt(); int layerRecordsOffset = in.readInt(); int numLayerRecords = in.readUnsignedShort(); // TODO int baseGlyphListOffset = (version < 1) ? 0 : in.readInt(); // TODO int layerListOffset = (version < 1) ? 0 : in.readInt(); // TODO int clipListOffset = (version < 1) ? 0 : in.readInt(); // TODO int varIndexMapOffset = (version < 1) ? 0 : in.readInt(); // TODO int itemVariationStoreOffset = (version < 1) ? 0 : in.readInt(); if (baseGlyphRecordsOffset > 0) { in.reset(); in.skipBytes(baseGlyphRecordsOffset); baseGlyphRecords = new BaseGlyph[numBaseGlyphRecords]; for (int i = 0; i < numBaseGlyphRecords; i++) { (baseGlyphRecords[i] = new BaseGlyph()).read(in); } } else { baseGlyphRecords = null; } if (layerRecordsOffset > 0) { in.reset(); in.skipBytes(layerRecordsOffset); layerRecords = new Layer[numLayerRecords]; for (int i = 0; i < numLayerRecords; i++) { (layerRecords[i] = new Layer()).read(in); } } else { layerRecords = null; } // TODO BaseGlyphList // TODO LayerList // TODO ClipList // TODO DeltaSetIndexMap // TODO ItemVariationStore } public static final class BaseGlyph { public int glyphID; public int firstLayerIndex; public int numLayers; public void read(DataInputStream in) throws IOException { glyphID = in.readUnsignedShort(); firstLayerIndex = in.readUnsignedShort(); numLayers = in.readUnsignedShort(); } public void write(DataOutputStream out) throws IOException { out.writeShort(glyphID); out.writeShort(firstLayerIndex); out.writeShort(numLayers); } } public static final class Layer { public int glyphID; public int paletteIndex; public void read(DataInputStream in) throws IOException { glyphID = in.readUnsignedShort(); paletteIndex = in.readUnsignedShort(); } public void write(DataOutputStream out) throws IOException { out.writeShort(glyphID); out.writeShort(paletteIndex); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/CpalTable.java000066400000000000000000000101421506470510200320070ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class CpalTable extends TrueTypeTable { public static final int USABLE_WITH_LIGHT_BACKGROUND = 0x0001; public static final int USABLE_WITH_DARK_BACKGROUND = 0x0002; public int version = 0; public int numPaletteEntries = 0; public int[] colorRecordIndices = new int[0]; public int[] colorRecordsArray = new int[0]; public int[] paletteTypesArray = null; public int[] paletteLabelsArray = null; public int[] paletteEntryLabelsArray = null; @Override public String tableName() { return "CPAL"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { int offset = colorRecordIndices.length * 2 + 12; if (version >= 1) offset += 12; // Version 0 Header out.writeShort(version); out.writeShort(numPaletteEntries); out.writeShort(colorRecordIndices.length); out.writeShort(colorRecordsArray.length); out.writeInt(offset); // colorRecordsArrayOffset offset += colorRecordsArray.length * 4; for (int i : colorRecordIndices) { out.writeShort(i); } // Version 1 Header if (version >= 1) { if (paletteTypesArray != null) { out.writeInt(offset); offset += paletteTypesArray.length * 4; } else { out.writeInt(0); } if (paletteLabelsArray != null) { out.writeInt(offset); offset += paletteLabelsArray.length * 2; } else { out.writeInt(0); } if (paletteEntryLabelsArray != null) { out.writeInt(offset); offset += paletteEntryLabelsArray.length * 2; } else { out.writeInt(0); } } // Color Records for (int argb : colorRecordsArray) { out.writeInt(Integer.reverseBytes(argb)); } // Palette Records if (version >= 1) { if (paletteTypesArray != null) { for (int type : paletteTypesArray) { out.writeInt(type); } } if (paletteLabelsArray != null) { for (int label : paletteLabelsArray) { out.writeShort(label); } } if (paletteEntryLabelsArray != null) { for (int label : paletteEntryLabelsArray) { out.writeShort(label); } } } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { // Version 0 Header version = in.readUnsignedShort(); numPaletteEntries = in.readUnsignedShort(); colorRecordIndices = new int[in.readUnsignedShort()]; colorRecordsArray = new int[in.readUnsignedShort()]; int colorRecordsArrayOffset = in.readInt(); for (int i = 0; i < colorRecordIndices.length; i++) { colorRecordIndices[i] = in.readUnsignedShort(); } // Version 1 Header int paletteTypesArrayOffset = (version < 1) ? 0 : in.readInt(); int paletteLabelsArrayOffset = (version < 1) ? 0 : in.readInt(); int paletteEntryLabelsArrayOffset = (version < 1) ? 0 : in.readInt(); // Color Records in.reset(); in.skipBytes(colorRecordsArrayOffset); for (int i = 0; i < colorRecordsArray.length; i++) { colorRecordsArray[i] = Integer.reverseBytes(in.readInt()); } // Palette Records if (paletteTypesArrayOffset > 0) { in.reset(); in.skipBytes(paletteTypesArrayOffset); paletteTypesArray = new int[colorRecordIndices.length]; for (int i = 0; i < colorRecordIndices.length; i++) { paletteTypesArray[i] = in.readInt(); } } else { paletteTypesArray = null; } if (paletteLabelsArrayOffset > 0) { in.reset(); in.skipBytes(paletteLabelsArrayOffset); paletteLabelsArray = new int[colorRecordIndices.length]; for (int i = 0; i < colorRecordIndices.length; i++) { paletteLabelsArray[i] = in.readUnsignedShort(); } } else { paletteLabelsArray = null; } if (paletteEntryLabelsArrayOffset > 0) { in.reset(); in.skipBytes(paletteEntryLabelsArrayOffset); paletteEntryLabelsArray = new int[colorRecordsArray.length]; for (int i = 0; i < colorRecordsArray.length; i++) { paletteEntryLabelsArray[i] = in.readUnsignedShort(); } } else { paletteEntryLabelsArray = null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtComponent.java000066400000000000000000000010311506470510200327160ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtComponent { public int glyphID; public int xOffset; public int yOffset; protected void read(DataInputStream in) throws IOException { glyphID = in.readUnsignedShort(); xOffset = in.readByte(); yOffset = in.readByte(); } protected void write(DataOutputStream out) throws IOException { out.writeShort(glyphID); out.writeByte(xOffset); out.writeByte(yOffset); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntry.java000066400000000000000000000006111506470510200320600ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public abstract class EbdtEntry { public abstract int format(); protected abstract void read(DataInputStream in, int length) throws IOException; protected abstract void write(DataOutputStream out) throws IOException; protected abstract int length(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat1.java000066400000000000000000000014341506470510200333160ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat1 extends EbdtEntry { public SbitSmallGlyphMetrics smallMetrics; public byte[] imageData; @Override public int format() { return 1; } @Override protected void read(DataInputStream in, int length) throws IOException { smallMetrics = new SbitSmallGlyphMetrics(); smallMetrics.read(in); imageData = new byte[length - 5]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((smallMetrics != null) ? smallMetrics : new SbitSmallGlyphMetrics()).write(out); out.write(imageData); } @Override protected int length() { return 5 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat2.java000066400000000000000000000014341506470510200333170ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat2 extends EbdtEntry { public SbitSmallGlyphMetrics smallMetrics; public byte[] imageData; @Override public int format() { return 2; } @Override protected void read(DataInputStream in, int length) throws IOException { smallMetrics = new SbitSmallGlyphMetrics(); smallMetrics.read(in); imageData = new byte[length - 5]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((smallMetrics != null) ? smallMetrics : new SbitSmallGlyphMetrics()).write(out); out.write(imageData); } @Override protected int length() { return 5 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat5.java000066400000000000000000000011151506470510200333160ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat5 extends EbdtEntry { public byte[] imageData; @Override public int format() { return 5; } @Override protected void read(DataInputStream in, int length) throws IOException { imageData = new byte[length]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { out.write(imageData); } @Override protected int length() { return imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat6.java000066400000000000000000000014141506470510200333210ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat6 extends EbdtEntry { public SbitBigGlyphMetrics bigMetrics; public byte[] imageData; @Override public int format() { return 6; } @Override protected void read(DataInputStream in, int length) throws IOException { bigMetrics = new SbitBigGlyphMetrics(); bigMetrics.read(in); imageData = new byte[length - 8]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((bigMetrics != null) ? bigMetrics : new SbitBigGlyphMetrics()).write(out); out.write(imageData); } @Override protected int length() { return 8 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat7.java000066400000000000000000000014141506470510200333220ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat7 extends EbdtEntry { public SbitBigGlyphMetrics bigMetrics; public byte[] imageData; @Override public int format() { return 7; } @Override protected void read(DataInputStream in, int length) throws IOException { bigMetrics = new SbitBigGlyphMetrics(); bigMetrics.read(in); imageData = new byte[length - 8]; in.readFully(imageData); } @Override protected void write(DataOutputStream out) throws IOException { ((bigMetrics != null) ? bigMetrics : new SbitBigGlyphMetrics()).write(out); out.write(imageData); } @Override protected int length() { return 8 + imageData.length; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat8.java000066400000000000000000000017151506470510200333270ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat8 extends ListBasedEbdtEntry { public SbitSmallGlyphMetrics smallMetrics; @Override public int format() { return 8; } @Override protected void read(DataInputStream in, int length) throws IOException { smallMetrics = new SbitSmallGlyphMetrics(); smallMetrics.read(in); in.readByte(); int n = in.readUnsignedShort(); for (int i = 0; i < n; i++) { EbdtComponent c = new EbdtComponent(); c.read(in); this.add(c); } } @Override protected void write(DataOutputStream out) throws IOException { ((smallMetrics != null) ? smallMetrics : new SbitSmallGlyphMetrics()).write(out); out.writeByte(0); out.writeShort(this.size()); for (EbdtComponent c : this) { c.write(out); } } @Override protected int length() { return 8 + (this.size() * 4); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtEntryFormat9.java000066400000000000000000000016311506470510200333250ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EbdtEntryFormat9 extends ListBasedEbdtEntry { public SbitBigGlyphMetrics bigMetrics; @Override public int format() { return 9; } @Override protected void read(DataInputStream in, int length) throws IOException { bigMetrics = new SbitBigGlyphMetrics(); bigMetrics.read(in); int n = in.readUnsignedShort(); for (int i = 0; i < n; i++) { EbdtComponent c = new EbdtComponent(); c.read(in); this.add(c); } } @Override protected void write(DataOutputStream out) throws IOException { ((bigMetrics != null) ? bigMetrics : new SbitBigGlyphMetrics()).write(out); out.writeShort(this.size()); for (EbdtComponent c : this) { c.write(out); } } @Override protected int length() { return 10 + (this.size() * 4); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EbdtTable.java000066400000000000000000000107711506470510200320160ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; public class EbdtTable extends MapBasedTable { public SbitTableType type; public int version; public EbdtTable(SbitTableType type) { this.type = type; this.version = type.version; } @Override public String tableName() { return type.dataTableName; } @Override public String[] dependencyNames() { return new String[]{type.locTableName}; } public int getNextKey() { int nextKey = 4; for (Map.Entry e : this.entrySet()) { int end = e.getKey() + e.getValue().length(); if (end > nextKey) nextKey = end; } return nextKey; } public void recalculate(EblcTable eblc) { SortedSet oldOffsets = new TreeSet(); SortedMap remap = new TreeMap(); Map newmap = new HashMap(); int newOffset = 4; oldOffsets.addAll(this.keySet()); for (int oldOffset : oldOffsets) { EbdtEntry entry = this.get(oldOffset); remap.put(oldOffset, newOffset); newmap.put(newOffset, entry); newOffset += entry.length(); } for (EblcBitmapSize ebs : eblc) { for (EblcIndexSubtable st : ebs) { int[] oldOffs = st.getOffsets(); int[] newOffs = new int[oldOffs.length]; int newBase = -1; for (int i = 0; i < oldOffs.length; i++) { newOffs[i] = remap(remap, oldOffs[i]); if (newBase < 0 || newOffs[i] < newBase) { newBase = newOffs[i]; } } st.header.imageDataOffset = newBase; st.setOffsets(newOffs); } } this.clear(); this.putAll(newmap); } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { Map dataRuns = new HashMap(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); dos.writeInt(version); dos.flush(); dos.close(); byte[] data = bos.toByteArray(); dataRuns.put(0, data); int totalLength = data.length; for (Map.Entry e : this.entrySet()) { bos = new ByteArrayOutputStream(); dos = new DataOutputStream(bos); e.getValue().write(dos); dos.flush(); dos.close(); data = bos.toByteArray(); dataRuns.put(e.getKey(), data); int end = e.getKey() + data.length; if (end > totalLength) totalLength = end; } byte[] dest = new byte[totalLength]; for (Map.Entry e : dataRuns.entrySet()) { byte[] src = e.getValue(); for (int di = e.getKey(), si = 0; si < src.length; si++, di++) { dest[di] = src[si]; } } out.write(dest); } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readInt(); EblcTable eblc = (EblcTable)dependencies[0]; for (EblcBitmapSize ebs : eblc) { for (EblcIndexSubtable st : ebs) { int[] offsets = st.getOffsets(); for (int i = 1; i < offsets.length; i++) { int dataOffset = offsets[i - 1]; int dataLength = offsets[i] - dataOffset; if (dataLength > 0 && !this.containsKey(dataOffset)) { in.reset(); in.skip(dataOffset); EbdtEntry e = createEbdtEntry(st.header.imageFormat); e.read(in, dataLength); this.put(dataOffset, e); } } } } } private static final EbdtEntry createEbdtEntry(int format) throws IOException { switch (format) { case 1: return new EbdtEntryFormat1(); case 2: return new EbdtEntryFormat2(); case 5: return new EbdtEntryFormat5(); case 6: return new EbdtEntryFormat6(); case 7: return new EbdtEntryFormat7(); case 8: return new EbdtEntryFormat8(); case 9: return new EbdtEntryFormat9(); case 17: return new CbdtEntryFormat17(); case 18: return new CbdtEntryFormat18(); case 19: return new CbdtEntryFormat19(); default: throw new IOException("invalid imageFormat: " + format); } } private static final int remap(SortedMap remap, int v) { int lastOldBase = 0, lastNewBase = 0; for (Map.Entry e : remap.entrySet()) { int oldBase = e.getKey(), newBase = e.getValue(); if (v < oldBase) return lastNewBase + (v - lastOldBase); lastOldBase = oldBase; lastNewBase = newBase; } return lastNewBase + (v - lastOldBase); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EblcBitmapSize.java000066400000000000000000000036351506470510200330260ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; public class EblcBitmapSize extends ArrayList { private static final long serialVersionUID = 1L; public static final int BIT_DEPTH_BLACK_WHITE = 1; public static final int BIT_DEPTH_LEVELS_4 = 2; public static final int BIT_DEPTH_LEVELS_16 = 4; public static final int BIT_DEPTH_LEVELS_256 = 8; public static final int FLAGS_HORIZONTAL_METRICS = 1; public static final int FLAGS_VERTICAL_METRICS = 2; public int indexSubTableArrayOffset; public int indexTablesSize; public int numberOfIndexSubTables; public int colorRef; public SbitLineMetrics hori; public SbitLineMetrics vert; public int startGlyphIndex; public int endGlyphIndex; public int ppemX; public int ppemY; public int bitDepth; public int flags; protected void read(DataInputStream in) throws IOException { indexSubTableArrayOffset = in.readInt(); indexTablesSize = in.readInt(); numberOfIndexSubTables = in.readInt(); colorRef = in.readInt(); hori = new SbitLineMetrics(); hori.read(in); vert = new SbitLineMetrics(); vert.read(in); startGlyphIndex = in.readUnsignedShort(); endGlyphIndex = in.readUnsignedShort(); ppemX = in.readUnsignedByte(); ppemY = in.readUnsignedByte(); bitDepth = in.readUnsignedByte(); flags = in.readUnsignedByte(); } protected void write(DataOutputStream out) throws IOException { out.writeInt(indexSubTableArrayOffset); out.writeInt(indexTablesSize); out.writeInt(numberOfIndexSubTables); out.writeInt(colorRef); ((hori != null) ? hori : new SbitLineMetrics()).write(out); ((vert != null) ? vert : new SbitLineMetrics()).write(out); out.writeShort(startGlyphIndex); out.writeShort(endGlyphIndex); out.writeByte(ppemX); out.writeByte(ppemY); out.writeByte(bitDepth); out.writeByte(flags); } } EblcGlyphIdOffsetPair.java000066400000000000000000000007361506470510200342220ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcGlyphIdOffsetPair { public int glyphID; public int offset; protected void read(DataInputStream in) throws IOException { glyphID = in.readUnsignedShort(); offset = in.readUnsignedShort(); } protected void write(DataOutputStream out) throws IOException { out.writeShort(glyphID); out.writeShort(offset); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EblcIndexSubtable.java000066400000000000000000000011661506470510200335050ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public abstract class EblcIndexSubtable { public EblcIndexSubtableHeader header; protected abstract void read(DataInputStream in) throws IOException; protected abstract void write(DataOutputStream out) throws IOException; protected abstract int length(); public abstract int[] getOffsets(); public abstract void setOffsets(int[] offsets); public abstract EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs(); public abstract void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs); } EblcIndexSubtable1.java000066400000000000000000000031471506470510200335100ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtable1 extends ListBasedEblcIndexSubtable { @Override protected void read(DataInputStream in) throws IOException { int n = header.lastGlyphIndex - header.firstGlyphIndex + 2; for (int i = 0; i < n; i++) this.add(in.readInt()); } @Override protected void write(DataOutputStream out) throws IOException { for (int offset : this) out.writeInt(offset); } @Override protected int length() { return this.size() * 4; } @Override public int[] getOffsets() { int n = this.size(); int[] offsets = new int[n]; for (int i = 0; i < n; i++) { offsets[i] = this.get(i) + header.imageDataOffset; } return offsets; } @Override public void setOffsets(int[] offsets) { this.clear(); for (int offset : offsets) { this.add(offset - header.imageDataOffset); } } @Override public EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs() { int n = this.size(); EblcGlyphIdOffsetPair[] pairs = new EblcGlyphIdOffsetPair[n]; for (int i = 0; i < n; i++) { pairs[i] = new EblcGlyphIdOffsetPair(); pairs[i].glyphID = header.firstGlyphIndex + i; pairs[i].offset = this.get(i) + header.imageDataOffset; } return pairs; } @Override public void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs) { header.firstGlyphIndex = pairs[0].glyphID; header.lastGlyphIndex = pairs[0].glyphID + pairs.length - 2; this.clear(); for (EblcGlyphIdOffsetPair pair : pairs) { this.add(pair.offset - header.imageDataOffset); } } } EblcIndexSubtable2.java000066400000000000000000000032001506470510200334770ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtable2 extends EblcIndexSubtable { public int imageSize; public SbitBigGlyphMetrics bigMetrics; @Override protected void read(DataInputStream in) throws IOException { imageSize = in.readInt(); bigMetrics = new SbitBigGlyphMetrics(); bigMetrics.read(in); } @Override protected void write(DataOutputStream out) throws IOException { out.writeInt(imageSize); ((bigMetrics != null) ? bigMetrics : new SbitBigGlyphMetrics()).write(out); } @Override protected int length() { return 12; } @Override public int[] getOffsets() { int n = header.lastGlyphIndex - header.firstGlyphIndex + 2; int[] offsets = new int[n]; for (int i = 0; i < n; i++) { offsets[i] = i * imageSize + header.imageDataOffset; } return offsets; } @Override public void setOffsets(int[] offsets) { imageSize = offsets[1] - offsets[0]; } @Override public EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs() { int n = header.lastGlyphIndex - header.firstGlyphIndex + 2; EblcGlyphIdOffsetPair[] pairs = new EblcGlyphIdOffsetPair[n]; for (int i = 0; i < n; i++) { pairs[i] = new EblcGlyphIdOffsetPair(); pairs[i].glyphID = header.firstGlyphIndex + i; pairs[i].offset = i * imageSize + header.imageDataOffset; } return pairs; } @Override public void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs) { header.firstGlyphIndex = pairs[0].glyphID; header.lastGlyphIndex = pairs[0].glyphID + pairs.length - 2; imageSize = pairs[1].offset - pairs[0].offset; } } EblcIndexSubtable3.java000066400000000000000000000033271506470510200335120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtable3 extends ListBasedEblcIndexSubtable { @Override protected void read(DataInputStream in) throws IOException { int n = header.lastGlyphIndex - header.firstGlyphIndex + 2; for (int i = 0; i < n; i++) this.add(in.readUnsignedShort()); } @Override protected void write(DataOutputStream out) throws IOException { for (int offset : this) out.writeShort(offset); if ((this.size() & 1) != 0) out.writeShort(0); } @Override protected int length() { int l = this.size() * 2; if ((this.size() & 1) != 0) l += 2; return l; } @Override public int[] getOffsets() { int n = this.size(); int[] offsets = new int[n]; for (int i = 0; i < n; i++) { offsets[i] = this.get(i) + header.imageDataOffset; } return offsets; } @Override public void setOffsets(int[] offsets) { this.clear(); for (int offset : offsets) { this.add(offset - header.imageDataOffset); } } @Override public EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs() { int n = this.size(); EblcGlyphIdOffsetPair[] pairs = new EblcGlyphIdOffsetPair[n]; for (int i = 0; i < n; i++) { pairs[i] = new EblcGlyphIdOffsetPair(); pairs[i].glyphID = header.firstGlyphIndex + i; pairs[i].offset = this.get(i) + header.imageDataOffset; } return pairs; } @Override public void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs) { header.firstGlyphIndex = pairs[0].glyphID; header.lastGlyphIndex = pairs[0].glyphID + pairs.length - 2; this.clear(); for (EblcGlyphIdOffsetPair pair : pairs) { this.add(pair.offset - header.imageDataOffset); } } } EblcIndexSubtable4.java000066400000000000000000000034221506470510200335070ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtable4 extends ListBasedEblcIndexSubtable { @Override protected void read(DataInputStream in) throws IOException { int n = in.readInt() + 1; for (int i = 0; i < n; i++) { EblcGlyphIdOffsetPair pair = new EblcGlyphIdOffsetPair(); pair.read(in); this.add(pair); } } @Override protected void write(DataOutputStream out) throws IOException { out.writeInt(this.size() - 1); for (EblcGlyphIdOffsetPair pair : this) { pair.write(out); } } @Override protected int length() { return 4 + (this.size() * 4); } @Override public int[] getOffsets() { int n = this.size(); int[] offsets = new int[n]; for (int i = 0; i < n; i++) { offsets[i] = this.get(i).offset + header.imageDataOffset; } return offsets; } @Override public void setOffsets(int[] offsets) { int n = Math.min(offsets.length, this.size()); for (int i = 0; i < n; i++) { this.get(i).offset = offsets[i] - header.imageDataOffset; } } @Override public EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs() { int n = this.size(); EblcGlyphIdOffsetPair[] pairs = new EblcGlyphIdOffsetPair[n]; for (int i = 0; i < n; i++) { pairs[i] = new EblcGlyphIdOffsetPair(); pairs[i].glyphID = this.get(i).glyphID; pairs[i].offset = this.get(i).offset + header.imageDataOffset; } return pairs; } @Override public void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs) { this.clear(); for (EblcGlyphIdOffsetPair pair : pairs) { EblcGlyphIdOffsetPair p = new EblcGlyphIdOffsetPair(); p.glyphID = pair.glyphID; p.offset = pair.offset - header.imageDataOffset; this.add(p); } } } EblcIndexSubtable5.java000066400000000000000000000041711506470510200335120ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtable5 extends ListBasedEblcIndexSubtable { public int imageSize; public SbitBigGlyphMetrics bigMetrics; @Override protected void read(DataInputStream in) throws IOException { imageSize = in.readInt(); bigMetrics = new SbitBigGlyphMetrics(); bigMetrics.read(in); int n = in.readInt(); for (int i = 0; i < n; i++) { this.add(in.readUnsignedShort()); } } @Override protected void write(DataOutputStream out) throws IOException { out.writeInt(imageSize); ((bigMetrics != null) ? bigMetrics : new SbitBigGlyphMetrics()).write(out); out.writeInt(this.size()); for (int glyphID : this) { out.writeShort(glyphID); } if ((size() & 1) != 0) { out.writeShort(0); } } @Override protected int length() { int l = 16 + (this.size() * 2); if ((size() & 1) != 0) l += 2; return l; } @Override public int[] getOffsets() { int n = this.size() + 1; int[] offsets = new int[n]; for (int i = 0; i < n; i++) { offsets[i] = i * imageSize + header.imageDataOffset; } return offsets; } @Override public void setOffsets(int[] offsets) { imageSize = offsets[1] - offsets[0]; } @Override public EblcGlyphIdOffsetPair[] getGlyphIdOffsetPairs() { int n = this.size() + 1; EblcGlyphIdOffsetPair[] pairs = new EblcGlyphIdOffsetPair[n]; for (int i = 0; i < n; i++) { pairs[i] = new EblcGlyphIdOffsetPair(); pairs[i].glyphID = (i < this.size()) ? this.get(i) : -1; pairs[i].offset = i * imageSize + header.imageDataOffset; } return pairs; } @Override public void setGlyphIdOffsetPairs(EblcGlyphIdOffsetPair[] pairs) { header.firstGlyphIndex = pairs[0].glyphID; header.lastGlyphIndex = pairs[0].glyphID; this.clear(); for (EblcGlyphIdOffsetPair pair : pairs) { if (pair.glyphID < header.firstGlyphIndex) header.firstGlyphIndex = pair.glyphID; if (pair.glyphID > header.lastGlyphIndex) header.lastGlyphIndex = pair.glyphID; this.add(pair.glyphID); } imageSize = pairs[1].offset - pairs[0].offset; } } EblcIndexSubtableHeader.java000066400000000000000000000021431506470510200345330ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class EblcIndexSubtableHeader { public int firstGlyphIndex; public int lastGlyphIndex; public int additionalOffsetToIndexSubtable; public int indexFormat; public int imageFormat; public int imageDataOffset; protected void readElement(DataInputStream in) throws IOException { firstGlyphIndex = in.readUnsignedShort(); lastGlyphIndex = in.readUnsignedShort(); additionalOffsetToIndexSubtable = in.readInt(); } protected void writeElement(DataOutputStream out) throws IOException { out.writeShort(firstGlyphIndex); out.writeShort(lastGlyphIndex); out.writeInt(additionalOffsetToIndexSubtable); } protected void readHeader(DataInputStream in) throws IOException { indexFormat = in.readUnsignedShort(); imageFormat = in.readUnsignedShort(); imageDataOffset = in.readInt(); } protected void writeHeader(DataOutputStream out) throws IOException { out.writeShort(indexFormat); out.writeShort(imageFormat); out.writeInt(imageDataOffset); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/EblcTable.java000066400000000000000000000054361506470510200320070ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class EblcTable extends ListBasedTable { public SbitTableType type; public int version; public EblcTable(SbitTableType type) { this.type = type; this.version = type.version; } @Override public String tableName() { return type.locTableName; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { // Recalculate offsets. int ptr = 8 + (this.size() * 48); for (EblcBitmapSize ebs : this) { ebs.indexSubTableArrayOffset = ptr; ebs.indexTablesSize = ebs.size() * 8; ebs.numberOfIndexSubTables = ebs.size(); ptr += ebs.size() * 8; for (EblcIndexSubtable st : ebs) { st.header.additionalOffsetToIndexSubtable = ptr - ebs.indexSubTableArrayOffset; ebs.indexTablesSize += 8 + st.length(); ptr += 8 + st.length(); } } // Write new table. out.writeInt(version); out.writeInt(this.size()); for (EblcBitmapSize ebs : this) { ebs.write(out); } for (EblcBitmapSize ebs : this) { for (EblcIndexSubtable st : ebs) { st.header.writeElement(out); } for (EblcIndexSubtable st : ebs) { st.header.writeHeader(out); st.write(out); } } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readInt(); int n = in.readInt(); for (int i = 0; i < n; i++) { EblcBitmapSize ebs = new EblcBitmapSize(); ebs.read(in); this.add(ebs); } for (EblcBitmapSize ebs : this) { List headers = new ArrayList(); in.reset(); in.skip(ebs.indexSubTableArrayOffset); for (int i = 0; i < ebs.numberOfIndexSubTables; i++) { EblcIndexSubtableHeader header = new EblcIndexSubtableHeader(); header.readElement(in); headers.add(header); } for (EblcIndexSubtableHeader header : headers) { in.reset(); in.skip(ebs.indexSubTableArrayOffset + header.additionalOffsetToIndexSubtable); header.readHeader(in); EblcIndexSubtable st = createEblcIndexSubtable(header.indexFormat); st.header = header; st.read(in); ebs.add(st); } } } private static final EblcIndexSubtable createEblcIndexSubtable(int format) throws IOException { switch (format) { case 1: return new EblcIndexSubtable1(); case 2: return new EblcIndexSubtable2(); case 3: return new EblcIndexSubtable3(); case 4: return new EblcIndexSubtable4(); case 5: return new EblcIndexSubtable5(); default: throw new IOException("invalid indexFormat: " + format); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/GlyfTable.java000077500000000000000000000016721506470510200320440ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.List; public class GlyfTable extends ListBasedTable { @Override public String tableName() { return "glyf"; } @Override public String[] dependencyNames() { return new String[]{"loca"}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { for (byte[] data : this) { out.write(data); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { List locations = (LocaTable)dependencies[0]; this.clear(); int s = locations.get(0); for (int i = 1; i < locations.size(); i++) { int e = locations.get(i); byte[] data = new byte[e - s]; in.reset(); in.skipBytes(s); in.readFully(data); this.add(data); s = e; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/GlyfTableEntry.java000077500000000000000000000274771506470510200331010ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; // FIXME THIS IS CURRENTLY BROKEN. SO, SO BROKEN. public class GlyfTableEntry { public static final int FLAG_ON_CURVE = 0x01; public static final int FLAG_X_SHORT_VECTOR = 0x02; public static final int FLAG_Y_SHORT_VECTOR = 0x04; public static final int FLAG_REPEAT = 0x08; public static final int FLAG_THIS_X_IS_SAME = 0x10; public static final int FLAG_POSITIVE_X_SHORT_VECTOR = 0x10; public static final int FLAG_THIS_Y_IS_SAME = 0x20; public static final int FLAG_POSITIVE_Y_SHORT_VECTOR = 0x20; public static final int FLAG_RESERVED_1 = 0x40; public static final int FLAG_RESERVED_2 = 0x80; public static final int COMPONENT_FLAG_ARG_1_AND_2_ARE_WORDS = 0x0001; public static final int COMPONENT_FLAG_ARGS_ARE_XY_VALUES = 0x0002; public static final int COMPONENT_FLAG_ROUND_XY_TO_GRID = 0x0004; public static final int COMPONENT_FLAG_WE_HAVE_A_SCALE = 0x0008; public static final int COMPONENT_FLAG_OBSOLETE = 0x0010; public static final int COMPONENT_FLAG_MORE_COMPONENTS = 0x0020; public static final int COMPONENT_FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 0x0040; public static final int COMPONENT_FLAG_WE_HAVE_A_TWO_BY_TWO = 0x0080; public static final int COMPONENT_FLAG_WE_HAVE_INSTRUCTIONS = 0x0100; public static final int COMPONENT_FLAG_USE_MY_METRICS = 0x0200; public static final int COMPONENT_FLAG_OVERLAP_COMPOUND = 0x0400; public int numberOfContours = 0; public int xMin = 0; public int yMin = 0; public int xMax = 0; public int yMax = 0; // For simple glyphs. public int[] endPointsOfContours = new int[0]; public int[] instructions = new int[0]; public int[] flags = new int[0]; public int[] xCoordinates = new int[0]; public int[] yCoordinates = new int[0]; // For compound glyphs. public int numberOfComponents = 0; public int[] componentFlags = new int[0]; public int[] componentGlyphIndex = new int[0]; public int[] componentArgument1 = new int[0]; public int[] componentArgument2 = new int[0]; public double[] componentTransformA = new double[0]; public double[] componentTransformB = new double[0]; public double[] componentTransformC = new double[0]; public double[] componentTransformD = new double[0]; public void compile(DataOutputStream out) throws IOException { out.writeShort(numberOfContours); out.writeShort(xMin); out.writeShort(yMin); out.writeShort(xMax); out.writeShort(yMax); if (numberOfContours >= 0) { // Simple glyph. int lastPointIndex = 0; for (int i = 0; i < numberOfContours; i++) { lastPointIndex = endPointsOfContours[i]; out.writeShort(lastPointIndex); } out.writeShort(instructions.length); for (int i = 0; i < instructions.length; i++) { out.writeByte(instructions[i]); } for (int i = 0; i <= lastPointIndex; i++) { out.writeByte(flags[i]); if ((flags[i] & FLAG_REPEAT) != 0) { int repeat = 1; while (i + repeat <= lastPointIndex && flags[i + repeat] == (flags[i] & ~FLAG_REPEAT)) { repeat++; } out.writeByte(repeat - 1); i += repeat; } } int lastXCoordinate = 0; for (int i = 0; i <= lastPointIndex; i++) { if ((flags[i] & FLAG_X_SHORT_VECTOR) != 0) { out.writeByte(Math.abs(xCoordinates[i] - lastXCoordinate)); lastXCoordinate = xCoordinates[i]; } else if ((flags[i] & FLAG_THIS_X_IS_SAME) != 0) { lastXCoordinate = xCoordinates[i]; } else { out.writeShort(xCoordinates[i] - lastXCoordinate); lastXCoordinate = xCoordinates[i]; } } int lastYCoordinate = 0; for (int i = 0; i <= lastPointIndex; i++) { if ((flags[i] & FLAG_Y_SHORT_VECTOR) != 0) { out.writeByte(Math.abs(yCoordinates[i] - lastYCoordinate)); lastYCoordinate = yCoordinates[i]; } else if ((flags[i] & FLAG_THIS_Y_IS_SAME) != 0) { lastYCoordinate = yCoordinates[i]; } else { out.writeShort(yCoordinates[i] - lastYCoordinate); lastYCoordinate = yCoordinates[i]; } } } else if (numberOfContours == -1) { // Compound glyph. for (int i = 0; i < numberOfComponents; i++) { if (i < numberOfComponents - 1) { componentFlags[i] |= COMPONENT_FLAG_MORE_COMPONENTS; } else { componentFlags[i] &= ~COMPONENT_FLAG_MORE_COMPONENTS; } int flags = componentFlags[i]; boolean words = ((flags & COMPONENT_FLAG_ARG_1_AND_2_ARE_WORDS) != 0); boolean scale = ((flags & COMPONENT_FLAG_WE_HAVE_A_SCALE) != 0); boolean xyScale = ((flags & COMPONENT_FLAG_WE_HAVE_AN_X_AND_Y_SCALE) != 0); boolean twoByTwo = ((flags & COMPONENT_FLAG_WE_HAVE_A_TWO_BY_TWO) != 0); out.writeShort(flags); out.writeShort(componentGlyphIndex[i]); if (words) { out.writeShort(componentArgument1[i]); out.writeShort(componentArgument2[i]); } else { out.writeByte(componentArgument1[i]); out.writeByte(componentArgument2[i]); } if (twoByTwo) { out.writeShort((int)Math.round(componentTransformA[i] * 16384.0) + ((componentTransformA[i] < 0) ? 0x8000 : 0)); out.writeShort((int)Math.round(componentTransformB[i] * 16384.0) + ((componentTransformB[i] < 0) ? 0x8000 : 0)); out.writeShort((int)Math.round(componentTransformC[i] * 16384.0) + ((componentTransformC[i] < 0) ? 0x8000 : 0)); out.writeShort((int)Math.round(componentTransformD[i] * 16384.0) + ((componentTransformD[i] < 0) ? 0x8000 : 0)); } else if (xyScale) { out.writeShort((int)Math.round(componentTransformA[i] * 16384.0) + ((componentTransformA[i] < 0) ? 0x8000 : 0)); out.writeShort((int)Math.round(componentTransformD[i] * 16384.0) + ((componentTransformD[i] < 0) ? 0x8000 : 0)); } else if (scale) { out.writeShort((int)Math.round(componentTransformA[i] * 16384.0) + ((componentTransformA[i] < 0) ? 0x8000 : 0)); } } } else { throw new IllegalStateException("Unknown glyph format."); } } public void decompile(DataInputStream in) throws IOException { numberOfContours = in.readShort(); xMin = in.readShort(); yMin = in.readShort(); xMax = in.readShort(); yMax = in.readShort(); if (numberOfContours >= 0) { // Simple glyph. endPointsOfContours = new int[numberOfContours]; int lastPointIndex = 0; for (int i = 0; i < numberOfContours; i++) { lastPointIndex = in.readUnsignedShort(); endPointsOfContours[i] = lastPointIndex; } instructions = new int[in.readUnsignedShort()]; for (int i = 0; i < instructions.length; i++) { instructions[i] = in.readUnsignedByte(); } flags = new int[lastPointIndex + 1]; for (int i = 0; i <= lastPointIndex; i++) { flags[i] = in.readUnsignedByte(); if ((flags[i] & FLAG_REPEAT) != 0) { int repeat = in.readUnsignedByte(); for (int j = 1; j <= repeat; j++) { flags[i+j] = flags[i] & ~FLAG_REPEAT; } i += repeat; } } xCoordinates = new int[lastPointIndex + 1]; int lastXCoordinate = 0; for (int i = 0; i <= lastPointIndex; i++) { if ((flags[i] & FLAG_X_SHORT_VECTOR) != 0) { int sign = ((flags[i] & FLAG_POSITIVE_X_SHORT_VECTOR) != 0) ? 1 : -1; xCoordinates[i] = lastXCoordinate + sign * in.readUnsignedByte(); lastXCoordinate = xCoordinates[i]; } else if ((flags[i] & FLAG_THIS_X_IS_SAME) != 0) { xCoordinates[i] = lastXCoordinate; } else { xCoordinates[i] = lastXCoordinate + in.readShort(); lastXCoordinate = xCoordinates[i]; } } yCoordinates = new int[lastPointIndex + 1]; int lastYCoordinate = 0; for (int i = 0; i <= lastPointIndex; i++) { if ((flags[i] & FLAG_Y_SHORT_VECTOR) != 0) { int sign = ((flags[i] & FLAG_POSITIVE_Y_SHORT_VECTOR) != 0) ? 1 : -1; yCoordinates[i] = lastYCoordinate + sign * in.readUnsignedByte(); lastYCoordinate = yCoordinates[i]; } else if ((flags[i] & FLAG_THIS_Y_IS_SAME) != 0) { yCoordinates[i] = lastYCoordinate; } else { yCoordinates[i] = lastYCoordinate + in.readShort(); lastYCoordinate = yCoordinates[i]; } } } else if (numberOfContours == -1) { // Compound glyph. numberOfComponents = 0; List componentFlags = new ArrayList(); List componentGlyphIndex = new ArrayList(); List componentArgument1 = new ArrayList(); List componentArgument2 = new ArrayList(); List componentTransformA = new ArrayList(); List componentTransformB = new ArrayList(); List componentTransformC = new ArrayList(); List componentTransformD = new ArrayList(); while (true) { int flags = in.readUnsignedShort(); boolean words = ((flags & COMPONENT_FLAG_ARG_1_AND_2_ARE_WORDS) != 0); boolean signed = ((flags & COMPONENT_FLAG_ARGS_ARE_XY_VALUES) != 0); boolean scale = ((flags & COMPONENT_FLAG_WE_HAVE_A_SCALE) != 0); boolean xyScale = ((flags & COMPONENT_FLAG_WE_HAVE_AN_X_AND_Y_SCALE) != 0); boolean twoByTwo = ((flags & COMPONENT_FLAG_WE_HAVE_A_TWO_BY_TWO) != 0); boolean more = ((flags & COMPONENT_FLAG_MORE_COMPONENTS) != 0); numberOfComponents++; componentFlags.add(flags); componentGlyphIndex.add(in.readUnsignedShort()); if (words) { if (signed) { componentArgument1.add((int)in.readShort()); componentArgument2.add((int)in.readShort()); } else { componentArgument1.add(in.readUnsignedShort()); componentArgument2.add(in.readUnsignedShort()); } } else { if (signed) { componentArgument1.add((int)in.readByte()); componentArgument2.add((int)in.readByte()); } else { componentArgument1.add(in.readUnsignedByte()); componentArgument2.add(in.readUnsignedByte()); } } double transformA; double transformB; double transformC; double transformD; if (twoByTwo) { int a = in.readShort(); transformA = Math.signum(a) * (a & 0x7FFF) / 16384.0; int b = in.readShort(); transformB = Math.signum(b) * (b & 0x7FFF) / 16384.0; int c = in.readShort(); transformC = Math.signum(c) * (c & 0x7FFF) / 16384.0; int d = in.readShort(); transformD = Math.signum(d) * (d & 0x7FFF) / 16384.0; } else if (xyScale) { int a = in.readShort(); transformA = Math.signum(a) * (a & 0x7FFF) / 16384.0; transformB = 0.0; transformC = 0.0; int d = in.readShort(); transformD = Math.signum(d) * (d & 0x7FFF) / 16384.0; } else if (scale) { int a = in.readShort(); transformA = Math.signum(a) * (a & 0x7FFF) / 16384.0; transformB = 0.0; transformC = 0.0; transformD = transformA; } else { transformA = 1.0; transformB = 0.0; transformC = 0.0; transformD = 1.0; } componentTransformA.add(transformA); componentTransformB.add(transformB); componentTransformC.add(transformC); componentTransformD.add(transformD); if (!more) break; } this.componentFlags = new int[numberOfComponents]; this.componentGlyphIndex = new int[numberOfComponents]; this.componentArgument1 = new int[numberOfComponents]; this.componentArgument2 = new int[numberOfComponents]; this.componentTransformA = new double[numberOfComponents]; this.componentTransformB = new double[numberOfComponents]; this.componentTransformC = new double[numberOfComponents]; this.componentTransformD = new double[numberOfComponents]; for (int i = 0; i < numberOfComponents; i++) { this.componentFlags[i] = componentFlags.get(i); this.componentGlyphIndex[i] = componentGlyphIndex.get(i); this.componentArgument1[i] = componentArgument1.get(i); this.componentArgument2[i] = componentArgument2.get(i); this.componentTransformA[i] = componentTransformA.get(i); this.componentTransformB[i] = componentTransformB.get(i); this.componentTransformC[i] = componentTransformC.get(i); this.componentTransformD[i] = componentTransformD.get(i); } } else { throw new IllegalStateException("Unknown glyph format."); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/HeadTable.java000077500000000000000000000125411506470510200320010ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.GregorianCalendar; public class HeadTable extends TrueTypeTable { public static final int VERSION_DEFAULT = 0x00010000; public static final int MAGIC_NUMBER = 0x5F0F3CF5; public static final int FLAGS_Y_VALUE_OF_ZERO_SPECIFIES_BASELINE = 0x0001; public static final int FLAGS_MINIMUM_X_VALUE_IS_LEFT_SIDE_BEARING = 0x0002; public static final int FLAGS_SCALED_AND_ACTUAL_POINT_SIZE_DIFFER = 0x0004; public static final int FLAGS_USE_INTEGER_SCALING = 0x0008; public static final int FLAGS_USED_BY_MICROSOFT = 0x0010; public static final int FLAGS_X_VALUE_OF_ZERO_SPECIFIES_BASELINE = 0x0020; public static final int FLAGS_MUST_BE_ZERO = 0x0040; public static final int FLAGS_REQUIRES_LAYOUT_FOR_CORRECT_RENDERING = 0x0080; public static final int FLAGS_METAMORPHOSIS_EFFECT_BY_DEFAULT = 0x0100; public static final int FLAGS_CONTAINS_RIGHT_TO_LEFT_GLYPHS = 0x0200; public static final int FLAGS_CONTAINS_INDIC_STYLE_REARRANGEMENT = 0x0400; public static final int FLAGS_DEFINED_BY_ADOBE_1 = 0x0800; public static final int FLAGS_DEFINED_BY_ADOBE_2 = 0x1000; public static final int FLAGS_DEFINED_BY_ADOBE_3 = 0x2000; public static final int FLAGS_GENERIC_SYMBOLS_FOR_CODE_POINT_RANGES = 0x4000; public static final long DATE_EPOCH = new GregorianCalendar(1904, Calendar.JANUARY, 1, 0, 0, 0).getTimeInMillis(); public static final int MAC_STYLE_PLAIN = 0x00; public static final int MAC_STYLE_BOLD = 0x01; public static final int MAC_STYLE_ITALIC = 0x02; public static final int MAC_STYLE_BOLD_ITALIC = 0x03; public static final int MAC_STYLE_UNDERLINE = 0x04; public static final int MAC_STYLE_OUTLINE = 0x08; public static final int MAC_STYLE_SHADOW = 0x10; public static final int MAC_STYLE_CONDENSED = 0x20; public static final int MAC_STYLE_EXTENDED = 0x40; public static final int MAC_STYLE_GROUPED = 0x80; public static final int FONT_DIRECTION_HINT_MIXED = 0; public static final int FONT_DIRECTION_HINT_ONLY_LTR = 1; public static final int FONT_DIRECTION_HINT_LTR_WITH_NEUTRAL = 2; public static final int FONT_DIRECTION_HINT_ONLY_RTL = -1; public static final int FONT_DIRECTION_HINT_RTL_WITH_NEUTRAL = -2; public static final int INDEX_TO_LOC_FORMAT_SHORT = 0; public static final int INDEX_TO_LOC_FORMAT_LONG = 1; public static final int GLYPH_DATA_FORMAT_DEFAULT = 0; public int version = VERSION_DEFAULT; public int fontRevision = 0; public int checkSum = 0; public int magicNumber = MAGIC_NUMBER; public int flags = 0; public int unitsPerEm = 0; public long dateCreated = 0; public long dateModified = 0; public int xMin = 0; public int yMin = 0; public int xMax = 0; public int yMax = 0; public int macStyle = MAC_STYLE_PLAIN; public int lowestRecPPEM = 0; public int fontDirectionHint = FONT_DIRECTION_HINT_MIXED; public int indexToLocFormat = INDEX_TO_LOC_FORMAT_SHORT; public int glyphDataFormat = GLYPH_DATA_FORMAT_DEFAULT; @Override public String tableName() { return "head"; } @Override public String[] dependencyNames() { return new String[]{}; } public double getFontRevisionDouble() { return fontRevision / 65536.0; } public void setFontRevisionDouble(double revision) { fontRevision = (int)Math.round(revision * 65536.0); } public GregorianCalendar getDateCreatedCalendar() { GregorianCalendar cal = new GregorianCalendar(); cal.setTimeInMillis(DATE_EPOCH + (dateCreated * 1000L)); return cal; } public void setDateCreatedCalendar(Calendar cal) { dateCreated = (cal.getTimeInMillis() - DATE_EPOCH) / 1000L; } public GregorianCalendar getDateModifiedCalendar() { GregorianCalendar cal = new GregorianCalendar(); cal.setTimeInMillis(DATE_EPOCH + (dateModified * 1000L)); return cal; } public void setDateModifiedCalendar(Calendar cal) { dateModified = (cal.getTimeInMillis() - DATE_EPOCH) / 1000L; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeInt(version); out.writeInt(fontRevision); out.writeInt(checkSum); out.writeInt(magicNumber); out.writeShort(flags); out.writeShort(unitsPerEm); out.writeLong(dateCreated); out.writeLong(dateModified); out.writeShort(xMin); out.writeShort(yMin); out.writeShort(xMax); out.writeShort(yMax); out.writeShort(macStyle); out.writeShort(lowestRecPPEM); out.writeShort(fontDirectionHint); out.writeShort(indexToLocFormat); out.writeShort(glyphDataFormat); } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readInt(); fontRevision = in.readInt(); checkSum = in.readInt(); magicNumber = in.readInt(); flags = in.readUnsignedShort(); unitsPerEm = in.readUnsignedShort(); dateCreated = in.readLong(); dateModified = in.readLong(); xMin = in.readShort(); yMin = in.readShort(); xMax = in.readShort(); yMax = in.readShort(); macStyle = in.readUnsignedShort(); lowestRecPPEM = in.readUnsignedShort(); fontDirectionHint = in.readShort(); indexToLocFormat = in.readShort(); glyphDataFormat = in.readShort(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/HheaTable.java000077500000000000000000000042761506470510200320130ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class HheaTable extends TrueTypeTable { public static final int VERSION_DEFAULT = 0x00010000; public int version = VERSION_DEFAULT; public int ascent = 0; public int descent = 0; public int lineGap = 0; public int advanceWidthMax = 0; public int minLeftSideBearing = 0; public int minRightSideBearing = 0; public int xMaxExtent = 0; public int caretSlopeRise = 1; public int caretSlopeRun = 0; public int caretOffset = 0; public int reserved1 = 0; public int reserved2 = 0; public int reserved3 = 0; public int reserved4 = 0; public int metricDataFormat = 0; public int numLongHorMetrics = 0; @Override public String tableName() { return "hhea"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeInt(version); out.writeShort(ascent); out.writeShort(descent); out.writeShort(lineGap); out.writeShort(advanceWidthMax); out.writeShort(minLeftSideBearing); out.writeShort(minRightSideBearing); out.writeShort(xMaxExtent); out.writeShort(caretSlopeRise); out.writeShort(caretSlopeRun); out.writeShort(caretOffset); out.writeShort(reserved1); out.writeShort(reserved2); out.writeShort(reserved3); out.writeShort(reserved4); out.writeShort(metricDataFormat); out.writeShort(numLongHorMetrics); } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readInt(); ascent = in.readShort(); descent = in.readShort(); lineGap = in.readShort(); advanceWidthMax = in.readUnsignedShort(); minLeftSideBearing = in.readShort(); minRightSideBearing = in.readShort(); xMaxExtent = in.readShort(); caretSlopeRise = in.readShort(); caretSlopeRun = in.readShort(); caretOffset = in.readShort(); reserved1 = in.readShort(); reserved2 = in.readShort(); reserved3 = in.readShort(); reserved4 = in.readShort(); metricDataFormat = in.readShort(); numLongHorMetrics = in.readUnsignedShort(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/HmtxTable.java000077500000000000000000000024571506470510200320650ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class HmtxTable extends ListBasedTable { @Override public String tableName() { return "hmtx"; } @Override public String[] dependencyNames() { return new String[]{"hhea","maxp"}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { int numLongHorMetrics = ((HheaTable)dependencies[0]).numLongHorMetrics; for (int i = 0; i < this.size(); i++) { HmtxTableEntry entry = this.get(i); if (i < numLongHorMetrics) { out.writeShort(entry.advanceWidth); } out.writeShort(entry.leftSideBearing); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { int numLongHorMetrics = ((HheaTable)dependencies[0]).numLongHorMetrics; int numGlyphs = ((MaxpTable)dependencies[1]).numGlyphs; int lastAdvanceWidth = 0; this.clear(); for (int i = 0; i < numGlyphs; i++) { if (i < numLongHorMetrics) { lastAdvanceWidth = in.readUnsignedShort(); } HmtxTableEntry entry = new HmtxTableEntry(); entry.advanceWidth = lastAdvanceWidth; entry.leftSideBearing = in.readShort(); this.add(entry); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/HmtxTableEntry.java000077500000000000000000000005521506470510200331010ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public class HmtxTableEntry { public int advanceWidth; public int leftSideBearing; public HmtxTableEntry() { this.advanceWidth = 0; this.leftSideBearing = 0; } public HmtxTableEntry(int advanceWidth, int leftSideBearing) { this.advanceWidth = advanceWidth; this.leftSideBearing = leftSideBearing; } } ListBasedCmapSubtable.java000077500000000000000000000041531506470510200342460ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public abstract class ListBasedCmapSubtable extends CmapSubtable implements List { private final List list = new ArrayList(); @Override public boolean add(E e) { return list.add(e); } @Override public void add(int index, E e) { list.add(index, e); } @Override public boolean addAll(Collection c) { return list.addAll(c); } @Override public boolean addAll(int index, Collection c) { return list.addAll(index, c); } @Override public void clear() { list.clear(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(Collection c) { return list.containsAll(c); } @Override public E get(int index) { return list.get(index); } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return list.iterator(); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator listIterator() { return list.listIterator(); } @Override public ListIterator listIterator(int index) { return list.listIterator(index); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public E remove(int index) { return list.remove(index); } @Override public boolean removeAll(Collection c) { return list.removeAll(c); } @Override public boolean retainAll(Collection c) { return list.retainAll(c); } @Override public E set(int index, E e) { return list.set(index, e); } @Override public int size() { return list.size(); } @Override public List subList(int start, int end) { return list.subList(start, end); } @Override public Object[] toArray() { return list.toArray(); } @Override public T[] toArray(T[] a) { return list.toArray(a); } } ListBasedEbdtEntry.java000066400000000000000000000041451506470510200336020ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public abstract class ListBasedEbdtEntry extends EbdtEntry implements List { private final List list = new ArrayList(); @Override public boolean add(E e) { return list.add(e); } @Override public void add(int index, E e) { list.add(index, e); } @Override public boolean addAll(Collection c) { return list.addAll(c); } @Override public boolean addAll(int index, Collection c) { return list.addAll(index, c); } @Override public void clear() { list.clear(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(Collection c) { return list.containsAll(c); } @Override public E get(int index) { return list.get(index); } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return list.iterator(); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator listIterator() { return list.listIterator(); } @Override public ListIterator listIterator(int index) { return list.listIterator(index); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public E remove(int index) { return list.remove(index); } @Override public boolean removeAll(Collection c) { return list.removeAll(c); } @Override public boolean retainAll(Collection c) { return list.retainAll(c); } @Override public E set(int index, E e) { return list.set(index, e); } @Override public int size() { return list.size(); } @Override public List subList(int start, int end) { return list.subList(start, end); } @Override public Object[] toArray() { return list.toArray(); } @Override public T[] toArray(T[] a) { return list.toArray(a); } } ListBasedEblcIndexSubtable.java000066400000000000000000000041651506470510200352230ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public abstract class ListBasedEblcIndexSubtable extends EblcIndexSubtable implements List { private final List list = new ArrayList(); @Override public boolean add(E e) { return list.add(e); } @Override public void add(int index, E e) { list.add(index, e); } @Override public boolean addAll(Collection c) { return list.addAll(c); } @Override public boolean addAll(int index, Collection c) { return list.addAll(index, c); } @Override public void clear() { list.clear(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(Collection c) { return list.containsAll(c); } @Override public E get(int index) { return list.get(index); } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return list.iterator(); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator listIterator() { return list.listIterator(); } @Override public ListIterator listIterator(int index) { return list.listIterator(index); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public E remove(int index) { return list.remove(index); } @Override public boolean removeAll(Collection c) { return list.removeAll(c); } @Override public boolean retainAll(Collection c) { return list.retainAll(c); } @Override public E set(int index, E e) { return list.set(index, e); } @Override public int size() { return list.size(); } @Override public List subList(int start, int end) { return list.subList(start, end); } @Override public Object[] toArray() { return list.toArray(); } @Override public T[] toArray(T[] a) { return list.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/ListBasedTable.java000077500000000000000000000041451506470510200330130ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public abstract class ListBasedTable extends TrueTypeTable implements List { private final List list = new ArrayList(); @Override public boolean add(E e) { return list.add(e); } @Override public void add(int index, E e) { list.add(index, e); } @Override public boolean addAll(Collection c) { return list.addAll(c); } @Override public boolean addAll(int index, Collection c) { return list.addAll(index, c); } @Override public void clear() { list.clear(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(Collection c) { return list.containsAll(c); } @Override public E get(int index) { return list.get(index); } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return list.iterator(); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator listIterator() { return list.listIterator(); } @Override public ListIterator listIterator(int index) { return list.listIterator(index); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public E remove(int index) { return list.remove(index); } @Override public boolean removeAll(Collection c) { return list.removeAll(c); } @Override public boolean retainAll(Collection c) { return list.retainAll(c); } @Override public E set(int index, E e) { return list.set(index, e); } @Override public int size() { return list.size(); } @Override public List subList(int start, int end) { return list.subList(start, end); } @Override public Object[] toArray() { return list.toArray(); } @Override public T[] toArray(T[] a) { return list.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/LocaTable.java000077500000000000000000000027751506470510200320260ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class LocaTable extends ListBasedTable { @Override public String tableName() { return "loca"; } @Override public String[] dependencyNames() { return new String[]{"head","maxp"}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { int indexToLocFormat = ((HeadTable)dependencies[0]).indexToLocFormat; switch (indexToLocFormat) { case HeadTable.INDEX_TO_LOC_FORMAT_SHORT: for (int loc : this) out.writeShort(loc / 2); break; case HeadTable.INDEX_TO_LOC_FORMAT_LONG: for (int loc : this) out.writeInt(loc); break; default: throw new IllegalStateException("Invalid indexToLocFormat."); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { int indexToLocFormat = ((HeadTable)dependencies[0]).indexToLocFormat; int numGlyphs = ((MaxpTable)dependencies[1]).numGlyphs; switch (indexToLocFormat) { case HeadTable.INDEX_TO_LOC_FORMAT_SHORT: this.clear(); for (int i = 0; i <= numGlyphs; i++) { this.add(in.readUnsignedShort() * 2); } break; case HeadTable.INDEX_TO_LOC_FORMAT_LONG: this.clear(); for (int i = 0; i <= numGlyphs; i++) { this.add(in.readInt()); } break; default: throw new IllegalStateException("Invalid indexToLocFormat."); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/MapBasedTable.java000066400000000000000000000021631506470510200326100ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public abstract class MapBasedTable extends TrueTypeTable implements Map { private final Map map = new HashMap(); @Override public void clear() { map.clear(); } @Override public boolean containsKey(Object k) { return map.containsKey(k); } @Override public boolean containsValue(Object v) { return map.containsValue(v); } @Override public Set> entrySet() { return map.entrySet(); } @Override public V get(Object k) { return map.get(k); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public Set keySet() { return map.keySet(); } @Override public V put(K k, V v) { return map.put(k, v); } @Override public void putAll(Map m) { map.putAll(m); } @Override public V remove(Object k) { return map.remove(k); } @Override public int size() { return map.size(); } @Override public Collection values() { return map.values(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/MaxpTable.java000077500000000000000000000060351506470510200320460ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class MaxpTable extends TrueTypeTable { public static final int VERSION_DEFAULT = 0x00010000; public static final int VERSION_CFF = 0x00005000; public int version = VERSION_DEFAULT; /** Number of glyphs in the font. */ public int numGlyphs = 0; /** Maximum number of points in any non-compound glyph. */ public int maxPoints = 0; /** Maximum number of contours in any non-compound glyph. */ public int maxContours = 0; /** Maximum number of points in any compound glyph. */ public int maxComponentPoints = 0; /** Maximum number of contours in any compound glyph. */ public int maxComponentContours = 0; public int maxZones = 2; /** Maximum number of points in Twilight Zone (Z0). */ public int maxTwilightPoints = 0; /** Maximum number of variables. */ public int maxStorage = 0; /** Maximum number of function definitions. */ public int maxFunctionDefs = 0; /** Maximum number of instruction definitions. */ public int maxInstructionDefs = 0; /** Maximum stack depth. */ public int maxStackElements = 0; /** Maximum byte count of glyph instructions. */ public int maxSizeOfInstructions = 0; /** Maximum number of glyphs in any compound glyph. */ public int maxComponentElements = 0; /** Maximum levels of recursion in any compound glyph. */ public int maxComponentDepth = 0; @Override public String tableName() { return "maxp"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeInt(version); out.writeShort(numGlyphs); if (version < VERSION_DEFAULT) return; out.writeShort(maxPoints); out.writeShort(maxContours); out.writeShort(maxComponentPoints); out.writeShort(maxComponentContours); out.writeShort(maxZones); out.writeShort(maxTwilightPoints); out.writeShort(maxStorage); out.writeShort(maxFunctionDefs); out.writeShort(maxInstructionDefs); out.writeShort(maxStackElements); out.writeShort(maxSizeOfInstructions); out.writeShort(maxComponentElements); out.writeShort(maxComponentDepth); } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { version = in.readInt(); numGlyphs = in.readUnsignedShort(); if (version < VERSION_DEFAULT) return; maxPoints = in.readUnsignedShort(); maxContours = in.readUnsignedShort(); maxComponentPoints = in.readUnsignedShort(); maxComponentContours = in.readUnsignedShort(); maxZones = in.readUnsignedShort(); maxTwilightPoints = in.readUnsignedShort(); maxStorage = in.readUnsignedShort(); maxFunctionDefs = in.readUnsignedShort(); maxInstructionDefs = in.readUnsignedShort(); maxStackElements = in.readUnsignedShort(); maxSizeOfInstructions = in.readUnsignedShort(); maxComponentElements = in.readUnsignedShort(); maxComponentDepth = in.readUnsignedShort(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/NameTable.java000077500000000000000000000071351506470510200320230ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class NameTable extends ListBasedTable { public static final int FORMAT_DEFAULT = 0; public int format = FORMAT_DEFAULT; @Override public String tableName() { return "name"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeShort(format); out.writeShort(this.size()); out.writeShort(6 + this.size() * 12); List entryInfo = new ArrayList(); int currentLocation = 0; for (NameTableEntry e : this) { NameTableEntryInfo info = new NameTableEntryInfo(); info.entry = e; info.location = currentLocation; entryInfo.add(info); currentLocation += e.nameData.length; if (e.padding > 0 && e.padding <= 4) { currentLocation += e.padding; } } Collections.sort(entryInfo, SORT_BY_NAME_ID); for (NameTableEntryInfo info : entryInfo) { out.writeShort(info.entry.platformID); out.writeShort(info.entry.platformSpecificID); out.writeShort(info.entry.languageID); out.writeShort(info.entry.nameID); out.writeShort(info.entry.nameData.length); out.writeShort(info.location); } Collections.sort(entryInfo, SORT_BY_LOCATION); for (NameTableEntryInfo info : entryInfo) { out.write(info.entry.nameData); if (info.entry.padding > 0 && info.entry.padding <= 4) { out.write(new byte[info.entry.padding]); } } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { format = in.readUnsignedShort(); int count = in.readUnsignedShort(); int offset = in.readUnsignedShort(); List entryInfo = new ArrayList(); for (int i = 0; i < count; i++) { NameTableEntryInfo info = new NameTableEntryInfo(); info.entry = new NameTableEntry(); info.entry.index = i; info.entry.platformID = in.readUnsignedShort(); info.entry.platformSpecificID = in.readUnsignedShort(); info.entry.languageID = in.readUnsignedShort(); info.entry.nameID = in.readUnsignedShort(); info.entry.nameData = new byte[in.readUnsignedShort()]; info.location = offset + in.readUnsignedShort(); entryInfo.add(info); } for (NameTableEntryInfo info : entryInfo) { in.reset(); in.skipBytes(info.location); in.readFully(info.entry.nameData); } Collections.sort(entryInfo, SORT_BY_LOCATION); for (int i = 0; i < count; i++) { NameTableEntryInfo info = entryInfo.get(i); int nextLocation = (i+1 < count) ? entryInfo.get(i+1).location : length; info.entry.padding = nextLocation - info.location - info.entry.nameData.length; } this.clear(); for (NameTableEntryInfo info : entryInfo) { this.add(info.entry); } } private static final class NameTableEntryInfo { private NameTableEntry entry; private int location; } private static final Comparator SORT_BY_NAME_ID = new Comparator() { @Override public int compare(NameTableEntryInfo a, NameTableEntryInfo b) { return a.entry.compareTo(b.entry); } }; private static final Comparator SORT_BY_LOCATION = new Comparator() { @Override public int compare(NameTableEntryInfo a, NameTableEntryInfo b) { return a.location - b.location; } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/NameTableEntry.java000077500000000000000000000130211506470510200330340ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.UnsupportedEncodingException; public class NameTableEntry implements Comparable { public static final int NAME_ID_COPYRIGHT_NOTICE = 0; public static final int NAME_ID_FONT_FAMILY = 1; public static final int NAME_ID_FONT_SUBFAMILY = 2; public static final int NAME_ID_UNIQUE_SUBFAMILY_ID = 3; public static final int NAME_ID_FULL_NAME = 4; public static final int NAME_ID_VERSION = 5; public static final int NAME_ID_POSTSCRIPT_NAME = 6; public static final int NAME_ID_TRADEMARK_NOTICE = 7; public static final int NAME_ID_MANUFACTURER_NAME = 8; public static final int NAME_ID_DESIGNER = 9; public static final int NAME_ID_DESCRIPTION = 10; public static final int NAME_ID_FONT_VENDOR_URL = 11; public static final int NAME_ID_FONT_DESIGNER_URL = 12; public static final int NAME_ID_LICENSE_DESCRIPTION = 13; public static final int NAME_ID_LICENSE_INFORMATION_URL = 14; public static final int NAME_ID_PREFERRED_FAMILY = 16; public static final int NAME_ID_PREFERRED_SUBFAMILY = 17; public static final int NAME_ID_COMPATIBLE_FULL = 18; public static final int NAME_ID_SAMPLE_TEXT = 19; public int index; public int platformID; public int platformSpecificID; public int languageID; public int nameID; public byte[] nameData; public int padding; public static NameTableEntry forUnicode(int nameID, String name) { NameTableEntry e = new NameTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_UNICODE; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_UNICODE_2_0; e.languageID = 0; e.nameID = nameID; e.setNameString(name); return e; } public static NameTableEntry forMacintosh(int nameID, String name) { NameTableEntry e = new NameTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_MACINTOSH; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_MACINTOSH_ROMAN; e.languageID = PlatformConstants.LANGUAGE_ID_MACINTOSH_ENGLISH; e.nameID = nameID; e.setNameString(name); return e; } public static NameTableEntry forWindows(int nameID, String name) { NameTableEntry e = new NameTableEntry(); e.platformID = PlatformConstants.PLATFORM_ID_WINDOWS; e.platformSpecificID = PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16; e.languageID = PlatformConstants.LANGUAGE_ID_WINDOWS_ENGLISH; e.nameID = nameID; e.setNameString(name); return e; } @Override public int compareTo(NameTableEntry other) { if (this.index != other.index) return this.index - other.index; if (this.platformID != other.platformID) return this.platformID - other.platformID; if (this.platformSpecificID != other.platformSpecificID) return this.platformSpecificID - other.platformSpecificID; if (this.languageID != other.languageID) return this.languageID - other.languageID; if (this.nameID != other.nameID) return this.nameID - other.nameID; return 0; } public String getNameString() { try { switch (platformID) { case PlatformConstants.PLATFORM_ID_UNICODE: return new String(nameData, "UTF-16BE"); case PlatformConstants.PLATFORM_ID_MACINTOSH: switch (platformSpecificID) { case PlatformConstants.PLATFORM_SPECIFIC_ID_MACINTOSH_ROMAN: try { return new String(nameData, "MacRoman"); } catch (UnsupportedEncodingException uee2) { return new String(nameData, "US-ASCII"); } default: throw new IllegalStateException("I have no idea how to decode this."); } case PlatformConstants.PLATFORM_ID_ISO_10646: return new String(nameData, "UTF-16BE"); case PlatformConstants.PLATFORM_ID_WINDOWS: case PlatformConstants.PLATFORM_ID_WINDOWS_UNICODE: switch (platformSpecificID) { case PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16: return new String(nameData, "UTF-16BE"); case PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32: return new String(nameData, "UTF-32BE"); default: throw new IllegalStateException("I have no idea how to decode this."); } default: throw new IllegalStateException("I have no idea how to decode this."); } } catch (UnsupportedEncodingException uee) { throw new IllegalStateException("Java is stupid."); } } public void setNameString(String name) { try { switch (platformID) { case PlatformConstants.PLATFORM_ID_UNICODE: nameData = name.getBytes("UTF-16BE"); return; case PlatformConstants.PLATFORM_ID_MACINTOSH: switch (platformSpecificID) { case PlatformConstants.PLATFORM_SPECIFIC_ID_MACINTOSH_ROMAN: try { nameData = name.getBytes("MacRoman"); return; } catch (UnsupportedEncodingException uee2) { nameData = name.getBytes("US-ASCII"); return; } default: throw new IllegalStateException("I have no idea how to encode this."); } case PlatformConstants.PLATFORM_ID_ISO_10646: nameData = name.getBytes("UTF-16BE"); return; case PlatformConstants.PLATFORM_ID_WINDOWS: case PlatformConstants.PLATFORM_ID_WINDOWS_UNICODE: switch (platformSpecificID) { case PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16: nameData = name.getBytes("UTF-16BE"); return; case PlatformConstants.PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32: nameData = name.getBytes("UTF-32BE"); return; default: throw new IllegalStateException("I have no idea how to encode this."); } default: throw new IllegalStateException("I have no idea how to encode this."); } } catch (UnsupportedEncodingException uee) { throw new IllegalStateException("Java is stupid."); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/Os2Table.java000077500000000000000000000743401506470510200316100ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Collection; public class Os2Table extends TrueTypeTable { // Apple and Microsoft disagree about the length of the OS/2 table before version 3. // So we can't depend on the version number to determine which fields to include. public static final int LENGTH_68 = 68; // Apple's version 0 public static final int LENGTH_78 = 78; // Apple's version 1, Microsoft's version 0 public static final int LENGTH_86 = 86; // Apple's version 2, Microsoft's version 1 public static final int LENGTH_96 = 96; // Version 3, 4, Microsoft's version 2 public static final int LENGTH_100 = 100; // Version 5 public static final int LENGTH_MAX = 100; public static final int VERSION_TRUETYPE_1_5 = 0; public static final int VERSION_TRUETYPE_1_66 = 1; public static final int VERSION_OPENTYPE_1_1 = 2; public static final int VERSION_OPENTYPE_1_4 = 3; public static final int VERSION_OPENTYPE_1_5 = 4; public static final int VERSION_OPENTYPE_1_7 = 5; public static final int VERSION_MAX = 5; public static final int WEIGHT_CLASS_ULTRA_LIGHT = 100; public static final int WEIGHT_CLASS_EXTRA_LIGHT = 200; public static final int WEIGHT_CLASS_LIGHT = 300; public static final int WEIGHT_CLASS_SEMI_LIGHT = 400; public static final int WEIGHT_CLASS_MEDIUM = 500; public static final int WEIGHT_CLASS_SEMI_BOLD = 600; public static final int WEIGHT_CLASS_BOLD = 700; public static final int WEIGHT_CLASS_EXTRA_BOLD = 800; public static final int WEIGHT_CLASS_ULTRA_BOLD = 900; public static final int WIDTH_CLASS_ULTRA_CONDENSED = 1; public static final int WIDTH_CLASS_EXTRA_CONDENSED = 2; public static final int WIDTH_CLASS_CONDENSED = 3; public static final int WIDTH_CLASS_SEMI_CONDENSED = 4; public static final int WIDTH_CLASS_MEDIUM = 5; public static final int WIDTH_CLASS_SEMI_EXPANDED = 6; public static final int WIDTH_CLASS_EXPANDED = 7; public static final int WIDTH_CLASS_EXTRA_EXPANDED = 8; public static final int WIDTH_CLASS_ULTRA_EXPANDED = 9; public static final int FLAGS_INSTALLABLE_EMBEDDING = 0; public static final int FLAGS_RESTRICTED_LICENSE_EMBEDDING = 2; public static final int FLAGS_PREVIEW_AND_PRINT_EMBEDDING = 4; public static final int FLAGS_EDITABLE_EMBEDDING = 8; public static final int FLAGS_NO_SUBSETTING = 0x0100; public static final int FLAGS_BITMAP_EMBEDDING_ONLY = 0x0200; public static final int FAMILY_CLASS_NO_CLASSIFICATION = 0; public static final int FAMILY_CLASS_OLDSTYLE_SERIFS = 1; public static final int FAMILY_CLASS_TRANSITIONAL_SERIFS = 2; public static final int FAMILY_CLASS_MODERN_SERIFS = 3; public static final int FAMILY_CLASS_CLARENDON_SERIFS = 4; public static final int FAMILY_CLASS_SLAB_SERIFS = 5; public static final int FAMILY_CLASS_FREEFORM_SERIFS = 7; public static final int FAMILY_CLASS_SANS_SERIF = 8; public static final int FAMILY_CLASS_ORNAMENTAL = 9; public static final int FAMILY_CLASS_SCRIPT = 10; public static final int FAMILY_CLASS_SYMBOL = 12; public static final int FAMILY_SUBCLASS_NO_CLASSIFICATION = 0; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_IBM_ROUNDED_LEGIBILITY = 1; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_GARALDE = 2; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_VENETIAN = 3; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_MODIFIED_VENETIAN = 4; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_DUTCH_MODERN = 5; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_DUTCH_TRADITIONAL = 6; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_CONTEMPORARY = 7; public static final int FAMILY_SUBCLASS_OLDSTYLE_SERIFS_CALLIGRAPHIC = 8; public static final int FAMILY_SUBCLASS_TRANSITIONAL_SERIFS_DIRECT_LINE = 1; public static final int FAMILY_SUBCLASS_TRANSITIONAL_SERIFS_SCRIPT = 2; public static final int FAMILY_SUBCLASS_MODERN_SERIFS_ITALIAN = 1; public static final int FAMILY_SUBCLASS_MODERN_SERIFS_SCRIPT = 2; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_CLARENDON = 1; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_MODERN = 2; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_TRADITIONAL = 3; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_NEWSPAPER = 4; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_STUB_SERIF = 5; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_MONOTONE = 6; public static final int FAMILY_SUBCLASS_CLARENDON_SERIFS_TYPEWRITER = 7; public static final int FAMILY_SUBCLASS_SLAB_SERIFS_MONOTONE = 1; public static final int FAMILY_SUBCLASS_SLAB_SERIFS_HUMANIST = 2; public static final int FAMILY_SUBCLASS_SLAB_SERIFS_GEOMETRIC = 3; public static final int FAMILY_SUBCLASS_SLAB_SERIFS_SWISS = 4; public static final int FAMILY_SUBCLASS_SLAB_SERIFS_TYPEWRITER = 5; public static final int FAMILY_SUBCLASS_FREEFORM_SERIFS_MODERN = 1; public static final int FAMILY_SUBCLASS_SANS_SERIF_IBM_NEO_GROTESQUE_GOTHIC = 1; public static final int FAMILY_SUBCLASS_SANS_SERIF_HUMANIST = 2; public static final int FAMILY_SUBCLASS_SANS_SERIF_LOW_X_ROUND_GEOMETRIC = 3; public static final int FAMILY_SUBCLASS_SANS_SERIF_HIGH_X_ROUND_GEOMETRIC = 4; public static final int FAMILY_SUBCLASS_SANS_SERIF_NEO_GROTESQUE_GOTHIC = 5; public static final int FAMILY_SUBCLASS_SANS_SERIF_MODIFIED_NEO_GROTESQUE_GOTHIC = 6; public static final int FAMILY_SUBCLASS_SANS_SERIF_TYPEWRITER_GOTHIC = 9; public static final int FAMILY_SUBCLASS_SANS_SERIF_MATRIX = 10; public static final int FAMILY_SUBCLASS_ORNAMENTAL_ENGRAVER = 1; public static final int FAMILY_SUBCLASS_ORNAMENTAL_BLACK_LETTER = 2; public static final int FAMILY_SUBCLASS_ORNAMENTAL_DECORATIVE = 3; public static final int FAMILY_SUBCLASS_ORNAMENTAL_3D = 4; public static final int FAMILY_SUBCLASS_SCRIPT_UNCIAL = 1; public static final int FAMILY_SUBCLASS_SCRIPT_BRUSH_JOINED = 2; public static final int FAMILY_SUBCLASS_SCRIPT_FORMAL_JOINED = 3; public static final int FAMILY_SUBCLASS_SCRIPT_MONOTONE_JOINED = 4; public static final int FAMILY_SUBCLASS_SCRIPT_CALLIGRAPHIC = 5; public static final int FAMILY_SUBCLASS_SCRIPT_BRUSH_UNJOINED = 6; public static final int FAMILY_SUBCLASS_SCRIPT_FORMAL_UNJOINED = 7; public static final int FAMILY_SUBCLASS_SCRIPT_MONOTONE_UNJOINED = 8; public static final int FAMILY_SUBCLASS_SYMBOL_MIXED_SERIF = 3; public static final int FAMILY_SUBCLASS_SYMBOL_OLDSTYLE_SERIF = 6; public static final int FAMILY_SUBCLASS_SYMBOL_NEO_GROTESQUE_SANS_SERIF = 7; public static final int FAMILY_SUBCLASS_MISCELLANEOUS = 15; public static final int PANOSE_FAMILY_TYPE_ANY = 0; public static final int PANOSE_FAMILY_TYPE_NO_FIT = 1; public static final int PANOSE_FAMILY_TYPE_TEXT_AND_DISPLAY = 2; public static final int PANOSE_FAMILY_TYPE_SCRIPT = 3; public static final int PANOSE_FAMILY_TYPE_DECORATIVE = 4; public static final int PANOSE_FAMILY_TYPE_PICTORIAL = 5; public static final int PANOSE_SERIF_STYLE_ANY = 0; public static final int PANOSE_SERIF_STYLE_NO_FIT = 1; public static final int PANOSE_SERIF_STYLE_COVE = 2; public static final int PANOSE_SERIF_STYLE_OBTUSE_COVE = 3; public static final int PANOSE_SERIF_STYLE_SQUARE_COVE = 4; public static final int PANOSE_SERIF_STYLE_OBTUSE_SQUARE_COVE = 5; public static final int PANOSE_SERIF_STYLE_SQUARE = 6; public static final int PANOSE_SERIF_STYLE_THIN = 7; public static final int PANOSE_SERIF_STYLE_BONE = 8; public static final int PANOSE_SERIF_STYLE_EXAGGERATED = 9; public static final int PANOSE_SERIF_STYLE_TRIANGLE = 10; public static final int PANOSE_SERIF_STYLE_NORMAL_SANS = 11; public static final int PANOSE_SERIF_STYLE_OBTUSE_SANS = 12; public static final int PANOSE_SERIF_STYLE_PERP_SANS = 13; public static final int PANOSE_SERIF_STYLE_FLARED = 14; public static final int PANOSE_SERIF_STYLE_ROUNDED = 15; public static final int PANOSE_WEIGHT_ANY = 0; public static final int PANOSE_WEIGHT_NO_FIT = 1; public static final int PANOSE_WEIGHT_VERY_LIGHT = 2; public static final int PANOSE_WEIGHT_LIGHT = 3; public static final int PANOSE_WEIGHT_THIN = 4; public static final int PANOSE_WEIGHT_BOOK = 5; public static final int PANOSE_WEIGHT_MEDIUM = 6; public static final int PANOSE_WEIGHT_DEMI = 7; public static final int PANOSE_WEIGHT_BOLD = 8; public static final int PANOSE_WEIGHT_HEAVY = 9; public static final int PANOSE_WEIGHT_BLACK = 10; public static final int PANOSE_WEIGHT_NORD = 11; public static final int PANOSE_PROPORTION_ANY = 0; public static final int PANOSE_PROPORTION_NO_FIT = 1; public static final int PANOSE_PROPORTION_OLD_STYLE = 2; public static final int PANOSE_PROPORTION_MODERN = 3; public static final int PANOSE_PROPORTION_EVEN_WIDTH = 4; public static final int PANOSE_PROPORTION_EXPANDED = 5; public static final int PANOSE_PROPORTION_CONDENSED = 6; public static final int PANOSE_PROPORTION_VERY_EXPANDED = 7; public static final int PANOSE_PROPORTION_VERY_CONDENSED = 8; public static final int PANOSE_PROPORTION_MONOSPACED = 9; public static final int PANOSE_CONTRAST_ANY = 0; public static final int PANOSE_CONTRAST_NO_FIT = 1; public static final int PANOSE_CONTRAST_NONE = 2; public static final int PANOSE_CONTRAST_VERY_LOW = 3; public static final int PANOSE_CONTRAST_LOW = 4; public static final int PANOSE_CONTRAST_MEDIUM_LOW = 5; public static final int PANOSE_CONTRAST_MEDIUM = 6; public static final int PANOSE_CONTRAST_MEDIUM_HIGH = 7; public static final int PANOSE_CONTRAST_HIGH = 8; public static final int PANOSE_CONTRAST_VERY_HIGH = 9; public static final int PANOSE_STROKE_VARIATION_ANY = 0; public static final int PANOSE_STROKE_VARIATION_NO_FIT = 1; public static final int PANOSE_STROKE_VARIATION_GRADUAL_DIAGONAL = 2; public static final int PANOSE_STROKE_VARIATION_GRADUAL_TRANSITIONAL = 3; public static final int PANOSE_STROKE_VARIATION_GRADUAL_VERTICAL = 4; public static final int PANOSE_STROKE_VARIATION_GRADUAL_HORIZONTAL = 5; public static final int PANOSE_STROKE_VARIATION_RAPID_VERTICAL = 6; public static final int PANOSE_STROKE_VARIATION_RAPID_HORIZONTAL = 7; public static final int PANOSE_STROKE_VARIATION_INSTANT_VERTICAL = 8; public static final int PANOSE_ARM_STYLE_ANY = 0; public static final int PANOSE_ARM_STYLE_NO_FIT = 1; public static final int PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORIZONTAL = 2; public static final int PANOSE_ARM_STYLE_STRAIGHT_ARMS_WEDGE = 3; public static final int PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL = 4; public static final int PANOSE_ARM_STYLE_STRAIGHT_ARMS_SINGLE_SERIF = 5; public static final int PANOSE_ARM_STYLE_STRAIGHT_ARMS_DOUBLE_SERIF = 6; public static final int PANOSE_ARM_STYLE_NON_STRAIGHT_ARMS_HORIZONTAL = 7; public static final int PANOSE_ARM_STYLE_NON_STRAIGHT_ARMS_WEDGE = 8; public static final int PANOSE_ARM_STYLE_NON_STRAIGHT_ARMS_VERTICAL = 9; public static final int PANOSE_ARM_STYLE_NON_STRAIGHT_ARMS_SINGLE_SERIF = 10; public static final int PANOSE_ARM_STYLE_NON_STRAIGHT_ARMS_DOUBLE_SERIF = 11; public static final int PANOSE_LETTERFORM_ANY = 0; public static final int PANOSE_LETTERFORM_NO_FIT = 1; public static final int PANOSE_LETTERFORM_NORMAL_CONTACT = 2; public static final int PANOSE_LETTERFORM_NORMAL_WEIGHTED = 3; public static final int PANOSE_LETTERFORM_NORMAL_BOXED = 4; public static final int PANOSE_LETTERFORM_NORMAL_FLATTENED = 5; public static final int PANOSE_LETTERFORM_NORMAL_ROUNDED = 6; public static final int PANOSE_LETTERFORM_NORMAL_OFF_CENTER = 7; public static final int PANOSE_LETTERFORM_NORMAL_SQUARE = 8; public static final int PANOSE_LETTERFORM_OBLIQUE_CONTACT = 9; public static final int PANOSE_LETTERFORM_OBLIQUE_WEIGHTED = 10; public static final int PANOSE_LETTERFORM_OBLIQUE_BOXED = 11; public static final int PANOSE_LETTERFORM_OBLIQUE_FLATTENED = 12; public static final int PANOSE_LETTERFORM_OBLIQUE_ROUNDED = 13; public static final int PANOSE_LETTERFORM_OBLIQUE_OFF_CENTER = 14; public static final int PANOSE_LETTERFORM_OBLIQUE_SQUARE = 15; public static final int PANOSE_MIDLINE_ANY = 0; public static final int PANOSE_MIDLINE_NO_FIT = 1; public static final int PANOSE_MIDLINE_STANDARD_TRIMMED = 2; public static final int PANOSE_MIDLINE_STANDARD_POINTED = 3; public static final int PANOSE_MIDLINE_STANDARD_SERIFED = 4; public static final int PANOSE_MIDLINE_HIGH_TRIMMED = 5; public static final int PANOSE_MIDLINE_HIGH_POINTED = 6; public static final int PANOSE_MIDLINE_HIGH_SERIFED = 7; public static final int PANOSE_MIDLINE_CONSTANT_TRIMMED = 8; public static final int PANOSE_MIDLINE_CONSTANT_POINTED = 9; public static final int PANOSE_MIDLINE_CONSTANT_SERIFED = 10; public static final int PANOSE_MIDLINE_LOW_TRIMMED = 11; public static final int PANOSE_MIDLINE_LOW_POINTED = 12; public static final int PANOSE_MIDLINE_LOW_SERIFED = 13; public static final int PANOSE_X_HEIGHT_ANY = 0; public static final int PANOSE_X_HEIGHT_NO_FIT = 1; public static final int PANOSE_X_HEIGHT_CONSTANT_SMALL = 2; public static final int PANOSE_X_HEIGHT_CONSTANT_STANDARD = 3; public static final int PANOSE_X_HEIGHT_CONSTANT_LARGE = 4; public static final int PANOSE_X_HEIGHT_DUCKING_SMALL = 5; public static final int PANOSE_X_HEIGHT_DUCKING_STANDARD = 6; public static final int PANOSE_X_HEIGHT_DUCKING_LARGE = 7; public static final int VENDOR_ID_KBnP = 0x4B426E50; public static final int VENDOR_ID_KrKo = 0x4B724B6F; public static final int VENDOR_ID_ckbt = 0x636B6274; public static final int FS_SELECTION_ITALIC = 0x0001; public static final int FS_SELECTION_UNDERLINE = 0x0002; public static final int FS_SELECTION_NEGATIVE = 0x0004; public static final int FS_SELECTION_OUTLINE = 0x0008; public static final int FS_SELECTION_STRIKEOUT = 0x0010; public static final int FS_SELECTION_BOLD = 0x0020; public static final int FS_SELECTION_REGULAR = 0x0040; public static final int FS_SELECTION_USE_TYPO_METRICS = 0x0080; public static final int FS_SELECTION_WWS = 0x0100; public static final int FS_SELECTION_OBLIQUE = 0x0200; // Apple version 0 (68-byte) begins public int length = LENGTH_MAX; public int version = VERSION_MAX; public int averageCharWidth = 0; public int weightClass = WEIGHT_CLASS_MEDIUM; public int widthClass = WIDTH_CLASS_MEDIUM; public int flags = 0; public int subscriptXSize = 0; public int subscriptYSize = 0; public int subscriptXOffset = 0; public int subscriptYOffset = 0; public int superscriptXSize = 0; public int superscriptYSize = 0; public int superscriptXOffset = 0; public int superscriptYOffset = 0; public int strikeoutWidth = 0; public int strikeoutPosition = 0; public int familyClass = FAMILY_CLASS_NO_CLASSIFICATION; public int familySubClass = FAMILY_SUBCLASS_NO_CLASSIFICATION; public int panoseFamilyType = PANOSE_FAMILY_TYPE_ANY; public int panoseSerifStyle = PANOSE_SERIF_STYLE_ANY; public int panoseWeight = PANOSE_WEIGHT_ANY; public int panoseProportion = PANOSE_PROPORTION_ANY; public int panoseContrast = PANOSE_CONTRAST_ANY; public int panoseStrokeVariation = PANOSE_STROKE_VARIATION_ANY; public int panoseArmStyle = PANOSE_ARM_STYLE_ANY; public int panoseLetterform = PANOSE_LETTERFORM_ANY; public int panoseMidline = PANOSE_MIDLINE_ANY; public int panoseXHeight = PANOSE_X_HEIGHT_ANY; public final int[] unicodeRanges = new int[4]; public int vendorID = VENDOR_ID_ckbt; public int fsSelection = 0; public int fsFirstCharIndex = 0x20; public int fsLastCharIndex = 0x20; // Apple version 0 (68-byte) ends // Apple version 1, Microsoft version 0 (78-byte) begins public int typoAscent = 0; public int typoDescent = 0; public int typoLineGap = 0; public int winAscent = 0; public int winDescent = 0; // Apple version 1, Microsoft version 0 (78-byte) ends // Apple version 2, Microsoft version 1 (86-byte) begins public final int[] codePages = new int[2]; // Apple version 2, Microsoft version 1 (86-byte) ends // Microsoft version 2, version 3 or 4 (96-byte) begins public int xHeight = 0; public int capHeight = 0; public int defaultChar = 0; public int breakChar = 0x20; public int maxContext = 0; // Microsoft version 2, version 3 or 4 (96-byte) ends // Version 5 (100-byte) begins public int lowerOpticalPointSize = 0; public int upperOpticalPointSize = 0xFFFF; // Version 5 (100-byte) ends @Override public String tableName() { return "OS/2"; } @Override public String[] dependencyNames() { return new String[]{}; } public String getVendorIDString() { return new String(new char[]{ (char)((vendorID >> 24) & 0xFF), (char)((vendorID >> 16) & 0xFF), (char)((vendorID >> 8) & 0xFF), (char)((vendorID >> 0) & 0xFF), }); } public void setVendorIDString(String vendorIDString) { char[] a = vendorIDString.toCharArray(); vendorID = (((a.length > 0 && a[0] >= 0x20 && a[0] < 0x7F) ? a[0] : 0x20) << 24) | (((a.length > 1 && a[1] >= 0x20 && a[1] < 0x7F) ? a[1] : 0x20) << 16) | (((a.length > 2 && a[2] >= 0x20 && a[2] < 0x7F) ? a[2] : 0x20) << 8) | (((a.length > 3 && a[3] >= 0x20 && a[3] < 0x7F) ? a[3] : 0x20) << 0); } public double getLowerOpticalPointSizeDouble() { if (lowerOpticalPointSize >= 0xFFFF) return Double.POSITIVE_INFINITY; if (lowerOpticalPointSize <= 0) return 0.0; return lowerOpticalPointSize / 20.0; } public double getUpperOpticalPointSizeDouble() { if (upperOpticalPointSize >= 0xFFFF) return Double.POSITIVE_INFINITY; if (upperOpticalPointSize <= 0) return 0.0; return upperOpticalPointSize / 20.0; } public void setLowerOpticalPointSizeDouble(double pt) { pt *= 20.0; lowerOpticalPointSize = (pt <= 0) ? 0 : (pt >= 0xFFFF) ? 0xFFFF : (int)Math.round(pt); } public void setUpperOpticalPointSizeDouble(double pt) { pt *= 20.0; upperOpticalPointSize = (pt <= 0) ? 0 : (pt >= 0xFFFF) ? 0xFFFF : (int)Math.round(pt); } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeShort(version); out.writeShort(averageCharWidth); out.writeShort(weightClass); out.writeShort(widthClass); out.writeShort(flags); out.writeShort(subscriptXSize); out.writeShort(subscriptYSize); out.writeShort(subscriptXOffset); out.writeShort(subscriptYOffset); out.writeShort(superscriptXSize); out.writeShort(superscriptYSize); out.writeShort(superscriptXOffset); out.writeShort(superscriptYOffset); out.writeShort(strikeoutWidth); out.writeShort(strikeoutPosition); out.writeByte(familyClass); out.writeByte(familySubClass); out.writeByte(panoseFamilyType); out.writeByte(panoseSerifStyle); out.writeByte(panoseWeight); out.writeByte(panoseProportion); out.writeByte(panoseContrast); out.writeByte(panoseStrokeVariation); out.writeByte(panoseArmStyle); out.writeByte(panoseLetterform); out.writeByte(panoseMidline); out.writeByte(panoseXHeight); out.writeInt(unicodeRanges[0]); out.writeInt(unicodeRanges[1]); out.writeInt(unicodeRanges[2]); out.writeInt(unicodeRanges[3]); out.writeInt(vendorID); out.writeShort(fsSelection); out.writeShort(fsFirstCharIndex); out.writeShort(fsLastCharIndex); if (length >= LENGTH_78) { out.writeShort(typoAscent); out.writeShort(typoDescent); out.writeShort(typoLineGap); out.writeShort(winAscent); out.writeShort(winDescent); } if (length >= LENGTH_86) { out.writeInt(codePages[0]); out.writeInt(codePages[1]); } if (length >= LENGTH_96) { out.writeShort(xHeight); out.writeShort(capHeight); out.writeShort(defaultChar); out.writeShort(breakChar); out.writeShort(maxContext); } if (length >= LENGTH_100) { out.writeShort(lowerOpticalPointSize); out.writeShort(upperOpticalPointSize); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { this.length = length; version = in.readUnsignedShort(); averageCharWidth = in.readShort(); weightClass = in.readUnsignedShort(); widthClass = in.readUnsignedShort(); flags = in.readUnsignedShort(); subscriptXSize = in.readShort(); subscriptYSize = in.readShort(); subscriptXOffset = in.readShort(); subscriptYOffset = in.readShort(); superscriptXSize = in.readShort(); superscriptYSize = in.readShort(); superscriptXOffset = in.readShort(); superscriptYOffset = in.readShort(); strikeoutWidth = in.readShort(); strikeoutPosition = in.readShort(); familyClass = in.readUnsignedByte(); familySubClass = in.readUnsignedByte(); panoseFamilyType = in.readUnsignedByte(); panoseSerifStyle = in.readUnsignedByte(); panoseWeight = in.readUnsignedByte(); panoseProportion = in.readUnsignedByte(); panoseContrast = in.readUnsignedByte(); panoseStrokeVariation = in.readUnsignedByte(); panoseArmStyle = in.readUnsignedByte(); panoseLetterform = in.readUnsignedByte(); panoseMidline = in.readUnsignedByte(); panoseXHeight = in.readUnsignedByte(); unicodeRanges[0] = in.readInt(); unicodeRanges[1] = in.readInt(); unicodeRanges[2] = in.readInt(); unicodeRanges[3] = in.readInt(); vendorID = in.readInt(); fsSelection = in.readUnsignedShort(); fsFirstCharIndex = in.readUnsignedShort(); fsLastCharIndex = in.readUnsignedShort(); typoAscent = (length >= LENGTH_78) ? in.readShort() : 0; typoDescent = (length >= LENGTH_78) ? in.readShort() : 0; typoLineGap = (length >= LENGTH_78) ? in.readShort() : 0; winAscent = (length >= LENGTH_78) ? in.readShort() : 0; winDescent = (length >= LENGTH_78) ? in.readShort() : 0; codePages[0] = (length >= LENGTH_86) ? in.readInt() : 0; codePages[1] = (length >= LENGTH_86) ? in.readInt() : 0; xHeight = (length >= LENGTH_96) ? in.readShort() : 0; capHeight = (length >= LENGTH_96) ? in.readShort() : 0; defaultChar = (length >= LENGTH_96) ? in.readUnsignedShort() : 0; breakChar = (length >= LENGTH_96) ? in.readUnsignedShort() : 0x20; maxContext = (length >= LENGTH_96) ? in.readUnsignedShort() : 0; lowerOpticalPointSize = (length >= LENGTH_100) ? in.readUnsignedShort() : 0; upperOpticalPointSize = (length >= LENGTH_100) ? in.readUnsignedShort() : 0xFFFF; } public static final int[][] UNICODE_RANGES = new int[][] { new int[] { 0x0000, 0x007F }, // 0 new int[] { 0x0080, 0x00FF }, // 1 new int[] { 0x0100, 0x017F }, // 2 new int[] { 0x0180, 0x024F }, // 3 new int[] { 0x0250, 0x02AF, 0x1D00, 0x1DBF }, // 4 new int[] { 0x02B0, 0x02FF, 0xA700, 0xA71F }, // 5 new int[] { 0x0300, 0x036F, 0x1DC0, 0x1DFF }, // 6 new int[] { 0x0370, 0x03FF }, // 7 new int[] { 0x2C80, 0x2CFF }, // 8 new int[] { 0x0400, 0x052F, 0x2DE0, 0x2DFF, 0xA640, 0xA69F }, // 9 new int[] { 0x0530, 0x058F }, // 10 new int[] { 0x0590, 0x05FF }, // 11 new int[] { 0xA500, 0xA63F }, // 12 new int[] { 0x0600, 0x06FF, 0x0750, 0x077F }, // 13 new int[] { 0x07C0, 0x07FF }, // 14 new int[] { 0x0900, 0x097F }, // 15 new int[] { 0x0980, 0x09FF }, // 16 new int[] { 0x0A00, 0x0A7F }, // 17 new int[] { 0x0A80, 0x0AFF }, // 18 new int[] { 0x0B00, 0x0B7F }, // 19 new int[] { 0x0B80, 0x0BFF }, // 20 new int[] { 0x0C00, 0x0C7F }, // 21 new int[] { 0x0C80, 0x0CFF }, // 22 new int[] { 0x0D00, 0x0D7F }, // 23 new int[] { 0x0E00, 0x0E7F }, // 24 new int[] { 0x0E80, 0x0EFF }, // 25 new int[] { 0x10A0, 0x10FF, 0x2D00, 0x2D2F }, // 26 new int[] { 0x1B00, 0x1B7F }, // 27 new int[] { 0x1100, 0x11FF }, // 28 new int[] { 0x1E00, 0x1EFF, 0x2C60, 0x2C7F, 0xA720, 0xA7FF }, // 29 new int[] { 0x1F00, 0x1FFF }, // 30 new int[] { 0x2000, 0x206F, 0x2E00, 0x2E7F }, // 31 new int[] { 0x2070, 0x209F }, // 32 new int[] { 0x20A0, 0x20CF }, // 33 new int[] { 0x20D0, 0x20FF }, // 34 new int[] { 0x2100, 0x214F }, // 35 new int[] { 0x2150, 0x218F }, // 36 new int[] { 0x2190, 0x21FF, 0x27F0, 0x27FF, 0x2900, 0x297F, 0x2B00, 0x2BFF }, // 37 new int[] { 0x2200, 0x22FF, 0x27C0, 0x27EF, 0x2980, 0x2AFF }, // 38 new int[] { 0x2300, 0x23FF }, // 39 new int[] { 0x2400, 0x243F }, // 40 new int[] { 0x2440, 0x245F }, // 41 new int[] { 0x2460, 0x24FF }, // 42 new int[] { 0x2500, 0x257F }, // 43 new int[] { 0x2580, 0x259F }, // 44 new int[] { 0x25A0, 0x25FF }, // 45 new int[] { 0x2600, 0x26FF }, // 46 new int[] { 0x2700, 0x27BF }, // 47 new int[] { 0x3000, 0x303F }, // 48 new int[] { 0x3040, 0x309F }, // 49 new int[] { 0x30A0, 0x30FF, 0x31F0, 0x31FF }, // 50 new int[] { 0x3100, 0x312F, 0x31A0, 0x31BF }, // 51 new int[] { 0x3130, 0x318F }, // 52 new int[] { 0xA840, 0xA87F }, // 53 new int[] { 0x3200, 0x32FF }, // 54 new int[] { 0x3300, 0x33FF }, // 55 new int[] { 0xAC00, 0xD7AF }, // 56 new int[] { 0x10000, 0x10FFFF }, // 57 new int[] { 0x10900, 0x1091F }, // 58 new int[] { 0x2E80, 0x2FDF, 0x2FF0, 0x2FFF, 0x3190, 0x319F, 0x3400, 0x4DBF, 0x4E00, 0x9FFF, 0x20000, 0x2A6DF }, // 59 new int[] { 0xE000, 0xF8FF }, // 60 new int[] { 0x31C0, 0x31EF, 0xF900, 0xFAFF, 0x2F800, 0x2FA1F }, // 61 new int[] { 0xFB00, 0xFB4F }, // 62 new int[] { 0xFB50, 0xFDFF }, // 63 new int[] { 0xFE20, 0xFE2F }, // 64 new int[] { 0xFE10, 0xFE1F, 0xFE30, 0xFE4F }, // 65 new int[] { 0xFE50, 0xFE6F }, // 66 new int[] { 0xFE70, 0xFEFF }, // 67 new int[] { 0xFF00, 0xFFEF }, // 68 new int[] { 0xFFF0, 0xFFFF }, // 69 new int[] { 0x0F00, 0x0FFF }, // 70 new int[] { 0x0700, 0x074F }, // 71 new int[] { 0x0780, 0x07BF }, // 72 new int[] { 0x0D80, 0x0DFF }, // 73 new int[] { 0x1000, 0x109F }, // 74 new int[] { 0x1200, 0x139F, 0x2D80, 0x2DDF }, // 75 new int[] { 0x13A0, 0x13FF }, // 76 new int[] { 0x1400, 0x167F }, // 77 new int[] { 0x1680, 0x169F }, // 78 new int[] { 0x16A0, 0x16FF }, // 79 new int[] { 0x1780, 0x17FF, 0x19E0, 0x19FF }, // 80 new int[] { 0x1800, 0x18AF }, // 81 new int[] { 0x2800, 0x28FF }, // 82 new int[] { 0xA000, 0xA4CF }, // 83 new int[] { 0x1700, 0x177F }, // 84 new int[] { 0x10300, 0x1032F }, // 85 new int[] { 0x10330, 0x1034F }, // 86 new int[] { 0x10400, 0x1044F }, // 87 new int[] { 0x1D000, 0x1D24F }, // 88 new int[] { 0x1D400, 0x1D7FF }, // 89 new int[] { 0xF0000, 0xFFFFD, 0x100000, 0x10FFFD }, // 90 new int[] { 0xFE00, 0xFE0F, 0xE0100, 0xE01EF }, // 91 new int[] { 0xE0000, 0xE007F }, // 92 new int[] { 0x1900, 0x194F }, // 93 new int[] { 0x1950, 0x197F }, // 94 new int[] { 0x1980, 0x19DF }, // 95 new int[] { 0x1A00, 0x1A1F }, // 96 new int[] { 0x2C00, 0x2C5F }, // 97 new int[] { 0x2D30, 0x2D7F }, // 98 new int[] { 0x4DC0, 0x4DFF }, // 99 new int[] { 0xA800, 0xA82F }, // 100 new int[] { 0x10000, 0x1013F }, // 101 new int[] { 0x10140, 0x1018F }, // 102 new int[] { 0x10380, 0x1039F }, // 103 new int[] { 0x103A0, 0x103DF }, // 104 new int[] { 0x10450, 0x1047F }, // 105 new int[] { 0x10480, 0x104AF }, // 106 new int[] { 0x10800, 0x1083F }, // 107 new int[] { 0x10A00, 0x10A5F }, // 108 new int[] { 0x1D300, 0x1D35F }, // 109 new int[] { 0x12000, 0x1247F }, // 110 new int[] { 0x1D360, 0x1D37F }, // 111 new int[] { 0x1B80, 0x1BBF }, // 112 new int[] { 0x1C00, 0x1C4F }, // 113 new int[] { 0x1C50, 0x1C7F }, // 114 new int[] { 0xA880, 0xA8DF }, // 115 new int[] { 0xA900, 0xA92F }, // 116 new int[] { 0xA930, 0xA95F }, // 117 new int[] { 0xAA00, 0xAA5F }, // 118 new int[] { 0x10190, 0x101CF }, // 119 new int[] { 0x101D0, 0x101FF }, // 120 new int[] { 0x10280, 0x102DF, 0x10920, 0x1093F }, // 121 new int[] { 0x1F000, 0x1F09F }, // 122 null, // 123 null, // 124 null, // 125 null, // 126 null, // 127 }; public static final String[] CODE_PAGES = new String[] { "CP1252", // 0 "CP1250", // 1 "CP1251", // 2 "CP1253", // 3 "CP1254", // 4 "CP1255", // 5 "CP1256", // 6 "CP1257", // 7 "CP1258", // 8 null, // 9 null, // 10 null, // 11 null, // 12 null, // 13 null, // 14 null, // 15 "CP874", // 16 "CP932", // 17 "CP936", // 18 "CP949", // 19 "CP950", // 20 "CP1361", // 21 null, // 22 null, // 23 null, // 24 null, // 25 null, // 26 null, // 27 null, // 28 "MACROMAN", // 29 null, // 30 null, // 31 null, // 32 null, // 33 null, // 34 null, // 35 null, // 36 null, // 37 null, // 38 null, // 39 null, // 40 null, // 41 null, // 42 null, // 43 null, // 44 null, // 45 null, // 46 null, // 47 "CP869", // 48 "CP866", // 49 "CP865", // 50 "CP864", // 51 "CP863", // 52 "CP862", // 53 "CP861", // 54 "CP860", // 55 "CP857", // 56 "CP855", // 57 "CP852", // 58 "CP775", // 59 "CP737", // 60 "CP708", // 61 "CP850", // 62 "CP437", // 63 }; public void setCharIndices(Collection codePoints) { int minChar = 0x7FFF0020; int maxChar = 0x80000020; for (int ch : codePoints) { if (ch >= 0x10000) { maxChar = 0xFFFF; } else if (ch >= 0) { if (ch < minChar) minChar = ch; if (ch > maxChar) maxChar = ch; } } fsFirstCharIndex = minChar & 0xFFFF; fsLastCharIndex = maxChar & 0xFFFF; } public void setUnicodeRanges(Collection codePoints) { for (int k = 0, mx = 31, mn = 0; k < 4; k++, mx += 32, mn += 32) { int uniRanges = 0; for (int i = mx; i >= mn; i--) { uniRanges <<= 1; if (UNICODE_RANGES[i] != null) { boolean supportsAny = false; int[] range = UNICODE_RANGES[i]; for (int j = 0; j < range.length; j+=2) { int start = range[j], end = range[j+1]; for (int ch : codePoints) { if (ch >= start && ch <= end) { supportsAny = true; break; } } } if (supportsAny) uniRanges |= 1; } } this.unicodeRanges[k] = uniRanges; } } public void setCodePages(Collection codePoints) { byte[] prog = new byte[256]; for (int i = 0; i < 256; i++) prog[i] = (byte)i; for (int k = 0, mx = 31, mn = 0; k < 2; k++, mx += 32, mn += 32) { int codePages = 0; for (int i = mx; i >= mn; i--) { codePages <<= 1; if (CODE_PAGES[i] != null) { try { String s = new String(prog, CODE_PAGES[i]); boolean supportsAll = true; CharacterIterator ci = new StringCharacterIterator(s); for (int ch = ci.first(); ch != CharacterIterator.DONE; ch = ci.next()) { if ((ch >= 0x20 && ch < 0x7F) || (ch >= 0xA0 && ch < 0xD800) || (ch >= 0xF900 && ch < 0xFFFD)) { if (!codePoints.contains(ch)) { supportsAll = false; break; } } } if (supportsAll) codePages |= 1; } catch (UnsupportedEncodingException uee) {} } } this.codePages[k] = codePages; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PlatformConstants.java000077500000000000000000000255561506470510200336630ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public interface PlatformConstants { public static final int PLATFORM_ID_UNICODE = 0; public static final int PLATFORM_ID_MACINTOSH = 1; public static final int PLATFORM_ID_ISO_10646 = 2; public static final int PLATFORM_ID_WINDOWS = 3; public static final int PLATFORM_ID_WINDOWS_UNICODE = 10; public static final int PLATFORM_SPECIFIC_ID_UNICODE_DEFAULT = 0; public static final int PLATFORM_SPECIFIC_ID_UNICODE_1_1 = 1; public static final int PLATFORM_SPECIFIC_ID_UNICODE_ISO_10646 = 2; public static final int PLATFORM_SPECIFIC_ID_UNICODE_2_0 = 3; public static final int PLATFORM_SPECIFIC_ID_UNICODE_2_0_NON_BMP = 4; public static final int PLATFORM_SPECIFIC_ID_UNICODE_VARIATION_SEQUENCES = 5; public static final int PLATFORM_SPECIFIC_ID_UNICODE_FULL = 6; public static final int PLATFORM_SPECIFIC_ID_UNICODE_FONTFORGE = 10; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_ROMAN = 0; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_JAPANESE = 1; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_TRADITIONAL_CHINESE = 2; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_KOREAN = 3; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_ARABIC = 4; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_HEBREW = 5; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_GREEK = 6; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_RUSSIAN = 7; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_SYMBOL = 8; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_DEVANAGARI = 9; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_GURMUKHI = 10; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_GUJARATI = 11; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_ORIYA = 12; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_BENGALI = 13; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_TAMIL = 14; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_TELUGU = 15; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_KANNADA = 16; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_MALAYALAM = 17; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_SINHALESE = 18; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_BURMESE = 19; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_KHMER = 20; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_THAI = 21; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_LAOTIAN = 22; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_GEORGIAN = 23; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_ARMENIAN = 24; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_SIMPLIFIED_CHINESE = 25; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_TIBETAN = 26; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_MONGOLIAN = 27; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_GEEZ = 28; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_SLAVIC = 29; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_VIETNAMESE = 30; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_SINDHI = 31; public static final int PLATFORM_SPECIFIC_ID_MACINTOSH_UNINTERPRETED = 32; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_SYMBOL = 0; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_16 = 1; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_SHIFT_JIS = 2; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_PRC = 3; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_BIG5 = 4; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_JOHAB = 5; public static final int PLATFORM_SPECIFIC_ID_WINDOWS_UNICODE_32 = 10; public static final int LANGUAGE_ID_MACINTOSH_ENGLISH = 0; public static final int LANGUAGE_ID_MACINTOSH_FRENCH = 1; public static final int LANGUAGE_ID_MACINTOSH_GERMAN = 2; public static final int LANGUAGE_ID_MACINTOSH_ITALIAN = 3; public static final int LANGUAGE_ID_MACINTOSH_DUTCH = 4; public static final int LANGUAGE_ID_MACINTOSH_SWEDISH = 5; public static final int LANGUAGE_ID_MACINTOSH_SPANISH = 6; public static final int LANGUAGE_ID_MACINTOSH_DANISH = 7; public static final int LANGUAGE_ID_MACINTOSH_PORTUGUESE = 8; public static final int LANGUAGE_ID_MACINTOSH_NORWEGIAN = 9; public static final int LANGUAGE_ID_MACINTOSH_HEBREW = 10; public static final int LANGUAGE_ID_MACINTOSH_JAPANESE = 11; public static final int LANGUAGE_ID_MACINTOSH_ARABIC = 12; public static final int LANGUAGE_ID_MACINTOSH_FINNISH = 13; public static final int LANGUAGE_ID_MACINTOSH_GREEK = 14; public static final int LANGUAGE_ID_MACINTOSH_ICELANDIC = 15; public static final int LANGUAGE_ID_MACINTOSH_MALTESE = 16; public static final int LANGUAGE_ID_MACINTOSH_TURKISH = 17; public static final int LANGUAGE_ID_MACINTOSH_CROATIAN = 18; public static final int LANGUAGE_ID_MACINTOSH_TRADITIONAL_CHINESE = 19; public static final int LANGUAGE_ID_MACINTOSH_URDU = 20; public static final int LANGUAGE_ID_MACINTOSH_HINDI = 21; public static final int LANGUAGE_ID_MACINTOSH_THAI = 22; public static final int LANGUAGE_ID_MACINTOSH_KOREAN = 23; public static final int LANGUAGE_ID_MACINTOSH_LITHUANIAN = 24; public static final int LANGUAGE_ID_MACINTOSH_POLISH = 25; public static final int LANGUAGE_ID_MACINTOSH_HUNGARIAN = 26; public static final int LANGUAGE_ID_MACINTOSH_ESTONIAN = 27; public static final int LANGUAGE_ID_MACINTOSH_LATVIAN = 28; public static final int LANGUAGE_ID_MACINTOSH_SAMI = 29; public static final int LANGUAGE_ID_MACINTOSH_FAROESE = 30; public static final int LANGUAGE_ID_MACINTOSH_FARSI = 31; public static final int LANGUAGE_ID_MACINTOSH_RUSSIAN = 32; public static final int LANGUAGE_ID_MACINTOSH_SIMPLIFIED_CHINESE = 33; public static final int LANGUAGE_ID_MACINTOSH_FLEMISH = 34; public static final int LANGUAGE_ID_MACINTOSH_IRISH_GAELIC = 35; public static final int LANGUAGE_ID_MACINTOSH_ALBANIAN = 36; public static final int LANGUAGE_ID_MACINTOSH_ROMANIAN = 37; public static final int LANGUAGE_ID_MACINTOSH_CZECH = 38; public static final int LANGUAGE_ID_MACINTOSH_SLOVAK = 39; public static final int LANGUAGE_ID_MACINTOSH_SLOVENIAN = 40; public static final int LANGUAGE_ID_MACINTOSH_YIDDISH = 41; public static final int LANGUAGE_ID_MACINTOSH_SERBIAN = 42; public static final int LANGUAGE_ID_MACINTOSH_MACEDONIAN = 43; public static final int LANGUAGE_ID_MACINTOSH_BULGARIAN = 44; public static final int LANGUAGE_ID_MACINTOSH_UKRAINIAN = 45; public static final int LANGUAGE_ID_MACINTOSH_BYELORUSSIAN = 46; public static final int LANGUAGE_ID_MACINTOSH_UZBEK = 47; public static final int LANGUAGE_ID_MACINTOSH_KAZAKH = 48; public static final int LANGUAGE_ID_MACINTOSH_AZERBAIJANI_CYRILLIC = 49; public static final int LANGUAGE_ID_MACINTOSH_AZERBAIJANI_ARABIC = 50; public static final int LANGUAGE_ID_MACINTOSH_ARMENIAN = 51; public static final int LANGUAGE_ID_MACINTOSH_GEORGIAN = 52; public static final int LANGUAGE_ID_MACINTOSH_MOLDAVIAN = 53; public static final int LANGUAGE_ID_MACINTOSH_KIRGHIZ = 54; public static final int LANGUAGE_ID_MACINTOSH_TAJIKI = 55; public static final int LANGUAGE_ID_MACINTOSH_TURKMEN = 56; public static final int LANGUAGE_ID_MACINTOSH_MONGOLIAN_MONGOLIAN = 57; public static final int LANGUAGE_ID_MACINTOSH_MONGOLIAN_CYRILLIC = 58; public static final int LANGUAGE_ID_MACINTOSH_PASHTO = 59; public static final int LANGUAGE_ID_MACINTOSH_KURDISH = 60; public static final int LANGUAGE_ID_MACINTOSH_KASHMIRI = 61; public static final int LANGUAGE_ID_MACINTOSH_SINDHI = 62; public static final int LANGUAGE_ID_MACINTOSH_TIBETAN = 63; public static final int LANGUAGE_ID_MACINTOSH_NEPALI = 64; public static final int LANGUAGE_ID_MACINTOSH_SANSKRIT = 65; public static final int LANGUAGE_ID_MACINTOSH_MARATHI = 66; public static final int LANGUAGE_ID_MACINTOSH_BENGALI = 67; public static final int LANGUAGE_ID_MACINTOSH_ASSAMESE = 68; public static final int LANGUAGE_ID_MACINTOSH_GUJARATI = 69; public static final int LANGUAGE_ID_MACINTOSH_PUNJABI = 70; public static final int LANGUAGE_ID_MACINTOSH_ORIYA = 71; public static final int LANGUAGE_ID_MACINTOSH_MALAYALAM = 72; public static final int LANGUAGE_ID_MACINTOSH_KANNADA = 73; public static final int LANGUAGE_ID_MACINTOSH_TAMIL = 74; public static final int LANGUAGE_ID_MACINTOSH_TELUGU = 75; public static final int LANGUAGE_ID_MACINTOSH_SINHALESE = 76; public static final int LANGUAGE_ID_MACINTOSH_BURMESE = 77; public static final int LANGUAGE_ID_MACINTOSH_KHMER = 78; public static final int LANGUAGE_ID_MACINTOSH_LAO = 79; public static final int LANGUAGE_ID_MACINTOSH_VIETNAMESE = 80; public static final int LANGUAGE_ID_MACINTOSH_INDONESIAN = 81; public static final int LANGUAGE_ID_MACINTOSH_TAGALOG = 82; public static final int LANGUAGE_ID_MACINTOSH_MALAY_ROMAN = 83; public static final int LANGUAGE_ID_MACINTOSH_MALAY_ARABIC = 84; public static final int LANGUAGE_ID_MACINTOSH_AMHARIC = 85; public static final int LANGUAGE_ID_MACINTOSH_TIGRINYA = 86; public static final int LANGUAGE_ID_MACINTOSH_GALLA = 87; public static final int LANGUAGE_ID_MACINTOSH_SOMALI = 88; public static final int LANGUAGE_ID_MACINTOSH_SWAHILI = 89; public static final int LANGUAGE_ID_MACINTOSH_KINYARWANDA = 90; public static final int LANGUAGE_ID_MACINTOSH_RUNDI = 91; public static final int LANGUAGE_ID_MACINTOSH_NYANJA = 92; public static final int LANGUAGE_ID_MACINTOSH_MALAGASY = 93; public static final int LANGUAGE_ID_MACINTOSH_ESPERANTO = 94; public static final int LANGUAGE_ID_MACINTOSH_WELSH = 128; public static final int LANGUAGE_ID_MACINTOSH_BASQUE = 129; public static final int LANGUAGE_ID_MACINTOSH_CATALAN = 130; public static final int LANGUAGE_ID_MACINTOSH_LATIN = 131; public static final int LANGUAGE_ID_MACINTOSH_QUECHUA = 132; public static final int LANGUAGE_ID_MACINTOSH_GUARANI = 133; public static final int LANGUAGE_ID_MACINTOSH_AYMARA = 134; public static final int LANGUAGE_ID_MACINTOSH_TATAR = 135; public static final int LANGUAGE_ID_MACINTOSH_UIGHUR = 136; public static final int LANGUAGE_ID_MACINTOSH_DZONGKHA = 137; public static final int LANGUAGE_ID_MACINTOSH_JAVANESE_ROMAN = 138; public static final int LANGUAGE_ID_MACINTOSH_SUNDANESE_ROMAN = 139; public static final int LANGUAGE_ID_MACINTOSH_GALICIAN = 140; public static final int LANGUAGE_ID_MACINTOSH_AFRIKAANS = 141; public static final int LANGUAGE_ID_MACINTOSH_BRETON = 142; public static final int LANGUAGE_ID_MACINTOSH_INUKTITUT = 143; public static final int LANGUAGE_ID_MACINTOSH_SCOTTISH_GAELIC = 144; public static final int LANGUAGE_ID_MACINTOSH_MANX_GAELIC = 145; public static final int LANGUAGE_ID_MACINTOSH_IRISH_GAELIC_WITH_DOT_ABOVE = 146; public static final int LANGUAGE_ID_MACINTOSH_TONGAN = 147; public static final int LANGUAGE_ID_MACINTOSH_GREEK_POLYTONIC = 148; public static final int LANGUAGE_ID_MACINTOSH_GREENLANDIC = 149; public static final int LANGUAGE_ID_MACINTOSH_AZERBAIJANI_ROMAN = 150; public static final int LANGUAGE_ID_WINDOWS_ENGLISH = 1033; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PostTable.java000077500000000000000000000121121506470510200320570ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; public class PostTable extends ListBasedTable { public static final int FORMAT_1 = 0x00010000; public static final int FORMAT_2 = 0x00020000; public static final int FORMAT_2_5 = 0x00028000; public static final int FORMAT_3 = 0x00030000; public static final int FORMAT_4 = 0x00040000; public static final int ITALIC_ANGLE_ISOMETRIC = 0xFFE56F59; public static final int ITALIC_ANGLE_UPRIGHT = 0; public static final int FIXED_PITCH_FALSE = 0; public static final int FIXED_PITCH_TRUE = 1; public static final int MEM_UNKNOWN = 0; public int format = FORMAT_2; public int italicAngle = ITALIC_ANGLE_UPRIGHT; public int underlinePosition = 0; public int underlineThickness = 0; public int fixedPitch = FIXED_PITCH_FALSE; public int minMemType42 = MEM_UNKNOWN; public int maxMemType42 = MEM_UNKNOWN; public int minMemType1 = MEM_UNKNOWN; public int maxMemType1 = MEM_UNKNOWN; @Override public String tableName() { return "post"; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeInt(format); out.writeInt(italicAngle); out.writeShort(underlinePosition); out.writeShort(underlineThickness); out.writeInt(fixedPitch); out.writeInt(minMemType42); out.writeInt(maxMemType42); out.writeInt(minMemType1); out.writeInt(maxMemType1); switch (format) { case FORMAT_1: // No additional content. break; case FORMAT_2: out.writeShort(this.size()); int stringIndex = 258; for (PostTableEntry e : this) { if (e.isInteger()) { out.writeShort(e.intValue()); } else if (e.isString()) { out.writeShort(stringIndex++); } } for (PostTableEntry e : this) { if (e.isString()) { byte[] data; try { data = e.stringValue().getBytes("US-ASCII"); } catch (UnsupportedEncodingException uee) { throw new IllegalStateException("Java is stupid."); } out.writeByte(data.length); out.write(data); stringIndex--; } } if (stringIndex != 258) { throw new IllegalStateException("Assertion failed: number of names written <> number of names assigned."); } break; case FORMAT_2_5: out.writeShort(this.size()); for (int i = 0; i < this.size(); i++) { PostTableEntry e = this.get(i); if (e.isInteger()) { out.writeByte(e.intValue() - i); } else { throw new IllegalStateException("Invalid entry in Format 2.5 'post' table."); } } break; case FORMAT_3: // No additional content. break; case FORMAT_4: for (int i = 0; i < this.size(); i++) { PostTableEntry e = this.get(i); if (e.isInteger()) { out.writeShort(e.intValue()); } else { throw new IllegalStateException("Invalid entry in Format 4 'post' table."); } } break; default: throw new IllegalStateException("Invalid format for 'post' table."); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { format = in.readInt(); italicAngle = in.readInt(); underlinePosition = in.readShort(); underlineThickness = in.readShort(); fixedPitch = in.readInt(); minMemType42 = in.readInt(); maxMemType42 = in.readInt(); minMemType1 = in.readInt(); maxMemType1 = in.readInt(); switch (format) { case FORMAT_1: this.clear(); // No additional content. break; case FORMAT_2: int count = in.readUnsignedShort(); int[] intValues = new int[count]; int maxValue = 0; for (int i = 0; i < count; i++) { intValues[i] = in.readUnsignedShort(); if (intValues[i] > maxValue) { maxValue = intValues[i]; } } String[] stringValues = new String[maxValue + 1]; for (int i = 258; i < stringValues.length; i++) { byte[] d = new byte[in.readUnsignedByte()]; in.readFully(d); try { stringValues[i] = new String(d, "US-ASCII"); } catch (UnsupportedEncodingException uee) { throw new IllegalStateException("Java is stupid."); } } this.clear(); for (int i = 0; i < count; i++) { int intValue = intValues[i]; String stringValue = stringValues[intValue]; if (stringValue != null) { this.add(new PostTableEntry(stringValue)); } else { this.add(new PostTableEntry(intValue)); } } break; case FORMAT_2_5: int cnt = in.readUnsignedShort(); this.clear(); for (int i = 0; i < cnt; i++) { int intValue = i + in.readByte(); this.add(new PostTableEntry(intValue)); } break; case FORMAT_3: this.clear(); // No additional content. break; case FORMAT_4: int n = (length - 32) / 2; this.clear(); for (int i = 0; i < n; i++) { int intValue = in.readUnsignedShort(); if (intValue == 0xFFFF) intValue = -1; this.add(new PostTableEntry(intValue)); } break; default: throw new IllegalStateException("Invalid format for 'post' table."); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PostTableEntry.java000077500000000000000000001377541506470510200331250ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public class PostTableEntry { private final Integer intValue; private final String stringValue; public PostTableEntry(int intValue) { this.intValue = intValue; this.stringValue = null; } public PostTableEntry(String stringValue) { this.intValue = null; this.stringValue = stringValue; } public static PostTableEntry forCharacter(int ch) { if (ch < 0) { return new PostTableEntry(0); } else if (ch >= 0x20 && ch <= 0x7E) { return new PostTableEntry(ch - 29); } else switch (ch) { case 0x0000: return new PostTableEntry(1); case 0x000d: return new PostTableEntry(2); case 0x00a0: return new PostTableEntry("uni00A0"); // 172 case 0x00a1: return new PostTableEntry(163); case 0x00a2: return new PostTableEntry(132); case 0x00a3: return new PostTableEntry(133); case 0x00a4: return new PostTableEntry(189); case 0x00a5: return new PostTableEntry(150); case 0x00a6: return new PostTableEntry(232); case 0x00a7: return new PostTableEntry(134); case 0x00a8: return new PostTableEntry(142); case 0x00a9: return new PostTableEntry(139); case 0x00aa: return new PostTableEntry(157); case 0x00ab: return new PostTableEntry(169); case 0x00ac: return new PostTableEntry(164); case 0x00ad: return new PostTableEntry("hyphen"); case 0x00ae: return new PostTableEntry(138); case 0x00af: return new PostTableEntry(218); case 0x00b0: return new PostTableEntry(131); case 0x00b1: return new PostTableEntry(147); case 0x00b2: return new PostTableEntry(242); case 0x00b3: return new PostTableEntry(243); case 0x00b4: return new PostTableEntry(141); case 0x00b5: return new PostTableEntry(151); case 0x00b6: return new PostTableEntry(136); case 0x00b7: return new PostTableEntry("periodcentered"); case 0x00b8: return new PostTableEntry(222); case 0x00b9: return new PostTableEntry(241); case 0x00ba: return new PostTableEntry(158); case 0x00bb: return new PostTableEntry(170); case 0x00bc: return new PostTableEntry(245); case 0x00bd: return new PostTableEntry(244); case 0x00be: return new PostTableEntry(246); case 0x00bf: return new PostTableEntry(162); case 0x00c0: return new PostTableEntry(173); case 0x00c1: return new PostTableEntry(201); case 0x00c2: return new PostTableEntry(199); case 0x00c3: return new PostTableEntry(174); case 0x00c4: return new PostTableEntry(98); case 0x00c5: return new PostTableEntry(99); case 0x00c6: return new PostTableEntry(144); case 0x00c7: return new PostTableEntry(100); case 0x00c8: return new PostTableEntry(203); case 0x00c9: return new PostTableEntry(101); case 0x00ca: return new PostTableEntry(200); case 0x00cb: return new PostTableEntry(202); case 0x00cc: return new PostTableEntry(207); case 0x00cd: return new PostTableEntry(204); case 0x00ce: return new PostTableEntry(205); case 0x00cf: return new PostTableEntry(206); case 0x00d0: return new PostTableEntry(233); case 0x00d1: return new PostTableEntry(102); case 0x00d2: return new PostTableEntry(211); case 0x00d3: return new PostTableEntry(208); case 0x00d4: return new PostTableEntry(209); case 0x00d5: return new PostTableEntry(175); case 0x00d6: return new PostTableEntry(103); case 0x00d7: return new PostTableEntry(240); case 0x00d8: return new PostTableEntry(145); case 0x00d9: return new PostTableEntry(214); case 0x00da: return new PostTableEntry(212); case 0x00db: return new PostTableEntry(213); case 0x00dc: return new PostTableEntry(104); case 0x00dd: return new PostTableEntry(235); case 0x00de: return new PostTableEntry(237); case 0x00df: return new PostTableEntry(137); case 0x00e0: return new PostTableEntry(106); case 0x00e1: return new PostTableEntry(105); case 0x00e2: return new PostTableEntry(107); case 0x00e3: return new PostTableEntry(109); case 0x00e4: return new PostTableEntry(108); case 0x00e5: return new PostTableEntry(110); case 0x00e6: return new PostTableEntry(160); case 0x00e7: return new PostTableEntry(111); case 0x00e8: return new PostTableEntry(113); case 0x00e9: return new PostTableEntry(112); case 0x00ea: return new PostTableEntry(114); case 0x00eb: return new PostTableEntry(115); case 0x00ec: return new PostTableEntry(117); case 0x00ed: return new PostTableEntry(116); case 0x00ee: return new PostTableEntry(118); case 0x00ef: return new PostTableEntry(119); case 0x00f0: return new PostTableEntry(234); case 0x00f1: return new PostTableEntry(120); case 0x00f2: return new PostTableEntry(122); case 0x00f3: return new PostTableEntry(121); case 0x00f4: return new PostTableEntry(123); case 0x00f5: return new PostTableEntry(125); case 0x00f6: return new PostTableEntry(124); case 0x00f7: return new PostTableEntry(184); case 0x00f8: return new PostTableEntry(161); case 0x00f9: return new PostTableEntry(127); case 0x00fa: return new PostTableEntry(126); case 0x00fb: return new PostTableEntry(128); case 0x00fc: return new PostTableEntry(129); case 0x00fd: return new PostTableEntry(236); case 0x00fe: return new PostTableEntry(238); case 0x00ff: return new PostTableEntry(186); case 0x0100: return new PostTableEntry("Amacron"); case 0x0101: return new PostTableEntry("amacron"); case 0x0102: return new PostTableEntry("Abreve"); case 0x0103: return new PostTableEntry("abreve"); case 0x0104: return new PostTableEntry("Aogonek"); case 0x0105: return new PostTableEntry("aogonek"); case 0x0106: return new PostTableEntry(253); case 0x0107: return new PostTableEntry(254); case 0x0108: return new PostTableEntry("Ccircumflex"); case 0x0109: return new PostTableEntry("ccircumflex"); case 0x010a: return new PostTableEntry("Cdotaccent"); case 0x010b: return new PostTableEntry("cdotaccent"); case 0x010c: return new PostTableEntry(255); case 0x010d: return new PostTableEntry(256); case 0x010e: return new PostTableEntry("Dcaron"); case 0x010f: return new PostTableEntry("dcaron"); case 0x0110: return new PostTableEntry("Dcroat"); case 0x0111: return new PostTableEntry(257); case 0x0112: return new PostTableEntry("Emacron"); case 0x0113: return new PostTableEntry("emacron"); case 0x0114: return new PostTableEntry("Ebreve"); case 0x0115: return new PostTableEntry("ebreve"); case 0x0116: return new PostTableEntry("Edotaccent"); case 0x0117: return new PostTableEntry("edotaccent"); case 0x0118: return new PostTableEntry("Eogonek"); case 0x0119: return new PostTableEntry("eogonek"); case 0x011a: return new PostTableEntry("Ecaron"); case 0x011b: return new PostTableEntry("ecaron"); case 0x011c: return new PostTableEntry("Gcircumflex"); case 0x011d: return new PostTableEntry("gcircumflex"); case 0x011e: return new PostTableEntry(248); case 0x011f: return new PostTableEntry(249); case 0x0120: return new PostTableEntry("Gdotaccent"); case 0x0121: return new PostTableEntry("gdotaccent"); case 0x0122: return new PostTableEntry("Gcommaaccent"); case 0x0123: return new PostTableEntry("gcommaaccent"); case 0x0124: return new PostTableEntry("Hcircumflex"); case 0x0125: return new PostTableEntry("hcircumflex"); case 0x0126: return new PostTableEntry("Hbar"); case 0x0127: return new PostTableEntry("hbar"); case 0x0128: return new PostTableEntry("Itilde"); case 0x0129: return new PostTableEntry("itilde"); case 0x012a: return new PostTableEntry("Imacron"); case 0x012b: return new PostTableEntry("imacron"); case 0x012c: return new PostTableEntry("Ibreve"); case 0x012d: return new PostTableEntry("ibreve"); case 0x012e: return new PostTableEntry("Iogonek"); case 0x012f: return new PostTableEntry("iogonek"); case 0x0130: return new PostTableEntry(250); case 0x0131: return new PostTableEntry(215); case 0x0132: return new PostTableEntry("IJ"); case 0x0133: return new PostTableEntry("ij"); case 0x0134: return new PostTableEntry("Jcircumflex"); case 0x0135: return new PostTableEntry("jcircumflex"); case 0x0136: return new PostTableEntry("Kcommaaccent"); case 0x0137: return new PostTableEntry("kcommaaccent"); case 0x0138: return new PostTableEntry("kgreenlandic"); case 0x0139: return new PostTableEntry("Lacute"); case 0x013a: return new PostTableEntry("lacute"); case 0x013b: return new PostTableEntry("Lcommaaccent"); case 0x013c: return new PostTableEntry("lcommaaccent"); case 0x013d: return new PostTableEntry("Lcaron"); case 0x013e: return new PostTableEntry("lcaron"); case 0x013f: return new PostTableEntry("Ldot"); case 0x0140: return new PostTableEntry("ldot"); case 0x0141: return new PostTableEntry(226); case 0x0142: return new PostTableEntry(227); case 0x0143: return new PostTableEntry("Nacute"); case 0x0144: return new PostTableEntry("nacute"); case 0x0145: return new PostTableEntry("Ncommaaccent"); case 0x0146: return new PostTableEntry("ncommaaccent"); case 0x0147: return new PostTableEntry("Ncaron"); case 0x0148: return new PostTableEntry("ncaron"); case 0x0149: return new PostTableEntry("napostrophe"); case 0x014a: return new PostTableEntry("Eng"); case 0x014b: return new PostTableEntry("eng"); case 0x014c: return new PostTableEntry("Omacron"); case 0x014d: return new PostTableEntry("omacron"); case 0x014e: return new PostTableEntry("Obreve"); case 0x014f: return new PostTableEntry("obreve"); case 0x0150: return new PostTableEntry("Ohungarumlaut"); case 0x0151: return new PostTableEntry("ohungarumlaut"); case 0x0152: return new PostTableEntry(176); case 0x0153: return new PostTableEntry(177); case 0x0154: return new PostTableEntry("Racute"); case 0x0155: return new PostTableEntry("racute"); case 0x0156: return new PostTableEntry("Rcommaaccent"); case 0x0157: return new PostTableEntry("rcommaaccent"); case 0x0158: return new PostTableEntry("Rcaron"); case 0x0159: return new PostTableEntry("rcaron"); case 0x015a: return new PostTableEntry("Sacute"); case 0x015b: return new PostTableEntry("sacute"); case 0x015c: return new PostTableEntry("Scircumflex"); case 0x015d: return new PostTableEntry("scircumflex"); case 0x015e: return new PostTableEntry(251); case 0x015f: return new PostTableEntry(252); case 0x0160: return new PostTableEntry(228); case 0x0161: return new PostTableEntry(229); case 0x0162: return new PostTableEntry("Tcommaaccent"); case 0x0163: return new PostTableEntry("tcommaaccent"); case 0x0164: return new PostTableEntry("Tcaron"); case 0x0165: return new PostTableEntry("tcaron"); case 0x0166: return new PostTableEntry("Tbar"); case 0x0167: return new PostTableEntry("tbar"); case 0x0168: return new PostTableEntry("Utilde"); case 0x0169: return new PostTableEntry("utilde"); case 0x016a: return new PostTableEntry("Umacron"); case 0x016b: return new PostTableEntry("umacron"); case 0x016c: return new PostTableEntry("Ubreve"); case 0x016d: return new PostTableEntry("ubreve"); case 0x016e: return new PostTableEntry("Uring"); case 0x016f: return new PostTableEntry("uring"); case 0x0170: return new PostTableEntry("Uhungarumlaut"); case 0x0171: return new PostTableEntry("uhungarumlaut"); case 0x0172: return new PostTableEntry("Uogonek"); case 0x0173: return new PostTableEntry("uogonek"); case 0x0174: return new PostTableEntry("Wcircumflex"); case 0x0175: return new PostTableEntry("wcircumflex"); case 0x0176: return new PostTableEntry("Ycircumflex"); case 0x0177: return new PostTableEntry("ycircumflex"); case 0x0178: return new PostTableEntry(187); case 0x0179: return new PostTableEntry("Zacute"); case 0x017a: return new PostTableEntry("zacute"); case 0x017b: return new PostTableEntry("Zdotaccent"); case 0x017c: return new PostTableEntry("zdotaccent"); case 0x017d: return new PostTableEntry(230); case 0x017e: return new PostTableEntry(231); case 0x017f: return new PostTableEntry("longs"); case 0x0192: return new PostTableEntry(166); case 0x01fa: return new PostTableEntry("Aringacute"); case 0x01fb: return new PostTableEntry("aringacute"); case 0x01fc: return new PostTableEntry("AEacute"); case 0x01fd: return new PostTableEntry("aeacute"); case 0x01fe: return new PostTableEntry("Oslashacute"); case 0x01ff: return new PostTableEntry("oslashacute"); case 0x02c6: return new PostTableEntry(216); case 0x02c7: return new PostTableEntry(225); case 0x02c9: return new PostTableEntry("macron"); case 0x02d8: return new PostTableEntry(219); case 0x02d9: return new PostTableEntry(220); case 0x02da: return new PostTableEntry(221); case 0x02db: return new PostTableEntry(224); case 0x02dc: return new PostTableEntry("tilde"); case 0x02dd: return new PostTableEntry(223); case 0x0300: return new PostTableEntry("gravecomb"); case 0x0301: return new PostTableEntry("acutecomb"); case 0x0303: return new PostTableEntry("tildecomb"); case 0x0309: return new PostTableEntry("hookabovecomb"); case 0x0323: return new PostTableEntry("dotbelowcomb"); case 0x0384: return new PostTableEntry("tonos"); case 0x0385: return new PostTableEntry("dieresistonos"); case 0x0386: return new PostTableEntry("Alphatonos"); case 0x0387: return new PostTableEntry("anoteleia"); case 0x0388: return new PostTableEntry("Epsilontonos"); case 0x0389: return new PostTableEntry("Etatonos"); case 0x038a: return new PostTableEntry("Iotatonos"); case 0x038c: return new PostTableEntry("Omicrontonos"); case 0x038e: return new PostTableEntry("Upsilontonos"); case 0x038f: return new PostTableEntry("Omegatonos"); case 0x0390: return new PostTableEntry("iotadieresistonos"); case 0x0391: return new PostTableEntry("Alpha"); case 0x0392: return new PostTableEntry("Beta"); case 0x0393: return new PostTableEntry("Gamma"); case 0x0394: return new PostTableEntry("Delta"); case 0x0395: return new PostTableEntry("Epsilon"); case 0x0396: return new PostTableEntry("Zeta"); case 0x0397: return new PostTableEntry("Eta"); case 0x0398: return new PostTableEntry("Theta"); case 0x0399: return new PostTableEntry("Iota"); case 0x039a: return new PostTableEntry("Kappa"); case 0x039b: return new PostTableEntry("Lambda"); case 0x039c: return new PostTableEntry("Mu"); case 0x039d: return new PostTableEntry("Nu"); case 0x039e: return new PostTableEntry("Xi"); case 0x039f: return new PostTableEntry("Omicron"); case 0x03a0: return new PostTableEntry("Pi"); case 0x03a1: return new PostTableEntry("Rho"); case 0x03a3: return new PostTableEntry("Sigma"); case 0x03a4: return new PostTableEntry("Tau"); case 0x03a5: return new PostTableEntry("Upsilon"); case 0x03a6: return new PostTableEntry("Phi"); case 0x03a7: return new PostTableEntry("Chi"); case 0x03a8: return new PostTableEntry("Psi"); case 0x03a9: return new PostTableEntry("Omega"); case 0x03aa: return new PostTableEntry("Iotadieresis"); case 0x03ab: return new PostTableEntry("Upsilondieresis"); case 0x03ac: return new PostTableEntry("alphatonos"); case 0x03ad: return new PostTableEntry("epsilontonos"); case 0x03ae: return new PostTableEntry("etatonos"); case 0x03af: return new PostTableEntry("iotatonos"); case 0x03b0: return new PostTableEntry("upsilondieresistonos"); case 0x03b1: return new PostTableEntry("alpha"); case 0x03b2: return new PostTableEntry("beta"); case 0x03b3: return new PostTableEntry("gamma"); case 0x03b4: return new PostTableEntry("delta"); case 0x03b5: return new PostTableEntry("epsilon"); case 0x03b6: return new PostTableEntry("zeta"); case 0x03b7: return new PostTableEntry("eta"); case 0x03b8: return new PostTableEntry("theta"); case 0x03b9: return new PostTableEntry("iota"); case 0x03ba: return new PostTableEntry("kappa"); case 0x03bb: return new PostTableEntry("lambda"); case 0x03bc: return new PostTableEntry("mu"); case 0x03bd: return new PostTableEntry("nu"); case 0x03be: return new PostTableEntry("xi"); case 0x03bf: return new PostTableEntry("omicron"); case 0x03c0: return new PostTableEntry(155); case 0x03c1: return new PostTableEntry("rho"); case 0x03c2: return new PostTableEntry("sigma1"); case 0x03c3: return new PostTableEntry("sigma"); case 0x03c4: return new PostTableEntry("tau"); case 0x03c5: return new PostTableEntry("upsilon"); case 0x03c6: return new PostTableEntry("phi"); case 0x03c7: return new PostTableEntry("chi"); case 0x03c8: return new PostTableEntry("psi"); case 0x03c9: return new PostTableEntry("omega"); case 0x03ca: return new PostTableEntry("iotadieresis"); case 0x03cb: return new PostTableEntry("upsilondieresis"); case 0x03cc: return new PostTableEntry("omicrontonos"); case 0x03cd: return new PostTableEntry("upsilontonos"); case 0x03ce: return new PostTableEntry("omegatonos"); case 0x0400: return new PostTableEntry("uni0400"); case 0x0401: return new PostTableEntry("afii10023"); case 0x0402: return new PostTableEntry("afii10051"); case 0x0403: return new PostTableEntry("afii10052"); case 0x0404: return new PostTableEntry("afii10053"); case 0x0405: return new PostTableEntry("afii10054"); case 0x0406: return new PostTableEntry("afii10055"); case 0x0407: return new PostTableEntry("afii10056"); case 0x0408: return new PostTableEntry("afii10057"); case 0x0409: return new PostTableEntry("afii10058"); case 0x040a: return new PostTableEntry("afii10059"); case 0x040b: return new PostTableEntry("afii10060"); case 0x040c: return new PostTableEntry("afii10061"); case 0x040D: return new PostTableEntry("uni040D"); case 0x040e: return new PostTableEntry("afii10062"); case 0x040f: return new PostTableEntry("afii10145"); case 0x0410: return new PostTableEntry("afii10017"); case 0x0411: return new PostTableEntry("afii10018"); case 0x0412: return new PostTableEntry("afii10019"); case 0x0413: return new PostTableEntry("afii10020"); case 0x0414: return new PostTableEntry("afii10021"); case 0x0415: return new PostTableEntry("afii10022"); case 0x0416: return new PostTableEntry("afii10024"); case 0x0417: return new PostTableEntry("afii10025"); case 0x0418: return new PostTableEntry("afii10026"); case 0x0419: return new PostTableEntry("afii10027"); case 0x041a: return new PostTableEntry("afii10028"); case 0x041b: return new PostTableEntry("afii10029"); case 0x041c: return new PostTableEntry("afii10030"); case 0x041d: return new PostTableEntry("afii10031"); case 0x041e: return new PostTableEntry("afii10032"); case 0x041f: return new PostTableEntry("afii10033"); case 0x0420: return new PostTableEntry("afii10034"); case 0x0421: return new PostTableEntry("afii10035"); case 0x0422: return new PostTableEntry("afii10036"); case 0x0423: return new PostTableEntry("afii10037"); case 0x0424: return new PostTableEntry("afii10038"); case 0x0425: return new PostTableEntry("afii10039"); case 0x0426: return new PostTableEntry("afii10040"); case 0x0427: return new PostTableEntry("afii10041"); case 0x0428: return new PostTableEntry("afii10042"); case 0x0429: return new PostTableEntry("afii10043"); case 0x042a: return new PostTableEntry("afii10044"); case 0x042b: return new PostTableEntry("afii10045"); case 0x042c: return new PostTableEntry("afii10046"); case 0x042d: return new PostTableEntry("afii10047"); case 0x042e: return new PostTableEntry("afii10048"); case 0x042f: return new PostTableEntry("afii10049"); case 0x0430: return new PostTableEntry("afii10065"); case 0x0431: return new PostTableEntry("afii10066"); case 0x0432: return new PostTableEntry("afii10067"); case 0x0433: return new PostTableEntry("afii10068"); case 0x0434: return new PostTableEntry("afii10069"); case 0x0435: return new PostTableEntry("afii10070"); case 0x0436: return new PostTableEntry("afii10072"); case 0x0437: return new PostTableEntry("afii10073"); case 0x0438: return new PostTableEntry("afii10074"); case 0x0439: return new PostTableEntry("afii10075"); case 0x043a: return new PostTableEntry("afii10076"); case 0x043b: return new PostTableEntry("afii10077"); case 0x043c: return new PostTableEntry("afii10078"); case 0x043d: return new PostTableEntry("afii10079"); case 0x043e: return new PostTableEntry("afii10080"); case 0x043f: return new PostTableEntry("afii10081"); case 0x0440: return new PostTableEntry("afii10082"); case 0x0441: return new PostTableEntry("afii10083"); case 0x0442: return new PostTableEntry("afii10084"); case 0x0443: return new PostTableEntry("afii10085"); case 0x0444: return new PostTableEntry("afii10086"); case 0x0445: return new PostTableEntry("afii10087"); case 0x0446: return new PostTableEntry("afii10088"); case 0x0447: return new PostTableEntry("afii10089"); case 0x0448: return new PostTableEntry("afii10090"); case 0x0449: return new PostTableEntry("afii10091"); case 0x044a: return new PostTableEntry("afii10092"); case 0x044b: return new PostTableEntry("afii10093"); case 0x044c: return new PostTableEntry("afii10094"); case 0x044d: return new PostTableEntry("afii10095"); case 0x044e: return new PostTableEntry("afii10096"); case 0x044f: return new PostTableEntry("afii10097"); case 0x0450: return new PostTableEntry("uni0450"); case 0x0451: return new PostTableEntry("afii10071"); case 0x0452: return new PostTableEntry("afii10099"); case 0x0453: return new PostTableEntry("afii10100"); case 0x0454: return new PostTableEntry("afii10101"); case 0x0455: return new PostTableEntry("afii10102"); case 0x0456: return new PostTableEntry("afii10103"); case 0x0457: return new PostTableEntry("afii10104"); case 0x0458: return new PostTableEntry("afii10105"); case 0x0459: return new PostTableEntry("afii10106"); case 0x045a: return new PostTableEntry("afii10107"); case 0x045b: return new PostTableEntry("afii10108"); case 0x045c: return new PostTableEntry("afii10109"); case 0x045D: return new PostTableEntry("uni045D"); case 0x045e: return new PostTableEntry("afii10110"); case 0x045f: return new PostTableEntry("afii10193"); case 0x0490: return new PostTableEntry("afii10050"); case 0x0491: return new PostTableEntry("afii10098"); case 0x1e80: return new PostTableEntry("Wgrave"); case 0x1e81: return new PostTableEntry("wgrave"); case 0x1e82: return new PostTableEntry("Wacute"); case 0x1e83: return new PostTableEntry("wacute"); case 0x1e84: return new PostTableEntry("Wdieresis"); case 0x1e85: return new PostTableEntry("wdieresis"); case 0x1ef2: return new PostTableEntry("Ygrave"); case 0x1ef3: return new PostTableEntry("ygrave"); case 0x2013: return new PostTableEntry(178); case 0x2014: return new PostTableEntry(179); case 0x2015: return new PostTableEntry("afii00208"); case 0x2017: return new PostTableEntry("underscoredbl"); case 0x2018: return new PostTableEntry(182); case 0x2019: return new PostTableEntry(183); case 0x201a: return new PostTableEntry(196); case 0x201b: return new PostTableEntry("quotereversed"); case 0x201c: return new PostTableEntry(180); case 0x201d: return new PostTableEntry(181); case 0x201e: return new PostTableEntry(197); case 0x2020: return new PostTableEntry(130); case 0x2021: return new PostTableEntry(194); case 0x2022: return new PostTableEntry(135); case 0x2026: return new PostTableEntry(171); case 0x2030: return new PostTableEntry(198); case 0x2032: return new PostTableEntry("minute"); case 0x2033: return new PostTableEntry("second"); case 0x2039: return new PostTableEntry(190); case 0x203a: return new PostTableEntry(191); case 0x203c: return new PostTableEntry("exclamdbl"); case 0x203e: return new PostTableEntry("uni203E"); case 0x2044: return new PostTableEntry("fraction"); case 0x207f: return new PostTableEntry("nsuperior"); case 0x20a3: return new PostTableEntry(247); case 0x20a4: return new PostTableEntry("lira"); case 0x20a7: return new PostTableEntry("peseta"); case 0x20ac: return new PostTableEntry("Euro"); case 0x2105: return new PostTableEntry("afii61248"); case 0x2113: return new PostTableEntry("afii61289"); case 0x2116: return new PostTableEntry("afii61352"); case 0x2122: return new PostTableEntry(140); case 0x2126: return new PostTableEntry(159); case 0x212e: return new PostTableEntry("estimated"); case 0x215b: return new PostTableEntry("oneeighth"); case 0x215c: return new PostTableEntry("threeeighths"); case 0x215d: return new PostTableEntry("fiveeighths"); case 0x215e: return new PostTableEntry("seveneighths"); case 0x2190: return new PostTableEntry("arrowleft"); case 0x2191: return new PostTableEntry("arrowup"); case 0x2192: return new PostTableEntry("arrowright"); case 0x2193: return new PostTableEntry("arrowdown"); case 0x2194: return new PostTableEntry("arrowboth"); case 0x2195: return new PostTableEntry("arrowupdn"); case 0x21a8: return new PostTableEntry("arrowupdnbse"); case 0x2202: return new PostTableEntry(152); case 0x2206: return new PostTableEntry(168); case 0x220f: return new PostTableEntry(154); case 0x2211: return new PostTableEntry(153); case 0x2212: return new PostTableEntry(239); case 0x2215: return new PostTableEntry(188); case 0x2219: return new PostTableEntry(195); case 0x221a: return new PostTableEntry(165); case 0x221e: return new PostTableEntry(146); case 0x221f: return new PostTableEntry("orthogonal"); case 0x2229: return new PostTableEntry("intersection"); case 0x222b: return new PostTableEntry(156); case 0x2248: return new PostTableEntry(167); case 0x2260: return new PostTableEntry(143); case 0x2261: return new PostTableEntry("equivalence"); case 0x2264: return new PostTableEntry(148); case 0x2265: return new PostTableEntry(149); case 0x2302: return new PostTableEntry("house"); case 0x2310: return new PostTableEntry("revlogicalnot"); case 0x2320: return new PostTableEntry("integraltp"); case 0x2321: return new PostTableEntry("integralbt"); case 0x2500: return new PostTableEntry("SF100000"); case 0x2502: return new PostTableEntry("SF110000"); case 0x250c: return new PostTableEntry("SF010000"); case 0x2510: return new PostTableEntry("SF030000"); case 0x2514: return new PostTableEntry("SF020000"); case 0x2518: return new PostTableEntry("SF040000"); case 0x251c: return new PostTableEntry("SF080000"); case 0x2524: return new PostTableEntry("SF090000"); case 0x252c: return new PostTableEntry("SF060000"); case 0x2534: return new PostTableEntry("SF070000"); case 0x253c: return new PostTableEntry("SF050000"); case 0x2550: return new PostTableEntry("SF430000"); case 0x2551: return new PostTableEntry("SF240000"); case 0x2552: return new PostTableEntry("SF510000"); case 0x2553: return new PostTableEntry("SF520000"); case 0x2554: return new PostTableEntry("SF390000"); case 0x2555: return new PostTableEntry("SF220000"); case 0x2556: return new PostTableEntry("SF210000"); case 0x2557: return new PostTableEntry("SF250000"); case 0x2558: return new PostTableEntry("SF500000"); case 0x2559: return new PostTableEntry("SF490000"); case 0x255a: return new PostTableEntry("SF380000"); case 0x255b: return new PostTableEntry("SF280000"); case 0x255c: return new PostTableEntry("SF270000"); case 0x255d: return new PostTableEntry("SF260000"); case 0x255e: return new PostTableEntry("SF360000"); case 0x255f: return new PostTableEntry("SF370000"); case 0x2560: return new PostTableEntry("SF420000"); case 0x2561: return new PostTableEntry("SF190000"); case 0x2562: return new PostTableEntry("SF200000"); case 0x2563: return new PostTableEntry("SF230000"); case 0x2564: return new PostTableEntry("SF470000"); case 0x2565: return new PostTableEntry("SF480000"); case 0x2566: return new PostTableEntry("SF410000"); case 0x2567: return new PostTableEntry("SF450000"); case 0x2568: return new PostTableEntry("SF460000"); case 0x2569: return new PostTableEntry("SF400000"); case 0x256a: return new PostTableEntry("SF540000"); case 0x256b: return new PostTableEntry("SF530000"); case 0x256c: return new PostTableEntry("SF440000"); case 0x2580: return new PostTableEntry("upblock"); case 0x2584: return new PostTableEntry("dnblock"); case 0x2588: return new PostTableEntry("block"); case 0x258c: return new PostTableEntry("lfblock"); case 0x2590: return new PostTableEntry("rtblock"); case 0x2591: return new PostTableEntry("ltshade"); case 0x2592: return new PostTableEntry("shade"); case 0x2593: return new PostTableEntry("dkshade"); case 0x25a0: return new PostTableEntry("filledbox"); case 0x25a1: return new PostTableEntry("H22073"); case 0x25aa: return new PostTableEntry("H18543"); case 0x25ab: return new PostTableEntry("H18551"); case 0x25ac: return new PostTableEntry("filledrect"); case 0x25b2: return new PostTableEntry("triagup"); case 0x25ba: return new PostTableEntry("triagrt"); case 0x25bc: return new PostTableEntry("triagdn"); case 0x25c4: return new PostTableEntry("triaglf"); case 0x25ca: return new PostTableEntry(185); case 0x25cb: return new PostTableEntry("circle"); case 0x25cf: return new PostTableEntry("H18533"); case 0x25d8: return new PostTableEntry("invbullet"); case 0x25d9: return new PostTableEntry("invcircle"); case 0x25e6: return new PostTableEntry("openbullet"); case 0x263a: return new PostTableEntry("smileface"); case 0x263b: return new PostTableEntry("invsmileface"); case 0x263c: return new PostTableEntry("sun"); case 0x2640: return new PostTableEntry("female"); case 0x2642: return new PostTableEntry("male"); case 0x2660: return new PostTableEntry("spade"); case 0x2663: return new PostTableEntry("club"); case 0x2665: return new PostTableEntry("heart"); case 0x2666: return new PostTableEntry("diamond"); case 0x266a: return new PostTableEntry("musicalnote"); case 0x266b: return new PostTableEntry("musicalnotedbl"); case 0xfb01: return new PostTableEntry(192); case 0xfb02: return new PostTableEntry(193); default: String s = Integer.toHexString(ch).toUpperCase(); while (s.length() < 4) s = "0" + s; s = ((ch < 0x10000) ? "uni" : "u") + s; return new PostTableEntry(s); } } public static PostTableEntry forCharacterName(String name) { if (name == null) return new PostTableEntry(0); else if (name.equals(".notdef")) return new PostTableEntry(0); else if (name.equals(".null")) return new PostTableEntry(1); else if (name.equals("nonmarkingreturn")) return new PostTableEntry(2); else if (name.equals("space")) return new PostTableEntry(3); else if (name.equals("exclam")) return new PostTableEntry(4); else if (name.equals("quotedbl")) return new PostTableEntry(5); else if (name.equals("numbersign")) return new PostTableEntry(6); else if (name.equals("dollar")) return new PostTableEntry(7); else if (name.equals("percent")) return new PostTableEntry(8); else if (name.equals("ampersand")) return new PostTableEntry(9); else if (name.equals("quotesingle")) return new PostTableEntry(10); else if (name.equals("parenleft")) return new PostTableEntry(11); else if (name.equals("parenright")) return new PostTableEntry(12); else if (name.equals("asterisk")) return new PostTableEntry(13); else if (name.equals("plus")) return new PostTableEntry(14); else if (name.equals("comma")) return new PostTableEntry(15); else if (name.equals("hyphen")) return new PostTableEntry(16); else if (name.equals("period")) return new PostTableEntry(17); else if (name.equals("slash")) return new PostTableEntry(18); else if (name.equals("zero")) return new PostTableEntry(19); else if (name.equals("one")) return new PostTableEntry(20); else if (name.equals("two")) return new PostTableEntry(21); else if (name.equals("three")) return new PostTableEntry(22); else if (name.equals("four")) return new PostTableEntry(23); else if (name.equals("five")) return new PostTableEntry(24); else if (name.equals("six")) return new PostTableEntry(25); else if (name.equals("seven")) return new PostTableEntry(26); else if (name.equals("eight")) return new PostTableEntry(27); else if (name.equals("nine")) return new PostTableEntry(28); else if (name.equals("colon")) return new PostTableEntry(29); else if (name.equals("semicolon")) return new PostTableEntry(30); else if (name.equals("less")) return new PostTableEntry(31); else if (name.equals("equal")) return new PostTableEntry(32); else if (name.equals("greater")) return new PostTableEntry(33); else if (name.equals("question")) return new PostTableEntry(34); else if (name.equals("at")) return new PostTableEntry(35); else if (name.equals("A")) return new PostTableEntry(36); else if (name.equals("B")) return new PostTableEntry(37); else if (name.equals("C")) return new PostTableEntry(38); else if (name.equals("D")) return new PostTableEntry(39); else if (name.equals("E")) return new PostTableEntry(40); else if (name.equals("F")) return new PostTableEntry(41); else if (name.equals("G")) return new PostTableEntry(42); else if (name.equals("H")) return new PostTableEntry(43); else if (name.equals("I")) return new PostTableEntry(44); else if (name.equals("J")) return new PostTableEntry(45); else if (name.equals("K")) return new PostTableEntry(46); else if (name.equals("L")) return new PostTableEntry(47); else if (name.equals("M")) return new PostTableEntry(48); else if (name.equals("N")) return new PostTableEntry(49); else if (name.equals("O")) return new PostTableEntry(50); else if (name.equals("P")) return new PostTableEntry(51); else if (name.equals("Q")) return new PostTableEntry(52); else if (name.equals("R")) return new PostTableEntry(53); else if (name.equals("S")) return new PostTableEntry(54); else if (name.equals("T")) return new PostTableEntry(55); else if (name.equals("U")) return new PostTableEntry(56); else if (name.equals("V")) return new PostTableEntry(57); else if (name.equals("W")) return new PostTableEntry(58); else if (name.equals("X")) return new PostTableEntry(59); else if (name.equals("Y")) return new PostTableEntry(60); else if (name.equals("Z")) return new PostTableEntry(61); else if (name.equals("bracketleft")) return new PostTableEntry(62); else if (name.equals("backslash")) return new PostTableEntry(63); else if (name.equals("bracketright")) return new PostTableEntry(64); else if (name.equals("asciicircum")) return new PostTableEntry(65); else if (name.equals("underscore")) return new PostTableEntry(66); else if (name.equals("grave")) return new PostTableEntry(67); else if (name.equals("a")) return new PostTableEntry(68); else if (name.equals("b")) return new PostTableEntry(69); else if (name.equals("c")) return new PostTableEntry(70); else if (name.equals("d")) return new PostTableEntry(71); else if (name.equals("e")) return new PostTableEntry(72); else if (name.equals("f")) return new PostTableEntry(73); else if (name.equals("g")) return new PostTableEntry(74); else if (name.equals("h")) return new PostTableEntry(75); else if (name.equals("i")) return new PostTableEntry(76); else if (name.equals("j")) return new PostTableEntry(77); else if (name.equals("k")) return new PostTableEntry(78); else if (name.equals("l")) return new PostTableEntry(79); else if (name.equals("m")) return new PostTableEntry(80); else if (name.equals("n")) return new PostTableEntry(81); else if (name.equals("o")) return new PostTableEntry(82); else if (name.equals("p")) return new PostTableEntry(83); else if (name.equals("q")) return new PostTableEntry(84); else if (name.equals("r")) return new PostTableEntry(85); else if (name.equals("s")) return new PostTableEntry(86); else if (name.equals("t")) return new PostTableEntry(87); else if (name.equals("u")) return new PostTableEntry(88); else if (name.equals("v")) return new PostTableEntry(89); else if (name.equals("w")) return new PostTableEntry(90); else if (name.equals("x")) return new PostTableEntry(91); else if (name.equals("y")) return new PostTableEntry(92); else if (name.equals("z")) return new PostTableEntry(93); else if (name.equals("braceleft")) return new PostTableEntry(94); else if (name.equals("bar")) return new PostTableEntry(95); else if (name.equals("braceright")) return new PostTableEntry(96); else if (name.equals("asciitilde")) return new PostTableEntry(97); else if (name.equals("Adieresis")) return new PostTableEntry(98); else if (name.equals("Aring")) return new PostTableEntry(99); else if (name.equals("Ccedilla")) return new PostTableEntry(100); else if (name.equals("Eacute")) return new PostTableEntry(101); else if (name.equals("Ntilde")) return new PostTableEntry(102); else if (name.equals("Odieresis")) return new PostTableEntry(103); else if (name.equals("Udieresis")) return new PostTableEntry(104); else if (name.equals("aacute")) return new PostTableEntry(105); else if (name.equals("agrave")) return new PostTableEntry(106); else if (name.equals("acircumflex")) return new PostTableEntry(107); else if (name.equals("adieresis")) return new PostTableEntry(108); else if (name.equals("atilde")) return new PostTableEntry(109); else if (name.equals("aring")) return new PostTableEntry(110); else if (name.equals("ccedilla")) return new PostTableEntry(111); else if (name.equals("eacute")) return new PostTableEntry(112); else if (name.equals("egrave")) return new PostTableEntry(113); else if (name.equals("ecircumflex")) return new PostTableEntry(114); else if (name.equals("edieresis")) return new PostTableEntry(115); else if (name.equals("iacute")) return new PostTableEntry(116); else if (name.equals("igrave")) return new PostTableEntry(117); else if (name.equals("icircumflex")) return new PostTableEntry(118); else if (name.equals("idieresis")) return new PostTableEntry(119); else if (name.equals("ntilde")) return new PostTableEntry(120); else if (name.equals("oacute")) return new PostTableEntry(121); else if (name.equals("ograve")) return new PostTableEntry(122); else if (name.equals("ocircumflex")) return new PostTableEntry(123); else if (name.equals("odieresis")) return new PostTableEntry(124); else if (name.equals("otilde")) return new PostTableEntry(125); else if (name.equals("uacute")) return new PostTableEntry(126); else if (name.equals("ugrave")) return new PostTableEntry(127); else if (name.equals("ucircumflex")) return new PostTableEntry(128); else if (name.equals("udieresis")) return new PostTableEntry(129); else if (name.equals("dagger")) return new PostTableEntry(130); else if (name.equals("degree")) return new PostTableEntry(131); else if (name.equals("cent")) return new PostTableEntry(132); else if (name.equals("sterling")) return new PostTableEntry(133); else if (name.equals("section")) return new PostTableEntry(134); else if (name.equals("bullet")) return new PostTableEntry(135); else if (name.equals("paragraph")) return new PostTableEntry(136); else if (name.equals("germandbls")) return new PostTableEntry(137); else if (name.equals("registered")) return new PostTableEntry(138); else if (name.equals("copyright")) return new PostTableEntry(139); else if (name.equals("trademark")) return new PostTableEntry(140); else if (name.equals("acute")) return new PostTableEntry(141); else if (name.equals("dieresis")) return new PostTableEntry(142); else if (name.equals("notequal")) return new PostTableEntry(143); else if (name.equals("AE")) return new PostTableEntry(144); else if (name.equals("Oslash")) return new PostTableEntry(145); else if (name.equals("infinity")) return new PostTableEntry(146); else if (name.equals("plusminus")) return new PostTableEntry(147); else if (name.equals("lessequal")) return new PostTableEntry(148); else if (name.equals("greaterequal")) return new PostTableEntry(149); else if (name.equals("yen")) return new PostTableEntry(150); else if (name.equals("mu")) return new PostTableEntry(151); else if (name.equals("partialdiff")) return new PostTableEntry(152); else if (name.equals("summation")) return new PostTableEntry(153); else if (name.equals("product")) return new PostTableEntry(154); else if (name.equals("pi")) return new PostTableEntry(155); else if (name.equals("integral")) return new PostTableEntry(156); else if (name.equals("ordfeminine")) return new PostTableEntry(157); else if (name.equals("ordmasculine")) return new PostTableEntry(158); else if (name.equals("Omega")) return new PostTableEntry(159); else if (name.equals("ae")) return new PostTableEntry(160); else if (name.equals("oslash")) return new PostTableEntry(161); else if (name.equals("questiondown")) return new PostTableEntry(162); else if (name.equals("exclamdown")) return new PostTableEntry(163); else if (name.equals("logicalnot")) return new PostTableEntry(164); else if (name.equals("radical")) return new PostTableEntry(165); else if (name.equals("florin")) return new PostTableEntry(166); else if (name.equals("approxequal")) return new PostTableEntry(167); else if (name.equals("Delta")) return new PostTableEntry(168); else if (name.equals("guillemotleft")) return new PostTableEntry(169); else if (name.equals("guillemotright")) return new PostTableEntry(170); else if (name.equals("ellipsis")) return new PostTableEntry(171); else if (name.equals("nonbreakingspace")) return new PostTableEntry(172); else if (name.equals("Agrave")) return new PostTableEntry(173); else if (name.equals("Atilde")) return new PostTableEntry(174); else if (name.equals("Otilde")) return new PostTableEntry(175); else if (name.equals("OE")) return new PostTableEntry(176); else if (name.equals("oe")) return new PostTableEntry(177); else if (name.equals("endash")) return new PostTableEntry(178); else if (name.equals("emdash")) return new PostTableEntry(179); else if (name.equals("quotedblleft")) return new PostTableEntry(180); else if (name.equals("quotedblright")) return new PostTableEntry(181); else if (name.equals("quoteleft")) return new PostTableEntry(182); else if (name.equals("quoteright")) return new PostTableEntry(183); else if (name.equals("divide")) return new PostTableEntry(184); else if (name.equals("lozenge")) return new PostTableEntry(185); else if (name.equals("ydieresis")) return new PostTableEntry(186); else if (name.equals("Ydieresis")) return new PostTableEntry(187); else if (name.equals("fraction")) return new PostTableEntry(188); else if (name.equals("currency")) return new PostTableEntry(189); else if (name.equals("guilsinglleft")) return new PostTableEntry(190); else if (name.equals("guilsinglright")) return new PostTableEntry(191); else if (name.equals("fi")) return new PostTableEntry(192); else if (name.equals("fl")) return new PostTableEntry(193); else if (name.equals("daggerdbl")) return new PostTableEntry(194); else if (name.equals("periodcentered")) return new PostTableEntry(195); else if (name.equals("quotesinglbase")) return new PostTableEntry(196); else if (name.equals("quotedblbase")) return new PostTableEntry(197); else if (name.equals("perthousand")) return new PostTableEntry(198); else if (name.equals("Acircumflex")) return new PostTableEntry(199); else if (name.equals("Ecircumflex")) return new PostTableEntry(200); else if (name.equals("Aacute")) return new PostTableEntry(201); else if (name.equals("Edieresis")) return new PostTableEntry(202); else if (name.equals("Egrave")) return new PostTableEntry(203); else if (name.equals("Iacute")) return new PostTableEntry(204); else if (name.equals("Icircumflex")) return new PostTableEntry(205); else if (name.equals("Idieresis")) return new PostTableEntry(206); else if (name.equals("Igrave")) return new PostTableEntry(207); else if (name.equals("Oacute")) return new PostTableEntry(208); else if (name.equals("Ocircumflex")) return new PostTableEntry(209); else if (name.equals("apple")) return new PostTableEntry(210); else if (name.equals("Ograve")) return new PostTableEntry(211); else if (name.equals("Uacute")) return new PostTableEntry(212); else if (name.equals("Ucircumflex")) return new PostTableEntry(213); else if (name.equals("Ugrave")) return new PostTableEntry(214); else if (name.equals("dotlessi")) return new PostTableEntry(215); else if (name.equals("circumflex")) return new PostTableEntry(216); else if (name.equals("tilde")) return new PostTableEntry(217); else if (name.equals("macron")) return new PostTableEntry(218); else if (name.equals("breve")) return new PostTableEntry(219); else if (name.equals("dotaccent")) return new PostTableEntry(220); else if (name.equals("ring")) return new PostTableEntry(221); else if (name.equals("cedilla")) return new PostTableEntry(222); else if (name.equals("hungarumlaut")) return new PostTableEntry(223); else if (name.equals("ogonek")) return new PostTableEntry(224); else if (name.equals("caron")) return new PostTableEntry(225); else if (name.equals("Lslash")) return new PostTableEntry(226); else if (name.equals("lslash")) return new PostTableEntry(227); else if (name.equals("Scaron")) return new PostTableEntry(228); else if (name.equals("scaron")) return new PostTableEntry(229); else if (name.equals("Zcaron")) return new PostTableEntry(230); else if (name.equals("zcaron")) return new PostTableEntry(231); else if (name.equals("brokenbar")) return new PostTableEntry(232); else if (name.equals("Eth")) return new PostTableEntry(233); else if (name.equals("eth")) return new PostTableEntry(234); else if (name.equals("Yacute")) return new PostTableEntry(235); else if (name.equals("yacute")) return new PostTableEntry(236); else if (name.equals("Thorn")) return new PostTableEntry(237); else if (name.equals("thorn")) return new PostTableEntry(238); else if (name.equals("minus")) return new PostTableEntry(239); else if (name.equals("multiply")) return new PostTableEntry(240); else if (name.equals("onesuperior")) return new PostTableEntry(241); else if (name.equals("twosuperior")) return new PostTableEntry(242); else if (name.equals("threesuperior")) return new PostTableEntry(243); else if (name.equals("onehalf")) return new PostTableEntry(244); else if (name.equals("onequarter")) return new PostTableEntry(245); else if (name.equals("threequarters")) return new PostTableEntry(246); else if (name.equals("franc")) return new PostTableEntry(247); else if (name.equals("Gbreve")) return new PostTableEntry(248); else if (name.equals("gbreve")) return new PostTableEntry(249); else if (name.equals("Idotaccent")) return new PostTableEntry(250); else if (name.equals("Scedilla")) return new PostTableEntry(251); else if (name.equals("scedilla")) return new PostTableEntry(252); else if (name.equals("Cacute")) return new PostTableEntry(253); else if (name.equals("cacute")) return new PostTableEntry(254); else if (name.equals("Ccaron")) return new PostTableEntry(255); else if (name.equals("ccaron")) return new PostTableEntry(256); else if (name.equals("dcroat")) return new PostTableEntry(257); else return new PostTableEntry(name); } public boolean isInteger() { return intValue != null; } public boolean isString() { return stringValue != null; } public int intValue() { if (intValue != null) { return intValue; } else { return 0; } } public String stringValue() { if (stringValue != null) { return stringValue; } else { return ""; } } @Override public String toString() { if (intValue != null) { return intValue.toString(); } else if (stringValue != null) { return stringValue; } else { return ""; } } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof PostTableEntry) { PostTableEntry other = (PostTableEntry)o; boolean intEq = (this.intValue == null) ? (other.intValue == null) : this.intValue.equals(other.intValue); boolean strEq = (this.stringValue == null) ? (other.stringValue == null) : this.stringValue.equals(other.stringValue); return intEq && strEq; } else { return false; } } @Override public int hashCode() { if (intValue != null) { return intValue.hashCode(); } else if (stringValue != null) { return stringValue.hashCode(); } else { return 0; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PuaaSubtable.java000066400000000000000000000015621506470510200325360ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.util.ArrayList; import java.util.BitSet; public class PuaaSubtable extends ArrayList { private static final long serialVersionUID = 1L; public String property = null; public String getPropertyValue(int cp) { boolean found = false; StringBuffer sb = new StringBuffer(); for (PuaaSubtableEntry e : this) { if (e.contains(cp)) { String value = e.getPropertyValue(cp); if (value != null) { found = true; sb.append(value); } } } return found ? sb.toString() : null; } public boolean isSortable() { BitSet codePoints = new BitSet(); for (PuaaSubtableEntry e : this) { if (codePoints.get(e.firstCodePoint, e.lastCodePoint + 1).isEmpty()) { codePoints.set(e.firstCodePoint, e.lastCodePoint + 1); } else { return false; } } return true; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PuaaSubtableEntry.java000066400000000000000000000064761506470510200335710ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public abstract class PuaaSubtableEntry { public static final int SINGLE = 1; public static final int MULTIPLE = 2; public static final int BOOLEAN = 3; public static final int DECIMAL = 4; public static final int HEXADECIMAL = 5; public static final int HEXMULTIPLE = 6; public static final int HEXSEQUENCE = 7; public static final int CASEMAPPING = 8; public static final int NAMEALIAS = 9; public int firstCodePoint = 0; public int lastCodePoint = 0; public boolean contains(int cp) { return (cp >= firstCodePoint && cp <= lastCodePoint); } public abstract String getPropertyValue(int cp); public static class Single extends PuaaSubtableEntry { public String value = null; @Override public String getPropertyValue(int cp) { return value; } } public static class Multiple extends PuaaSubtableEntry { public String[] values = new String[0]; @Override public String getPropertyValue(int cp) { if (values == null) return null; return values[cp - firstCodePoint]; } } public static class Boolean extends PuaaSubtableEntry { public boolean value = false; @Override public String getPropertyValue(int cp) { return value ? "Y" : "N"; } } public static class Decimal extends PuaaSubtableEntry { public int value = 0; @Override public String getPropertyValue(int cp) { return Integer.toString(value); } } public static class Hexadecimal extends PuaaSubtableEntry { public int value = 0; @Override public String getPropertyValue(int cp) { String s = Integer.toHexString(value).toUpperCase(); while (s.length() < 4) s = "0" + s; return s; } } public static class HexMultiple extends PuaaSubtableEntry { public int[] values = new int[0]; @Override public String getPropertyValue(int cp) { if (values == null) return null; int value = values[cp - firstCodePoint]; String s = Integer.toHexString(value).toUpperCase(); while (s.length() < 4) s = "0" + s; return s; } } public static class HexSequence extends PuaaSubtableEntry { public int[] values = new int[0]; @Override public String getPropertyValue(int cp) { if (values == null) return null; StringBuffer sb = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) sb.append(" "); String s = Integer.toHexString(values[i]).toUpperCase(); while (s.length() < 4) s = "0" + s; sb.append(s); } return sb.toString(); } } public static class CaseMapping extends PuaaSubtableEntry { public int[] values = new int[0]; public String condition = null; @Override public String getPropertyValue(int cp) { if (values == null) return null; StringBuffer sb = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) sb.append(" "); String s = Integer.toHexString(values[i]).toUpperCase(); while (s.length() < 4) s = "0" + s; sb.append(s); } if (condition != null && condition.length() > 0) { sb.append("; "); sb.append(condition); } return sb.toString(); } } public static class NameAlias extends PuaaSubtableEntry { public String alias = null; public String type = null; @Override public String getPropertyValue(int cp) { if (alias == null || type == null) return null; return alias + ";" + type; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/PuaaTable.java000066400000000000000000000350071506470510200320250ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class PuaaTable extends ListBasedTable { public static final int DEFAULT_VERSION = 1; public int version = DEFAULT_VERSION; @Override public String tableName() { return "PUAA"; } @Override public String[] dependencyNames() { return new String[]{}; } public PuaaSubtable getOrCreateSubtable(String property) { if (property == null) return null; for (PuaaSubtable subtable : this) { if (property.equals(subtable.property)) { return subtable; } } PuaaSubtable subtable = new PuaaSubtable(); subtable.property = property; this.add(subtable); return subtable; } public PuaaSubtable getSubtable(String property) { if (property == null) return null; for (PuaaSubtable subtable : this) { if (property.equals(subtable.property)) { return subtable; } } return null; } public String getPropertyValue(String property, int cp) { if (property == null) return null; for (PuaaSubtable subtable : this) { if (property.equals(subtable.property)) { return subtable.getPropertyValue(cp); } } return null; } public void removeEmptySubtables() { Iterator iter = this.iterator(); while (iter.hasNext()) { PuaaSubtable subtable = iter.next(); if (subtable == null || subtable.isEmpty()) { iter.remove(); } } } public void sortSubtables() { Collections.sort(this, BY_PROPERTY); for (PuaaSubtable subtable : this) { if (subtable.isSortable()) { Collections.sort(subtable, BY_CODE_POINT); } } } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { removeEmptySubtables(); sortSubtables(); // Calculate table header values. int propertyCount = this.size(); int[] propertyNameOffset = new int[propertyCount]; int[] subtableHeaderOffset = new int[propertyCount]; int[] entryCount = new int[propertyCount]; int[][] entryType = new int[propertyCount][]; int[][] entryData = new int[propertyCount][]; int[][] valueCount = new int[propertyCount][]; int[][][] valueData = new int[propertyCount][][]; Map stringTable = new HashMap(); List stringData = new ArrayList(); int p = 4 + propertyCount * 8; // Calculate subtable header values. for (int i = 0; i < propertyCount; i++) { subtableHeaderOffset[i] = p; entryCount[i] = this.get(i).size(); entryType[i] = new int[entryCount[i]]; entryData[i] = new int[entryCount[i]]; valueCount[i] = new int[entryCount[i]]; valueData[i] = new int[entryCount[i]][]; p += 2 + entryCount[i] * 10; } // Calculate entry header values. for (int i = 0; i < propertyCount; i++) { for (int j = 0; j < entryCount[i]; j++) { PuaaSubtableEntry e = this.get(i).get(j); if (e instanceof PuaaSubtableEntry.Single) { entryType[i][j] = PuaaSubtableEntry.SINGLE; } if (e instanceof PuaaSubtableEntry.Multiple) { entryType[i][j] = PuaaSubtableEntry.MULTIPLE; entryData[i][j] = p; valueCount[i][j] = ((PuaaSubtableEntry.Multiple)e).values.length; valueData[i][j] = new int[valueCount[i][j]]; p += 2 + valueCount[i][j] * 4; } if (e instanceof PuaaSubtableEntry.Boolean) { entryType[i][j] = PuaaSubtableEntry.BOOLEAN; entryData[i][j] = ((PuaaSubtableEntry.Boolean)e).value ? -1 : 0; } if (e instanceof PuaaSubtableEntry.Decimal) { entryType[i][j] = PuaaSubtableEntry.DECIMAL; entryData[i][j] = ((PuaaSubtableEntry.Decimal)e).value; } if (e instanceof PuaaSubtableEntry.Hexadecimal) { entryType[i][j] = PuaaSubtableEntry.HEXADECIMAL; entryData[i][j] = ((PuaaSubtableEntry.Hexadecimal)e).value; } if (e instanceof PuaaSubtableEntry.HexMultiple) { entryType[i][j] = PuaaSubtableEntry.HEXMULTIPLE; entryData[i][j] = p; valueCount[i][j] = ((PuaaSubtableEntry.HexMultiple)e).values.length; valueData[i][j] = ((PuaaSubtableEntry.HexMultiple)e).values; p += 2 + valueCount[i][j] * 4; } if (e instanceof PuaaSubtableEntry.HexSequence) { entryType[i][j] = PuaaSubtableEntry.HEXSEQUENCE; entryData[i][j] = p; valueCount[i][j] = ((PuaaSubtableEntry.HexSequence)e).values.length; valueData[i][j] = ((PuaaSubtableEntry.HexSequence)e).values; p += 2 + valueCount[i][j] * 4; } if (e instanceof PuaaSubtableEntry.CaseMapping) { entryType[i][j] = PuaaSubtableEntry.CASEMAPPING; entryData[i][j] = p; valueCount[i][j] = ((PuaaSubtableEntry.CaseMapping)e).values.length + 1; valueData[i][j] = new int[valueCount[i][j]]; p += 2 + valueCount[i][j] * 4; } if (e instanceof PuaaSubtableEntry.NameAlias) { entryType[i][j] = PuaaSubtableEntry.NAMEALIAS; entryData[i][j] = p; valueCount[i][j] = 2; valueData[i][j] = new int[2]; p += 10; } } } // Calculate property name offsets. for (int i = 0; i < propertyCount; i++) { String s = this.get(i).property; p = setString(propertyNameOffset, i, s, stringTable, stringData, p, true); } // Calculate string data offsets. for (int i = 0; i < propertyCount; i++) { for (int j = 0; j < entryCount[i]; j++) { PuaaSubtableEntry e = this.get(i).get(j); if (e instanceof PuaaSubtableEntry.Single) { String s = ((PuaaSubtableEntry.Single)e).value; p = setString(entryData[i], j, s, stringTable, stringData, p, false); } if (e instanceof PuaaSubtableEntry.Multiple) { for (int k = 0; k < valueCount[i][j]; k++) { String s = ((PuaaSubtableEntry.Multiple)e).values[k]; p = setString(valueData[i][j], k, s, stringTable, stringData, p, false); } } if (e instanceof PuaaSubtableEntry.CaseMapping) { int[] values = ((PuaaSubtableEntry.CaseMapping)e).values; for (int k = 0; k < values.length; k++) valueData[i][j][k] = values[k]; String s = ((PuaaSubtableEntry.CaseMapping)e).condition; p = setString(valueData[i][j], values.length, s, stringTable, stringData, p, false); } if (e instanceof PuaaSubtableEntry.NameAlias) { String s1 = ((PuaaSubtableEntry.NameAlias)e).alias; p = setString(valueData[i][j], 0, s1, stringTable, stringData, p, false); String s2 = ((PuaaSubtableEntry.NameAlias)e).type; p = setString(valueData[i][j], 1, s2, stringTable, stringData, p, false); } } } // Write table header. out.writeShort(version); out.writeShort(propertyCount); for (int i = 0; i < propertyCount; i++) { out.writeInt(propertyNameOffset[i]); out.writeInt(subtableHeaderOffset[i]); } // Write subtable headers. for (int i = 0; i < propertyCount; i++) { out.writeShort(entryCount[i]); for (int j = 0; j < entryCount[i]; j++) { PuaaSubtableEntry e = this.get(i).get(j); out.writeByte(entryType[i][j]); out.writeByte(e.firstCodePoint >> 16); out.writeShort(e.firstCodePoint); out.writeShort(e.lastCodePoint); out.writeInt(entryData[i][j]); } } // Write entry data. for (int i = 0; i < propertyCount; i++) { for (int j = 0; j < entryCount[i]; j++) { if (valueData[i][j] != null) { out.writeShort(valueCount[i][j]); for (int k = 0; k < valueCount[i][j]; k++) { out.writeInt(valueData[i][j][k]); } } } } // Write string data. for (byte[] d : stringData) { out.writeByte(d.length); out.write(d); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { // Read table header. version = in.readUnsignedShort(); int propertyCount = in.readUnsignedShort(); int[] propertyNameOffset = new int[propertyCount]; int[] subtableHeaderOffset = new int[propertyCount]; for (int i = 0; i < propertyCount; i++) { propertyNameOffset[i] = in.readInt(); subtableHeaderOffset[i] = in.readInt(); } // Read subtables. for (int i = 0; i < propertyCount; i++) { // Read property name. PuaaSubtable subtable = new PuaaSubtable(); subtable.property = readString(in, propertyNameOffset[i]); // Read subtable header. in.reset(); in.skipBytes(subtableHeaderOffset[i]); int entryCount = in.readUnsignedShort(); int[] entryType = new int[entryCount]; int[] firstCodePoint = new int[entryCount]; int[] lastCodePoint = new int[entryCount]; int[] entryData = new int[entryCount]; for (int j = 0; j < entryCount; j++) { entryType[j] = in.readUnsignedByte(); int plane = in.readUnsignedByte() << 16; firstCodePoint[j] = in.readUnsignedShort() | plane; lastCodePoint[j] = in.readUnsignedShort() | plane; entryData[j] = in.readInt(); } // Read entries. for (int j = 0; j < entryCount; j++) { switch (entryType[j]) { case PuaaSubtableEntry.SINGLE: PuaaSubtableEntry.Single se = new PuaaSubtableEntry.Single(); se.firstCodePoint = firstCodePoint[j]; se.lastCodePoint = lastCodePoint[j]; se.value = readString(in, entryData[j]); subtable.add(se); break; case PuaaSubtableEntry.MULTIPLE: PuaaSubtableEntry.Multiple me = new PuaaSubtableEntry.Multiple(); me.firstCodePoint = firstCodePoint[j]; me.lastCodePoint = lastCodePoint[j]; int[] mv = readIntArray(in, entryData[j]); if (mv != null) { me.values = new String[mv.length]; for (int k = 0; k < mv.length; k++) { me.values[k] = readString(in, mv[k]); } } subtable.add(me); break; case PuaaSubtableEntry.BOOLEAN: PuaaSubtableEntry.Boolean be = new PuaaSubtableEntry.Boolean(); be.firstCodePoint = firstCodePoint[j]; be.lastCodePoint = lastCodePoint[j]; be.value = entryData[j] != 0; subtable.add(be); break; case PuaaSubtableEntry.DECIMAL: PuaaSubtableEntry.Decimal de = new PuaaSubtableEntry.Decimal(); de.firstCodePoint = firstCodePoint[j]; de.lastCodePoint = lastCodePoint[j]; de.value = entryData[j]; subtable.add(de); break; case PuaaSubtableEntry.HEXADECIMAL: PuaaSubtableEntry.Hexadecimal he = new PuaaSubtableEntry.Hexadecimal(); he.firstCodePoint = firstCodePoint[j]; he.lastCodePoint = lastCodePoint[j]; he.value = entryData[j]; subtable.add(he); break; case PuaaSubtableEntry.HEXMULTIPLE: PuaaSubtableEntry.HexMultiple xe = new PuaaSubtableEntry.HexMultiple(); xe.firstCodePoint = firstCodePoint[j]; xe.lastCodePoint = lastCodePoint[j]; xe.values = readIntArray(in, entryData[j]); subtable.add(xe); break; case PuaaSubtableEntry.HEXSEQUENCE: PuaaSubtableEntry.HexSequence qe = new PuaaSubtableEntry.HexSequence(); qe.firstCodePoint = firstCodePoint[j]; qe.lastCodePoint = lastCodePoint[j]; qe.values = readIntArray(in, entryData[j]); subtable.add(qe); break; case PuaaSubtableEntry.CASEMAPPING: PuaaSubtableEntry.CaseMapping ce = new PuaaSubtableEntry.CaseMapping(); ce.firstCodePoint = firstCodePoint[j]; ce.lastCodePoint = lastCodePoint[j]; int[] cv = readIntArray(in, entryData[j]); if (cv != null && cv.length > 0) { int n = cv.length - 1; ce.values = new int[n]; for (int k = 0; k < n; k++) ce.values[k] = cv[k]; ce.condition = readString(in, cv[n]); } subtable.add(ce); break; case PuaaSubtableEntry.NAMEALIAS: PuaaSubtableEntry.NameAlias ne = new PuaaSubtableEntry.NameAlias(); ne.firstCodePoint = firstCodePoint[j]; ne.lastCodePoint = lastCodePoint[j]; int[] nv = readIntArray(in, entryData[j]); if (nv != null && nv.length > 1) { ne.alias = readString(in, nv[0]); ne.type = readString(in, nv[1]); } subtable.add(ne); break; default: throw new IOException("Invalid entryType: " + entryType[j]); } } this.add(subtable); } } private static final int minify(byte[] d) { int value = Integer.MIN_VALUE; if (d.length > 4) return 0; if (d.length > 3) { if (d[3] < 0) return 0; value |= (d[3] & 0x7F) << 0; } if (d.length > 2) { if (d[2] < 0) return 0; value |= (d[2] & 0x7F) << 8; } if (d.length > 1) { if (d[1] < 0) return 0; value |= (d[1] & 0x7F) << 16; } if (d.length > 0) { if (d[0] < 0) return 0; value |= (d[0] & 0x7F) << 24; } return value; } private static final int setString( int[] array, int index, String s, Map stringTable, List stringData, int p, boolean forceFull ) throws IOException { if (s == null) { array[index] = 0; } else if (stringTable.containsKey(s)) { array[index] = stringTable.get(s); } else { byte[] d = s.getBytes("UTF-8"); if (forceFull || (array[index] = minify(d)) == 0) { array[index] = p; stringTable.put(s, p); stringData.add(d); p += d.length + 1; } } return p; } private static final String readString(DataInputStream in, int offset) throws IOException { if (offset > 0) { in.reset(); in.skipBytes(offset); byte[] d = new byte[in.readUnsignedByte()]; in.readFully(d); return new String(d, "UTF-8"); } if (offset < 0) { StringBuffer sb = new StringBuffer(); char ch0 = (char)((offset >> 24) & 0x7F); if (ch0 != 0) sb.append(ch0); char ch1 = (char)((offset >> 16) & 0x7F); if (ch1 != 0) sb.append(ch1); char ch2 = (char)((offset >> 8) & 0x7F); if (ch2 != 0) sb.append(ch2); char ch3 = (char)((offset >> 0) & 0x7F); if (ch3 != 0) sb.append(ch3); return sb.toString(); } return null; } private static final int[] readIntArray(DataInputStream in, int offset) throws IOException { if (offset > 0) { in.reset(); in.skipBytes(offset); int[] a = new int[in.readUnsignedShort()]; for (int i = 0; i < a.length; i++) a[i] = in.readInt(); return a; } return null; } private static final Comparator BY_PROPERTY = new Comparator() { @Override public int compare(PuaaSubtable a, PuaaSubtable b) { String ap = a.property; if (ap == null) ap = ""; String bp = b.property; if (bp == null) bp = ""; return ap.compareTo(bp); } }; private static final Comparator BY_CODE_POINT = new Comparator() { @Override public int compare(PuaaSubtableEntry a, PuaaSubtableEntry b) { if (a.firstCodePoint != b.firstCodePoint) return a.firstCodePoint - b.firstCodePoint; if (a.lastCodePoint != b.lastCodePoint) return a.lastCodePoint - b.lastCodePoint; return 0; } }; } SbitBigGlyphMetrics.java000066400000000000000000000017621506470510200337670ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class SbitBigGlyphMetrics { public int height; public int width; public int horiBearingX; public int horiBearingY; public int horiAdvance; public int vertBearingX; public int vertBearingY; public int vertAdvance; protected void read(DataInputStream in) throws IOException { height = in.readUnsignedByte(); width = in.readUnsignedByte(); horiBearingX = in.readByte(); horiBearingY = in.readByte(); horiAdvance = in.readUnsignedByte(); vertBearingX = in.readByte(); vertBearingY = in.readByte(); vertAdvance = in.readUnsignedByte(); } protected void write(DataOutputStream out) throws IOException { out.writeByte(height); out.writeByte(width); out.writeByte(horiBearingX); out.writeByte(horiBearingY); out.writeByte(horiAdvance); out.writeByte(vertBearingX); out.writeByte(vertBearingY); out.writeByte(vertAdvance); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SbitLineMetrics.java000066400000000000000000000023651506470510200332300ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class SbitLineMetrics { public int ascender; public int descender; public int widthMax; public int caretSlopeNumerator; public int caretSlopeDenominator; public int caretOffset; public int minOriginSB; public int minAdvanceSB; public int maxBeforeBL; public int minAfterBL; public int pad; protected void read(DataInputStream in) throws IOException { ascender = in.readByte(); descender = in.readByte(); widthMax = in.readUnsignedByte(); caretSlopeNumerator = in.readByte(); caretSlopeDenominator = in.readByte(); caretOffset = in.readByte(); minOriginSB = in.readByte(); minAdvanceSB = in.readByte(); maxBeforeBL = in.readByte(); minAfterBL = in.readByte(); pad = in.readShort(); } protected void write(DataOutputStream out) throws IOException { out.writeByte(ascender); out.writeByte(descender); out.writeByte(widthMax); out.writeByte(caretSlopeNumerator); out.writeByte(caretSlopeDenominator); out.writeByte(caretOffset); out.writeByte(minOriginSB); out.writeByte(minAdvanceSB); out.writeByte(maxBeforeBL); out.writeByte(minAfterBL); out.writeShort(pad); } } SbitSmallGlyphMetrics.java000066400000000000000000000013001506470510200343220ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class SbitSmallGlyphMetrics { public int height; public int width; public int bearingX; public int bearingY; public int advance; protected void read(DataInputStream in) throws IOException { height = in.readUnsignedByte(); width = in.readUnsignedByte(); bearingX = in.readByte(); bearingY = in.readByte(); advance = in.readUnsignedByte(); } protected void write(DataOutputStream out) throws IOException { out.writeByte(height); out.writeByte(width); out.writeByte(bearingX); out.writeByte(bearingY); out.writeByte(advance); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SbitTableType.java000066400000000000000000000006551506470510200327030ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; public enum SbitTableType { TRUETYPE("bdat", "bloc", 0x00020000), OPENTYPE("EBDT", "EBLC", 0x00020000), COLOR("CBDT", "CBLC", 0x00030000); public final String dataTableName; public final String locTableName; public final int version; private SbitTableType(String dtn, String ltn, int vers) { this.dataTableName = dtn; this.locTableName = ltn; this.version = vers; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SbixEntry.java000077500000000000000000000046431506470510200321230ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class SbixEntry { public static final int IMAGE_TYPE_JPEG = 0x6A706720; public static final int IMAGE_TYPE_PDF = 0x70646620; public static final int IMAGE_TYPE_PNG = 0x706E6720; public static final int IMAGE_TYPE_TIFF = 0x74696666; public static final int IMAGE_TYPE_DUPE = 0x64757065; public static final int IMAGE_TYPE_MASK = 0x6D61736B; public int offsetX = 0; public int offsetY = 0; public int imageType = 0; public byte[] imageData = new byte[0]; public String getImageTypeString() { return new String(new char[]{ (char)((imageType >> 24) & 0xFF), (char)((imageType >> 16) & 0xFF), (char)((imageType >> 8) & 0xFF), (char)((imageType >> 0) & 0xFF), }); } public void setImageTypeString(String imageTypeString) { char[] a = imageTypeString.toCharArray(); imageType = (((a.length > 0 && a[0] >= 0x20 && a[0] < 0x7F) ? a[0] : 0x20) << 24) | (((a.length > 1 && a[1] >= 0x20 && a[1] < 0x7F) ? a[1] : 0x20) << 16) | (((a.length > 2 && a[2] >= 0x20 && a[2] < 0x7F) ? a[2] : 0x20) << 8) | (((a.length > 3 && a[3] >= 0x20 && a[3] < 0x7F) ? a[3] : 0x20) << 0); } private void compile(DataOutputStream out) throws IOException { if (imageData != null && imageData.length > 0) { out.writeShort(offsetX); out.writeShort(offsetY); out.writeInt(imageType); out.write(imageData); } } public byte[] compile() throws IOException { ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); compile(out); out.flush(); byteout.flush(); out.close(); byteout.close(); return byteout.toByteArray(); } private void decompile(DataInputStream in, int length) throws IOException { if (length == 0) { offsetX = 0; offsetY = 0; imageType = 0; imageData = new byte[0]; } else { offsetX = in.readShort(); offsetY = in.readShort(); imageType = in.readInt(); imageData = new byte[length - 8]; in.readFully(imageData); } } public void decompile(byte[] data) throws IOException { ByteArrayInputStream bytein = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bytein); decompile(in, data.length); in.close(); bytein.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SbixSubtable.java000077500000000000000000000041431506470510200325560ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class SbixSubtable extends ArrayList { private static final long serialVersionUID = 1L; public static final int DPI_DEFAULT = 72; public int ppem = 0; public int dpi = DPI_DEFAULT; private void compile(DataOutputStream out, int numGlyphs) throws IOException { out.writeShort(ppem); out.writeShort(dpi); List imageData = new ArrayList(); int currentLocation = 4 + (this.size() + 1) * 4; for (SbixEntry e : this) { out.writeInt(currentLocation); byte[] d = e.compile(); imageData.add(d); currentLocation += d.length; } out.writeInt(currentLocation); for (byte[] d : imageData) { out.write(d); } while ((currentLocation & 0x03) != 0) { out.writeByte(0); currentLocation++; } } public byte[] compile(int numGlyphs) throws IOException { ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); compile(out, numGlyphs); out.flush(); byteout.flush(); out.close(); byteout.close(); return byteout.toByteArray(); } private void decompile(DataInputStream in, int length, int numGlyphs) throws IOException { ppem = in.readUnsignedShort(); dpi = in.readUnsignedShort(); int[] imageOffset = new int[numGlyphs + 1]; for (int i = 0; i <= numGlyphs; i++) { imageOffset[i] = in.readInt(); } this.clear(); for (int i = 0; i < numGlyphs; i++) { in.reset(); in.skipBytes(imageOffset[i]); byte[] d = new byte[imageOffset[i+1] - imageOffset[i]]; in.readFully(d); SbixEntry e = new SbixEntry(); e.decompile(d); this.add(e); } } public void decompile(byte[] data, int numGlyphs) throws IOException { ByteArrayInputStream bytein = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bytein); decompile(in, data.length, numGlyphs); in.close(); bytein.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SbixTable.java000077500000000000000000000035701506470510200320470ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class SbixTable extends ListBasedTable { public static final int VERSION_DEFAULT = 1; public static final int FLAGS_DEFAULT = 0x0001; public static final int FLAGS_DRAW_OUTLINES = 0x0002; public int version = VERSION_DEFAULT; public int flags = FLAGS_DEFAULT; @Override public String tableName() { return "sbix"; } @Override public String[] dependencyNames() { return new String[]{"maxp"}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { int numGlyphs = ((MaxpTable)dependencies[0]).numGlyphs; out.writeShort(version); out.writeShort(flags); out.writeInt(this.size()); List subtableData = new ArrayList(); int currentLocation = 8 + this.size() * 4; for (SbixSubtable st : this) { out.writeInt(currentLocation); byte[] d = st.compile(numGlyphs); subtableData.add(d); currentLocation += d.length; } for (byte[] d : subtableData) { out.write(d); } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { int numGlyphs = ((MaxpTable)dependencies[0]).numGlyphs; version = in.readUnsignedShort(); flags = in.readUnsignedShort(); int numTables = in.readInt(); int[] tableOffset = new int[numTables + 1]; for (int i = 0; i < numTables; i++) { tableOffset[i] = in.readInt(); } tableOffset[numTables] = length; this.clear(); for (int i = 0; i < numTables; i++) { in.reset(); in.skipBytes(tableOffset[i]); byte[] d = new byte[tableOffset[i+1] - tableOffset[i]]; in.readFully(d); SbixSubtable e = new SbixSubtable(); e.decompile(d, numGlyphs); this.add(e); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SvgTable.java000066400000000000000000000050741506470510200316770ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class SvgTable extends ListBasedTable { @Override public String tableName() { return "SVG "; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.writeShort(0); out.writeInt(10); out.writeInt(0); out.writeShort(this.size()); Map documents = new HashMap(); int currentLocation = 2 + this.size() * 12; for (SvgTableEntry e : this) { out.writeShort(e.startGlyphID); out.writeShort(e.endGlyphID); if (documents.containsKey(e.svgDocument)) { out.writeInt(documents.get(e.svgDocument)); } else { out.writeInt(currentLocation); documents.put(e.svgDocument, currentLocation); currentLocation += e.svgDocument.length; } out.writeInt(e.svgDocument.length); } for (SvgTableEntry e : this) { if (documents.containsKey(e.svgDocument)) { out.write(e.svgDocument); documents.remove(e.svgDocument); } } } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { in.readUnsignedShort(); int offsetToIndex = in.readInt(); in.reset(); in.skipBytes(offsetToIndex); int numEntries = in.readUnsignedShort(); int[] entryStartGlyphID = new int[numEntries]; int[] entryEndGlyphID = new int[numEntries]; int[] entryOffset = new int[numEntries]; int[] entryLength = new int[numEntries]; long[] entryHash = new long[numEntries]; for (int i = 0; i < numEntries; i++) { entryStartGlyphID[i] = in.readUnsignedShort(); entryEndGlyphID[i] = in.readUnsignedShort(); entryOffset[i] = in.readInt(); entryLength[i] = in.readInt(); entryHash[i] = ((long)entryOffset[i] << 32L) | (long)entryLength[i]; } Map documents = new HashMap(); for (int i = 0; i < numEntries; i++) { if (!documents.containsKey(entryHash[i])) { byte[] document = new byte[entryLength[i]]; in.reset(); in.skipBytes(offsetToIndex + entryOffset[i]); in.readFully(document); documents.put(entryHash[i], document); } } this.clear(); for (int i = 0; i < numEntries; i++) { SvgTableEntry e = new SvgTableEntry(); e.startGlyphID = entryStartGlyphID[i]; e.endGlyphID = entryEndGlyphID[i]; e.svgDocument = documents.get(entryHash[i]); this.add(e); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/SvgTableEntry.java000066400000000000000000000040451506470510200327160ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class SvgTableEntry implements Comparable { public int startGlyphID = 0; public int endGlyphID = 0; public byte[] svgDocument = new byte[0]; public boolean isCompressed() { return svgDocument.length >= 18 && svgDocument[0] == (byte)0x1F && svgDocument[1] == (byte)0x8B; } public InputStream getInputStream() throws IOException { InputStream in = new ByteArrayInputStream(svgDocument); if (isCompressed()) in = new GZIPInputStream(in); return in; } public OutputStream getOutputStream(boolean compressed) throws IOException { // Note: Microsoft claims the SVG-in-OpenType specification supports // gzip-compressed SVG glyphs, and the availability of a version of // EmojiOne with gzip-compressed SVG glyphs appears to back this up. // However, I could not find any mention of gzip support in the W3C // specification, and I was unable to get fonts with gzip-compressed // SVG glyphs to work even in the latest version of Firefox (50.1.0). final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final OutputStream os = compressed ? new GZIPOutputStream(bos) : bos; return new OutputStream() { @Override public void write(int b) throws IOException { os.write(b); } @Override public void write(byte[] b) throws IOException { os.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { os.write(b, off, len); } @Override public void flush() throws IOException { os.flush(); bos.flush(); } @Override public void close() throws IOException { os.close(); bos.close(); svgDocument = bos.toByteArray(); } }; } @Override public int compareTo(SvgTableEntry that) { return this.startGlyphID - that.startGlyphID; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/TrueTypeFile.java000077500000000000000000000221171506470510200325510ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; public class TrueTypeFile extends ArrayList { private static final long serialVersionUID = 1L; public static final int SCALER_TRUETYPE = 0x00010000; public static final int SCALER_OPENTYPE = 0x4F54544F; public static final int SCALER_TRUETYPE_GX = 0x74727565; public static final int SCALER_POSTSCRIPT_GX = 0x74797031; public static final int SCALER_META = 0x778E7A00; public boolean interpret = true; public int scaler = SCALER_TRUETYPE; private TrueTypeTable createTable(int tableId) { if (!interpret) return new UnknownTable(tableId); switch (tableId) { case 0x43424454: return new EbdtTable(SbitTableType.COLOR); case 0x43424C43: return new EblcTable(SbitTableType.COLOR); case 0x434F4C52: return new ColrTable(); case 0x4350414C: return new CpalTable(); case 0x45424454: return new EbdtTable(SbitTableType.OPENTYPE); case 0x45424C43: return new EblcTable(SbitTableType.OPENTYPE); case 0x4F532F32: return new Os2Table(); case 0x50554141: return new PuaaTable(); case 0x53564720: return new SvgTable(); case 0x62646174: return new EbdtTable(SbitTableType.TRUETYPE); case 0x626C6F63: return new EblcTable(SbitTableType.TRUETYPE); case 0x636D6170: return new CmapTable(); case 0x676C7966: return new GlyfTable(); case 0x68656164: return new HeadTable(); case 0x68686561: return new HheaTable(); case 0x686D7478: return new HmtxTable(); case 0x6C6F6361: return new LocaTable(); case 0x6D617870: return new MaxpTable(); case 0x6E616D65: return new NameTable(); case 0x706F7374: return new PostTable(); case 0x73626978: return new SbixTable(); default: return new UnknownTable(tableId); } } public TrueTypeTable getByTableName(String name) { if (name != null) { for (TrueTypeTable table : this) { if (name.equals(table.tableName())) { return table; } } } return null; } public TrueTypeTable getByTableId(int id) { for (TrueTypeTable table : this) { if (id == table.tableId()) { return table; } } return null; } public boolean isOpenType() { for (TrueTypeTable table : this) { String name = table.tableName(); if ("CFF ".equals(name)) return true; if ("CFF2".equals(name)) return true; } return false; } public byte[] compile() throws IOException { ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); int numTables = this.size(); int searchRange = (1 << 30); while (searchRange > numTables) { searchRange >>>= 1; } int entrySelector = Integer.numberOfTrailingZeros(searchRange); searchRange <<= 4; int rangeShift = (numTables << 4) - searchRange; int headerLen = 12 + (numTables << 4); int checksumLoc = -1; out.writeInt(scaler); out.writeShort(numTables); out.writeShort(searchRange); out.writeShort(entrySelector); out.writeShort(rangeShift); // Gather tables. Map tablesById = new HashMap(); List tableInfo = new ArrayList(); for (TrueTypeTable table : this) { int id = table.tableId(); tablesById.put(id, table); TrueTypeTableInfo info = new TrueTypeTableInfo(); info.table = table; info.id = id; tableInfo.add(info); } // Compile. int currentLocation = headerLen; for (TrueTypeTableInfo info : tableInfo) { int[] depIds = info.table.dependencyIds(); TrueTypeTable[] depTables = new TrueTypeTable[depIds.length]; for (int i = 0; i < depIds.length; i++) { if (tablesById.containsKey(depIds[i])) { depTables[i] = tablesById.get(depIds[i]); } else { throw unresolvedDependency(info.table); } } info.data = info.table.compile(depTables); info.length = info.data.length; info.location = currentLocation; if (info.id == 0x68656164) { // This is the whole-file checksum in the head block. // It must be set to zero while calculating the checksum, // then updated after. checksumLoc = info.location + 8; putInt(info.data, 8, 0); } info.checksum = chksum(info.data); currentLocation += (info.length + 3) & ~0x3; } // Write headers. Collections.sort(tableInfo, SORT_BY_ID); for (TrueTypeTableInfo info : tableInfo) { out.writeInt(info.id); out.writeInt(info.checksum); out.writeInt(info.location); out.writeInt(info.length); } // Write data. Collections.sort(tableInfo, SORT_BY_LOCATION); for (TrueTypeTableInfo info : tableInfo) { out.write(info.data); int p = info.length & 0x3; if (p > 0) { while (p < 4) { out.writeByte(0); p++; } } } out.flush(); byteout.flush(); out.close(); byteout.close(); byte[] data = byteout.toByteArray(); if (checksumLoc >= 0) { putInt(data, checksumLoc, 0xB1B0AFBA - chksum(data)); } return data; } public void decompile(byte[] data) throws IOException { ByteArrayInputStream bytein = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bytein); scaler = in.readInt(); int numTables = in.readUnsignedShort(); /* int searchRange = */ in.readUnsignedShort(); /* int entrySelector = */ in.readUnsignedShort(); /* int rangeShift = */ in.readUnsignedShort(); // Read headers. List tableInfo = new ArrayList(); Map tableInfoById = new HashMap(); for (int i = 0; i < numTables; i++) { TrueTypeTableInfo info = new TrueTypeTableInfo(); info.id = in.readInt(); info.checksum = in.readInt(); info.location = in.readInt(); info.length = in.readInt(); tableInfo.add(info); tableInfoById.put(info.id, info); } // Read data. for (TrueTypeTableInfo info : tableInfo) { info.data = new byte[info.length]; in.reset(); in.skipBytes(info.location); in.readFully(info.data); } // Decompile. while (true) { int tablesDecompiled = 0; int tablesToDecompile = 0; for (TrueTypeTableInfo info : tableInfo) { if (info.table == null) { TrueTypeTable table = createTable(info.id); int[] depIds = table.dependencyIds(); TrueTypeTable[] depTables = new TrueTypeTable[depIds.length]; boolean depsComplete = true; for (int i = 0; i < depIds.length; i++) { if (tableInfoById.containsKey(depIds[i])) { depTables[i] = tableInfoById.get(depIds[i]).table; if (depTables[i] == null) { depsComplete = false; } } else { throw unresolvedDependency(table); } } if (depsComplete) { table.decompile(info.data, depTables); info.table = table; tablesDecompiled++; } else { tablesToDecompile++; } } } if (tablesToDecompile == 0) break; if (tablesDecompiled == 0) throw new IllegalStateException("Circular dependency detected."); } // Gather tables. this.clear(); Collections.sort(tableInfo, SORT_BY_LOCATION); for (TrueTypeTableInfo info : tableInfo) { this.add(info.table); } in.close(); bytein.close(); } private static final class TrueTypeTableInfo { private int id; private int checksum; private int location; private int length; private byte[] data; private TrueTypeTable table; } private static final Comparator SORT_BY_ID = new Comparator() { @Override public int compare(TrueTypeTableInfo a, TrueTypeTableInfo b) { return a.id - b.id; } }; private static final Comparator SORT_BY_LOCATION = new Comparator() { @Override public int compare(TrueTypeTableInfo a, TrueTypeTableInfo b) { return a.location - b.location; } }; private static final int chksum(byte[] data) { int sum = 0; int nl = data.length & ~0x3; for (int i = 0; i < nl; i += 4) { sum += getInt(data, i); } for (int i = nl, s = 24; i < data.length; i++, s -= 8) { sum += ((data[i] & 0xFF) << s); } return sum; } private static final int getInt(byte[] data, int i) { return ((data[i+0] & 0xFF) << 24) | ((data[i+1] & 0xFF) << 16) | ((data[i+2] & 0xFF) << 8) | ((data[i+3] & 0xFF) << 0); } private static final void putInt(byte[] data, int i, int v) { data[i+0] = (byte)((v >> 24) & 0xFF); data[i+1] = (byte)((v >> 16) & 0xFF); data[i+2] = (byte)((v >> 8) & 0xFF); data[i+3] = (byte)((v >> 0) & 0xFF); } private static final IllegalStateException unresolvedDependency(TrueTypeTable table) { StringBuffer message = new StringBuffer(); message.append("Unresolved dependency: "); message.append(table.tableName()); message.append(" depends on"); for (String depName : table.dependencyNames()) { message.append(" "); message.append(depName); } message.append("."); return new IllegalStateException(message.toString()); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/TrueTypeTable.java000077500000000000000000000042571506470510200327260ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public abstract class TrueTypeTable { public abstract String tableName(); public int tableId() { char[] name = tableName().toCharArray(); int id = (((name.length > 0 && name[0] >= 0x20 && name[0] < 0x7F) ? name[0] : 0x20) << 24) | (((name.length > 1 && name[1] >= 0x20 && name[1] < 0x7F) ? name[1] : 0x20) << 16) | (((name.length > 2 && name[2] >= 0x20 && name[2] < 0x7F) ? name[2] : 0x20) << 8) | (((name.length > 3 && name[3] >= 0x20 && name[3] < 0x7F) ? name[3] : 0x20) << 0); return id; } public abstract String[] dependencyNames(); public int[] dependencyIds() { String[] names = dependencyNames(); int[] ids = new int[names.length]; for (int i = 0; i < names.length; i++) { char[] name = names[i].toCharArray(); ids[i] = (((name.length > 0 && name[0] >= 0x20 && name[0] < 0x7F) ? name[0] : 0x20) << 24) | (((name.length > 1 && name[1] >= 0x20 && name[1] < 0x7F) ? name[1] : 0x20) << 16) | (((name.length > 2 && name[2] >= 0x20 && name[2] < 0x7F) ? name[2] : 0x20) << 8) | (((name.length > 3 && name[3] >= 0x20 && name[3] < 0x7F) ? name[3] : 0x20) << 0); } return ids; } protected abstract void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException; public byte[] compile(TrueTypeTable[] dependencies) throws IOException { ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); compile(out, dependencies); out.flush(); byteout.flush(); out.close(); byteout.close(); return byteout.toByteArray(); } protected abstract void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException; public void decompile(byte[] data, TrueTypeTable[] dependencies) throws IOException { ByteArrayInputStream bytein = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bytein); decompile(in, data.length, dependencies); in.close(); bytein.close(); } } UnknownCmapSubtable.java000077500000000000000000000014611506470510200340320ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetypepackage com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class UnknownCmapSubtable extends CmapSubtable { private final int format; public byte[] data; public UnknownCmapSubtable(int format) { this.format = format; this.data = new byte[0]; } public UnknownCmapSubtable(int format, byte[] data) { this.format = format; this.data = data; } @Override public int format() { return format; } @Override public int getGlyphIndex(int charCode) { return 0; } @Override protected void compile(DataOutputStream out) throws IOException { out.write(data); } @Override protected void decompile(DataInputStream in, int length) throws IOException { data = new byte[length]; in.readFully(data); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/truetype/UnknownTable.java000077500000000000000000000025341506470510200326000ustar00rootroot00000000000000package com.kreative.bitsnpicas.truetype; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class UnknownTable extends TrueTypeTable { private final String name; public byte[] data; public UnknownTable(String tableName) { name = tableName; data = new byte[0]; } public UnknownTable(String tableName, byte[] tableData) { name = tableName; data = tableData; } public UnknownTable(int tableId) { name = new String(new char[]{ (char)((tableId >> 24) & 0xFF), (char)((tableId >> 16) & 0xFF), (char)((tableId >> 8) & 0xFF), (char)((tableId >> 0) & 0xFF), }); data = new byte[0]; } public UnknownTable(int tableId, byte[] tableData) { name = new String(new char[]{ (char)((tableId >> 24) & 0xFF), (char)((tableId >> 16) & 0xFF), (char)((tableId >> 8) & 0xFF), (char)((tableId >> 0) & 0xFF), }); data = tableData; } @Override public String tableName() { return name; } @Override public String[] dependencyNames() { return new String[]{}; } @Override protected void compile(DataOutputStream out, TrueTypeTable[] dependencies) throws IOException { out.write(data); } @Override protected void decompile(DataInputStream in, int length, TrueTypeTable[] dependencies) throws IOException { data = new byte[length]; in.readFully(data); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/000077500000000000000000000000001506470510200261475ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MFile.java000066400000000000000000000175411506470510200302330ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; public class U8MFile { public static final int MAGIC_NUMBER = 0x55382F4D; public String familyName; public int familyID; public int style; public int pointSize; public int glyphTableLocation; public int glyphTableSize; public int mapTableLocation; public int mapTableSize; public final int[] nativeMapIndex = new int[4]; public final int[] lowBMPMapIndex = new int[32]; public final int[] highBMPMapIndex = new int[16]; public final int[] astralMapIndex = new int[6]; public int lineAscent; public int lineDescent; public int lineGap; public int lineHeight; public final U8MMapTable maps = new U8MMapTable(); public final U8MGlyphTable glyphs = new U8MGlyphTable(); public int createMap() { int i = maps.size(); maps.add(new U8MMapData()); return i; } public int createGlyph() { int i = glyphs.size(); glyphs.add(new U8MGlyph()); return i; } public int getNativeGlyphIndex(int cp) { if (cp < 0 || cp > 0xFF) return 0; int i = nativeMapIndex[cp >> 6]; if (i == 0) return 0; return maps.get(i).mapGet(cp & 0x3F); } public int getLowBMPGlyphIndex(int cp) { if (cp < 0 || cp > 0x07FF) return 0; int i = lowBMPMapIndex[cp >> 6]; if (i == 0) return 0; return maps.get(i).mapGet(cp & 0x3F); } public int getHighBMPGlyphIndex(int cp) { if (cp < 0 || cp > 0xFFFF) return 0; int i = highBMPMapIndex[cp >> 12]; if (i == 0) return 0; i = maps.get(i).mapGet((cp >> 6) & 0x3F); if (i == 0) return 0; return maps.get(i).mapGet(cp & 0x3F); } public int getAstralGlyphIndex(int cp) { if (cp < 0 || cp > 0x17FFFF) return 0; int i = astralMapIndex[cp >> 18]; if (i == 0) return 0; i = maps.get(i).mapGet((cp >> 12) & 0x3F); if (i == 0) return 0; i = maps.get(i).mapGet((cp >> 6) & 0x3F); if (i == 0) return 0; return maps.get(i).mapGet(cp & 0x3F); } public int getUnicodeGlyphIndex(int cp) { int i = getLowBMPGlyphIndex(cp); if (i != 0) return i; i = getHighBMPGlyphIndex(cp); if (i != 0) return i; return getAstralGlyphIndex(cp); } public void setNativeGlyphIndex(int cp, int index) { if (cp < 0 || cp > 0xFF) return; int i = nativeMapIndex[cp >> 6]; if (i == 0) nativeMapIndex[cp >> 6] = (i = createMap()); maps.get(i).mapPut(cp & 0x3F, index); } public void setLowBMPGlyphIndex(int cp, int index) { if (cp < 0 || cp > 0x07FF) return; int i = lowBMPMapIndex[cp >> 6]; if (i == 0) lowBMPMapIndex[cp >> 6] = (i = createMap()); maps.get(i).mapPut(cp & 0x3F, index); } public void setHighBMPGlyphIndex(int cp, int index) { if (cp < 0 || cp > 0xFFFF) return; int i = highBMPMapIndex[cp >> 12]; if (i == 0) highBMPMapIndex[cp >> 12] = (i = createMap()); U8MMapData map = maps.get(i); i = map.mapGet((cp >> 6) & 0x3F); if (i == 0) map.mapPut((cp >> 6) & 0x3F, (i = createMap())); maps.get(i).mapPut(cp & 0x3F, index); } public void setAstralGlyphIndex(int cp, int index) { if (cp < 0 || cp > 0x17FFFF) return; int i = astralMapIndex[cp >> 18]; if (i == 0) astralMapIndex[cp >> 18] = (i = createMap()); U8MMapData map = maps.get(i); i = map.mapGet((cp >> 12) & 0x3F); if (i == 0) map.mapPut((cp >> 12) & 0x3F, (i = createMap())); map = maps.get(i); i = map.mapGet((cp >> 6) & 0x3F); if (i == 0) map.mapPut((cp >> 6) & 0x3F, (i = createMap())); maps.get(i).mapPut(cp & 0x3F, index); } public void setUnicodeGlyphIndex(int cp, int index) { if (cp >= 0x10000) setAstralGlyphIndex(cp, index); else if (cp >= 0x800) setHighBMPGlyphIndex(cp, index); else setLowBMPGlyphIndex(cp, index); } public int setLocations(int loc) { loc += 0x100; if ((loc & 0xFF) != 0) loc = (loc | 0xFF) + 1; mapTableLocation = loc; mapTableSize = maps.size(); loc = maps.setMapLocations(loc); if ((loc & 0xFF) != 0) loc = (loc | 0xFF) + 1; glyphTableLocation = loc; glyphTableSize = glyphs.size(); loc = glyphs.setBitmapLocations(loc); return loc; } public void readHeader(DataInput in) throws IOException { if (in.readInt() != MAGIC_NUMBER) throw new IOException("bad magic"); int nameLength = in.readUnsignedByte(); byte[] nameData = new byte[118]; in.readFully(nameData); if (in.readByte() != 0) throw new IOException("bad name terminator"); familyName = new String(nameData, 0, Math.min(nameLength, 118), "UTF-8"); familyID = Short.reverseBytes(in.readShort()) & 0xFFFF; style = in.readUnsignedByte(); pointSize = in.readUnsignedByte(); glyphTableLocation = (Short.reverseBytes(in.readShort()) & 0xFFFF) << 8; glyphTableSize = Short.reverseBytes(in.readShort()) & 0xFFFF; mapTableLocation = (Short.reverseBytes(in.readShort()) & 0xFFFF) << 8; mapTableSize = Short.reverseBytes(in.readShort()) & 0xFFFF; for (int i = 0; i < 4; i++) nativeMapIndex [i] = Short.reverseBytes(in.readShort()) & 0xFFFF; for (int i = 0; i < 32; i++) lowBMPMapIndex [i] = Short.reverseBytes(in.readShort()) & 0xFFFF; for (int i = 0; i < 16; i++) highBMPMapIndex[i] = Short.reverseBytes(in.readShort()) & 0xFFFF; for (int i = 0; i < 6; i++) astralMapIndex [i] = Short.reverseBytes(in.readShort()) & 0xFFFF; lineAscent = in.readUnsignedByte(); lineDescent = in.readUnsignedByte(); lineGap = in.readUnsignedByte(); lineHeight = in.readUnsignedByte(); } public void writeHeader(DataOutput out) throws IOException { out.writeInt(MAGIC_NUMBER); if (familyName == null) { out.write(new byte[120]); } else { byte[] nameData = familyName.getBytes("UTF-8"); int nameLength = Math.min(nameData.length, 118); out.writeByte(nameLength); out.write(nameData, 0, nameLength); out.write(new byte[118 - nameLength]); out.writeByte(0); } out.writeShort(Short.reverseBytes((short)familyID)); out.writeByte(style); out.writeByte(pointSize); out.writeShort(Short.reverseBytes((short)(glyphTableLocation >> 8))); out.writeShort(Short.reverseBytes((short)glyphTableSize)); out.writeShort(Short.reverseBytes((short)(mapTableLocation >> 8))); out.writeShort(Short.reverseBytes((short)mapTableSize)); for (int i = 0; i < 4; i++) out.writeShort(Short.reverseBytes((short)nativeMapIndex [i])); for (int i = 0; i < 32; i++) out.writeShort(Short.reverseBytes((short)lowBMPMapIndex [i])); for (int i = 0; i < 16; i++) out.writeShort(Short.reverseBytes((short)highBMPMapIndex[i])); for (int i = 0; i < 6; i++) out.writeShort(Short.reverseBytes((short)astralMapIndex [i])); out.writeByte(lineAscent); out.writeByte(lineDescent); out.writeByte(lineGap); out.writeByte(lineHeight); } public void read(RandomAccessFile raf, long seekBase) throws IOException { readHeader(raf); maps.clear(); raf.seek(seekBase + mapTableLocation); for (int i = 0; i < mapTableSize; i++) { U8MMapData m = new U8MMapData(); m.readHeader(raf); maps.add(m); } for (U8MMapData m : maps) { if (m.mapLocation != 0) { raf.seek(seekBase + m.mapLocation); m.readData(raf); } } glyphs.clear(); raf.seek(seekBase + glyphTableLocation); for (int i = 0; i < glyphTableSize; i++) { U8MGlyph g = new U8MGlyph(); g.readGlyphRecord(raf); glyphs.add(g); } for (U8MGlyph g : glyphs) { if (g.bitmapLocation != 0) { raf.seek(seekBase + g.bitmapLocation); g.readBitmapRecord(raf); } } } public void write(RandomAccessFile raf, int locationBase, long seekBase) throws IOException { setLocations(locationBase); writeHeader(raf); raf.seek(seekBase + mapTableLocation); for (U8MMapData m : maps) { m.writeHeader(raf); } for (U8MMapData m : maps) { if (m.mapLocation != 0) { raf.seek(seekBase + m.mapLocation); m.writeData(raf); } } raf.seek(seekBase + glyphTableLocation); for (U8MGlyph g : glyphs) { g.writeGlyphRecord(raf); } for (U8MGlyph g : glyphs) { if (g.bitmapLocation != 0) { raf.seek(seekBase + g.bitmapLocation); g.writeBitmapRecord(raf); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MGlyph.java000066400000000000000000000056541506470510200304410ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.Arrays; public class U8MGlyph { public int bitmapLocation; public int advanceWidth; public int yOffset; public int xOffset; public int height; public int width; public byte[] data; public void from2DArray(byte[][] a) { if (a == null || a.length == 0) { height = 0; width = 0; data = new byte[0]; } else { height = a.length; width = a[0].length; data = new byte[(height * width + 7) / 8]; int i = 0, m = 0x80; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (a[y][x] < 0) data[i] |= m; if ((m >>= 1) == 0) { m = 0x80; i++; } } } } } public byte[][] to2DArray() { byte[][] a = new byte[height][width]; if (data != null) { int i = 0, m = 0x80; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { a[y][x] = ((data[i] & m) == 0) ? (byte)(0) : (byte)(-1); if ((m >>= 1) == 0) { m = 0x80; i++; } } } } return a; } public int setBitmapLocation(int loc) { if (data == null || data.length == 0) { bitmapLocation = 0; return loc; } else { int len = data.length + 4; if ((loc & 0xFF) + len > 0x100) loc = (loc | 0xFF) + 1; return ((bitmapLocation = loc)) + len; } } public void readGlyphRecord(DataInput in) throws IOException { int v = Integer.reverseBytes(in.readInt()); bitmapLocation = v & 0xFFFFFF; advanceWidth = (v >> 24) & 0xFF; } public void writeGlyphRecord(DataOutput out) throws IOException { int v = (bitmapLocation & 0xFFFFFF) | (advanceWidth << 24); out.writeInt(Integer.reverseBytes(v)); } public void readBitmapRecord(DataInput in) throws IOException { yOffset = in.readByte(); xOffset = in.readByte(); height = in.readUnsignedByte(); width = in.readUnsignedByte(); data = new byte[(height * width + 7) / 8]; in.readFully(data); } public void writeBitmapRecord(DataOutput out) throws IOException { out.writeByte(yOffset); out.writeByte(xOffset); out.writeByte(height); out.writeByte(width); if (data != null) out.write(data); } @Override public boolean equals(Object o) { if (o instanceof U8MGlyph) { U8MGlyph that = (U8MGlyph)o; return ( this.advanceWidth == that.advanceWidth && this.yOffset == that.yOffset && this.xOffset == that.xOffset && this.height == that.height && this.width == that.width && equals(this.data, that.data) ); } return false; } private static boolean equals(byte[] a, byte[] b) { if (a == null || a.length == 0) return (b == null || b.length == 0); if (b == null || b.length == 0) return (a == null || a.length == 0); return Arrays.equals(a, b); } @Override public int hashCode() { return Arrays.hashCode(new int[] { advanceWidth, yOffset, xOffset, height, width, ((data == null || data.length == 0) ? 0 : Arrays.hashCode(data)) }); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MGlyphTable.java000066400000000000000000000005011506470510200313730ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.util.ArrayList; public class U8MGlyphTable extends ArrayList { private static final long serialVersionUID = 1L; public int setBitmapLocations(int loc) { loc += this.size() * 4; for (U8MGlyph g : this) loc = g.setBitmapLocation(loc); return loc; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MMapData.java000066400000000000000000000040531506470510200306550ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; public class U8MMapData extends ArrayList { private static final long serialVersionUID = 1L; public int mapLocation; public int mapEntryCount; public boolean mapContains(int i) { for (U8MMapEntry e : this) { if (e.contains(i)) { return true; } } return false; } public int mapGet(int i) { for (U8MMapEntry e : this) { if (e.contains(i)) { return e.get(i); } } return 0; } public void mapPut(int index, int outdex) { for (U8MMapEntry e : this) { if (e.contains(index) && e.get(index) == outdex) { return; } if (e.contains(index - 1) && e.get(index - 1) == (outdex - 1)) { e.lastIndexValue++; return; } } U8MMapEntry e = new U8MMapEntry(); e.firstIndexValue = index; e.lastIndexValue = index; e.firstOutdexValue = outdex; this.add(e); Collections.sort(this); } public int mapSize() { int n = 0; for (U8MMapEntry e : this) { n += e.size(); } return n; } public int setMapLocation(int loc) { if (this.isEmpty()) { mapLocation = 0; mapEntryCount = 0; return loc; } else { int len = ((mapEntryCount = this.size())) * 4; if ((loc & 0xFF) + len > 0x100) loc = (loc | 0xFF) + 1; return ((mapLocation = loc)) + len; } } public void readHeader(DataInput in) throws IOException { int v = Integer.reverseBytes(in.readInt()); mapLocation = v & 0xFFFFFF; mapEntryCount = (v >> 24) & 0xFF; } public void writeHeader(DataOutput out) throws IOException { int v = (mapLocation & 0xFFFFFF) | (mapEntryCount << 24); out.writeInt(Integer.reverseBytes(v)); } public void readData(DataInput in) throws IOException { this.clear(); for (int i = 0; i < mapEntryCount; i++) { U8MMapEntry e = new U8MMapEntry(); e.read(in); this.add(e); } } public void writeData(DataOutput out) throws IOException { for (U8MMapEntry e : this) { e.write(out); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MMapEntry.java000066400000000000000000000031051506470510200311020ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.Arrays; public class U8MMapEntry implements Comparable { public int firstIndexValue; public int lastIndexValue; public int firstOutdexValue; public int lastOutdexValue() { return lastIndexValue - firstIndexValue + firstOutdexValue; } public boolean contains(int i) { return (i >= firstIndexValue && i <= lastIndexValue); } public int get(int i) { return i - firstIndexValue + firstOutdexValue; } public int size() { return lastIndexValue - firstIndexValue + 1; } public void read(DataInput in) throws IOException { firstIndexValue = in.readUnsignedByte(); lastIndexValue = in.readUnsignedByte(); firstOutdexValue = Short.reverseBytes(in.readShort()) & 0xFFFF; } public void write(DataOutput out) throws IOException { out.writeByte(firstIndexValue); out.writeByte(lastIndexValue); out.writeShort(Short.reverseBytes((short)firstOutdexValue)); } @Override public int compareTo(U8MMapEntry that) { return this.firstIndexValue - that.firstIndexValue; } @Override public boolean equals(Object o) { if (o instanceof U8MMapEntry) { U8MMapEntry that = (U8MMapEntry)o; return ( this.firstIndexValue == that.firstIndexValue && this.lastIndexValue == that.lastIndexValue && this.firstOutdexValue == that.firstOutdexValue ); } return false; } @Override public int hashCode() { return Arrays.hashCode(new int[] { firstIndexValue, lastIndexValue, firstOutdexValue }); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MMapTable.java000066400000000000000000000004751506470510200310370ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; import java.util.ArrayList; public class U8MMapTable extends ArrayList { private static final long serialVersionUID = 1L; public int setMapLocations(int loc) { loc += this.size() * 4; for (U8MMapData m : this) loc = m.setMapLocation(loc); return loc; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/bitsnpicas/u8m/U8MNativeMapping.java000066400000000000000000000046221506470510200321120ustar00rootroot00000000000000package com.kreative.bitsnpicas.u8m; public enum U8MNativeMapping { APPLE_II("Apple II", new int[]{ // ASCII 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, // MouseText 0xF813, 0xF812, 0x1FBB0, 0x231B, 0x2713, 0x1FBB1, 0x1FBB4, 0x1FB81, 0x2190, 0x2026, 0x2193, 0x2191, 0x2594, 0x21B2, 0x2589, 0x1FBB5, 0x1FBB6, 0x1FBB7, 0x1FBB8, 0x2500, 0x1FB7C, 0x2192, 0x2592, 0x1FB90, 0x1FBB9, 0x1FBBA, 0x2595, 0x25C6, 0x1FB80, 0x1FBBB, 0x1FBBC, 0x258F, // High ASCII 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, }), PETSCII("PETSCII", new int[]{ }); private final String name; private final int[] toUnicode; private U8MNativeMapping(String name, int[] toUnicode) { this.name = name; this.toUnicode = toUnicode; } @Override public String toString() { return name; } public int getCodePoint(int i) { if (i >= 0 && i < toUnicode.length) { return toUnicode[i]; } else { return 0; } } public void apply(U8MFile u) { for (int i = 0, n = toUnicode.length; i < n; i++) { int cp = toUnicode[i]; if (cp > 0) { int gi = u.getUnicodeGlyphIndex(cp); if (gi > 0) { u.setNativeGlyphIndex(cp, gi); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/000077500000000000000000000000001506470510200247355ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/Base64InputStream.java000066400000000000000000000055521506470510200310270ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.IOException; import java.io.InputStream; import java.text.CharacterIterator; import java.text.StringCharacterIterator; public class Base64InputStream extends InputStream { private final CharacterIterator ci; private final InputStream in; public Base64InputStream(String s) { this.ci = new StringCharacterIterator(s); this.in = null; } public Base64InputStream(CharacterIterator ci) { this.ci = ci; this.in = null; } public Base64InputStream(InputStream in) { this.ci = null; this.in = in; } private int word = 0; private int count = 0; private boolean eof = false; @Override public int read() throws IOException { for (;;) { if (count > 0) { word <<= 8; count--; return (word >>> 24); } if (eof) return -1; readWord(); } } private void readWord() throws IOException { for (;;) { int c = -1; if (ci != null) { c = ci.current(); ci.next(); } if (in != null) { c = in.read(); } if (c < 0 || c == '=' || c == CharacterIterator.DONE) { padWord(); eof = true; return; } c = b64d(c); if (c >= 0) { word <<= 6; word |= c; count++; if (count > 3) { count = 3; return; } } } } private void padWord() { if (count > 0) { for (int i = count; i <= 3; i++) { word <<= 6; } count--; } } private int b64d(int c) { switch (c) { case 'A': return 0; case 'B': return 1; case 'C': return 2; case 'D': return 3; case 'E': return 4; case 'F': return 5; case 'G': return 6; case 'H': return 7; case 'I': return 8; case 'J': return 9; case 'K': return 10; case 'L': return 11; case 'M': return 12; case 'N': return 13; case 'O': return 14; case 'P': return 15; case 'Q': return 16; case 'R': return 17; case 'S': return 18; case 'T': return 19; case 'U': return 20; case 'V': return 21; case 'W': return 22; case 'X': return 23; case 'Y': return 24; case 'Z': return 25; case 'a': return 26; case 'b': return 27; case 'c': return 28; case 'd': return 29; case 'e': return 30; case 'f': return 31; case 'g': return 32; case 'h': return 33; case 'i': return 34; case 'j': return 35; case 'k': return 36; case 'l': return 37; case 'm': return 38; case 'n': return 39; case 'o': return 40; case 'p': return 41; case 'q': return 42; case 'r': return 43; case 's': return 44; case 't': return 45; case 'u': return 46; case 'v': return 47; case 'w': return 48; case 'x': return 49; case 'y': return 50; case 'z': return 51; case '0': return 52; case '1': return 53; case '2': return 54; case '3': return 55; case '4': return 56; case '5': return 57; case '6': return 58; case '7': return 59; case '8': return 60; case '9': return 61; case '+': return 62; case '/': return 63; default: return -1; } } @Override public void close() throws IOException { if (in != null) in.close(); } }bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/Base64OutputStream.java000066400000000000000000000033751506470510200312310ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.IOException; import java.io.OutputStream; public class Base64OutputStream extends OutputStream { private final StringBuffer sb; private final OutputStream out; private final boolean pad; public Base64OutputStream(StringBuffer sb) { this(sb, true); } public Base64OutputStream(OutputStream out) { this(out, true); } public Base64OutputStream(StringBuffer sb, boolean pad) { this.sb = sb; this.out = null; this.pad = pad; } public Base64OutputStream(OutputStream out, boolean pad) { this.sb = null; this.out = out; this.pad = pad; } private int word = 0; private int count = 0; @Override public void write(int b) throws IOException { word <<= 8; word |= (b & 0xFF); count++; if (count >= 3) { writeWord(); word = 0; count = 0; } } @Override public void flush() throws IOException { if (out != null) out.flush(); } @Override public void close() throws IOException { if (count > 0) { for (int i = count; i < 3; i++) word <<= 8; writeWord(); } word = 0; count = 0; if (out != null) out.close(); } private void writeWord() throws IOException { for (int m = 18, i = 0; i <= count; m -= 6, i++) { char c = b64e[(word >> m) & 0x3F]; if (sb != null) sb.append(c); if (out != null) out.write(c); } if (pad) { for (int i = count; i < 3; i++) { if (sb != null) sb.append('='); if (out != null) out.write('='); } } } private static final char[] b64e = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', }; }bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/CapsLockMapping.java000066400000000000000000000001341506470510200306110ustar00rootroot00000000000000package com.kreative.keyedit; public enum CapsLockMapping { AUTO, UNSHIFTED, SHIFTED; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/ColorReducer.java000066400000000000000000000134561506470510200302010ustar00rootroot00000000000000package com.kreative.keyedit; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.imageio.ImageIO; public class ColorReducer { public static void main(String[] args) { int count = 256; for (String arg : args) { try { count = Integer.parseInt(arg); } catch (NumberFormatException nfe) { System.out.println(arg); try { BufferedImage image = ImageIO.read(new File(arg)); int[] colors = reduce(image, count); for (int color : colors) { int r = ((color >> 16) & 0xFF); int g = ((color >> 8) & 0xFF); int b = ((color >> 0) & 0xFF); int k = (r*30 + g*59 + b*11); System.out.print("\u001B[48;2;" + r + ";" + g + ";" + b + "m"); System.out.print((k < 12750) ? "\u001B[97m" : "\u001B[30m"); System.out.print(" " + Integer.toHexString(color).toUpperCase() + " "); System.out.print("\u001B[0m"); } System.out.println(); } catch (IOException e) { System.out.println("ERROR: " + e); } } } } public static int[] reduce(BufferedImage image, int count) { int w = image.getWidth(), h = image.getHeight(); int[] rgb = new int[w * h]; image.getRGB(0, 0, w, h, rgb, 0, w); return reduce(rgb, count); } public static int[] reduce(int[] rgb, int count) { return reduce(rgb, 0, rgb.length, count); } private static int[] reduce(int[] rgb, int start, int end, int count) { if (start >= end || count <= 0) return new int[0]; List vboxes = new ArrayList(); vboxes.add(new VBox(rgb, start, end)); while (vboxes.size() < count) { boolean wv = (vboxes.size() >= count * 0.85f); int largestIndex = -1; int largestWeight = -1; for (int i = 0, n = vboxes.size(); i < n; i++) { VBox vbox = vboxes.get(i); if (vbox.canSplit()) { int weight = vbox.population; if (wv) weight *= vbox.volume; if (weight > largestWeight) { largestIndex = i; largestWeight = weight; } } } if (largestIndex < 0) break; VBox vbox = vboxes.remove(largestIndex); vboxes.addAll(largestIndex, Arrays.asList(vbox.split())); } count = vboxes.size(); rgb = new int[count]; for (int i = 0; i < count; i++) { rgb[i] = vboxes.get(i).average; } return rgb; } private static class VBox { public final int[] rgb; public final int start, end; public final int population; public final int volume; public final int average; public final int median; public VBox(int[] rgb, int start, int end) { this.rgb = rgb; this.start = start; this.end = end; if (start >= end) { this.population = 0; this.volume = 0; this.average = (0xFF << 24); this.median = (start + end) / 2; return; } int minR = 255, maxR = 0; long totalR = 0; int minG = 255, maxG = 0; long totalG = 0; int minB = 255, maxB = 0; long totalB = 0; for (int i = start; i < end; i++) { int r = (rgb[i] >> 16) & 0xFF; if (r < minR) minR = r; if (r > maxR) maxR = r; totalR += r; int g = (rgb[i] >> 8) & 0xFF; if (g < minG) minG = g; if (g > maxG) maxG = g; totalG += g; int b = (rgb[i] >> 0) & 0xFF; if (b < minB) minB = b; if (b > maxB) maxB = b; totalB += b; } int diffR = maxR - minR + 1; int diffG = maxG - minG + 1; int diffB = maxB - minB + 1; int avgR = (int)(totalR / (end - start)); int avgG = (int)(totalG / (end - start)); int avgB = (int)(totalB / (end - start)); this.population = end - start; this.volume = diffR * diffG * diffB; this.average = (0xFF << 24) | (avgR << 16) | (avgG << 8) | (avgB << 0); if (diffG >= diffR && diffG >= diffB) { this.median = getVBoxMedian(rgb, start, end, 8, minG, maxG); } else if (diffR >= diffB) { this.median = getVBoxMedian(rgb, start, end, 16, minR, maxR); } else { this.median = getVBoxMedian(rgb, start, end, 0, minB, maxB); } } public boolean canSplit() { return population > 1 && volume > 1 && start < median && median < end; } public VBox[] split() { boolean leftEmpty = (start >= median); boolean rightEmpty = (median >= end); if (leftEmpty && rightEmpty) return new VBox[0]; if (leftEmpty || rightEmpty) return new VBox[]{this}; VBox left = new VBox(rgb, start, median); VBox right = new VBox(rgb, median, end); return new VBox[]{left, right}; } } private static int getVBoxMedian(int[] rgb, int start, int end, int shift, int min, int max) { Collections.sort( new IntegerListView(rgb).subList(start, end), new MaskedComparator(0xFF << shift) ); int mid = (rgb[(start + end) / 2] >> shift) & 0xFF; int left = mid - min; int right = max - mid; mid = ( (left <= right) ? Math.min(max - 1, mid + right / 2) : Math.max(min, mid - left / 2 - 1) ); for (int i = start; i < end; i++) { int c = (rgb[i] >> shift) & 0xFF; if (c > mid) return i; } return end; } private static class MaskedComparator implements Comparator { private final int mask; public MaskedComparator(int mask) { this.mask = mask; } @Override public int compare(Integer a, Integer b) { return (a & mask) - (b & mask); } } private static class IntegerListView extends AbstractList { private final int[] backingArray; public IntegerListView(int[] array) { this.backingArray = array; } @Override public Integer get(int index) { return backingArray[index]; } @Override public boolean isEmpty() { return backingArray.length == 0; } @Override public Integer set(int index, Integer value) { int oldValue = backingArray[index]; backingArray[index] = value; return oldValue; } @Override public int size() { return backingArray.length; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/ColorTables.java000066400000000000000000000354641506470510200300250ustar00rootroot00000000000000package com.kreative.keyedit; public class ColorTables { public static int[] createBlackToWhite(int bpp) { int colors = (1 << bpp); int[] colorTable = new int[colors]; colors--; for (int i = 0; i <= colors; i++) { colorTable[i] = ((255 * i / colors) * 0x010101) | 0xFF000000; } return colorTable; } public static int[] createWhiteToBlack(int bpp) { int colors = (1 << bpp); int[] colorTable = new int[colors]; colors--; for (int i = 0; i <= colors; i++) { colorTable[colors - i] = ((255 * i / colors) * 0x010101) | 0xFF000000; } return colorTable; } public static int[] createWindows4() { return new int[] { 0xFF000000, 0xFF800000, 0xFF008000, 0xFF808000, 0xFF000080, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFFFFFF00, 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF }; } public static int[] createMacintosh4() { return new int[] { 0xFFFFFFFF, 0xFFFCF305, 0xFFFF6503, 0xFFDD0907, 0xFFF30885, 0xFF4700A5, 0xFF0000D4, 0xFF02ABEB, 0xFF1FB814, 0xFF006512, 0xFF562D05, 0xFF91713A, 0xFFC0C0C0, 0xFF808080, 0xFF404040, 0xFF000000 }; } public static int[] createWindowsBase() { return new int[] { 0xFF000000, 0xFF800000, 0xFF008000, 0xFF808000, 0xFF000080, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFFC0DCC0, 0xFFA6CAF0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFFFFFBF0, 0xFFA0A0A4, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFFFFFF00, 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF }; } public static int[] createWindowsEis() { return new int[] { 0xFF000000, 0xFF800000, 0xFF008000, 0xFF808000, 0xFF000080, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFFC0DCC0, 0xFFA6CAF0, 0xFF2A3FAA, 0xFF2A3FFF, 0xFF2A5F00, 0xFF2A5F55, 0xFF2A5FAA, 0xFF2A5FFF, 0xFF2A7F00, 0xFF2A7F55, 0xFF2A7FAA, 0xFF2A7FFF, 0xFF2A9F00, 0xFF2A9F55, 0xFF2A9FAA, 0xFF2A9FFF, 0xFF2ABF00, 0xFF2ABF55, 0xFF2ABFAA, 0xFF2ABFFF, 0xFF2ADF00, 0xFF2ADF55, 0xFF2ADFAA, 0xFF2ADFFF, 0xFF2AFF00, 0xFF2AFF55, 0xFF2AFFAA, 0xFF2AFFFF, 0xFF550000, 0xFF550055, 0xFF5500AA, 0xFF5500FF, 0xFF551F00, 0xFF551F55, 0xFF551FAA, 0xFF551FFF, 0xFF553F00, 0xFF553F55, 0xFF553FAA, 0xFF553FFF, 0xFF555F00, 0xFF555F55, 0xFF555FAA, 0xFF555FFF, 0xFF557F00, 0xFF557F55, 0xFF557FAA, 0xFF557FFF, 0xFF559F00, 0xFF559F55, 0xFF559FAA, 0xFF559FFF, 0xFF55BF00, 0xFF55BF55, 0xFF55BFAA, 0xFF55BFFF, 0xFF55DF00, 0xFF55DF55, 0xFF55DFAA, 0xFF55DFFF, 0xFF55FF00, 0xFF55FF55, 0xFF55FFAA, 0xFF55FFFF, 0xFF7F0000, 0xFF7F0055, 0xFF7F00AA, 0xFF7F00FF, 0xFF7F1F00, 0xFF7F1F55, 0xFF7F1FAA, 0xFF7F1FFF, 0xFF7F3F00, 0xFF7F3F55, 0xFF7F3FAA, 0xFF7F3FFF, 0xFF7F5F00, 0xFF7F5F55, 0xFF7F5FAA, 0xFF7F5FFF, 0xFF7F7F00, 0xFF7F7F55, 0xFF7F7FAA, 0xFF7F7FFF, 0xFF7F9F00, 0xFF7F9F55, 0xFF7F9FAA, 0xFF7F9FFF, 0xFF7FBF00, 0xFF7FBF55, 0xFF7FBFAA, 0xFF7FBFFF, 0xFF7FDF00, 0xFF7FDF55, 0xFF7FDFAA, 0xFF7FDFFF, 0xFF7FFF00, 0xFF7FFF55, 0xFF7FFFAA, 0xFF7FFFFF, 0xFFAA0000, 0xFFAA0055, 0xFFAA00AA, 0xFFAA00FF, 0xFFAA1F00, 0xFFAA1F55, 0xFFAA1FAA, 0xFFAA1FFF, 0xFFAA3F00, 0xFFAA3F55, 0xFFAA3FAA, 0xFFAA3FFF, 0xFFAA5F00, 0xFFAA5F55, 0xFFAA5FAA, 0xFFAA5FFF, 0xFFAA7F00, 0xFFAA7F55, 0xFFAA7FAA, 0xFFAA7FFF, 0xFFAA9F00, 0xFFAA9F55, 0xFFAA9FAA, 0xFFAA9FFF, 0xFFAABF00, 0xFFAABF55, 0xFFAABFAA, 0xFFAABFFF, 0xFFAADF00, 0xFFAADF55, 0xFFAADFAA, 0xFFAADFFF, 0xFFAAFF00, 0xFFAAFF55, 0xFFAAFFAA, 0xFFAAFFFF, 0xFFD40000, 0xFFD40055, 0xFFD400AA, 0xFFD400FF, 0xFFD41F00, 0xFFD41F55, 0xFFD41FAA, 0xFFD41FFF, 0xFFD43F00, 0xFFD43F55, 0xFFD43FAA, 0xFFD43FFF, 0xFFD45F00, 0xFFD45F55, 0xFFD45FAA, 0xFFD45FFF, 0xFFD47F00, 0xFFD47F55, 0xFFD47FAA, 0xFFD47FFF, 0xFFD49F00, 0xFFD49F55, 0xFFD49FAA, 0xFFD49FFF, 0xFFD4BF00, 0xFFD4BF55, 0xFFD4BFAA, 0xFFD4BFFF, 0xFFD4DF00, 0xFFD4DF55, 0xFFD4DFAA, 0xFFD4DFFF, 0xFFD4FF00, 0xFFD4FF55, 0xFFD4FFAA, 0xFFD4FFFF, 0xFFFF0055, 0xFFFF00AA, 0xFFFF1F00, 0xFFFF1F55, 0xFFFF1FAA, 0xFFFF1FFF, 0xFFFF3F00, 0xFFFF3F55, 0xFFFF3FAA, 0xFFFF3FFF, 0xFFFF5F00, 0xFFFF5F55, 0xFFFF5FAA, 0xFFFF5FFF, 0xFFFF7F00, 0xFFFF7F55, 0xFFFF7FAA, 0xFFFF7FFF, 0xFFFF9F00, 0xFFFF9F55, 0xFFFF9FAA, 0xFFFF9FFF, 0xFFFFBF00, 0xFFFFBF55, 0xFFFFBFAA, 0xFFFFBFFF, 0xFFFFDF00, 0xFFFFDF55, 0xFFFFDFAA, 0xFFFFDFFF, 0xFFFFFF55, 0xFFFFFFAA, 0xFFCCCCFF, 0xFFFFCCFF, 0xFF33FFFF, 0xFF66FFFF, 0xFF99FFFF, 0xFFCCFFFF, 0xFF007F00, 0xFF007F55, 0xFF007FAA, 0xFF007FFF, 0xFF009F00, 0xFF009F55, 0xFF009FAA, 0xFF009FFF, 0xFF00BF00, 0xFF00BF55, 0xFF00BFAA, 0xFF00BFFF, 0xFF00DF00, 0xFF00DF55, 0xFF00DFAA, 0xFF00DFFF, 0xFF00FF55, 0xFF00FFAA, 0xFF2A0000, 0xFF2A0055, 0xFF2A00AA, 0xFF2A00FF, 0xFF2A1F00, 0xFF2A1F55, 0xFF2A1FAA, 0xFF2A1FFF, 0xFF2A3F00, 0xFF2A3F55, 0xFFFFFBF0, 0xFFA0A0A4, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFFFFFF00, 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF }; } public static int[] createWindowsPaint() { return new int[] { 0xFF000000, 0xFF800000, 0xFF008000, 0xFF808000, 0xFF000080, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFFC0DCC0, 0xFFA6CAF0, 0xFF402000, 0xFF602000, 0xFF802000, 0xFFA02000, 0xFFC02000, 0xFFE02000, 0xFF004000, 0xFF204000, 0xFF404000, 0xFF604000, 0xFF804000, 0xFFA04000, 0xFFC04000, 0xFFE04000, 0xFF006000, 0xFF206000, 0xFF406000, 0xFF606000, 0xFF806000, 0xFFA06000, 0xFFC06000, 0xFFE06000, 0xFF008000, 0xFF208000, 0xFF408000, 0xFF608000, 0xFF808000, 0xFFA08000, 0xFFC08000, 0xFFE08000, 0xFF00A000, 0xFF20A000, 0xFF40A000, 0xFF60A000, 0xFF80A000, 0xFFA0A000, 0xFFC0A000, 0xFFE0A000, 0xFF00C000, 0xFF20C000, 0xFF40C000, 0xFF60C000, 0xFF80C000, 0xFFA0C000, 0xFFC0C000, 0xFFE0C000, 0xFF00E000, 0xFF20E000, 0xFF40E000, 0xFF60E000, 0xFF80E000, 0xFFA0E000, 0xFFC0E000, 0xFFE0E000, 0xFF000040, 0xFF200040, 0xFF400040, 0xFF600040, 0xFF800040, 0xFFA00040, 0xFFC00040, 0xFFE00040, 0xFF002040, 0xFF202040, 0xFF402040, 0xFF602040, 0xFF802040, 0xFFA02040, 0xFFC02040, 0xFFE02040, 0xFF004040, 0xFF204040, 0xFF404040, 0xFF604040, 0xFF804040, 0xFFA04040, 0xFFC04040, 0xFFE04040, 0xFF006040, 0xFF206040, 0xFF406040, 0xFF606040, 0xFF806040, 0xFFA06040, 0xFFC06040, 0xFFE06040, 0xFF008040, 0xFF208040, 0xFF408040, 0xFF608040, 0xFF808040, 0xFFA08040, 0xFFC08040, 0xFFE08040, 0xFF00A040, 0xFF20A040, 0xFF40A040, 0xFF60A040, 0xFF80A040, 0xFFA0A040, 0xFFC0A040, 0xFFE0A040, 0xFF00C040, 0xFF20C040, 0xFF40C040, 0xFF60C040, 0xFF80C040, 0xFFA0C040, 0xFFC0C040, 0xFFE0C040, 0xFF00E040, 0xFF20E040, 0xFF40E040, 0xFF60E040, 0xFF80E040, 0xFFA0E040, 0xFFC0E040, 0xFFE0E040, 0xFF000080, 0xFF200080, 0xFF400080, 0xFF600080, 0xFF800080, 0xFFA00080, 0xFFC00080, 0xFFE00080, 0xFF002080, 0xFF202080, 0xFF402080, 0xFF602080, 0xFF802080, 0xFFA02080, 0xFFC02080, 0xFFE02080, 0xFF004080, 0xFF204080, 0xFF404080, 0xFF604080, 0xFF804080, 0xFFA04080, 0xFFC04080, 0xFFE04080, 0xFF006080, 0xFF206080, 0xFF406080, 0xFF606080, 0xFF806080, 0xFFA06080, 0xFFC06080, 0xFFE06080, 0xFF008080, 0xFF208080, 0xFF408080, 0xFF608080, 0xFF808080, 0xFFA08080, 0xFFC08080, 0xFFE08080, 0xFF00A080, 0xFF20A080, 0xFF40A080, 0xFF60A080, 0xFF80A080, 0xFFA0A080, 0xFFC0A080, 0xFFE0A080, 0xFF00C080, 0xFF20C080, 0xFF40C080, 0xFF60C080, 0xFF80C080, 0xFFA0C080, 0xFFC0C080, 0xFFE0C080, 0xFF00E080, 0xFF20E080, 0xFF40E080, 0xFF60E080, 0xFF80E080, 0xFFA0E080, 0xFFC0E080, 0xFFE0E080, 0xFF0000C0, 0xFF2000C0, 0xFF4000C0, 0xFF6000C0, 0xFF8000C0, 0xFFA000C0, 0xFFC000C0, 0xFFE000C0, 0xFF0020C0, 0xFF2020C0, 0xFF4020C0, 0xFF6020C0, 0xFF8020C0, 0xFFA020C0, 0xFFC020C0, 0xFFE020C0, 0xFF0040C0, 0xFF2040C0, 0xFF4040C0, 0xFF6040C0, 0xFF8040C0, 0xFFA040C0, 0xFFC040C0, 0xFFE040C0, 0xFF0060C0, 0xFF2060C0, 0xFF4060C0, 0xFF6060C0, 0xFF8060C0, 0xFFA060C0, 0xFFC060C0, 0xFFE060C0, 0xFF0080C0, 0xFF2080C0, 0xFF4080C0, 0xFF6080C0, 0xFF8080C0, 0xFFA080C0, 0xFFC080C0, 0xFFE080C0, 0xFF00A0C0, 0xFF20A0C0, 0xFF40A0C0, 0xFF60A0C0, 0xFF80A0C0, 0xFFA0A0C0, 0xFFC0A0C0, 0xFFE0A0C0, 0xFF00C0C0, 0xFF20C0C0, 0xFF40C0C0, 0xFF60C0C0, 0xFF80C0C0, 0xFFA0C0C0, 0xFFFFFBF0, 0xFFA0A0A4, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFFFFFF00, 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF }; } public static int[] createWindowsWebSafe() { return new int[] { 0xFF000000, 0xFF800000, 0xFF008000, 0xFF808000, 0xFF000080, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFFC0DCC0, 0xFFA6CAF0, 0xFF330000, 0xFF660000, 0xFF990000, 0xFFCC0000, 0xFF003300, 0xFF333300, 0xFF663300, 0xFF993300, 0xFFCC3300, 0xFFFF3300, 0xFF006600, 0xFF336600, 0xFF666600, 0xFF996600, 0xFFCC6600, 0xFFFF6600, 0xFF009900, 0xFF339900, 0xFF669900, 0xFF999900, 0xFFCC9900, 0xFFFF9900, 0xFF00CC00, 0xFF33CC00, 0xFF66CC00, 0xFF99CC00, 0xFFCCCC00, 0xFFFFCC00, 0xFF33FF00, 0xFF66FF00, 0xFF99FF00, 0xFFCCFF00, 0xFF000033, 0xFF330033, 0xFF660033, 0xFF990033, 0xFFCC0033, 0xFFFF0033, 0xFF003333, 0xFF333333, 0xFF663333, 0xFF993333, 0xFFCC3333, 0xFFFF3333, 0xFF006633, 0xFF336633, 0xFF666633, 0xFF996633, 0xFFCC6633, 0xFFFF6633, 0xFF009933, 0xFF339933, 0xFF669933, 0xFF999933, 0xFFCC9933, 0xFFFF9933, 0xFF00CC33, 0xFF33CC33, 0xFF66CC33, 0xFF99CC33, 0xFFCCCC33, 0xFFFFCC33, 0xFF00FF33, 0xFF33FF33, 0xFF66FF33, 0xFF99FF33, 0xFFCCFF33, 0xFFFFFF33, 0xFF000066, 0xFF330066, 0xFF660066, 0xFF990066, 0xFFCC0066, 0xFFFF0066, 0xFF003366, 0xFF333366, 0xFF663366, 0xFF993366, 0xFFCC3366, 0xFFFF3366, 0xFF006666, 0xFF336666, 0xFF666666, 0xFF996666, 0xFFCC6666, 0xFFFF6666, 0xFF009966, 0xFF339966, 0xFF669966, 0xFF999966, 0xFFCC9966, 0xFFFF9966, 0xFF00CC66, 0xFF33CC66, 0xFF66CC66, 0xFF99CC66, 0xFFCCCC66, 0xFFFFCC66, 0xFF00FF66, 0xFF33FF66, 0xFF66FF66, 0xFF99FF66, 0xFFCCFF66, 0xFFFFFF66, 0xFF000099, 0xFF330099, 0xFF660099, 0xFF990099, 0xFFCC0099, 0xFFFF0099, 0xFF003399, 0xFF333399, 0xFF663399, 0xFF993399, 0xFFCC3399, 0xFFFF3399, 0xFF006699, 0xFF336699, 0xFF666699, 0xFF996699, 0xFFCC6699, 0xFFFF6699, 0xFF009999, 0xFF339999, 0xFF669999, 0xFF999999, 0xFFCC9999, 0xFFFF9999, 0xFF00CC99, 0xFF33CC99, 0xFF66CC99, 0xFF99CC99, 0xFFCCCC99, 0xFFFFCC99, 0xFF00FF99, 0xFF33FF99, 0xFF66FF99, 0xFF99FF99, 0xFFCCFF99, 0xFFFFFF99, 0xFF0000CC, 0xFF3300CC, 0xFF6600CC, 0xFF9900CC, 0xFFCC00CC, 0xFFFF00CC, 0xFF0033CC, 0xFF3333CC, 0xFF6633CC, 0xFF9933CC, 0xFFCC33CC, 0xFFFF33CC, 0xFF0066CC, 0xFF3366CC, 0xFF6666CC, 0xFF9966CC, 0xFFCC66CC, 0xFFFF66CC, 0xFF0099CC, 0xFF3399CC, 0xFF6699CC, 0xFF9999CC, 0xFFCC99CC, 0xFFFF99CC, 0xFF00CCCC, 0xFF33CCCC, 0xFF66CCCC, 0xFF99CCCC, 0xFFCCCCCC, 0xFFFFCCCC, 0xFF00FFCC, 0xFF33FFCC, 0xFF66FFCC, 0xFF99FFCC, 0xFFCCFFCC, 0xFFFFFFCC, 0xFF3300FF, 0xFF6600FF, 0xFF9900FF, 0xFFCC00FF, 0xFF0033FF, 0xFF3333FF, 0xFF6633FF, 0xFF9933FF, 0xFFCC33FF, 0xFFFF33FF, 0xFF0066FF, 0xFF3366FF, 0xFF6666FF, 0xFF9966FF, 0xFFCC66FF, 0xFFFF66FF, 0xFF0099FF, 0xFF3399FF, 0xFF6699FF, 0xFF9999FF, 0xFFCC99FF, 0xFFFF99FF, 0xFF00CCFF, 0xFF33CCFF, 0xFF66CCFF, 0xFF99CCFF, 0xFFCCCCFF, 0xFFFFCCFF, 0xFF33FFFF, 0xFF66FFFF, 0xFF99FFFF, 0xFFCCFFFF, 0xFF111111, 0xFF222222, 0xFF444444, 0xFF555555, 0xFF777777, 0xFF888888, 0xFFAAAAAA, 0xFFBBBBBB, 0xFFDDDDDD, 0xFFEEEEEE, 0xFF804000, 0xFFFF8000, 0xFF80FF00, 0xFF004040, 0xFF404040, 0xFF808040, 0xFFFF8040, 0xFFFF0080, 0xFF004080, 0xFFFF8080, 0xFF00FF80, 0xFF80FF80, 0xFFFFFF80, 0xFF8000FF, 0xFF0080FF, 0xFF8080FF, 0xFFFF80FF, 0xFF80FFFF, 0xFFFFFBF0, 0xFFA0A0A4, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFFFFFF00, 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF }; } public static int[] createMacintosh8() { return new int[] { 0xFFFFFFFF, 0xFFFFFFCC, 0xFFFFFF99, 0xFFFFFF66, 0xFFFFFF33, 0xFFFFFF00, 0xFFFFCCFF, 0xFFFFCCCC, 0xFFFFCC99, 0xFFFFCC66, 0xFFFFCC33, 0xFFFFCC00, 0xFFFF99FF, 0xFFFF99CC, 0xFFFF9999, 0xFFFF9966, 0xFFFF9933, 0xFFFF9900, 0xFFFF66FF, 0xFFFF66CC, 0xFFFF6699, 0xFFFF6666, 0xFFFF6633, 0xFFFF6600, 0xFFFF33FF, 0xFFFF33CC, 0xFFFF3399, 0xFFFF3366, 0xFFFF3333, 0xFFFF3300, 0xFFFF00FF, 0xFFFF00CC, 0xFFFF0099, 0xFFFF0066, 0xFFFF0033, 0xFFFF0000, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFCCFF99, 0xFFCCFF66, 0xFFCCFF33, 0xFFCCFF00, 0xFFCCCCFF, 0xFFCCCCCC, 0xFFCCCC99, 0xFFCCCC66, 0xFFCCCC33, 0xFFCCCC00, 0xFFCC99FF, 0xFFCC99CC, 0xFFCC9999, 0xFFCC9966, 0xFFCC9933, 0xFFCC9900, 0xFFCC66FF, 0xFFCC66CC, 0xFFCC6699, 0xFFCC6666, 0xFFCC6633, 0xFFCC6600, 0xFFCC33FF, 0xFFCC33CC, 0xFFCC3399, 0xFFCC3366, 0xFFCC3333, 0xFFCC3300, 0xFFCC00FF, 0xFFCC00CC, 0xFFCC0099, 0xFFCC0066, 0xFFCC0033, 0xFFCC0000, 0xFF99FFFF, 0xFF99FFCC, 0xFF99FF99, 0xFF99FF66, 0xFF99FF33, 0xFF99FF00, 0xFF99CCFF, 0xFF99CCCC, 0xFF99CC99, 0xFF99CC66, 0xFF99CC33, 0xFF99CC00, 0xFF9999FF, 0xFF9999CC, 0xFF999999, 0xFF999966, 0xFF999933, 0xFF999900, 0xFF9966FF, 0xFF9966CC, 0xFF996699, 0xFF996666, 0xFF996633, 0xFF996600, 0xFF9933FF, 0xFF9933CC, 0xFF993399, 0xFF993366, 0xFF993333, 0xFF993300, 0xFF9900FF, 0xFF9900CC, 0xFF990099, 0xFF990066, 0xFF990033, 0xFF990000, 0xFF66FFFF, 0xFF66FFCC, 0xFF66FF99, 0xFF66FF66, 0xFF66FF33, 0xFF66FF00, 0xFF66CCFF, 0xFF66CCCC, 0xFF66CC99, 0xFF66CC66, 0xFF66CC33, 0xFF66CC00, 0xFF6699FF, 0xFF6699CC, 0xFF669999, 0xFF669966, 0xFF669933, 0xFF669900, 0xFF6666FF, 0xFF6666CC, 0xFF666699, 0xFF666666, 0xFF666633, 0xFF666600, 0xFF6633FF, 0xFF6633CC, 0xFF663399, 0xFF663366, 0xFF663333, 0xFF663300, 0xFF6600FF, 0xFF6600CC, 0xFF660099, 0xFF660066, 0xFF660033, 0xFF660000, 0xFF33FFFF, 0xFF33FFCC, 0xFF33FF99, 0xFF33FF66, 0xFF33FF33, 0xFF33FF00, 0xFF33CCFF, 0xFF33CCCC, 0xFF33CC99, 0xFF33CC66, 0xFF33CC33, 0xFF33CC00, 0xFF3399FF, 0xFF3399CC, 0xFF339999, 0xFF339966, 0xFF339933, 0xFF339900, 0xFF3366FF, 0xFF3366CC, 0xFF336699, 0xFF336666, 0xFF336633, 0xFF336600, 0xFF3333FF, 0xFF3333CC, 0xFF333399, 0xFF333366, 0xFF333333, 0xFF333300, 0xFF3300FF, 0xFF3300CC, 0xFF330099, 0xFF330066, 0xFF330033, 0xFF330000, 0xFF00FFFF, 0xFF00FFCC, 0xFF00FF99, 0xFF00FF66, 0xFF00FF33, 0xFF00FF00, 0xFF00CCFF, 0xFF00CCCC, 0xFF00CC99, 0xFF00CC66, 0xFF00CC33, 0xFF00CC00, 0xFF0099FF, 0xFF0099CC, 0xFF009999, 0xFF009966, 0xFF009933, 0xFF009900, 0xFF0066FF, 0xFF0066CC, 0xFF006699, 0xFF006666, 0xFF006633, 0xFF006600, 0xFF0033FF, 0xFF0033CC, 0xFF003399, 0xFF003366, 0xFF003333, 0xFF003300, 0xFF0000FF, 0xFF0000CC, 0xFF000099, 0xFF000066, 0xFF000033, 0xFFEE0000, 0xFFDD0000, 0xFFBB0000, 0xFFAA0000, 0xFF880000, 0xFF770000, 0xFF550000, 0xFF440000, 0xFF220000, 0xFF110000, 0xFF00EE00, 0xFF00DD00, 0xFF00BB00, 0xFF00AA00, 0xFF008800, 0xFF007700, 0xFF005500, 0xFF004400, 0xFF002200, 0xFF001100, 0xFF0000EE, 0xFF0000DD, 0xFF0000BB, 0xFF0000AA, 0xFF000088, 0xFF000077, 0xFF000055, 0xFF000044, 0xFF000022, 0xFF000011, 0xFFEEEEEE, 0xFFDDDDDD, 0xFFBBBBBB, 0xFFAAAAAA, 0xFF888888, 0xFF777777, 0xFF555555, 0xFF444444, 0xFF222222, 0xFF111111, 0xFF000000 }; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/ConvertKeyboard.java000066400000000000000000000036531506470510200307100ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; public class ConvertKeyboard { public static void main(String[] args) { KeyboardFormat inFormat = null, outFormat = null; File inFile = null, outFile = null; boolean parseOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parseOptions && arg.startsWith("-")) { if (arg.equals("--")) { parseOptions = false; } else if (arg.equalsIgnoreCase("-if") && argi < args.length) { inFormat = KeyboardFormat.forInputFormatName(args[argi++]); } else if (arg.equalsIgnoreCase("-of") && argi < args.length) { outFormat = KeyboardFormat.forOutputFormatName(args[argi++]); } else if (arg.equalsIgnoreCase("-i") && argi < args.length) { inFile = new File(args[argi++]); } else if (arg.equalsIgnoreCase("-o") && argi < args.length) { outFile = new File(args[argi++]); } else { printHelp(); return; } } else if (inFile == null) { inFile = new File(arg); } else if (outFile == null) { outFile = new File(arg); } else { printHelp(); return; } } if (inFile == null || outFile == null) { printHelp(); return; } if (inFormat == null) inFormat = KeyboardFormat.forInputFile(inFile); if (outFormat == null) outFormat = KeyboardFormat.forOutputFile(outFile); if (inFormat == null || outFormat == null) { printHelp(); return; } KeyboardMapping km; try { km = inFormat.read(inFile); } catch (IOException e) { System.err.println("Error reading: " + e.getMessage()); return; } km.autoFill(); try { outFormat.write(outFile, km); } catch (IOException e) { System.err.println("Error writing: " + e.getMessage()); return; } } private static void printHelp() { System.err.println("Usage: ConvertKeyboard [-if ] [-of ]"); System.err.println(" [-i] [-o] "); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/DeadKeyTable.java000066400000000000000000000020621506470510200300560ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.LinkedHashMap; import java.util.Map; public class DeadKeyTable { public int winTerminator; public int macTerminator; public String macStateId; public int xkbOutput; public XkbDeadKey xkbDeadKey; public final Map keyMap; public DeadKeyTable() { this.winTerminator = -1; this.macTerminator = -1; this.macStateId = null; this.xkbOutput = -1; this.xkbDeadKey = XkbDeadKey.none; this.keyMap = new LinkedHashMap(); } public DeadKeyTable(int u) { this.winTerminator = u; this.macTerminator = u; this.macStateId = (u < 0) ? null : XkbKeySym.MAP.getKeySym(u); this.xkbOutput = u; this.xkbDeadKey = (u < 0) ? XkbDeadKey.none : XkbDeadKey.forUnicode(u); this.keyMap = new LinkedHashMap(); } public void setTerminator(int u) { this.winTerminator = u; this.macTerminator = u; this.macStateId = (u < 0) ? null : XkbKeySym.MAP.getKeySym(u); this.xkbOutput = u; this.xkbDeadKey = (u < 0) ? XkbDeadKey.none : XkbDeadKey.forUnicode(u); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/DumpChars.java000066400000000000000000000047261506470510200274770ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.TreeSet; import com.kreative.unicode.data.NameResolver; public class DumpChars { public static void main(String[] args) throws IOException { KeyboardFormat inFormat = null; ArrayList inFiles = new ArrayList(); boolean includeDeadKeys = true; boolean includeLongPress = false; boolean verbose = false; boolean parseOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parseOptions && arg.startsWith("-")) { if (arg.equals("--")) { parseOptions = false; } else if (arg.equalsIgnoreCase("-f") && argi < args.length) { inFormat = KeyboardFormat.forInputFormatName(args[argi++]); } else if (arg.equalsIgnoreCase("-i") && argi < args.length) { inFiles.add(new File(args[argi++])); } else if (arg.equals("-d")) { includeDeadKeys = true; } else if (arg.equals("-D")) { includeDeadKeys = false; } else if (arg.equals("-l")) { includeLongPress = true; } else if (arg.equals("-L")) { includeLongPress = false; } else if (arg.equals("-v")) { verbose = true; } else if (arg.equals("-V")) { verbose = false; } else { System.err.println("Unknown option: "+ arg); return; } } else { inFiles.add(new File(arg)); } } TreeSet all = new TreeSet(); for (File file : inFiles) { KeyboardFormat format = inFormat; if (format == null) { format = KeyboardFormat.forInputFile(file); if (format == null) { System.err.println("Error reading " + file + ": Unknown format"); continue; } } try { KeyboardMapping km = format.read(file); km.getAllOutputs(all, includeDeadKeys, includeLongPress); } catch (IOException e) { System.err.println("Error reading " + file + ": " + e); continue; } } PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"), true); for (int output : all) { if (output >= 32) { if (verbose) { String h = Integer.toHexString(output); while (h.length() < 4) h = "0" + h; out.print("U+" + h.toUpperCase() + "\t"); } out.print(Character.toChars(output)); if (verbose) { String n = NameResolver.instance(output).getName(output); out.println("\t" + n); } } } if (!verbose) out.println(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/HTMLWriter.java000066400000000000000000000561351506470510200275530ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.BitSet; import java.util.Map; import java.util.Scanner; import com.kreative.unicode.data.NameResolver; public class HTMLWriter { public static void writeStandalone(File file, KeyboardMapping km) throws IOException { write(file, km, true, false); } public static void writeKeymanHTM(File file, KeyboardMapping km) throws IOException { write(file, km, false, false); } public static void writeKeymanPHP(File file, KeyboardMapping km) throws IOException { write(file, km, false, true); } private static void write(File file, KeyboardMapping km, boolean install, boolean keymanPHP) throws IOException { FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write(pw, km, install, keymanPHP); pw.flush(); pw.close(); fos.close(); if (km.htmlSquareChars != null && !km.htmlSquareChars.isEmpty()) { File fontFile = new File(file.getParentFile(), "KreativeSquare.ttf"); FileOutputStream fontOut = new FileOutputStream(fontFile); InputStream fontIn = HTMLWriter.class.getResourceAsStream("ksquare.ttf"); int read; byte[] buf = new byte[65536]; while ((read = fontIn.read(buf)) >= 0) fontOut.write(buf, 0, read); fontIn.close(); fontOut.flush(); fontOut.close(); } } public static void writeStandalone(PrintWriter out, KeyboardMapping km) { write(out, km, true, false); } public static void writeKeymanHTM(PrintWriter out, KeyboardMapping km) { write(out, km, false, false); } public static void writeKeymanPHP(PrintWriter out, KeyboardMapping km) { write(out, km, false, true); } private static void write(PrintWriter out, KeyboardMapping km, boolean install, boolean keymanPHP) { String t = (km.htmlTitle == null || km.htmlTitle.length() == 0) ? (km.getNameNotEmpty() + " Keyboard Layout") : km.htmlTitle; String h1 = (km.htmlH1 == null || km.htmlH1.length() == 0) ? (km.getNameNotEmpty() + " Keyboard Layout") : km.htmlH1; String h2 = (km.htmlH2 == null || km.htmlH2.length() == 0) ? (install ? "for Mac OS X, Linux, and Windows" : "for Keyman") : km.htmlH2; String prefix; if (keymanPHP) { out.println(""); prefix = ""; } else { out.println(""); out.println(""); out.println("\t"); out.println("\t\t"); out.println("\t\t" + HTMLWriterUtility.htmlSpecialChars(t) + ""); out.println("\t\t"); out.println("\t"); out.println("\t"); out.println("\t\t

" + HTMLWriterUtility.htmlSpecialChars(h1) + "

"); prefix = "\t\t"; } out.println(prefix + "

" + HTMLWriterUtility.htmlSpecialChars(h2) + "

"); writeInline(out, prefix, km.htmlBody1); out.println(prefix + "

The Layout

"); writeInline(out, prefix, km.htmlBody2); writeKeyboard(out, km); writeInline(out, prefix, km.htmlBody3); if (install) { if (km.htmlInstall != null && km.htmlInstall.length() > 0) { writeInline(out, prefix, km.htmlInstall); } else { String rn = km.isWindowsNativeCompatible() ? "install.html" : "install-nonbmp.html"; writeResource(out, prefix, rn, km); } } writeInline(out, prefix, km.htmlBody4); out.println(prefix + ""); if (!keymanPHP) { out.println("\t"); out.println(""); } } private static void writeKeyboard(PrintWriter out, KeyboardMapping km) { out.println("\t\t"); out.println("\t\t\t"); writeRowTop(out, km, NUMROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); writeRowBot(out, km, NUMROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowTop(out, km, TOPROW); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowBot(out, km, TOPROW); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowTop(out, km, HOMEROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowBot(out, km, HOMEROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowTop(out, km, BOTROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); writeRowBot(out, km, BOTROW); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println(spaceTop(km, 26)); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println(spaceBot(km, 26)); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println(linuxModTop(km, 6, XkbComposeKey.lctrl)); out.println(linuxModTop(km, 5, XkbComposeKey.lwin, XkbAltGrKey.lwin_switch, XkbAltGrKey.win_switch)); out.println(linuxModTop(km, 5, null, XkbAltGrKey.lalt_switch, XkbAltGrKey.alt_switch)); out.println(spaceTop(km, 23)); out.println(linuxModTop(km, 5, XkbComposeKey.ralt, XkbAltGrKey.ralt_switch, XkbAltGrKey.alt_switch)); out.println(linuxModTop(km, 5, XkbComposeKey.rwin, XkbAltGrKey.rwin_switch, XkbAltGrKey.win_switch)); out.println(linuxModTop(km, 5, XkbComposeKey.menu, XkbAltGrKey.menu_switch)); out.println(linuxModTop(km, 6, XkbComposeKey.rctrl)); out.println("\t\t\t"); out.println("\t\t\t"); out.println(linuxModBot(km, 6, "ctrl", XkbComposeKey.lctrl)); out.println(linuxModBot(km, 5, "❖", XkbComposeKey.lwin, XkbAltGrKey.lwin_switch, XkbAltGrKey.win_switch)); out.println(linuxModBot(km, 5, "alt", null, XkbAltGrKey.lalt_switch, XkbAltGrKey.alt_switch)); out.println(spaceBot(km, 23)); out.println(linuxModBot(km, 5, "alt", XkbComposeKey.ralt, XkbAltGrKey.ralt_switch, XkbAltGrKey.alt_switch)); out.println(linuxModBot(km, 5, "❖", XkbComposeKey.rwin, XkbAltGrKey.rwin_switch, XkbAltGrKey.win_switch)); out.println(linuxModBot(km, 5, "▤", XkbComposeKey.menu, XkbAltGrKey.menu_switch)); out.println(linuxModBot(km, 6, "ctrl", XkbComposeKey.rctrl)); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println(spaceTop(km, 23)); out.println(winModTop(km)); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println(spaceBot(km, 23)); out.println(winModBot(km)); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t\t"); out.println("\t\t\t"); out.println("\t\t
"); out.println("\t\t\t\t\tdelete"); out.println("\t\t\t\t\tbackspace"); out.println("\t\t\t\t
tab
caps lock"); out.println("\t\t\t\t\treturn"); out.println("\t\t\t\t\tenter"); out.println("\t\t\t\t
shiftshift
controloptioncommandcommandoptioncontrol
ctrlaltctrl
"); } private static void writeInline(PrintWriter out, String prefix, String content) { if (content != null) { for (String line : content.split("\r\n|\r|\n")) { out.println(prefix + line); } } } private static void writeResource(PrintWriter out, String prefix, String name, KeyboardMapping km) { Scanner scan = HTMLWriterUtility.getTemplate(name); while (scan.hasNextLine()) out.println(prefix + HTMLWriterUtility.replaceFields(scan.nextLine(), km)); scan.close(); } private static void writeRowTop(PrintWriter out, KeyboardMapping km, Key... keys) { for (Key key : keys) { KeyMapping m = km.map.get(key); String l = olcpString(km, m.shiftedOutput, m.shiftedDeadKey ); String r = olcpString(km, m.altShiftedOutput, m.altShiftedDeadKey); String lc = classString(km, m.shiftedOutput, m.shiftedDeadKey, "tl"); String rc = classString(km, m.altShiftedOutput, m.altShiftedDeadKey, "tr"); String span = "\"" + ((key == Key.BACKSLASH) ? 3 : 2) + "\""; out.println("\t\t\t\t" + l + ""); out.println("\t\t\t\t" + r + ""); } } private static void writeRowBot(PrintWriter out, KeyboardMapping km, Key... keys) { for (Key key : keys) { KeyMapping m = km.map.get(key); String l = olcpString(km, m.unshiftedOutput, m.unshiftedDeadKey ); String r = olcpString(km, m.altUnshiftedOutput, m.altUnshiftedDeadKey); String lc = classString(km, m.unshiftedOutput, m.unshiftedDeadKey, "bl"); String rc = classString(km, m.altUnshiftedOutput, m.altUnshiftedDeadKey, "br"); String span = "\"" + ((key == Key.BACKSLASH) ? 3 : 2) + "\""; out.println("\t\t\t\t" + l + ""); out.println("\t\t\t\t" + r + ""); } } private static String olcpString(KeyboardMapping km, int output, DeadKeyTable dead) { String s = cpString(output, dead, km.htmlCpLabels); if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } if (output > 0) { ArrayList classes = new ArrayList(); if (km.htmlOutlineChars != null && km.htmlOutlineChars.get(output)) { classes.add("ol"); } if (km.htmlSpanClasses != null) { for (Map.Entry e : km.htmlSpanClasses.entrySet()) { if (e.getValue() != null && e.getValue().get(output)) { classes.add(e.getKey()); } } } if (!classes.isEmpty()) { StringBuffer sb = new StringBuffer(); sb.append(""); sb.append(s); sb.append(""); s = sb.toString(); } } return s; } private static String classString(KeyboardMapping km, int output, DeadKeyTable dead, String base) { StringBuffer sb = new StringBuffer("\""); sb.append(base); if (dead != null) { sb.append(" d"); if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } if (output > 0) { if (km.htmlSquareChars != null && km.htmlSquareChars.get(output)) { sb.append(" ksq"); } if (km.htmlTdClasses != null) { for (Map.Entry e : km.htmlTdClasses.entrySet()) { if (e.getValue() != null && e.getValue().get(output)) { sb.append(" "); sb.append(e.getKey()); } } } } sb.append("\""); return sb.toString(); } private static String spaceTop(KeyboardMapping km, int span) { KeyMapping m = km.map.get(Key.SPACE); String bu = cpString(m.unshiftedOutput, m.unshiftedDeadKey, km.htmlCpLabels); String bs = cpString(m.shiftedOutput, m.shiftedDeadKey, km.htmlCpLabels); String b = bu.equals(bs) ? bu : (bu + " / " + bs); String tu = cpString(m.altUnshiftedOutput, m.altUnshiftedDeadKey, km.htmlCpLabels); String ts = cpString(m.altShiftedOutput, m.altShiftedDeadKey, km.htmlCpLabels); String t = tu.equals(ts) ? tu : (tu + " / " + ts); if (t.equals(b)) { String c = (m.unshiftedDeadKey == null && m.shiftedDeadKey == null) ? "\"t\"" : "\"t d\""; return "\t\t\t\t"; } else { String c = (m.altUnshiftedDeadKey == null && m.altShiftedDeadKey == null) ? "\"t\"" : "\"t d\""; return "\t\t\t\t" + t + ""; } } private static String spaceBot(KeyboardMapping km, int span) { KeyMapping m = km.map.get(Key.SPACE); String bu = cpString(m.unshiftedOutput, m.unshiftedDeadKey, km.htmlCpLabels); String bs = cpString(m.shiftedOutput, m.shiftedDeadKey, km.htmlCpLabels); String b = bu.equals(bs) ? bu : (bu + " / " + bs); String c = (m.unshiftedDeadKey == null && m.shiftedDeadKey == null) ? "\"b\"" : "\"b d\""; return "\t\t\t\t" + b + ""; } private static String winModTop(KeyboardMapping km) { String c = km.winAltGrEnable ? "\"t o\"" : "\"t m\""; return "\t\t\t\t"; } private static String winModBot(KeyboardMapping km) { String c = km.winAltGrEnable ? "\"b o\"" : "\"b m\""; String label = km.winAltGrEnable ? "alt gr" : "alt"; return "\t\t\t\t" + label + ""; } private static String linuxModTop(KeyboardMapping km, int span, XkbComposeKey compose, XkbAltGrKey... altgr) { boolean isCompose = (compose != null && km.xkbComposeKey == compose); boolean isAltGr = false; for (XkbAltGrKey a : altgr) if (km.xkbAltGrKey == a) isAltGr = true; String c = (isAltGr || isCompose) ? "\"t o\"" : "\"t m\""; return "\t\t\t\t"; } private static String linuxModBot(KeyboardMapping km, int span, String label, XkbComposeKey compose, XkbAltGrKey... altgr) { boolean isCompose = (compose != null && km.xkbComposeKey == compose); boolean isAltGr = false; for (XkbAltGrKey a : altgr) if (km.xkbAltGrKey == a) isAltGr = true; if (isCompose) label = "compose"; else if (isAltGr) label = "alt gr"; String c = (isAltGr || isCompose) ? "\"b o\"" : "\"b m\""; return "\t\t\t\t" + label + ""; } private static String cpString(int output, DeadKeyTable dead, Map cpLabels) { if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } if (output <= 0) return ""; if (cpLabels.containsKey(output)) return cpLabels.get(output); if (output >= 0xFE00 && output <= 0xFE0F) return "vs" + (output - 0xFE00 + 1); if (output >= 0xE0100 && output <= 0xE01EF) return "vs" + (output - 0xE0100 + 17); switch (output) { case 0x00: return "nul"; case 0x01: return "soh"; case 0x02: return "stx"; case 0x03: return "etx"; case 0x04: return "eot"; case 0x05: return "enq"; case 0x06: return "ack"; case 0x07: return "bel"; case 0x08: return "bs"; case 0x09: return "ht"; case 0x0A: return "lf"; case 0x0B: return "vt"; case 0x0C: return "ff"; case 0x0D: return "cr"; case 0x0E: return "so"; case 0x0F: return "si"; case 0x10: return "dle"; case 0x11: return "dc1"; case 0x12: return "dc2"; case 0x13: return "dc3"; case 0x14: return "dc4"; case 0x15: return "nak"; case 0x16: return "syn"; case 0x17: return "etb"; case 0x18: return "can"; case 0x19: return "em"; case 0x1A: return "sub"; case 0x1B: return "esc"; case 0x1C: return "fs"; case 0x1D: return "gs"; case 0x1E: return "rs"; case 0x1F: return "us"; case 0x20: return "space"; case 0x26: return "&"; case 0x3C: return "<"; case 0x3E: return ">"; case 0x7F: return "del"; case 0x80: return "pad"; case 0x81: return "hop"; case 0x82: return "bph"; case 0x83: return "nbh"; case 0x84: return "ind"; case 0x85: return "nel"; case 0x86: return "ssa"; case 0x87: return "esa"; case 0x88: return "hts"; case 0x89: return "htj"; case 0x8A: return "vts"; case 0x8B: return "pld"; case 0x8C: return "plu"; case 0x8D: return "ri"; case 0x8E: return "ss2"; case 0x8F: return "ss3"; case 0x90: return "dcs"; case 0x91: return "pu1"; case 0x92: return "pu2"; case 0x93: return "sts"; case 0x94: return "cch"; case 0x95: return "mw"; case 0x96: return "spa"; case 0x97: return "epa"; case 0x98: return "sos"; case 0x99: return "sgc"; case 0x9A: return "sci"; case 0x9B: return "csi"; case 0x9C: return "st"; case 0x9D: return "osc"; case 0x9E: return "pm"; case 0x9F: return "apc"; case 0xA0: return "nbsp"; case 0xAD: return "-"; case 0x02DE: return "◌˞"; case 0x034F: return "cgj"; case 0x061C: return "alm"; case 0x070F: return "sam"; case 0x115F: return "hcf"; case 0x1160: return "hjf"; case 0x17B4: return "kivaq"; case 0x17B5: return "kivaa"; case 0x180B: return "fvs1"; case 0x180C: return "fvs2"; case 0x180D: return "fvs3"; case 0x180E: return "mvs"; case 0x180F: return "fvs4"; case 0x2000: return "nqsp"; case 0x2001: return "mqsp"; case 0x2002: return "ensp"; case 0x2003: return "emsp"; case 0x2004: return "3/msp"; case 0x2005: return "4/msp"; case 0x2006: return "6/msp"; case 0x2007: return "fsp"; case 0x2008: return "psp"; case 0x2009: return "thsp"; case 0x200A: return "hsp"; case 0x200B: return "zwsp"; case 0x200C: return "zwnj"; case 0x200D: return "zwj"; case 0x200E: return "lrm"; case 0x200F: return "rlm"; case 0x2028: return "lsep"; case 0x2029: return "psep"; case 0x202A: return "lre"; case 0x202B: return "rle"; case 0x202C: return "pdf"; case 0x202D: return "lro"; case 0x202E: return "rlo"; case 0x202F: return "nnbsp"; case 0x205F: return "mmsp"; case 0x2060: return "wj"; case 0x2066: return "lri"; case 0x2067: return "rli"; case 0x2068: return "fsi"; case 0x2069: return "pdi"; case 0x206A: return "iss"; case 0x206B: return "ass"; case 0x206C: return "iafs"; case 0x206D: return "aafs"; case 0x206E: return "nads"; case 0x206F: return "nods"; case 0x3000: return "idsp"; case 0x3164: return "hf"; case 0xFEFF: return "zwnbsp"; case 0xFFA0: return "hwhf"; case 0xFFF0: return "cd"; case 0xFFF1: return "rd"; case 0xFFF2: return "pd"; case 0xFFF3: return "sd"; case 0xFFF9: return "iaa"; case 0xFFFA: return "ias"; case 0xFFFB: return "iat"; case 0xFFFC: return "obj"; case 0x1107F: return "bnj"; case 0x16FE4: return "kssf"; case 0x1BC9D: return "dtls"; case 0x1D159: return "msnn"; case 0x1D173: return "msbb"; case 0x1D174: return "mseb"; case 0x1D175: return "msbt"; case 0x1D176: return "mset"; case 0x1D177: return "msbs"; case 0x1D178: return "mses"; case 0x1D179: return "msbp"; case 0x1D17A: return "msep"; case 0x1DA9B: return "swf2"; case 0x1DA9C: return "swf3"; case 0x1DA9D: return "swf4"; case 0x1DA9E: return "swf5"; case 0x1DA9F: return "swf6"; case 0x1DAA1: return "swr2"; case 0x1DAA2: return "swr3"; case 0x1DAA3: return "swr4"; case 0x1DAA4: return "swr5"; case 0x1DAA5: return "swr6"; case 0x1DAA6: return "swr7"; case 0x1DAA7: return "swr8"; case 0x1DAA8: return "swr9"; case 0x1DAA9: return "swr10"; case 0x1DAAA: return "swr11"; case 0x1DAAB: return "swr12"; case 0x1DAAC: return "swr13"; case 0x1DAAD: return "swr14"; case 0x1DAAE: return "swr15"; case 0x1DAAF: return "swr16"; } String s = String.valueOf(Character.toChars(output)); NameResolver r = NameResolver.instance(output); if (r.getCategory(output).startsWith("M")) { // Combining Mark s = "◌" + s; String ccc = r.getCombiningClass(output); if (ccc.equals("233") || ccc.equals("234")) { // Double Combining Mark s = s + "◌"; } } return s; } private static final Key[] NUMROW = { Key.GRAVE_TILDE, Key.NUMROW_1, Key.NUMROW_2, Key.NUMROW_3, Key.NUMROW_4, Key.NUMROW_5, Key.NUMROW_6, Key.NUMROW_7, Key.NUMROW_8, Key.NUMROW_9, Key.NUMROW_0, Key.HYPHEN_UNDERSCORE, Key.EQUALS_PLUS }; private static final Key[] TOPROW = { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P, Key.LEFT_BRACKET, Key.RIGHT_BRACKET, Key.BACKSLASH }; private static final Key[] HOMEROW = { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L, Key.SEMICOLON, Key.QUOTE }; private static final Key[] BOTROW = { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M, Key.COMMA, Key.PERIOD, Key.SLASH }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/HTMLWriterUtility.java000066400000000000000000000040021506470510200311210ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class HTMLWriterUtility { private HTMLWriterUtility() {} public static Scanner getTemplate(String name) { return new Scanner(HTMLWriterUtility.class.getResourceAsStream(name), "UTF-8"); } private static Pattern FIELD_PATTERN = Pattern.compile("[{][{]([^}]+)[}][}]"); public static String replaceFields(String s, KeyboardMapping km) { StringBuffer sb = new StringBuffer(); Matcher m = FIELD_PATTERN.matcher(s); while (m.find()) { String field = m.group(1).trim(); String repl = m.group(); if (field.equalsIgnoreCase("name")) repl = htmlSpecialChars(km.getNameNotEmpty()); if (field.equalsIgnoreCase("shortname")) repl = htmlSpecialChars(km.getWinIdentifierNotEmpty()); if (field.equalsIgnoreCase("copyright")) repl = htmlSpecialChars(km.getWinCopyrightNotEmpty()); if (field.equalsIgnoreCase("company")) repl = htmlSpecialChars(km.getWinCompanyNotEmpty()); if (field.equalsIgnoreCase("lang")) repl = htmlSpecialChars(km.getWinLocaleNotNull().tag); if (field.equalsIgnoreCase("locale")) repl = htmlSpecialChars(km.getWinLocaleNotNull().name); if (field.equalsIgnoreCase("path")) repl = htmlSpecialChars(km.getXkbPathNotEmpty()); if (field.equalsIgnoreCase("label")) repl = htmlSpecialChars(km.getXkbLabelNotEmpty()); if (field.equalsIgnoreCase("comment")) repl = htmlSpecialChars(km.xkbComment); m.appendReplacement(sb, repl); } m.appendTail(sb); return sb.toString(); } public static String htmlSpecialChars(String s) { if (s == null) return ""; StringBuffer sb = new StringBuffer(); for (char ch : s.toCharArray()) { switch (ch) { case '&': sb.append("&"); break; case '<': sb.append("<"); break; case '>': sb.append(">"); break; case '"': sb.append("""); break; case '\'': sb.append("'"); break; case '\n': sb.append("
"); break; default: sb.append(ch); } } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/Key.java000066400000000000000000000122731506470510200263350ustar00rootroot00000000000000package com.kreative.keyedit; public enum Key { GRAVE_TILDE ('`', '~', -1, -1, -1, KeyBlock.ALPHA), NUMROW_1 ('1', '!', -1, -1, -1, KeyBlock.ALPHA), NUMROW_2 ('2', '@', '@'&0x1F, -1, -1, KeyBlock.ALPHA), NUMROW_3 ('3', '#', -1, -1, -1, KeyBlock.ALPHA), NUMROW_4 ('4', '$', -1, -1, -1, KeyBlock.ALPHA), NUMROW_5 ('5', '%', -1, -1, -1, KeyBlock.ALPHA), NUMROW_6 ('6', '^', '^'&0x1F, -1, -1, KeyBlock.ALPHA), NUMROW_7 ('7', '&', -1, -1, -1, KeyBlock.ALPHA), NUMROW_8 ('8', '*', -1, -1, -1, KeyBlock.ALPHA), NUMROW_9 ('9', '(', -1, -1, -1, KeyBlock.ALPHA), NUMROW_0 ('0', ')', -1, -1, -1, KeyBlock.ALPHA), HYPHEN_UNDERSCORE ('-', '_', '_'&0x1F, -1, -1, KeyBlock.ALPHA), EQUALS_PLUS ('=', '+', -1, -1, -1, KeyBlock.ALPHA), Q ('q', 'Q', 'Q'&0x1F, -1, -1, KeyBlock.ALPHA), W ('w', 'W', 'W'&0x1F, -1, -1, KeyBlock.ALPHA), E ('e', 'E', 'E'&0x1F, -1, -1, KeyBlock.ALPHA), R ('r', 'R', 'R'&0x1F, -1, -1, KeyBlock.ALPHA), T ('t', 'T', 'T'&0x1F, -1, -1, KeyBlock.ALPHA), Y ('y', 'Y', 'Y'&0x1F, -1, -1, KeyBlock.ALPHA), U ('u', 'U', 'U'&0x1F, -1, -1, KeyBlock.ALPHA), I ('i', 'I', 'I'&0x1F, -1, -1, KeyBlock.ALPHA), O ('o', 'O', 'O'&0x1F, -1, -1, KeyBlock.ALPHA), P ('p', 'P', 'P'&0x1F, -1, -1, KeyBlock.ALPHA), LEFT_BRACKET ('[', '{', '['&0x1F, -1, -1, KeyBlock.ALPHA), RIGHT_BRACKET (']', '}', ']'&0x1F, -1, -1, KeyBlock.ALPHA), BACKSLASH ('\\','|','\\'&0x1F, -1, -1, KeyBlock.ALPHA), A ('a', 'A', 'A'&0x1F, -1, -1, KeyBlock.ALPHA), S ('s', 'S', 'S'&0x1F, -1, -1, KeyBlock.ALPHA), D ('d', 'D', 'D'&0x1F, -1, -1, KeyBlock.ALPHA), F ('f', 'F', 'F'&0x1F, -1, -1, KeyBlock.ALPHA), G ('g', 'G', 'G'&0x1F, -1, -1, KeyBlock.ALPHA), H ('h', 'H', 'H'&0x1F, -1, -1, KeyBlock.ALPHA), J ('j', 'J', 'J'&0x1F, -1, -1, KeyBlock.ALPHA), K ('k', 'K', 'K'&0x1F, -1, -1, KeyBlock.ALPHA), L ('l', 'L', 'L'&0x1F, -1, -1, KeyBlock.ALPHA), SEMICOLON (';', ':', -1, -1, -1, KeyBlock.ALPHA), QUOTE ('\'','"', -1, -1, -1, KeyBlock.ALPHA), Z ('z', 'Z', 'Z'&0x1F, -1, -1, KeyBlock.ALPHA), X ('x', 'X', 'X'&0x1F, -1, -1, KeyBlock.ALPHA), C ('c', 'C', 'C'&0x1F, -1, -1, KeyBlock.ALPHA), V ('v', 'V', 'V'&0x1F, -1, -1, KeyBlock.ALPHA), B ('b', 'B', 'B'&0x1F, -1, -1, KeyBlock.ALPHA), N ('n', 'N', 'N'&0x1F, -1, -1, KeyBlock.ALPHA), M ('m', 'M', 'M'&0x1F, -1, -1, KeyBlock.ALPHA), COMMA (',', '<', -1, -1, -1, KeyBlock.ALPHA), PERIOD ('.', '>', -1, -1, -1, KeyBlock.ALPHA), SLASH ('/', '?', -1, -1, -1, KeyBlock.ALPHA), SECTION (0xA7,0xB1, -1,0xA7,0xB1, KeyBlock.INTL), YEN (0xA5,'|', -1,0xA5,0xA5, KeyBlock.INTL), UNDERSCORE ('_', '_', '_'&0x1F, '_', '_', KeyBlock.INTL), BACKSLASH_102 ('\\','|','\\'&0x1F, -1, -1, KeyBlock.INTL), SPACE (' ', ' ', -1, ' ', ' ', KeyBlock.ALPHA), NUMPAD_0 ('0', '0', -1, '0', '0', KeyBlock.NUMPAD), NUMPAD_COMMA (',', ',', -1, ',', ',', KeyBlock.NUMPAD), NUMPAD_PERIOD ('.', '.', -1, '.', '.', KeyBlock.NUMPAD), NUMPAD_1 ('1', '1', -1, '1', '1', KeyBlock.NUMPAD), NUMPAD_2 ('2', '2', -1, '2', '2', KeyBlock.NUMPAD), NUMPAD_3 ('3', '3', -1, '3', '3', KeyBlock.NUMPAD), NUMPAD_4 ('4', '4', -1, '4', '4', KeyBlock.NUMPAD), NUMPAD_5 ('5', '5', -1, '5', '5', KeyBlock.NUMPAD), NUMPAD_6 ('6', '6', -1, '6', '6', KeyBlock.NUMPAD), NUMPAD_7 ('7', '7', -1, '7', '7', KeyBlock.NUMPAD), NUMPAD_8 ('8', '8', -1, '8', '8', KeyBlock.NUMPAD), NUMPAD_9 ('9', '9', -1, '9', '9', KeyBlock.NUMPAD), NUMPAD_PLUS ('+', '+', -1, '+', '+', KeyBlock.NUMPAD), NUMPAD_MINUS ('-', '-', -1, '-', '-', KeyBlock.NUMPAD), NUMPAD_TIMES ('*', '*', -1, '*', '*', KeyBlock.NUMPAD), NUMPAD_DIVIDE ('/', '/', -1, '/', '/', KeyBlock.NUMPAD), NUMPAD_EQUALS ('=', '=', -1, '=', '=', KeyBlock.NUMPAD); public final int defaultUnshifted; public final int defaultShifted; public final int defaultCtrl; public final int defaultAltUnshifted; public final int defaultAltShifted; public final KeyBlock keyBlock; private Key(int u, int s, int c, int au, int as, KeyBlock keyBlock) { this.defaultUnshifted = u; this.defaultShifted = s; this.defaultCtrl = c; this.defaultAltUnshifted = au; this.defaultAltShifted = as; this.keyBlock = keyBlock; } public static Key forName(String name) { for (Key key : values()) { if (key.name().equalsIgnoreCase(name)) { return key; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyBlock.java000066400000000000000000000001161506470510200273010ustar00rootroot00000000000000package com.kreative.keyedit; public enum KeyBlock { ALPHA, INTL, NUMPAD; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManKey.java000066400000000000000000000047221506470510200274420ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Arrays; import java.util.Collections; import java.util.List; public final class KeyManKey { public static final List KEYS = Collections.unmodifiableList(Arrays.asList( new KeyManKey("K_BKQUOTE", Key.GRAVE_TILDE), new KeyManKey("K_1", Key.NUMROW_1), new KeyManKey("K_2", Key.NUMROW_2), new KeyManKey("K_3", Key.NUMROW_3), new KeyManKey("K_4", Key.NUMROW_4), new KeyManKey("K_5", Key.NUMROW_5), new KeyManKey("K_6", Key.NUMROW_6), new KeyManKey("K_7", Key.NUMROW_7), new KeyManKey("K_8", Key.NUMROW_8), new KeyManKey("K_9", Key.NUMROW_9), new KeyManKey("K_0", Key.NUMROW_0), new KeyManKey("K_HYPHEN", Key.HYPHEN_UNDERSCORE), new KeyManKey("K_EQUAL", Key.EQUALS_PLUS), new KeyManKey("K_Q", Key.Q), new KeyManKey("K_W", Key.W), new KeyManKey("K_E", Key.E), new KeyManKey("K_R", Key.R), new KeyManKey("K_T", Key.T), new KeyManKey("K_Y", Key.Y), new KeyManKey("K_U", Key.U), new KeyManKey("K_I", Key.I), new KeyManKey("K_O", Key.O), new KeyManKey("K_P", Key.P), new KeyManKey("K_LBRKT", Key.LEFT_BRACKET), new KeyManKey("K_RBRKT", Key.RIGHT_BRACKET), new KeyManKey("K_BKSLASH", Key.BACKSLASH), new KeyManKey("K_A", Key.A), new KeyManKey("K_S", Key.S), new KeyManKey("K_D", Key.D), new KeyManKey("K_F", Key.F), new KeyManKey("K_G", Key.G), new KeyManKey("K_H", Key.H), new KeyManKey("K_J", Key.J), new KeyManKey("K_K", Key.K), new KeyManKey("K_L", Key.L), new KeyManKey("K_COLON", Key.SEMICOLON), new KeyManKey("K_QUOTE", Key.QUOTE), new KeyManKey("K_oE2", Key.BACKSLASH_102), new KeyManKey("K_Z", Key.Z), new KeyManKey("K_X", Key.X), new KeyManKey("K_C", Key.C), new KeyManKey("K_V", Key.V), new KeyManKey("K_B", Key.B), new KeyManKey("K_N", Key.N), new KeyManKey("K_M", Key.M), new KeyManKey("K_COMMA", Key.COMMA), new KeyManKey("K_PERIOD", Key.PERIOD), new KeyManKey("K_SLASH", Key.SLASH), new KeyManKey("K_SPACE", Key.SPACE) )); public final String id; public final Key key; private KeyManKey(String id, Key key) { this.id = id; this.key = key; } public static KeyManKey forId(String id) { for (KeyManKey key : KEYS) { if (key.id.equalsIgnoreCase(id)) { return key; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManPackageWriter.java000066400000000000000000000211431506470510200314360ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Map; public class KeyManPackageWriter { public static void write(File file, KeyboardMapping km, String buildPrefix) throws IOException { if (file.isDirectory()) { String basename = km.getKeymanIdentifierNotEmpty(); File packageFile = new File(file, basename + ".kps"); write(file, packageFile, basename, km, buildPrefix); } else if (file.isFile() || file.getName().contains(".")) { String basename = stripSuffix(file.getName(), ".kps"); write(file.getParentFile(), file, basename, km, buildPrefix); } else { file.mkdir(); String basename = km.getKeymanIdentifierNotEmpty(); File packageFile = new File(file, basename + ".kps"); write(file, packageFile, basename, km, buildPrefix); } } public static void write(File parentFile, File packageFile, String basename, KeyboardMapping km, String buildPrefix) throws IOException { if (buildPrefix == null) buildPrefix = ""; String kmxFileName = buildPrefix + basename + ".kmx"; String jsFileName = buildPrefix + basename.replaceAll("[^A-Za-z0-9_]", "_").toLowerCase() + ".js"; String kvkFileName = buildPrefix + basename + ".kvk"; String welcomeFileName = "welcome.htm"; String readmeFileName = "readme.htm"; File kmnFile = new File(parentFile, basename + ".kmn"); File ktlFile = new File(parentFile, basename + ".keyman-touch-layout"); File kvksFile = new File(parentFile, basename + ".kvks"); File welcomeFile = new File(parentFile, welcomeFileName); File readmeFile = new File(parentFile, readmeFileName); HTMLWriter.writeKeymanHTM(readmeFile, km); HTMLWriter.writeKeymanHTM(welcomeFile, km); KeyManVisualWriter.write(kvksFile, km); KeyManTouchWriter.write(ktlFile, km); KeyManWriter.write(kmnFile, km); ArrayList extras = new ArrayList(); if (!(km.htmlSquareChars == null || km.htmlSquareChars.isEmpty())) { extras.add("KreativeSquare.ttf"); } if (!(km.keymanAttachments == null || km.keymanAttachments.isEmpty())) { for (Map.Entry e : km.keymanAttachments.entrySet()) { FileOutputStream fos = new FileOutputStream(new File(parentFile, e.getKey())); fos.write(e.getValue()); fos.flush(); fos.close(); extras.add(e.getKey()); } } FileOutputStream fos = new FileOutputStream(packageFile); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write( pw, km, kmxFileName, jsFileName, kvkFileName, welcomeFileName, readmeFileName, extras.toArray(new String[extras.size()]) ); pw.flush(); pw.close(); fos.close(); } public static void write( PrintWriter out, KeyboardMapping km, String kmxFileName, String jsFileName, String kvkFileName, String welcomeFileName, String readmeFileName, String... extras ) { out.print("\r\n"); out.print("\r\n"); out.print(" \r\n"); out.print(" 16.0\r\n"); out.print(" 7.0\r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" " + quote(readmeFileName) + "\r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" " + quote(km.getKeymanNameNotEmpty()) + "\r\n"); out.print(" " + quote(km.getKeymanCopyrightNotEmpty()) + "\r\n"); String email = ( (km.keymanEmailAddress != null && km.keymanEmailAddress.length() > 0) ? ("mailto:" + km.keymanEmailAddress) : null ); out.print(" " + quote(km.getKeymanAuthorNotEmpty()) + "\r\n"); out.print(" \r\n"); out.print(" " + quote(km.keymanWebSite) + "\r\n"); out.print(" \r\n"); out.print(" \r\n"); if (kmxFileName != null && kmxFileName.length() > 0) { out.print(" \r\n"); out.print(" " + quote(kmxFileName) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" .kmx\r\n"); out.print(" \r\n"); } if (jsFileName != null && jsFileName.length() > 0) { out.print(" \r\n"); out.print(" " + quote(jsFileName) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" .js\r\n"); out.print(" \r\n"); } if (kvkFileName != null && kvkFileName.length() > 0) { out.print(" \r\n"); out.print(" " + quote(kvkFileName) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" .kvk\r\n"); out.print(" \r\n"); } if (welcomeFileName != null && welcomeFileName.length() > 0) { out.print(" \r\n"); out.print(" " + quote(welcomeFileName) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" .htm\r\n"); out.print(" \r\n"); } if (readmeFileName != null && readmeFileName.length() > 0) { out.print(" \r\n"); out.print(" " + quote(readmeFileName) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" .htm\r\n"); out.print(" \r\n"); } if (extras != null && extras.length > 0) { for (String extra : extras) { if (extra != null && extra.length() > 0) { String[] parts = extra.split("[\\\\/.]"); String ext = parts[parts.length - 1]; out.print(" \r\n"); out.print(" " + quote(extra) + "\r\n"); out.print(" \r\n"); out.print(" 0\r\n"); out.print(" ." + ext + "\r\n"); out.print(" \r\n"); } } } out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" " + quote(km.getKeymanNameNotEmpty()) + "\r\n"); out.print(" " + quote(km.getKeymanIdentifierNotEmpty()) + "\r\n"); out.print(" " + quote(km.getKeymanVersionNotEmpty()) + "\r\n"); if (km.keymanOSKFontFile != null && km.keymanOSKFontFile.length() > 0) { out.print(" " + quote(km.keymanOSKFontFile) + "\r\n"); } if (km.keymanDisplayFontFile != null && km.keymanDisplayFontFile.length() > 0) { out.print(" " + quote(km.keymanDisplayFontFile) + "\r\n"); } out.print(" \r\n"); if (km.keymanLanguages.isEmpty()) { out.print(" English\r\n"); } else for (Map.Entry e : km.keymanLanguages.entrySet()) { String id = e.getKey(); if (id.equals("und-fonipa")) { // Hack recommended by SIL to work around bugs in Windows. if (km.keymanLanguages.containsKey("und-Latn")) continue; id = "und-Latn"; } String name = e.getValue(); out.print(" " + quote(name) + "\r\n"); } out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print(" \r\n"); out.print("\r\n"); } private static String quote(String s) { if (s == null || s.length() == 0) return ""; return s.replace("&", "&").replace("<", "<").replace(">", ">"); } private static String aquote(String s) { if (s == null || s.length() == 0) return "\"\""; return "\"" + quote(s).replace("\"", """) + "\""; } private static String stripSuffix(String s, String suffix) { if (s.toLowerCase().endsWith(suffix.toLowerCase())) { return s.substring(0, s.length() - suffix.length()); } else { return s; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManPlatform.java000066400000000000000000000007071506470510200304750ustar00rootroot00000000000000package com.kreative.keyedit; public enum KeyManPlatform { TABLET, PHONE, DESKTOP; private final String stringValue; private KeyManPlatform() { stringValue = name().toLowerCase(); } public String toString() { return stringValue; } public static KeyManPlatform forString(String s) { if (s != null) { s = s.toLowerCase(); for (KeyManPlatform p : values()) { if (p.stringValue.equals(s)) { return p; } } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManProjectWriter.java000066400000000000000000000411021506470510200315060ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Scanner; import com.kreative.unicode.ttflib.NameTable; import com.kreative.unicode.ttflib.TtfFile; public class KeyManProjectWriter { public static void write(File file, KeyboardMapping km) throws IOException { if (file.isDirectory()) { String basename = km.getKeymanIdentifierNotEmpty(); File projectFile = new File(file, basename + ".kpj"); write(file, projectFile, basename, km); } else if (file.isFile() || file.getName().contains(".")) { String basename = stripSuffix(file.getName(), ".kpj"); write(file.getParentFile(), file, basename, km); } else { file.mkdir(); String basename = km.getKeymanIdentifierNotEmpty(); File projectFile = new File(file, basename + ".kpj"); write(file, projectFile, basename, km); } } public static void write(File parentFile, File projectFile, String basename, KeyboardMapping km) throws IOException { File sourceFile = new File(parentFile, "source"); sourceFile.mkdir(); File packageFile = new File(sourceFile, basename + ".kps"); KeyManPackageWriter.write(sourceFile, packageFile, basename, km, "..\\build\\"); File helpFile = new File(sourceFile, "help"); helpFile.mkdir(); HTMLWriter.writeKeymanPHP(new File(helpFile, basename + ".php"), km); writeHistory(new File(parentFile, "HISTORY.md"), km); writeLicense(new File(parentFile, "LICENSE.md"), km); writeReadme(new File(parentFile, "README.md"), km); writeKeyboardInfo(new File(parentFile, basename + ".keyboard_info"), km); ArrayList extras = new ArrayList(); if (!(km.htmlSquareChars == null || km.htmlSquareChars.isEmpty())) { extras.add("source\\KreativeSquare.ttf"); } if (!(km.keymanAttachments == null || km.keymanAttachments.isEmpty())) { for (String name : km.keymanAttachments.keySet()) { extras.add("source\\" + name); } } PrintWriter out = open(projectFile); writeProject( out, km, "$PROJECTPATH\\build", "source\\" + basename + ".kmn", "source\\" + basename + ".kps", "HISTORY.md", "LICENSE.md", "README.md", basename + ".keyboard_info", "source\\" + basename + ".ico", "build\\" + basename + ".kmx", "build\\" + basename.replaceAll("[^A-Za-z0-9_]", "_").toLowerCase() + ".js", "build\\" + basename + ".kvk", "source\\welcome.htm", "source\\readme.htm", extras.toArray(new String[extras.size()]) ); out.flush(); out.close(); } public static void updateFileIds(KeyboardMapping km) { ArrayList keys = new ArrayList(Arrays.asList( "*.kmn", "*.kps", "HISTORY.md", "LICENSE.md", "README.md", "*.keyboard_info", "*.ico", "*.kmx", "*.js", "*.kvk", "welcome.htm", "readme.htm" )); if (!(km.htmlSquareChars == null || km.htmlSquareChars.isEmpty())) { keys.add("KreativeSquare.ttf"); } if (!(km.keymanAttachments == null || km.keymanAttachments.isEmpty())) { keys.addAll(km.keymanAttachments.keySet()); } km.keymanFileIds.keySet().retainAll(keys); for (String key : keys) km.getKeymanFileId(key); } public static void writeKeyboardInfo(File file, KeyboardMapping km) throws IOException { PrintWriter out = open(file); writeKeyboardInfo(out, km); out.flush(); out.close(); } public static void writeHistory(File file, KeyboardMapping km) throws IOException { PrintWriter out = open(file); writeHistory(out, km); out.flush(); out.close(); } public static void writeLicense(File file, KeyboardMapping km) throws IOException { PrintWriter out = open(file); writeLicense(out, km); out.flush(); out.close(); } public static void writeReadme(File file, KeyboardMapping km) throws IOException { PrintWriter out = open(file); writeReadme(out, km); out.flush(); out.close(); } public static void writeProject( PrintWriter out, KeyboardMapping km, String buildPath, String kmnPath, String kpsPath, String historyMdPath, String licenseMdPath, String readmeMdPath, String keyboardInfoPath, String icoPath, String kmxPath, String jsPath, String kvkPath, String welcomeHtmPath, String readmeHtmPath, String... extras ) { String kmnID = km.getKeymanFileId("*.kmn"); String kpsID = km.getKeymanFileId("*.kps"); out.print("\r\n"); out.print("\r\n"); out.print(" \r\n"); out.print(" " + xquote(basepath(buildPath)) + "\r\n"); out.print(" True\r\n"); out.print(" True\r\n"); out.print(" False\r\n"); out.print(" keyboard\r\n"); out.print(" \r\n"); out.print(" \r\n"); if (kmnPath != null && kmnPath.length() > 0) { out.print(" \r\n"); out.print(" " + kmnID + "\r\n"); out.print(" " + xquote(basename(kmnPath)) + "\r\n"); out.print(" " + xquote(basepath(kmnPath)) + "\r\n"); out.print(" " + xquote(km.getKeymanVersionNotEmpty()) + "\r\n"); out.print(" .kmn\r\n"); out.print("
\r\n"); out.print(" " + xquote(km.getKeymanNameNotEmpty()) + "\r\n"); out.print(" " + xquote(km.getKeymanCopyrightNotEmpty()) + "\r\n"); if (km.keymanMessage != null && km.keymanMessage.length() > 0) { out.print(" " + xquote(km.keymanMessage) + "\r\n"); } out.print("
\r\n"); out.print("
\r\n"); } if (kpsPath != null && kpsPath.length() > 0) { out.print(" \r\n"); out.print(" " + kpsID + "\r\n"); out.print(" " + xquote(basename(kpsPath)) + "\r\n"); out.print(" " + xquote(basepath(kpsPath)) + "\r\n"); out.print(" \r\n"); out.print(" .kps\r\n"); out.print("
\r\n"); out.print(" " + xquote(km.getKeymanNameNotEmpty()) + "\r\n"); out.print(" " + xquote(km.getKeymanCopyrightNotEmpty()) + "\r\n"); out.print("
\r\n"); out.print("
\r\n"); } if (historyMdPath != null && historyMdPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("HISTORY.md") + "\r\n"); out.print(" " + xquote(basename(historyMdPath)) + "\r\n"); out.print(" " + xquote(basepath(historyMdPath)) + "\r\n"); out.print(" \r\n"); out.print(" .md\r\n"); out.print(" \r\n"); } if (licenseMdPath != null && licenseMdPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("LICENSE.md") + "\r\n"); out.print(" " + xquote(basename(licenseMdPath)) + "\r\n"); out.print(" " + xquote(basepath(licenseMdPath)) + "\r\n"); out.print(" \r\n"); out.print(" .md\r\n"); out.print(" \r\n"); } if (readmeMdPath != null && readmeMdPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("README.md") + "\r\n"); out.print(" " + xquote(basename(readmeMdPath)) + "\r\n"); out.print(" " + xquote(basepath(readmeMdPath)) + "\r\n"); out.print(" \r\n"); out.print(" .md\r\n"); out.print(" \r\n"); } if (keyboardInfoPath != null && keyboardInfoPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("*.keyboard_info") + "\r\n"); out.print(" " + xquote(basename(keyboardInfoPath)) + "\r\n"); out.print(" " + xquote(basepath(keyboardInfoPath)) + "\r\n"); out.print(" \r\n"); out.print(" .keyboard_info\r\n"); out.print(" \r\n"); } if (icoPath != null && icoPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("*.ico") + "\r\n"); out.print(" " + xquote(basename(icoPath)) + "\r\n"); out.print(" " + xquote(basepath(icoPath)) + "\r\n"); out.print(" \r\n"); out.print(" .ico\r\n"); out.print(" " + kmnID + "\r\n"); out.print(" \r\n"); } if (kmxPath != null && kmxPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("*.kmx") + "\r\n"); out.print(" " + xquote(basename(kmxPath)) + "\r\n"); out.print(" " + xquote(basepath(kmxPath)) + "\r\n"); out.print(" \r\n"); out.print(" .kmx\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } if (jsPath != null && jsPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("*.js") + "\r\n"); out.print(" " + xquote(basename(jsPath)) + "\r\n"); out.print(" " + xquote(basepath(jsPath)) + "\r\n"); out.print(" \r\n"); out.print(" .js\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } if (kvkPath != null && kvkPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("*.kvk") + "\r\n"); out.print(" " + xquote(basename(kvkPath)) + "\r\n"); out.print(" " + xquote(basepath(kvkPath)) + "\r\n"); out.print(" \r\n"); out.print(" .kvk\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } if (welcomeHtmPath != null && welcomeHtmPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("welcome.htm") + "\r\n"); out.print(" " + xquote(basename(welcomeHtmPath)) + "\r\n"); out.print(" " + xquote(basepath(welcomeHtmPath)) + "\r\n"); out.print(" \r\n"); out.print(" .htm\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } if (readmeHtmPath != null && readmeHtmPath.length() > 0) { out.print(" \r\n"); out.print(" " + km.getKeymanFileId("readme.htm") + "\r\n"); out.print(" " + xquote(basename(readmeHtmPath)) + "\r\n"); out.print(" " + xquote(basepath(readmeHtmPath)) + "\r\n"); out.print(" \r\n"); out.print(" .htm\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } if (extras != null && extras.length > 0) { for (String extra : extras) { if (extra != null && extra.length() > 0) { String[] parts = extra.split("[\\\\/.]"); String ext = parts[parts.length - 1]; out.print(" \r\n"); out.print(" " + km.getKeymanFileId(basename(extra)) + "\r\n"); out.print(" " + xquote(basename(extra)) + "\r\n"); out.print(" " + xquote(basepath(extra)) + "\r\n"); out.print(" \r\n"); out.print(" ." + xquote(ext) + "\r\n"); out.print(" " + kpsID + "\r\n"); out.print(" \r\n"); } } } out.print("
\r\n"); out.print("
\r\n"); } public static void writeKeyboardInfo(PrintWriter out, KeyboardMapping km) { out.print("{\r\n"); out.print(" \"license\": " + jquote(km.getKeymanLicenseTypeNotEmpty()) + ",\r\n"); String displayFont = ttfName(km.keymanDisplayFontFile, km.keymanAttachments); String oskFont = ttfName(km.keymanOSKFontFile, km.keymanAttachments); Collection languages = ( (km.keymanLanguages == null || km.keymanLanguages.isEmpty()) ? Arrays.asList("en") : km.keymanLanguages.keySet() ); if (displayFont != null || oskFont != null) { out.print(" \"languages\": {\r\n"); boolean first = true; for (String lang : languages) { if (first) first = false; else out.print(",\r\n"); out.print(" " + jquote(lang) + ": {\r\n"); if (displayFont != null) { out.print(" \"font\": {\r\n"); out.print(" \"family\": " + jquote(displayFont) + ",\r\n"); out.print(" \"source\": " + jquote(km.keymanDisplayFontFile) + "\r\n"); out.print(" }"); } if (displayFont != null && oskFont != null) { out.print(",\r\n"); } if (oskFont != null) { out.print(" \"oskFont\": {\r\n"); out.print(" \"family\": " + jquote(oskFont) + ",\r\n"); out.print(" \"source\": " + jquote(km.keymanOSKFontFile) + "\r\n"); out.print(" }"); } out.print("\r\n }"); } out.print("\r\n },\r\n"); } else { out.print(" \"languages\": [\r\n "); boolean first = true; for (String lang : languages) { if (first) first = false; else out.print(", "); out.print(jquote(lang)); } out.print("\r\n ],\r\n"); } out.print(" \"description\": " + jquote(km.getKeymanDescriptionNotEmpty()) + "\r\n"); out.print("}\r\n"); } public static void writeHistory(PrintWriter out, KeyboardMapping km) { writeContent(out, km.keymanHistory, "keyman-history.md", km); } public static void writeLicense(PrintWriter out, KeyboardMapping km) { writeContent(out, km.keymanLicenseText, "keyman-license.md", km); } public static void writeReadme(PrintWriter out, KeyboardMapping km) { writeContent(out, km.keymanReadme, "keyman-readme.md", km); } private static PrintWriter open(File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); return new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); } private static void writeContent(PrintWriter out, String content, String name, KeyboardMapping km) { if (content != null && content.length() > 0) { for (String line : content.split("\r\n|\r|\n")) { out.print(line + "\r\n"); } } else { Scanner scan = KeyManWriterUtility.getTemplate(name); while (scan.hasNextLine()) { content = KeyManWriterUtility.replaceFields(scan.nextLine(), km); for (String line : content.split("\r\n|\r|\n")) { out.print(line + "\r\n"); } } scan.close(); } } private static String basename(String path) { String[] parts = path.split("[\\\\/]"); return parts[parts.length - 1]; } private static String basepath(String path) { return path.replaceAll("[\\\\/]", "\\\\"); } private static String xquote(String s) { if (s == null || s.length() == 0) return ""; return s.replace("&", "&").replace("<", "<").replace(">", ">"); } private static String jquote(String s) { if (s == null || s.length() == 0) return "\"\""; return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } private static String stripSuffix(String s, String suffix) { if (s.toLowerCase().endsWith(suffix.toLowerCase())) { return s.substring(0, s.length() - suffix.length()); } else { return s; } } private static String ttfName(String key, Map dataMap) { if (key == null || key.length() == 0) return null; if (dataMap == null || dataMap.isEmpty()) return null; byte[] data = dataMap.get(key); if (data == null || data.length == 0) return null; try { TtfFile ttf = new TtfFile(data); NameTable name = ttf.getTableAs(NameTable.class, "name"); return name.getName(1); } catch (Exception e) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManTarget.java000066400000000000000000000010621506470510200301320ustar00rootroot00000000000000package com.kreative.keyedit; public enum KeyManTarget { ANY, WINDOWS, MACOSX, LINUX, WEB, IPHONE, IPAD, ANDROID_PHONE, ANDROID_TABLET, MOBILE, DESKTOP, TABLET; private final String stringValue; private KeyManTarget() { stringValue = name().replace("_", "").toLowerCase(); } public String toString() { return stringValue; } public static KeyManTarget forString(String s) { if (s != null) { s = s.replace("_", "").toLowerCase(); for (KeyManTarget t : values()) { if (t.stringValue.equals(s)) { return t; } } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManTouchWriter.java000066400000000000000000000262451506470510200311750ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; public class KeyManTouchWriter { public static void write(File file, KeyboardMapping km) throws IOException { FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write(pw, km); pw.flush(); pw.close(); fos.close(); } public static void write(PrintWriter out, KeyboardMapping km) { StringBuffer sb = new StringBuffer(); write(sb, km); String s = sb.toString(); s = s.replaceAll(",(\n *[\\}\\]])", "$1"); out.print(s); } private static void write(StringBuffer out, KeyboardMapping km) { out.append("{\n"); if (km.keymanPlatforms == null || km.keymanPlatforms.isEmpty()) { writeLayout(out, " ", "tablet", km); } else { for (KeyManPlatform p : KeyManPlatform.values()) { if (km.keymanPlatforms.contains(p)) { writeLayout(out, " ", p.toString(), km); } } } out.append("}"); } private static void writeLayout(StringBuffer out, String prefix, String key, KeyboardMapping km) { out.append(prefix + quote(key) + ": {\n"); out.append(prefix + " \"displayUnderlying\": false,\n"); if (km.keymanFontFamily != null && km.keymanFontFamily.length() > 0) { out.append(prefix + " \"font\": " + quote(km.keymanFontFamily) + ",\n"); } out.append(prefix + " \"layer\": [\n"); String layerPrefix = prefix + " "; writeLayer(out, layerPrefix, "default", false, false, km); writeLayer(out, layerPrefix, "shift", true, false, km); writeLayer(out, layerPrefix, "alt", false, true, km); writeLayer(out, layerPrefix, "shift-alt", true, true, km); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeLayer(StringBuffer out, String prefix, String id, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": " + quote(id) + ",\n"); out.append(prefix + " \"row\": [\n"); String rowPrefix = prefix + " "; writeNumberRow(out, rowPrefix, shift, alt, km); writeTopRow(out, rowPrefix, shift, alt, km); writeHomeRow(out, rowPrefix, shift, alt, km); writeBottomRow(out, rowPrefix, shift, alt, km); writeFunctionRow(out, rowPrefix, shift, alt, km); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeNumberRow(StringBuffer out, String prefix, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": 1,\n"); out.append(prefix + " \"key\": [\n"); String keyPrefix = prefix + " "; writeKeyMapping(out, keyPrefix, "K_1", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_2", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_3", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_4", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_5", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_6", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_7", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_8", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_9", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_0", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_HYPHEN", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_EQUAL", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_BKSP", "*BkSp*", null, null, 0, 100, 1, null); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeTopRow(StringBuffer out, String prefix, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": 2,\n"); out.append(prefix + " \"key\": [\n"); String keyPrefix = prefix + " "; writeKeyMapping(out, keyPrefix, "K_Q", 75, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_W", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_E", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_R", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_T", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_Y", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_U", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_I", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_O", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_P", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_LBRKT", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_RBRKT", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "T_0", null, null, null, 0, 40, 10, null); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeHomeRow(StringBuffer out, String prefix, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": 3,\n"); out.append(prefix + " \"key\": [\n"); String keyPrefix = prefix + " "; writeKeyMapping(out, keyPrefix, "K_BKQUOTE", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_A", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_S", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_D", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_F", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_G", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_H", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_J", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_K", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_L", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_COLON", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_QUOTE", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_BKSLASH", 0, 100, shift, alt, km); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeBottomRow(StringBuffer out, String prefix, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": 4,\n"); out.append(prefix + " \"key\": [\n"); String keyPrefix = prefix + " "; String nextLayer = alt ? (shift ? "alt" : "shift-alt") : (shift ? "default" : "shift"); if (km.keymanKey102) { writeKeyMapping(out, keyPrefix, "K_oE2", 0, 160, shift, alt, km); } else { writeKeyMapping(out, keyPrefix, "K_SHIFT", (shift ? "*Shifted*" : "*Shift*"), null, null, 0, 160, (shift ? 2 : 1), nextLayer); } writeKeyMapping(out, keyPrefix, "K_Z", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_X", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_C", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_V", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_B", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_N", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_M", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_COMMA", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_PERIOD", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_SLASH", 0, 100, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_SHIFT", (shift ? "*Shifted*" : "*Shift*"), null, null, 0, 155, (shift ? 2 : 1), nextLayer); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeFunctionRow(StringBuffer out, String prefix, boolean shift, boolean alt, KeyboardMapping km) { out.append(prefix + "{\n"); out.append(prefix + " \"id\": 5,\n"); out.append(prefix + " \"key\": [\n"); String keyPrefix = prefix + " "; String nextLayer = alt ? (shift ? "shift" : "default") : (shift ? "shift-alt" : "alt"); writeKeyMapping(out, keyPrefix, "K_LCONTROL", "alt", null, null, 0, 130, (alt ? 2 : 1), nextLayer); writeKeyMapping(out, keyPrefix, "K_LOPT", "*Menu*", null, null, 0, 140, 1, null); // writeKeyMapping(out, keyPrefix, "K_SPACE", 0, 930, shift, alt, km); writeKeyMapping(out, keyPrefix, "K_SPACE", null, null, null, 0, 930, 0, null); writeKeyMapping(out, keyPrefix, "K_ENTER", "*Enter*", null, null, 0, 235, 1, null); out.append(prefix + " ],\n"); out.append(prefix + "},\n"); } private static void writeKeyMapping(StringBuffer out, String prefix, String id, int pad, int width, boolean shift, boolean alt, KeyboardMapping km) { KeyMapping m = km.map.get(KeyManKey.forId(id).key); int[] lpo = alt ? (shift ? m.altShiftedLongPressOutput : m.altUnshiftedLongPressOutput) : (shift ? m.shiftedLongPressOutput : m.unshiftedLongPressOutput); DeadKeyTable dead = alt ? (shift ? m.altShiftedDeadKey : m.altUnshiftedDeadKey) : (shift ? m.shiftedDeadKey : m.unshiftedDeadKey); int output = alt ? (shift ? m.altShiftedOutput : m.altUnshiftedOutput) : (shift ? m.shiftedOutput : m.unshiftedOutput); boolean isSpace = (id.equals("K_SPACE") && output == 32 && dead == null); String kmId = isSpace ? id : KeyManWriterUtility.keymanIdString(output, dead); String kmText = isSpace ? null : KeyManWriterUtility.keymanDisplayString(output, dead, km.keymanCpLabels); List sk = getSK(lpo, output, dead, km); writeKeyMapping(out, prefix, kmId, kmText, sk, km.keymanCpLabels, pad, width, 0, null); } private static List getSK(int[] lpo, int output, DeadKeyTable dead, KeyboardMapping km) { if (lpo != null) { List sk = new ArrayList(); for (int o : lpo) sk.add(o); return sk; } if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } List sk = new ArrayList(); km.getAutoLongPressOutput(sk, output); return sk; } private static void writeKeyMapping(StringBuffer out, String prefix, String id, String text, List sk, Map cpLabels, int pad, int width, int sp, String nextlayer) { out.append(prefix + "{\n"); if (id != null) out.append(prefix + " \"id\": " + quote(id) + ",\n"); if (text != null) out.append(prefix + " \"text\": " + quote(text) + ",\n"); if (sk != null && sk.size() > 0) { out.append(prefix + " \"sk\": [\n"); for (int cp : sk) { String skText = quote(KeyManWriterUtility.keymanDisplayString(cp, null, cpLabels)); String skId = quote(KeyManWriterUtility.keymanIdString(cp, null)); out.append(prefix + " {\n"); out.append(prefix + " \"text\": " + skText + ",\n"); out.append(prefix + " \"id\": " + skId + ",\n"); out.append(prefix + " },\n"); } out.append(prefix + " ],\n"); } if (pad > 0) out.append(prefix + " \"pad\": " + pad + ",\n"); if (width > 0) out.append(prefix + " \"width\": " + width + ",\n"); if (sp > 0) out.append(prefix + " \"sp\": " + sp + ",\n"); if (nextlayer != null) out.append(prefix + " \"nextlayer\": " + quote(nextlayer) + ",\n"); out.append(prefix + "},\n"); } private static String quote(String s) { if (s == null || s.length() == 0) return "\"\""; return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManVisualWriter.java000066400000000000000000000060161506470510200313500ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Map; public class KeyManVisualWriter { public static void write(File file, KeyboardMapping km) throws IOException { FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write(pw, km); pw.flush(); pw.close(); fos.close(); } public static void write(PrintWriter out, KeyboardMapping km) { out.print("\r\n"); out.print("\r\n"); out.print("
\r\n"); out.print(" 10.0\r\n"); out.print(" " + quote(km.getKeymanIdentifierNotEmpty()) + "\r\n"); out.print(" \r\n"); if (km.keymanKey102) out.print(" \r\n"); if (km.keymanDisplayUnderlying) out.print(" \r\n"); if (km.keymanUseAltGr) out.print(" \r\n"); out.print(" \r\n"); out.print("
\r\n"); out.print(" \r\n"); out.print(" \r\n"); for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, k.id, m.unshiftedOutput, m.unshiftedDeadKey, km.keymanCpLabels); } out.print(" \r\n"); out.print(" \r\n"); for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, k.id, m.shiftedOutput, m.shiftedDeadKey, km.keymanCpLabels); } out.print(" \r\n"); out.print(" \r\n"); for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, k.id, m.altUnshiftedOutput, m.altUnshiftedDeadKey, km.keymanCpLabels); } out.print(" \r\n"); out.print(" \r\n"); for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, k.id, m.altShiftedOutput, m.altShiftedDeadKey, km.keymanCpLabels); } out.print(" \r\n"); out.print(" \r\n"); out.print("
\r\n"); } private static void writeKeyMapping(PrintWriter out, String keyCode, int output, DeadKeyTable dead, Map cpLabels) { String qs = quote(KeyManWriterUtility.keymanDisplayString(output, dead, cpLabels)); out.print(" " + qs + "\r\n"); } private static String ifEmpty(String s, String def) { return (s != null && s.length() > 0) ? s : def; } private static String quote(String s) { if (s == null || s.length() == 0) return ""; return s.replace("&", "&").replace("<", "<").replace(">", ">"); } private static String aquote(String s) { if (s == null || s.length() == 0) return "\"\""; return "\"" + quote(s).replace("\"", """) + "\""; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManWriter.java000066400000000000000000000321501506470510200301620ustar00rootroot00000000000000package com.kreative.keyedit; import java.awt.image.BufferedImage; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; public class KeyManWriter { public static void write(File file, KeyboardMapping km) throws IOException { String basename = stripSuffix(file.getName(), ".kmn"); File icoFile = new File(file.getParentFile(), basename + ".ico"); File kvksFile = new File(file.getParentFile(), basename + ".kvks"); File ktlFile = new File(file.getParentFile(), basename + ".keyman-touch-layout"); FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write( pw, km, ((km.icon != null) ? icoFile.getName() : null), (kvksFile.exists() ? kvksFile.getName() : null), (ktlFile.exists() ? ktlFile.getName() : null) ); pw.flush(); pw.close(); fos.close(); if (km.icon != null) { FileOutputStream ifos = new FileOutputStream(icoFile); DataOutputStream idos = new DataOutputStream(ifos); WinIconDir ico = new WinIconDir(); ico.add(newIcoSize(km.icon, 8, ColorTables.createWindowsBase())); ico.add(newIcoSize(km.icon, 4, ColorTables.createWindows4())); ico.add(newIcoSize(km.icon, 1, ColorTables.createBlackToWhite(1))); ico.write(idos); idos.flush(); idos.close(); ifos.close(); } } public static void write(PrintWriter out, KeyboardMapping km, String icoFileName, String kvksFileName, String ktlFileName) { out.print("\uFEFF"); if (km.keymanComments != null && km.keymanComments.length() > 0) { String[] lines = km.keymanComments.replaceAll("\r\n","\n").replaceAll("\r","\n").split("\n"); for (String line : lines) out.print("c " + line + "\r\n"); out.print("\r\n"); } else if (km.xkbComment != null && km.xkbComment.length() > 0) { String[] lines = km.xkbComment.replaceAll("\r\n","\n").replaceAll("\r","\n").split("\n"); for (String line : lines) out.print("c " + line + "\r\n"); out.print("\r\n"); } out.print("store(&VERSION) '10.0'\r\n"); out.print("store(&NAME) " + quote(km.getKeymanNameNotEmpty()) + "\r\n"); out.print("store(©RIGHT) " + quote(km.getKeymanCopyrightNotEmpty()) + "\r\n"); out.print("store(&KEYBOARDVERSION) " + quote(km.getKeymanVersionNotEmpty()) + "\r\n"); if (km.keymanTargets != null && km.keymanTargets.size() > 0) { StringBuffer sb = new StringBuffer(); boolean first = true; for (KeyManTarget t : KeyManTarget.values()) { if (km.keymanTargets.contains(t)) { if (first) first = false; else sb.append(" "); sb.append(t); } } out.print("store(&TARGETS) " + quote(sb.toString()) + "\r\n"); } if (icoFileName != null) out.print("store(&BITMAP) " + quote(icoFileName) + "\r\n"); if (kvksFileName != null) out.print("store(&VISUALKEYBOARD) " + quote(kvksFileName) + "\r\n"); if (ktlFileName != null) out.print("store(&LAYOUTFILE) " + quote(ktlFileName) + "\r\n"); if (km.keymanMessage != null && km.keymanMessage.length() > 0) { out.print("store(&MESSAGE) " + quote(km.keymanMessage) + "\r\n"); } if (km.keymanRightToLeft) { out.print("store(&KMW_RTL) '1'\r\n"); } if (km.keymanWebHelpText != null && km.keymanWebHelpText.length() > 0) { out.print("store(&KMW_HELPTEXT) " + quote(km.keymanWebHelpText) + "\r\n"); } out.print("\r\n"); out.print("begin Unicode > use(main)\r\n"); out.print("\r\n"); out.print("group(main) using keys\r\n"); Map deadKeys = new TreeMap(); Map> deadKeyInputs = new TreeMap>(); if (km.keymanIgnoreCaps || canIgnoreCaps(km)) { for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "SHIFT RALT " + k.id, m.altShiftedOutput, m.altShiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "RALT " + k.id, m.altUnshiftedOutput, m.altUnshiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "SHIFT " + k.id, m.shiftedOutput, m.shiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, k.id, m.unshiftedOutput, m.unshiftedDeadKey, deadKeys, deadKeyInputs); } } else { for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "CAPS SHIFT RALT " + k.id, m.altShiftedOutput, m.altShiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "NCAPS SHIFT RALT " + k.id, m.altShiftedOutput, m.altShiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "CAPS RALT " + k.id, m.altCapsLockMapping, m.altUnshiftedOutput, m.altUnshiftedDeadKey, m.altShiftedOutput, m.altShiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "NCAPS RALT " + k.id, m.altUnshiftedOutput, m.altUnshiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "CAPS SHIFT " + k.id, m.shiftedOutput, m.shiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "NCAPS SHIFT " + k.id, m.shiftedOutput, m.shiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "CAPS " + k.id, m.capsLockMapping, m.unshiftedOutput, m.unshiftedDeadKey, m.shiftedOutput, m.shiftedDeadKey, deadKeys, deadKeyInputs); } for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); writeKeyMapping(out, km, "NCAPS " + k.id, m.unshiftedOutput, m.unshiftedDeadKey, deadKeys, deadKeyInputs); } } for (Map.Entry dke : deadKeys.entrySet()) { out.print("\r\n"); String name = dke.getKey(); StringBuffer input = new StringBuffer(); StringBuffer output = new StringBuffer(); for (Map.Entry kme : dke.getValue().keyMap.entrySet()) { Set dki = deadKeyInputs.get(kme.getKey()); if (dki == null || dki.isEmpty()) { System.err.println( "Hint: 109A The rule will never be matched for key " + quote(kme.getKey()) + " because its key code is never fired. (╯°□°)╯⁔ ┴─┴" // flip the DeadKeyTable ); } else { String valueCode = quote(kme.getValue()); for (String keyCode : dki) { input.append(" ["); input.append(keyCode); input.append("]"); output.append(" "); output.append(valueCode); } } } out.print("store(" + name + "in)" + input + "\r\n"); out.print("store(" + name + "out)" + output + "\r\n"); out.print("dk(" + name + ") + any(" + name + "in) > index(" + name + "out, 2)\r\n"); } } private static boolean canIgnoreCaps(KeyboardMapping km) { for (KeyManKey k : KeyManKey.KEYS) { KeyMapping m = km.map.get(k.key); int ut = outputToken(CapsLockMapping.UNSHIFTED, m.unshiftedOutput, m.unshiftedDeadKey, m.shiftedOutput, m.shiftedDeadKey); int ct = outputToken(m.capsLockMapping, m.unshiftedOutput, m.unshiftedDeadKey, m.shiftedOutput, m.shiftedDeadKey); if (ut != ct) return false; ut = outputToken(CapsLockMapping.UNSHIFTED, m.altUnshiftedOutput, m.altUnshiftedDeadKey, m.altShiftedOutput, m.altShiftedDeadKey); ct = outputToken(m.altCapsLockMapping, m.altUnshiftedOutput, m.altUnshiftedDeadKey, m.altShiftedOutput, m.altShiftedDeadKey); if (ut != ct) return false; } return true; } private static int outputToken(CapsLockMapping caps, int uout, DeadKeyTable udead, int sout, DeadKeyTable sdead) { if (caps == CapsLockMapping.UNSHIFTED) { return (udead == null) ? uout : (Integer.MIN_VALUE + getCP(uout, udead)); } else if (caps == CapsLockMapping.SHIFTED) { return (sdead == null) ? sout : (Integer.MIN_VALUE + getCP(sout, sdead)); } else if (udead != null && sdead != null) { caps = isCasePair(udead.winTerminator, sdead.winTerminator) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; return outputToken(caps, uout, udead, sout, sdead); } else if (udead != null) { caps = (udead.winTerminator == sout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; return outputToken(caps, uout, udead, sout, sdead); } else if (sdead != null) { caps = (sdead.winTerminator == uout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; return outputToken(caps, uout, udead, sout, sdead); } else { caps = isCasePair(uout, sout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; return outputToken(caps, uout, udead, sout, sdead); } } private static void writeKeyMapping(PrintWriter out, KeyboardMapping km, String keyCode, CapsLockMapping caps, int uout, DeadKeyTable udead, int sout, DeadKeyTable sdead, Map deadKeys, Map> deadKeyInputs) { if (caps == CapsLockMapping.UNSHIFTED) { writeKeyMapping(out, km, keyCode, uout, udead, deadKeys, deadKeyInputs); } else if (caps == CapsLockMapping.SHIFTED) { writeKeyMapping(out, km, keyCode, sout, sdead, deadKeys, deadKeyInputs); } else if (udead != null && sdead != null) { caps = isCasePair(udead.winTerminator, sdead.winTerminator) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; writeKeyMapping(out, km, keyCode, caps, uout, udead, sout, sdead, deadKeys, deadKeyInputs); } else if (udead != null) { caps = (udead.winTerminator == sout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; writeKeyMapping(out, km, keyCode, caps, uout, udead, sout, sdead, deadKeys, deadKeyInputs); } else if (sdead != null) { caps = (sdead.winTerminator == uout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; writeKeyMapping(out, km, keyCode, caps, uout, udead, sout, sdead, deadKeys, deadKeyInputs); } else { caps = isCasePair(uout, sout) ? CapsLockMapping.SHIFTED : CapsLockMapping.UNSHIFTED; writeKeyMapping(out, km, keyCode, caps, uout, udead, sout, sdead, deadKeys, deadKeyInputs); } } private static boolean isCasePair(int u, int s) { return (u != s) && (Character.toUpperCase(u) == s || Character.toLowerCase(s) == u); } private static void writeKeyMapping(PrintWriter out, KeyboardMapping km, String keyCode, int output, DeadKeyTable dead, Map deadKeys, Map> deadKeyInputs) { if (dead != null) { String dk = getActionId(km, getCP(output, dead)); deadKeys.put(dk, dead); out.print("+ [" + keyCode + "] > dk(" + dk + ")\r\n"); } else if (output > 0) { Set dki = deadKeyInputs.get(output); if (dki == null) deadKeyInputs.put(output, (dki = new TreeSet())); dki.add(keyCode); out.print("+ [" + keyCode + "] > " + quote(output) + "\r\n"); } } private static int getCP(int output, DeadKeyTable dead) { if (dead != null) { if (dead.winTerminator > 0) { return dead.winTerminator; } } if (output > 0) { return output; } return -1; } private static String getActionId(KeyboardMapping km, int cp) { if (km.macActionIds.containsKey(cp)) { return km.macActionIds.get(cp); } else { return XkbKeySym.MAP.getKeySym(cp); } } private static String quote(int cp) { switch (cp) { case '\"': return "\'\"\'"; case '\'': return "\"\'\""; } switch (Character.getType(cp)) { case Character.UPPERCASE_LETTER: case Character.LOWERCASE_LETTER: case Character.TITLECASE_LETTER: case Character.MODIFIER_LETTER: case Character.OTHER_LETTER: case Character.DECIMAL_DIGIT_NUMBER: case Character.LETTER_NUMBER: case Character.OTHER_NUMBER: case Character.CONNECTOR_PUNCTUATION: case Character.DASH_PUNCTUATION: case Character.START_PUNCTUATION: case Character.END_PUNCTUATION: case Character.INITIAL_QUOTE_PUNCTUATION: case Character.FINAL_QUOTE_PUNCTUATION: case Character.OTHER_PUNCTUATION: case Character.MATH_SYMBOL: case Character.CURRENCY_SYMBOL: case Character.MODIFIER_SYMBOL: case Character.OTHER_SYMBOL: return "'" + String.valueOf(Character.toChars(cp)) + "'"; } String h = Integer.toHexString(cp); while (h.length() < 4) h = "0" + h; return "U+" + h.toUpperCase(); } private static String quote(String s) { if (s == null || s.length() == 0) return "''"; s = "'" + s.replace("'", "' U+0027 '") + "' "; return s.replace("'' ", "").trim(); } private static WinIconDirEntry newIcoSize(BufferedImage image, int bpp, int[] colorTable) { WinIconDirEntry e = new WinIconDirEntry(); e.setBMPImage(image, bpp, colorTable); return e; } private static String stripSuffix(String s, String suffix) { if (s.toLowerCase().endsWith(suffix.toLowerCase())) { return s.substring(0, s.length() - suffix.length()); } else { return s; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyManWriterUtility.java000066400000000000000000000105021506470510200315430ustar00rootroot00000000000000package com.kreative.keyedit; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.kreative.unicode.data.NameResolver; public final class KeyManWriterUtility { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private KeyManWriterUtility() {} public static Scanner getTemplate(String name) { return new Scanner(KeyManWriterUtility.class.getResourceAsStream(name), "UTF-8"); } private static Pattern FIELD_PATTERN = Pattern.compile("[{][{]([^}]+)[}][}]"); public static String replaceFields(String s, KeyboardMapping km) { StringBuffer sb = new StringBuffer(); Matcher m = FIELD_PATTERN.matcher(s); while (m.find()) { String field = m.group(1).trim(); String repl = m.group(); if (field.equalsIgnoreCase("id")) repl = km.getKeymanIdentifierNotEmpty(); if (field.equalsIgnoreCase("name")) repl = km.getKeymanNameNotEmpty(); if (field.equalsIgnoreCase("copyright")) repl = km.getKeymanCopyrightNotEmpty(); if (field.equalsIgnoreCase("message")) repl = notNull(km.keymanMessage); if (field.equalsIgnoreCase("webhelptext")) repl = notNull(km.keymanWebHelpText); if (field.equalsIgnoreCase("version")) repl = km.getKeymanVersionNotEmpty(); if (field.equalsIgnoreCase("comments")) repl = notNull(km.keymanComments); if (field.equalsIgnoreCase("author")) repl = km.getKeymanAuthorNotEmpty(); if (field.equalsIgnoreCase("emailaddress")) repl = notNull(km.keymanEmailAddress); if (field.equalsIgnoreCase("website")) repl = notNull(km.keymanEmailAddress); if (field.equalsIgnoreCase("description")) repl = km.getKeymanDescriptionNotEmpty(); if (field.equalsIgnoreCase("date")) repl = DATE_FORMAT.format(new Date()); if (field.equalsIgnoreCase("targets")) { StringBuffer tsb = new StringBuffer(); addTarget(km, KeyManTarget.WINDOWS, tsb, "Windows"); addTarget(km, KeyManTarget.MACOSX, tsb, "Mac OS X"); // No, I will not use Apple's new stupid capitalization. addTarget(km, KeyManTarget.LINUX, tsb, "Linux"); addTarget(km, KeyManTarget.WEB, tsb, "Web"); addTarget(km, KeyManTarget.IPHONE, tsb, "iPhone"); addTarget(km, KeyManTarget.IPAD, tsb, "iPad"); addTarget(km, KeyManTarget.ANDROID_PHONE, tsb, "Android phone"); addTarget(km, KeyManTarget.ANDROID_TABLET, tsb, "Android tablet"); addTarget(km, KeyManTarget.MOBILE, tsb, "Mobile devices"); addTarget(km, KeyManTarget.DESKTOP, tsb, "Desktop devices"); addTarget(km, KeyManTarget.TABLET, tsb, "Tablet devices"); repl = tsb.toString(); } m.appendReplacement(sb, repl); } m.appendTail(sb); return sb.toString(); } private static String notNull(String s) { return (s != null) ? s : ""; } private static void addTarget(KeyboardMapping km, KeyManTarget t, StringBuffer sb, String s) { if (km.keymanTargets != null) { if (km.keymanTargets.contains(KeyManTarget.ANY) || km.keymanTargets.contains(t)) { sb.append(" * " + s + "\n"); } } } public static String keymanIdString(int output, DeadKeyTable dead) { if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } if (output <= 0) return ""; String skId = Integer.toHexString(output); while (skId.length() < 4) skId = "0" + skId; return "U_" + skId.toUpperCase(); } public static String keymanDisplayString(int output, DeadKeyTable dead, Map cpLabels) { if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } if (output <= 0) return ""; if (cpLabels.containsKey(output)) return cpLabels.get(output); switch (output) { case 0x00AD: return "(-)"; case 0x02DE: return "◌˞"; } String s = String.valueOf(Character.toChars(output)); NameResolver r = NameResolver.instance(output); if (r.getCategory(output).startsWith("M")) { // Combining Mark s = "◌" + s; String ccc = r.getCombiningClass(output); if (ccc.equals("233") || ccc.equals("234")) { // Double Combining Mark s = s + "◌"; } } return s; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyMapping.java000066400000000000000000000037041506470510200276500ustar00rootroot00000000000000package com.kreative.keyedit; public class KeyMapping { public int commandOutput; public int unshiftedOutput; public int shiftedOutput; public int ctrlOutput; public int altUnshiftedOutput; public int altShiftedOutput; public CapsLockMapping capsLockMapping; public CapsLockMapping altCapsLockMapping; public DeadKeyTable commandDeadKey; public DeadKeyTable unshiftedDeadKey; public DeadKeyTable shiftedDeadKey; public DeadKeyTable ctrlDeadKey; public DeadKeyTable altUnshiftedDeadKey; public DeadKeyTable altShiftedDeadKey; public int[] unshiftedLongPressOutput; public int[] shiftedLongPressOutput; public int[] altUnshiftedLongPressOutput; public int[] altShiftedLongPressOutput; public KeyMapping(Key key) { this.commandOutput = key.defaultUnshifted; this.unshiftedOutput = key.defaultUnshifted; this.shiftedOutput = key.defaultShifted; this.ctrlOutput = key.defaultCtrl; this.altUnshiftedOutput = key.defaultAltUnshifted; this.altShiftedOutput = key.defaultAltShifted; this.capsLockMapping = CapsLockMapping.AUTO; this.altCapsLockMapping = CapsLockMapping.AUTO; this.commandDeadKey = null; this.unshiftedDeadKey = null; this.shiftedDeadKey = null; this.ctrlDeadKey = null; this.altUnshiftedDeadKey = null; this.altShiftedDeadKey = null; this.unshiftedLongPressOutput = null; this.shiftedLongPressOutput = null; this.altUnshiftedLongPressOutput = null; this.altShiftedLongPressOutput = null; } public void swapAlt() { int o; CapsLockMapping m; DeadKeyTable d; o = unshiftedOutput ; unshiftedOutput = altUnshiftedOutput ; altUnshiftedOutput = o; o = shiftedOutput ; shiftedOutput = altShiftedOutput ; altShiftedOutput = o; m = capsLockMapping ; capsLockMapping = altCapsLockMapping ; altCapsLockMapping = m; d = unshiftedDeadKey ; unshiftedDeadKey = altUnshiftedDeadKey ; altUnshiftedDeadKey = d; d = shiftedDeadKey ; shiftedDeadKey = altShiftedDeadKey ; altShiftedDeadKey = d; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyboardFormat.java000066400000000000000000000256131506470510200305200ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; public enum KeyboardFormat { KKB { @Override public String getName() { return "KeyEdit (kkbx)"; } @Override public String getSuffix() { return ".kkbx"; } @Override public boolean recognizesInputFormatName(String s) { return s.equalsIgnoreCase(".kkb") || s.equalsIgnoreCase(".kkbx") || s.equalsIgnoreCase("kkb") || s.equalsIgnoreCase("kkbx") || s.equalsIgnoreCase("keyedit"); } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".kkb") || s.equalsIgnoreCase(".kkbx") || s.equalsIgnoreCase("kkb") || s.equalsIgnoreCase("kkbx") || s.equalsIgnoreCase("keyedit"); } @Override public boolean recognizesInputFile(File f) { return f.getName().toLowerCase().endsWith(".kkbx"); } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".kkbx"); } @Override public KeyboardMapping read(File f) throws IOException { return KkbReader.read(f); } @Override public void write(File f, KeyboardMapping km) throws IOException { KkbWriter.write(f, km); } }, MAC { @Override public String getName() { return "Mac OS X (keylayout)"; } @Override public String getSuffix() { return ".keylayout"; } @Override public boolean recognizesInputFormatName(String s) { return s.equalsIgnoreCase(".keylayout") || s.equalsIgnoreCase("keylayout") || s.equalsIgnoreCase("mac") || s.equalsIgnoreCase("macos") || s.equalsIgnoreCase("macintosh"); } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".keylayout") || s.equalsIgnoreCase("keylayout") || s.equalsIgnoreCase("mac") || s.equalsIgnoreCase("macos") || s.equalsIgnoreCase("macintosh"); } @Override public boolean recognizesInputFile(File f) { return f.getName().toLowerCase().endsWith(".keylayout"); } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".keylayout"); } @Override public KeyboardMapping read(File f) throws IOException { return MacReader.read(f); } @Override public void write(File f, KeyboardMapping km) throws IOException { MacWriter.write(f, km); } }, WIN { @Override public String getName() { return "Microsoft Keyboard Layout Creator (klc)"; } @Override public String getSuffix() { return ".klc"; } @Override public boolean recognizesInputFormatName(String s) { return s.equalsIgnoreCase(".klc") || s.equalsIgnoreCase("klc") || s.equalsIgnoreCase("msklc") || s.equalsIgnoreCase("win") || s.equalsIgnoreCase("windows"); } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".klc") || s.equalsIgnoreCase("klc") || s.equalsIgnoreCase("msklc") || s.equalsIgnoreCase("win") || s.equalsIgnoreCase("windows"); } @Override public boolean recognizesInputFile(File f) { return f.getName().toLowerCase().endsWith(".klc"); } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".klc"); } @Override public KeyboardMapping read(File f) throws IOException { return WinReader.read(f); } @Override public void write(File f, KeyboardMapping km) throws IOException { WinWriter.write(f, km); } }, KEYMAN { @Override public String getName() { return "Keyman Developer (kmn)"; } @Override public String getSuffix() { return ".kmn"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".kmn") || s.equalsIgnoreCase("kmn") || s.equalsIgnoreCase("keyman"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".kmn"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("Keyman import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { KeyManWriter.write(f, km); } }, KEYMAN_VISUAL { @Override public String getName() { return "Keyman Developer (kvks)"; } @Override public String getSuffix() { return ".kvks"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".kvks") || s.equalsIgnoreCase("kvks") || s.equalsIgnoreCase("keymanvisual"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".kvks"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("Keyman import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { KeyManVisualWriter.write(f, km); } }, KEYMAN_TOUCH { @Override public String getName() { return "Keyman Developer (keyman-touch-layout)"; } @Override public String getSuffix() { return ".keyman-touch-layout"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".keyman-touch-layout") || s.equalsIgnoreCase("keyman-touch-layout") || s.equalsIgnoreCase("keymantouch"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".keyman-touch-layout"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("Keyman import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { KeyManTouchWriter.write(f, km); } }, KEYMAN_PACKAGE { @Override public String getName() { return "Keyman Developer Package (kps)"; } @Override public String getSuffix() { return ".kps"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".kps") || s.equalsIgnoreCase("kps") || s.equalsIgnoreCase("keymanpackage"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".kps"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("Keyman import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { KeyManPackageWriter.write(f, km, null); } }, KEYMAN_PROJECT { @Override public String getName() { return "Keyman Developer Project (kpj)"; } @Override public String getSuffix() { return ".kpj"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".kpj") || s.equalsIgnoreCase("kpj") || s.equalsIgnoreCase("keymanproject"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".kpj"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("Keyman import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { KeyManProjectWriter.write(f, km); } }, XKB { @Override public String getName() { return "Linux (xkb)"; } @Override public String getSuffix() { return ""; } @Override public boolean recognizesInputFormatName(String s) { return s.equalsIgnoreCase("xkb") || s.equalsIgnoreCase("x11") || s.equalsIgnoreCase("linux"); } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase("xkb") || s.equalsIgnoreCase("x11") || s.equalsIgnoreCase("linux"); } @Override public boolean recognizesInputFile(File f) { return !f.getName().contains("."); } @Override public boolean recognizesOutputFile(File f) { return !f.getName().contains("."); } @Override public KeyboardMapping read(File f) throws IOException { return XkbReader.read(f); } @Override public void write(File f, KeyboardMapping km) throws IOException { XkbWriter.write(f, km); } }, HTML { @Override public String getName() { return "HTML"; } @Override public String getSuffix() { return ".html"; } @Override public boolean recognizesInputFormatName(String s) { return false; } @Override public boolean recognizesOutputFormatName(String s) { return s.equalsIgnoreCase(".html") || s.equalsIgnoreCase(".htm") || s.equalsIgnoreCase("html") || s.equalsIgnoreCase("htm"); } @Override public boolean recognizesInputFile(File f) { return false; } @Override public boolean recognizesOutputFile(File f) { return f.getName().toLowerCase().endsWith(".html"); } @Override public KeyboardMapping read(File f) throws IOException { throw new IOException("HTML import unsupported."); } @Override public void write(File f, KeyboardMapping km) throws IOException { HTMLWriter.writeStandalone(f, km); } }; public abstract String getName(); public abstract String getSuffix(); public abstract boolean recognizesInputFormatName(String s); public abstract boolean recognizesOutputFormatName(String s); public abstract boolean recognizesInputFile(File f); public abstract boolean recognizesOutputFile(File f); public abstract KeyboardMapping read(File f) throws IOException; public abstract void write(File f, KeyboardMapping km) throws IOException; public static KeyboardFormat forInputFormatName(String s) { for (KeyboardFormat format : values()) { if (format.recognizesInputFormatName(s)) { return format; } } return null; } public static KeyboardFormat forOutputFormatName(String s) { for (KeyboardFormat format : values()) { if (format.recognizesOutputFormatName(s)) { return format; } } return null; } public static KeyboardFormat forInputFile(File f) { for (KeyboardFormat format : values()) { if (format.recognizesInputFile(f)) { return format; } } return null; } public static KeyboardFormat forOutputFile(File f) { for (KeyboardFormat format : values()) { if (format.recognizesOutputFile(f)) { return format; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KeyboardMapping.java000066400000000000000000000250441506470510200306610ustar00rootroot00000000000000package com.kreative.keyedit; import java.awt.image.BufferedImage; import java.text.Collator; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.GregorianCalendar; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; public class KeyboardMapping { public String name; public String winIdentifier; public String winCopyright; public String winCompany; public WinLocale winLocale = WinLocale.EN_US; public boolean winAltGrEnable = true; public boolean winShiftLock = false; public boolean winLrmRlm = false; public int macGroupNumber = 126; public int macIdNumber = -1; public String xkbPath; public String xkbLabel; public String xkbComment; public boolean xkbUseKeySym = false; public XkbAltGrKey xkbAltGrKey = XkbAltGrKey.ralt_switch; public XkbComposeKey xkbComposeKey = XkbComposeKey.none; public String keymanIdentifier; public String keymanName; public String keymanCopyright; public String keymanMessage; public String keymanWebHelpText; public String keymanVersion; public String keymanComments; public String keymanAuthor; public String keymanEmailAddress; public String keymanWebSite; public boolean keymanRightToLeft = false; public boolean keymanKey102 = false; public boolean keymanDisplayUnderlying = false; public boolean keymanUseAltGr = false; public boolean keymanIgnoreCaps = false; public final EnumSet keymanTargets; public final EnumSet keymanPlatforms; public final Map keymanLanguages; public final Map keymanAttachments; public final Map keymanFileIds; public final Map keymanCpLabels; public String keymanFontFamily; public String keymanOSKFontFile; public String keymanDisplayFontFile; public String keymanDescription; public String keymanLicenseType; public String keymanLicenseText; public String keymanReadme; public String keymanHistory; public BufferedImage icon; public Integer macIconVersion; public final Map map; public final Map macActionIds; public String htmlTitle; public String htmlStyle; public String htmlH1; public String htmlH2; public String htmlBody1; public String htmlBody2; public String htmlBody3; public String htmlBody4; public String htmlInstall; public BitSet htmlSquareChars; public BitSet htmlOutlineChars; public final Map htmlTdClasses; public final Map htmlSpanClasses; public final Map htmlCpLabels; public final Map winAttachments; public final Map macAttachments; public final Map xkbAttachments; public KeyboardMapping() { TreeMap map = new TreeMap(); for (Key key : Key.values()) map.put(key, new KeyMapping(key)); this.map = Collections.unmodifiableMap(map); this.macActionIds = new TreeMap(); this.htmlTdClasses = new TreeMap(); this.htmlSpanClasses = new TreeMap(); this.htmlCpLabels = new TreeMap(); this.keymanTargets = EnumSet.noneOf(KeyManTarget.class); this.keymanPlatforms = EnumSet.noneOf(KeyManPlatform.class); this.keymanLanguages = new LinkedHashMap(); this.keymanAttachments = new TreeMap(); this.keymanFileIds = new TreeMap(); this.keymanCpLabels = new TreeMap(); this.winAttachments = new TreeMap(); this.macAttachments = new TreeMap(); this.xkbAttachments = new TreeMap(); } public String getNameNotEmpty() { if (name != null && name.length() > 0) return name; return "Untitled Layout"; } public String getWinIdentifierNotEmpty() { if (winIdentifier != null && winIdentifier.length() > 0) return winIdentifier; String winId = getNameNotEmpty().replaceAll("[^A-Za-z0-9]", ""); if (winId.length() > 8) winId = winId.substring(0, 8); return winId; } public String getWinCompanyNotEmpty() { if (winCompany != null && winCompany.length() > 0) return winCompany; return "Anonymous"; } public String getWinCopyrightNotEmpty() { if (winCopyright != null && winCopyright.length() > 0) return winCopyright; int year = new GregorianCalendar().get(GregorianCalendar.YEAR); return "(c) " + year + " " + getWinCompanyNotEmpty(); } public WinLocale getWinLocaleNotNull() { if (winLocale != null) return winLocale; return WinLocale.EN_US; } public String getXkbPathNotEmpty() { if (xkbPath != null && xkbPath.length() > 0) return xkbPath; return getNameNotEmpty().replaceAll("[^A-Za-z0-9_-]", "").toLowerCase(); } public String getXkbLabelNotEmpty() { if (xkbLabel != null && xkbLabel.length() > 0) return xkbLabel; String name = getNameNotEmpty(); return (name.length() > 2) ? name.substring(0, 2) : name; } public XkbAltGrKey getXkbAltGrKeyNotNull() { if (xkbAltGrKey != null) return xkbAltGrKey; return XkbAltGrKey.none; } public XkbComposeKey getXkbComposeKeyNotNull() { if (xkbComposeKey != null) return xkbComposeKey; return XkbComposeKey.none; } public String getKeymanIdentifierNotEmpty() { if (keymanIdentifier != null && keymanIdentifier.length() > 0) return keymanIdentifier; return getKeymanNameNotEmpty().toLowerCase().replaceAll("[^A-Za-z0-9]+", "_"); } public String getKeymanNameNotEmpty() { if (keymanName != null && keymanName.length() > 0) return keymanName; return getNameNotEmpty(); } public String getKeymanCopyrightNotEmpty() { if (keymanCopyright != null && keymanCopyright.length() > 0) return keymanCopyright; return getWinCopyrightNotEmpty().replaceAll("[(][Cc][)]", "©"); } public String getKeymanVersionNotEmpty() { if (keymanVersion != null && keymanVersion.length() > 0) return keymanVersion; return "1.0"; } public String getKeymanAuthorNotEmpty() { if (keymanAuthor != null && keymanAuthor.length() > 0) return keymanAuthor; return getWinCompanyNotEmpty(); } public String getKeymanDescriptionNotEmpty() { if (keymanDescription != null && keymanDescription.length() > 0) return keymanDescription; return getKeymanNameNotEmpty() + " generated by Kreative KeyEdit"; } public String getKeymanLicenseTypeNotEmpty() { if (keymanLicenseType != null && keymanLicenseType.length() > 0) return keymanLicenseType; if (keymanLicenseText != null && keymanLicenseText.length() > 0) return "unknown"; return "mit"; } public String getKeymanFileId(String filename) { String id = keymanFileIds.get(filename); if (id == null) { do { id = "id_" + UUID.randomUUID().toString().replace("-", ""); } while (keymanFileIds.values().contains(id)); keymanFileIds.put(filename, id); } return id; } public void autoFill() { name = getNameNotEmpty(); winIdentifier = getWinIdentifierNotEmpty(); winCompany = getWinCompanyNotEmpty(); winCopyright = getWinCopyrightNotEmpty(); winLocale = getWinLocaleNotNull(); xkbPath = getXkbPathNotEmpty(); xkbLabel = getXkbLabelNotEmpty(); xkbAltGrKey = getXkbAltGrKeyNotNull(); xkbComposeKey = getXkbComposeKeyNotNull(); keymanIdentifier = getKeymanIdentifierNotEmpty(); keymanName = getKeymanNameNotEmpty(); keymanCopyright = getKeymanCopyrightNotEmpty(); keymanVersion = getKeymanVersionNotEmpty(); keymanAuthor = getKeymanAuthorNotEmpty(); keymanDescription = getKeymanDescriptionNotEmpty(); } public boolean isWindowsNativeCompatible() { // Windows doesn't like non-BMP characters on altgr. // Trying to type them just makes it beep at you. // But MSKLC doesn't even issue a warning about this. // A third-party input method has to be used for these layouts. for (KeyMapping km : map.values()) { if (km.altUnshiftedOutput > 0xFFFF) return false; if (km.altShiftedOutput > 0xFFFF) return false; for (DeadKeyTable dead : new DeadKeyTable[] { km.unshiftedDeadKey, km.shiftedDeadKey, km.ctrlDeadKey, km.altUnshiftedDeadKey, km.altShiftedDeadKey }) { if (dead != null) { if (dead.winTerminator > 0xFFFF) return false; for (int output : dead.keyMap.values()) { if (output > 0xFFFF) return false; } } } } return true; } public void getAllOutputs(Collection all, boolean includeDeadKeys, boolean includeLongPress) { for (KeyMapping km : map.values()) { for (int output : new int[] { km.unshiftedOutput, km.shiftedOutput, km.altUnshiftedOutput, km.altShiftedOutput }) { if (output > 0) all.add(output); } if (includeDeadKeys) { for (DeadKeyTable dead : new DeadKeyTable[] { km.unshiftedDeadKey, km.shiftedDeadKey, km.altUnshiftedDeadKey, km.altShiftedDeadKey }) { if (dead != null) { if (dead.winTerminator > 0) all.add(dead.winTerminator); if (dead.macTerminator > 0) all.add(dead.macTerminator); for (int o : dead.keyMap.values()) if (o > 0) all.add(o); } } } if (includeLongPress) { for (int[] lpo : new int[][] { km.unshiftedLongPressOutput, km.shiftedLongPressOutput, km.altUnshiftedLongPressOutput, km.altShiftedLongPressOutput }) { if (lpo != null) { for (int o : lpo) { if (o > 0) all.add(o); } } } } } } public List getAutoLongPressOutput(List list, int cp) { if (list == null) list = new ArrayList(); for (KeyMapping mm : map.values()) { Integer audk = (mm.altUnshiftedDeadKey != null) ? mm.altUnshiftedDeadKey.keyMap.get(cp) : null; Integer asdk = (mm.altShiftedDeadKey != null) ? mm.altShiftedDeadKey.keyMap.get(cp) : null; Integer udk = (mm.unshiftedDeadKey != null) ? mm.unshiftedDeadKey.keyMap.get(cp) : null; Integer sdk = (mm.shiftedDeadKey != null) ? mm.shiftedDeadKey.keyMap.get(cp) : null; if (audk != null) list.add(audk); if (asdk != null) list.add(asdk); if (udk != null) list.add(udk); if (sdk != null) list.add(sdk); } final Collator coll = Collator.getInstance(); coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION); coll.setStrength(Collator.IDENTICAL); Collections.sort(list, new Comparator() { public int compare(Integer cp1, Integer cp2) { String s1 = String.valueOf(Character.toChars(cp1)); String s2 = String.valueOf(Character.toChars(cp2)); return coll.compare(s1, s2); } }); return list; } public int[] getAutoLongPressOutput(int cp) { List list = getAutoLongPressOutput(null, cp); int n = list.size(); int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = list.get(i); return a; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KkbCopy.java000066400000000000000000000020741506470510200271450ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; public class KkbCopy { public static void main(String[] args) { if (args.length < 2) { System.out.println("Usage: KkbCopy "); System.out.println(" KkbCopy "); } else { String outPath = args[args.length-1]; File out = new File(outPath); if (args.length > 2 || outPath.endsWith("/") || out.isDirectory()) { out.mkdir(); for (int i = 0; i < args.length-1; i++) { try { KeyboardMapping km = KkbReader.read(new File(args[i])); File output = new File(out, km.getNameNotEmpty() + ".kkbx"); KkbWriter.write(output, km); } catch (IOException e) { System.err.println("Failed copying " + args[i] + ": " + e.getMessage()); } } } else { try { KeyboardMapping km = KkbReader.read(new File(args[0])); KkbWriter.write(new File(args[1]), km); } catch (IOException e) { System.err.println("Failed copying " + args[0] + ": " + e.getMessage()); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KkbInfo.java000066400000000000000000000166261506470510200271360ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; public class KkbInfo { public static void main(String[] args) { ArrayList selectors = new ArrayList(); ArrayList files = new ArrayList(); boolean parseOptions = true; for (String arg : args) { if (parseOptions && arg.startsWith("-")) { if (arg.equals("--")) { parseOptions = false; } else { Selector selector = Selector.forOption(arg); if (selector == null) { help(); return; } selectors.add(selector); } } else { files.add(new File(arg)); } } if (selectors.isEmpty() || files.isEmpty()) { help(); return; } for (File file : files) { try { KeyboardMapping km = KkbReader.read(file); boolean first = true; for (Selector selector : selectors) { if (first) first = false; else System.out.print("\t"); System.out.print(selector.get(file, km)); } System.out.println(); } catch (IOException e) { System.err.println("Error reading " + file + ": " + e); } } } public static void help() { System.err.println("Usage: KkbInfo [--] "); System.err.println(); System.err.println("Options:"); Selector[] selectors = Selector.values(); Arrays.sort(selectors, new Comparator() { public int compare(Selector a, Selector b) { return a.option.compareTo(b.option); } }); for (Selector selector : selectors) { System.err.println(" " + selector.option + " " + selector.description); } } private static enum Selector { FILE_NAME("-f", "file name") { public String get(File file, KeyboardMapping km) { return file.getName(); } }, FILE_PATH("-F", "file path") { public String get(File file, KeyboardMapping km) { return file.getPath(); } }, PARENT_PATH("-P", "parent path") { public String get(File file, KeyboardMapping km) { return file.getParent(); } }, NAME("-n", "name") { public String get(File file, KeyboardMapping km) { return km.getNameNotEmpty(); } }, WIN_IDENTIFIER("-i", "(MSKLC) short name") { public String get(File file, KeyboardMapping km) { return km.getWinIdentifierNotEmpty(); } }, WIN_COPYRIGHT("-c", "(MSKLC) copyright") { public String get(File file, KeyboardMapping km) { return km.getWinCopyrightNotEmpty(); } }, WIN_COMPANY("-a", "(MSKLC) company") { public String get(File file, KeyboardMapping km) { return km.getWinCompanyNotEmpty(); } }, WIN_LOCALE("-l", "(MSKLC) locale") { public String get(File file, KeyboardMapping km) { return km.getWinLocaleNotNull().tag; } }, WIN_ALTGR_ENABLE("-g", "(MSKLC) treat right alt as ctrl+alt (altgr)") { public String get(File file, KeyboardMapping km) { return km.winAltGrEnable ? "Y" : "N"; } }, WIN_SHIFT_LOCK("-s", "(MSKLC) disable caps lock when shift is pressed (shiftlock)") { public String get(File file, KeyboardMapping km) { return km.winShiftLock ? "Y" : "N"; } }, WIN_LRM_RLM("-r", "(MSKLC) left shift + bksp = LRM, right shift + bksp = RLM") { public String get(File file, KeyboardMapping km) { return km.winLrmRlm ? "Y" : "N"; } }, MAC_GROUP_NUMBER("-J", "(Mac OS X) group number") { public String get(File file, KeyboardMapping km) { return Integer.toString(km.macGroupNumber); } }, MAC_ID_NUMBER("-j", "(Mac OS X) ID number") { public String get(File file, KeyboardMapping km) { return Integer.toString(km.macIdNumber); } }, XKB_PATH("-p", "(XKB) path / name") { public String get(File file, KeyboardMapping km) { return km.getXkbPathNotEmpty(); } }, XKB_LABEL("-d", "(XKB) label / short description") { public String get(File file, KeyboardMapping km) { return km.getXkbLabelNotEmpty(); } }, XKB_USE_KEYSYM("-u", "(XKB) use keysym constants") { public String get(File file, KeyboardMapping km) { return km.xkbUseKeySym ? "Y" : "N"; } }, XKB_ALTGR_KEY("-v", "(XKB) altgr key / level3 key") { public String get(File file, KeyboardMapping km) { return km.getXkbAltGrKeyNotNull().name(); } }, XKB_COMPOSE_KEY("-k", "(XKB) compose key") { public String get(File file, KeyboardMapping km) { return km.getXkbComposeKeyNotNull().name(); } }, KEYMAN_IDENTIFIER("-I", "(Keyman) ID") { public String get(File file, KeyboardMapping km) { return km.getKeymanIdentifierNotEmpty(); } }, KEYMAN_NAME("-N", "(Keyman) name") { public String get(File file, KeyboardMapping km) { return km.getKeymanNameNotEmpty(); } }, KEYMAN_COPYRIGHT("-C", "(Keyman) copyright") { public String get(File file, KeyboardMapping km) { return km.getKeymanCopyrightNotEmpty(); } }, KEYMAN_MESSAGE("-M", "(Keyman) message") { public String get(File file, KeyboardMapping km) { return (km.keymanMessage != null) ? km.keymanMessage : ""; } }, KEYMAN_WEB_HELP_TEXT("-H", "(Keyman) web help text") { public String get(File file, KeyboardMapping km) { return (km.keymanWebHelpText != null) ? km.keymanWebHelpText : ""; } }, KEYMAN_VERSION("-V", "(Keyman) keyboard version") { public String get(File file, KeyboardMapping km) { return km.getKeymanVersionNotEmpty(); } }, KEYMAN_AUTHOR("-A", "(Keyman) author") { public String get(File file, KeyboardMapping km) { return km.getKeymanAuthorNotEmpty(); } }, KEYMAN_EMAIL_ADDRESS("-E", "(Keyman) email address") { public String get(File file, KeyboardMapping km) { return (km.keymanEmailAddress != null) ? km.keymanEmailAddress : ""; } }, KEYMAN_WEB_SITE("-W", "(Keyman) web site") { public String get(File file, KeyboardMapping km) { return (km.keymanWebSite != null) ? km.keymanWebSite : ""; } }, KEYMAN_RIGHT_TO_LEFT("-R", "(Keyman) keyboard is right-to-left") { public String get(File file, KeyboardMapping km) { return km.keymanRightToLeft ? "Y" : "N"; } }, KEYMAN_KEY_102("-K", "(Keyman) display 102nd key") { public String get(File file, KeyboardMapping km) { return km.keymanKey102 ? "Y" : "N"; } }, KEYMAN_DISPLAY_UNDERLYING("-U", "(Keyman) display underlying layout characters") { public String get(File file, KeyboardMapping km) { return km.keymanDisplayUnderlying ? "Y" : "N"; } }, KEYMAN_USE_ALTGR("-G", "(Keyman) distinguish between left and right ctrl/alt") { public String get(File file, KeyboardMapping km) { return km.keymanUseAltGr ? "Y" : "N"; } }, KEYMAN_IGNORE_CAPS("-S", "(Keyman) disable caps lock") { public String get(File file, KeyboardMapping km) { return km.keymanIgnoreCaps ? "Y" : "N"; } }, KEYMAN_DESCRIPTION("-D", "(Keyman) description") { public String get(File file, KeyboardMapping km) { return km.getKeymanDescriptionNotEmpty(); } }, KEYMAN_LICENSE_TYPE("-L", "(Keyman) license type") { public String get(File file, KeyboardMapping km) { return km.getKeymanLicenseTypeNotEmpty(); } }; private final String option; private final String description; private Selector(String option, String description) { this.option = option; this.description = description; } public abstract String get(File file, KeyboardMapping km); public static Selector forOption(String s) { for (Selector selector : values()) { if (selector.option.equals(s)) { return selector; } } return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KkbLint.java000066400000000000000000000011001506470510200271260ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; public class KkbLint { public static void main(String[] args) { for (String arg : args) { try { KeyboardMapping km = KkbReader.read(new File(arg)); OutputStreamWriter ow = new OutputStreamWriter(System.out, "UTF-8"); PrintWriter pw = new PrintWriter(ow, true); KkbWriter.write(pw, km); } catch (IOException e) { System.err.println("Error: Failed to parse " + arg + ": " + e.getMessage()); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KkbReader.java000066400000000000000000000656411506470510200274460ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.BitSet; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class KkbReader { public static KeyboardMapping read(File file) throws IOException { FileInputStream in = new FileInputStream(file); KeyboardMapping km = parse(file.getName(), in); in.close(); return km; } public static KeyboardMapping parse(String name, InputStream in) throws IOException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); // make sure the XML is valid factory.setExpandEntityReferences(false); // don't allow custom entities DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new KkbEntityResolver()); builder.setErrorHandler(new KkbErrorHandler(name)); Document document = builder.parse(new InputSource(in)); return parseDocument(document); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException saxe) { throw new IOException(saxe); } } private static KeyboardMapping parseDocument(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("#document")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("keyboardMapping")) { if (child.hasAttributes() || child.hasChildNodes()) { return parseKeyboardMapping(child); } } else { throw new IOException("Unknown element: " + ctype); } } throw new IOException("Empty document."); } else { throw new IOException("Unknown element: " + type); } } private static KeyboardMapping parseKeyboardMapping(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyboardMapping")) { KeyboardMapping km = new KeyboardMapping(); for (Node child : getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("name")) { km.name = textContent(child); } else if (ctype.equalsIgnoreCase("winIdentifier")) { km.winIdentifier = textContent(child); } else if (ctype.equalsIgnoreCase("winCopyright")) { km.winCopyright = textContent(child); } else if (ctype.equalsIgnoreCase("winCompany")) { km.winCompany = textContent(child); } else if (ctype.equalsIgnoreCase("winLocale")) { km.winLocale = WinLocale.forTag(parseString(cattr, "tag"), km.winLocale); } else if (ctype.equalsIgnoreCase("winAltGrEnable")) { km.winAltGrEnable = parseBoolean(cattr, "altgr", "true", "false", km.winAltGrEnable); } else if (ctype.equalsIgnoreCase("winShiftLock")) { km.winShiftLock = parseBoolean(cattr, "shiftlock", "true", "false", km.winShiftLock); } else if (ctype.equalsIgnoreCase("winLrmRlm")) { km.winLrmRlm = parseBoolean(cattr, "lrmrlm", "true", "false", km.winLrmRlm); } else if (ctype.equalsIgnoreCase("macGroupNumber")) { km.macGroupNumber = parseInt(cattr, "group", km.macGroupNumber); } else if (ctype.equalsIgnoreCase("macIdNumber")) { km.macIdNumber = parseInt(cattr, "id", km.macIdNumber); } else if (ctype.equalsIgnoreCase("xkbPath")) { km.xkbPath = textContent(child); } else if (ctype.equalsIgnoreCase("xkbLabel")) { km.xkbLabel = textContent(child); } else if (ctype.equalsIgnoreCase("xkbComment")) { km.xkbComment = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("xkbUseKeySym")) { km.xkbUseKeySym = parseBoolean(cattr, "for", "unicode", "ascii", km.xkbUseKeySym); } else if (ctype.equalsIgnoreCase("xkbAltGrKey")) { km.xkbAltGrKey = XkbAltGrKey.forInclude(parseString(cattr, "include")); } else if (ctype.equalsIgnoreCase("xkbComposeKey")) { km.xkbComposeKey = XkbComposeKey.forInclude(parseString(cattr, "include")); } else if (ctype.equalsIgnoreCase("keymanIdentifier")) { km.keymanIdentifier = textContent(child); } else if (ctype.equalsIgnoreCase("keymanName")) { km.keymanName = textContent(child); } else if (ctype.equalsIgnoreCase("keymanCopyright")) { km.keymanCopyright = textContent(child); } else if (ctype.equalsIgnoreCase("keymanMessage")) { km.keymanMessage = textContent(child); } else if (ctype.equalsIgnoreCase("keymanWebHelpText")) { km.keymanWebHelpText = textContent(child); } else if (ctype.equalsIgnoreCase("keymanVersion")) { km.keymanVersion = textContent(child); } else if (ctype.equalsIgnoreCase("keymanComments")) { km.keymanComments = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("keymanAuthor")) { km.keymanAuthor = textContent(child); } else if (ctype.equalsIgnoreCase("keymanEmailAddress")) { km.keymanEmailAddress = textContent(child); } else if (ctype.equalsIgnoreCase("keymanWebSite")) { km.keymanWebSite = textContent(child); } else if (ctype.equalsIgnoreCase("keymanRightToLeft")) { km.keymanRightToLeft = parseBoolean(cattr, "value", "true", "false", km.keymanRightToLeft); } else if (ctype.equalsIgnoreCase("keymanKey102")) { km.keymanKey102 = parseBoolean(cattr, "value", "true", "false", km.keymanKey102); } else if (ctype.equalsIgnoreCase("keymanDisplayUnderlying")) { km.keymanDisplayUnderlying = parseBoolean(cattr, "value", "true", "false", km.keymanDisplayUnderlying); } else if (ctype.equalsIgnoreCase("keymanUseAltGr")) { km.keymanUseAltGr = parseBoolean(cattr, "value", "true", "false", km.keymanUseAltGr); } else if (ctype.equalsIgnoreCase("keymanIgnoreCaps")) { km.keymanIgnoreCaps = parseBoolean(cattr, "value", "true", "false", km.keymanIgnoreCaps); } else if (ctype.equalsIgnoreCase("keymanTargets")) { for (KeyManTarget t : KeyManTarget.values()) { parseBoolean(cattr, t.toString(), "true", "false", t, km.keymanTargets); } } else if (ctype.equalsIgnoreCase("keymanPlatforms")) { for (KeyManPlatform p : KeyManPlatform.values()) { parseBoolean(cattr, p.toString(), "true", "false", p, km.keymanPlatforms); } } else if (ctype.equalsIgnoreCase("keymanLanguages")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("keymanLanguage")) { NamedNodeMap gcattr = gchild.getAttributes(); String tag = parseString(gcattr, "tag"); if (tag != null && tag.length() > 0) { String name = parseString(gcattr, "name"); if (name == null || name.length() == 0) name = tag; km.keymanLanguages.put(tag, name); } } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("keymanAttachments")) { parseAttachments(child, km.keymanAttachments); } else if (ctype.equalsIgnoreCase("keymanFileIds")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("fileId")) { NamedNodeMap gcattr = gchild.getAttributes(); String name = parseString(gcattr, "name"); String id = parseString(gcattr, "id"); if (name != null && id != null) { km.keymanFileIds.put(name, id); } } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("keymanCpLabels")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("cpLabel")) { NamedNodeMap gcattr = gchild.getAttributes(); Integer cp = parseHex(gcattr, "cp", null); String label = parseString(gcattr, "label"); if (cp != null && label != null) { km.keymanCpLabels.put(cp, label); } } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("keymanFont")) { km.keymanFontFamily = parseString(cattr, "family"); } else if (ctype.equalsIgnoreCase("keymanOSKFont")) { km.keymanOSKFontFile = parseString(cattr, "file"); } else if (ctype.equalsIgnoreCase("keymanDisplayFont")) { km.keymanDisplayFontFile = parseString(cattr, "file"); } else if (ctype.equalsIgnoreCase("keymanDescription")) { km.keymanDescription = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("keymanLicense")) { km.keymanLicenseType = parseString(cattr, "type"); km.keymanLicenseText = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("keymanReadme")) { km.keymanReadme = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("keymanHistory")) { km.keymanHistory = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("icon")) { String data = textContent(child); if (data != null) { try { Base64InputStream b64 = new Base64InputStream(data); km.icon = ImageIO.read(b64); b64.close(); } catch (IOException e) { e.printStackTrace(); } } } else if (ctype.equalsIgnoreCase("macIconVersion")) { km.macIconVersion = parseHex(cattr, "version", null); } else if (ctype.equalsIgnoreCase("keyMappings")) { for (Node gchild : getChildren(child)) { parseKeyMapping(gchild, km); } } else if (ctype.equalsIgnoreCase("macActionIds")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("macActionId")) { NamedNodeMap gcattr = gchild.getAttributes(); Integer input = parseHex(gcattr, "input", null); String action = parseString(gcattr, "action"); if (input != null && action != null) { km.macActionIds.put(input, action); } } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("html")) { parseHTMLConfig(child, km); } else if (ctype.equalsIgnoreCase("winAttachments")) { parseAttachments(child, km.winAttachments); } else if (ctype.equalsIgnoreCase("macAttachments")) { parseAttachments(child, km.macAttachments); } else if (ctype.equalsIgnoreCase("xkbAttachments")) { parseAttachments(child, km.xkbAttachments); } else { throw new IOException("Unknown element: " + ctype); } } return km; } else { throw new IOException("Unknown element: " + type); } } private static void parseKeyMapping(Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyMapping")) { NamedNodeMap attr = node.getAttributes(); Key key = Key.forName(parseString(attr, "key")); KeyMapping map = km.map.get(key); if (map == null) return; for (Node child : getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("unshifted")) { map.unshiftedOutput = parseHex(cattr, "output", -1); map.unshiftedDeadKey = null; map.unshiftedLongPressOutput = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.unshiftedDeadKey = parseDeadKey(gchild); } else if (gctype.equalsIgnoreCase("longPressOutput")) { map.unshiftedLongPressOutput = parseLongPressOutput(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("shifted")) { map.shiftedOutput = parseHex(cattr, "output", -1); map.shiftedDeadKey = null; map.shiftedLongPressOutput = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.shiftedDeadKey = parseDeadKey(gchild); } else if (gctype.equalsIgnoreCase("longPressOutput")) { map.shiftedLongPressOutput = parseLongPressOutput(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("capsLock")) { map.capsLockMapping = parseCapsLock(cattr, "mapsTo", "unshifted", "shifted"); } else if (ctype.equalsIgnoreCase("altUnshifted")) { map.altUnshiftedOutput = parseHex(cattr, "output", -1); map.altUnshiftedDeadKey = null; map.altUnshiftedLongPressOutput = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.altUnshiftedDeadKey = parseDeadKey(gchild); } else if (gctype.equalsIgnoreCase("longPressOutput")) { map.altUnshiftedLongPressOutput = parseLongPressOutput(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("altShifted")) { map.altShiftedOutput = parseHex(cattr, "output", -1); map.altShiftedDeadKey = null; map.altShiftedLongPressOutput = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.altShiftedDeadKey = parseDeadKey(gchild); } else if (gctype.equalsIgnoreCase("longPressOutput")) { map.altShiftedLongPressOutput = parseLongPressOutput(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("altCapsLock")) { map.altCapsLockMapping = parseCapsLock(cattr, "mapsTo", "altUnshifted", "altShifted"); } else if (ctype.equalsIgnoreCase("ctrl")) { map.ctrlOutput = parseHex(cattr, "output", -1); map.ctrlDeadKey = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.ctrlDeadKey = parseDeadKey(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else if (ctype.equalsIgnoreCase("command")) { map.commandOutput = parseHex(cattr, "output", -1); map.commandDeadKey = null; for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKey")) { map.commandDeadKey = parseDeadKey(gchild); } else { throw new IOException("Unknown element: " + gctype); } } } else { throw new IOException("Unknown element: " + ctype); } } } else { throw new IOException("Unknown element: " + type); } } private static DeadKeyTable parseDeadKey(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("deadKey")) { DeadKeyTable dkt = new DeadKeyTable(); for (Node child : getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("winTerminator")) { dkt.winTerminator = parseHex(cattr, "output", -1); } else if (ctype.equalsIgnoreCase("macTerminator")) { dkt.macTerminator = parseHex(cattr, "output", -1); } else if (ctype.equalsIgnoreCase("macStateId")) { dkt.macStateId = parseString(cattr, "state"); } else if (ctype.equalsIgnoreCase("xkbOutput")) { dkt.xkbOutput = parseHex(cattr, "output", -1); } else if (ctype.equalsIgnoreCase("xkbDeadKey")) { dkt.xkbDeadKey = XkbDeadKey.forKeySym(parseString(cattr, "keysym")); } else if (ctype.equalsIgnoreCase("deadKeyMap")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("deadKeyEntry")) { NamedNodeMap gcattr = gchild.getAttributes(); Integer input = parseHex(gcattr, "input", null); Integer output = parseHex(gcattr, "output", null); if (input != null && output != null) { dkt.keyMap.put(input, output); } } else { throw new IOException("Unknown element: " + gctype); } } } else { throw new IOException("Unknown element: " + ctype); } } return dkt; } else { throw new IOException("Unknown element: " + type); } } private static int[] parseLongPressOutput(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("longPressOutput")) { List lpo = new ArrayList(); for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("longPressEntry")) { NamedNodeMap cattr = child.getAttributes(); Integer output = parseHex(cattr, "output", null); if (output != null) lpo.add(output); } else { throw new IOException("Unknown element: " + ctype); } } int n = lpo.size(); int[] output = new int[n]; for (int i = 0; i < n; i++) output[i] = lpo.get(i); return output; } else { throw new IOException("Unknown element: " + type); } } private static void parseHTMLConfig(Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("html")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); NamedNodeMap cattr = child.getAttributes(); if (ctype.equalsIgnoreCase("title")) { km.htmlTitle = textContent(child); } else if (ctype.equalsIgnoreCase("style")) { km.htmlStyle = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("h1")) { km.htmlH1 = textContent(child); } else if (ctype.equalsIgnoreCase("h2")) { km.htmlH2 = textContent(child); } else if (ctype.equalsIgnoreCase("body1")) { km.htmlBody1 = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("body2")) { km.htmlBody2 = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("body3")) { km.htmlBody3 = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("body4")) { km.htmlBody4 = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("install")) { km.htmlInstall = stripCommonLeadingWhitespace(textContent(child)); } else if (ctype.equalsIgnoreCase("square")) { km.htmlSquareChars = parseRanges(parseString(cattr, "chars")); } else if (ctype.equalsIgnoreCase("outline")) { km.htmlOutlineChars = parseRanges(parseString(cattr, "chars")); } else if (ctype.equalsIgnoreCase("cpClasses")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); Map classes; if (gctype.equalsIgnoreCase("td")) { classes = km.htmlTdClasses; } else if (gctype.equalsIgnoreCase("span")) { classes = km.htmlSpanClasses; } else { throw new IOException("Unknown element: " + gctype); } NamedNodeMap gcattr = gchild.getAttributes(); String className = parseString(gcattr, "class"); BitSet chars = parseRanges(parseString(gcattr, "chars")); if (className != null && chars != null) { BitSet bs = classes.get(className); if (bs != null) bs.or(chars); else classes.put(className, chars); } } } else if (ctype.equalsIgnoreCase("cpLabels")) { for (Node gchild : getChildren(child)) { String gctype = gchild.getNodeName(); if (gctype.equalsIgnoreCase("cpLabel")) { NamedNodeMap gcattr = gchild.getAttributes(); Integer cp = parseHex(gcattr, "cp", null); String label = parseString(gcattr, "label"); if (cp != null && label != null) { km.htmlCpLabels.put(cp, label); } } else { throw new IOException("Unknown element: " + gctype); } } } else { throw new IOException("Unknown element: " + ctype); } } } else { throw new IOException("Unknown element: " + type); } } private static void parseAttachments(Node node, Map attachments) throws IOException { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("attachment")) { NamedNodeMap cattr = child.getAttributes(); String name = parseString(cattr, "name"); String data = textContent(child); if (name != null && data != null) { try { ByteArrayOutputStream ba = new ByteArrayOutputStream(); Base64InputStream b64 = new Base64InputStream(data); byte[] buf = new byte[65536]; int n; while ((n = b64.read(buf)) > 0) ba.write(buf, 0, n); b64.close(); ba.close(); attachments.put(name, ba.toByteArray()); } catch (IOException e) { e.printStackTrace(); } } } else { throw new IOException("Unknown element: " + ctype); } } } public static BitSet parseRanges(String s) { if (s == null || (s = s.trim()).length() == 0) return null; BitSet bs = new BitSet(); for (String r : s.split(",")) { try { if (r.contains("-")) { String[] p = r.split("-", 2); int i = Integer.parseInt(p[0].trim(), 16); int j = Integer.parseInt(p[1].trim(), 16); bs.set(i, j + 1); } else { int i = Integer.parseInt(r.trim(), 16); bs.set(i); } } catch (NumberFormatException nfe) { // ignored } } return bs; } private static String stripCommonLeadingWhitespace(String s) { if (s == null) return null; String[] lines = s.split("\r\n|\r|\n"); if (lines.length < 2) return s; String prefix = leadingWhitespace(lines[1]); for (int i = 2; i < lines.length; i++) { String newPrefix = leadingWhitespace(lines[i]); prefix = commonPrefix(prefix, newPrefix); } StringBuffer sb = new StringBuffer(lines[0]); for (int i = 1; i < lines.length; i++) { sb.append("\n"); sb.append(lines[i].substring(prefix.length())); } return sb.toString(); } private static final Pattern LEADING_WHITESPACE = Pattern.compile("^\\s+"); private static String leadingWhitespace(String s) { Matcher m = LEADING_WHITESPACE.matcher(s); if (m.find()) return m.group(); return ""; } private static String commonPrefix(String a, String b) { if (a.startsWith(b)) return b; if (b.startsWith(a)) return a; return ""; } private static String textContent(Node node) { if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; return text.trim(); } private static CapsLockMapping parseCapsLock(NamedNodeMap attr, String key, String unshifted, String shifted) { if (attr == null) return CapsLockMapping.AUTO; Node node = attr.getNamedItem(key); if (node == null) return CapsLockMapping.AUTO; String text = node.getTextContent(); if (text == null) return CapsLockMapping.AUTO; text = text.trim(); if (text.equalsIgnoreCase(unshifted)) return CapsLockMapping.UNSHIFTED; if (text.equalsIgnoreCase(shifted)) return CapsLockMapping.SHIFTED; return CapsLockMapping.AUTO; } private static > void parseBoolean(NamedNodeMap attr, String key, String trueValue, String falseValue, E value, EnumSet set) { if (attr == null) return; Node node = attr.getNamedItem(key); if (node == null) return; String text = node.getTextContent(); if (text == null) return; text = text.trim(); if (text.equalsIgnoreCase(trueValue)) set.add(value); if (text.equalsIgnoreCase(falseValue)) set.remove(value); } private static boolean parseBoolean(NamedNodeMap attr, String key, String trueValue, String falseValue, boolean def) { if (attr == null) return def; Node node = attr.getNamedItem(key); if (node == null) return def; String text = node.getTextContent(); if (text == null) return def; text = text.trim(); if (text.equalsIgnoreCase(trueValue)) return true; if (text.equalsIgnoreCase(falseValue)) return false; return def; } private static int parseInt(NamedNodeMap attr, String key, int def) { if (attr == null) return def; Node node = attr.getNamedItem(key); if (node == null) return def; String text = node.getTextContent(); if (text == null) return def; try { return Integer.parseInt(text.trim()); } catch (NumberFormatException nfe) { return def; } } private static Integer parseHex(NamedNodeMap attr, String key, Integer def) { if (attr == null) return def; Node node = attr.getNamedItem(key); if (node == null) return def; String text = node.getTextContent(); if (text == null) return def; try { return Integer.parseInt(text.trim(), 16); } catch (NumberFormatException nfe) { return def; } } private static String parseString(NamedNodeMap attr, String key) { if (attr == null) return null; Node node = attr.getNamedItem(key); if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; return text.trim(); } private static List getChildren(Node node) { List list = new ArrayList(); if (node != null) { NodeList children = node.getChildNodes(); if (children != null) { int count = children.getLength(); for (int i = 0; i < count; i++) { Node child = children.item(i); if (child != null) { String type = child.getNodeName(); if (type.equalsIgnoreCase("#text") || type.equalsIgnoreCase("#comment")) { continue; } else { list.add(child); } } } } } return list; } private static class KkbEntityResolver implements EntityResolver { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (publicId.contains("KreativeKeyboard") || systemId.contains("kkbx.dtd")) { return new InputSource(KkbReader.class.getResourceAsStream("kkbx.dtd")); } else { return null; } } } private static class KkbErrorHandler implements ErrorHandler { private final String name; public KkbErrorHandler(String name) { this.name = name; } @Override public void error(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void fatalError(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("FATAL ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void warning(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("WARNING on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/KkbWriter.java000066400000000000000000000435011506470510200275070ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; public class KkbWriter { public static void write(File file, KeyboardMapping km) throws IOException { FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write(pw, km); pw.flush(); pw.close(); fos.close(); } public static void write(PrintWriter out, KeyboardMapping km) { out.println(""); out.println(""); out.println(""); out.println(wrap("\t", "name", km.name)); out.println(wrap("\t", "winIdentifier", km.winIdentifier)); out.println(wrap("\t", "winCopyright", km.winCopyright)); out.println(wrap("\t", "winCompany", km.winCompany)); out.println(wrap("\t", "winLocale", "tag", km.getWinLocaleNotNull().tag)); out.println(wrap("\t", "winAltGrEnable", "altgr", (km.winAltGrEnable ? "true" : "false"))); out.println(wrap("\t", "winShiftLock", "shiftlock", (km.winShiftLock ? "true" : "false"))); out.println(wrap("\t", "winLrmRlm", "lrmrlm", (km.winLrmRlm ? "true" : "false"))); out.println(wrap("\t", "macGroupNumber", "group", Integer.toString(km.macGroupNumber))); out.println(wrap("\t", "macIdNumber", "id", Integer.toString(km.macIdNumber))); out.println(wrap("\t", "xkbPath", km.xkbPath)); out.println(wrap("\t", "xkbLabel", km.xkbLabel)); writeBlock(out, "\t", "xkbComment", km.xkbComment); out.println(wrap("\t", "xkbUseKeySym", "for", (km.xkbUseKeySym ? "unicode" : "ascii"))); if (km.xkbAltGrKey != null && km.xkbAltGrKey != XkbAltGrKey.none) { String include = "level3(" + km.xkbAltGrKey.name() + ")"; out.println(wrap("\t", "xkbAltGrKey", "include", include)); } if (km.xkbComposeKey != null && km.xkbComposeKey != XkbComposeKey.none) { String include = "compose(" + km.xkbComposeKey.name() + ")"; out.println(wrap("\t", "xkbComposeKey", "include", include)); } writeKeymanConfig(out, km); if (km.icon != null) { try { StringBuffer sb = new StringBuffer(); Base64OutputStream b64 = new Base64OutputStream(sb); ImageIO.write(km.icon, "png", b64); b64.flush(); b64.close(); out.println(wrap("\t", "icon", sb.toString())); } catch (IOException ioe) { ioe.printStackTrace(); } } if (km.macIconVersion != null) { out.println(wrap("\t", "macIconVersion", "version", hex(km.macIconVersion,8))); } if (!km.map.isEmpty()) { out.println("\t"); for (Map.Entry e : km.map.entrySet()) { write(out, e.getKey(), e.getValue()); } out.println("\t"); } if (!km.macActionIds.isEmpty()) { out.println("\t"); for (Map.Entry e : km.macActionIds.entrySet()) { out.println(wrap("\t\t", "macActionId", "input", hex(e.getKey(),4), "action", e.getValue())); } out.println("\t"); } writeHTMLConfig(out, km); writeAttachments(out, "winAttachments", km.winAttachments); writeAttachments(out, "macAttachments", km.macAttachments); writeAttachments(out, "xkbAttachments", km.xkbAttachments); out.println(""); } private static void write(PrintWriter out, Key k, KeyMapping km) { out.println(wrap("\t\t", "keyMapping", "key", k.name().toLowerCase(), false)); write(out, "unshifted", km.unshiftedOutput, km.unshiftedDeadKey, km.unshiftedLongPressOutput); write(out, "shifted", km.shiftedOutput, km.shiftedDeadKey, km.shiftedLongPressOutput); out.println(wrap("\t\t\t", "capsLock", "mapsTo", caps(km.capsLockMapping, "unshifted", "shifted", "auto"))); write(out, "altUnshifted", km.altUnshiftedOutput, km.altUnshiftedDeadKey, km.altUnshiftedLongPressOutput); write(out, "altShifted", km.altShiftedOutput, km.altShiftedDeadKey, km.altShiftedLongPressOutput); out.println(wrap("\t\t\t", "altCapsLock", "mapsTo", caps(km.altCapsLockMapping, "altUnshifted", "altShifted", "auto"))); write(out, "ctrl", km.ctrlOutput, km.ctrlDeadKey, null); write(out, "command", km.commandOutput, km.commandDeadKey, null); out.println("\t\t"); } private static void write(PrintWriter out, String state, int output, DeadKeyTable dkt, int[] lpo) { if (output > 0) { out.println(wrap("\t\t\t", state, "output", hex(output,4), dkt == null && lpo == null)); } else { out.println(wrap("\t\t\t", state, dkt == null && lpo == null)); } if (dkt != null || lpo != null) { if (dkt != null) write(out, dkt); if (lpo != null) write(out, lpo); out.println("\t\t\t"); } } private static void write(PrintWriter out, DeadKeyTable dkt) { out.println("\t\t\t\t"); if (dkt.winTerminator > 0) { out.println(wrap("\t\t\t\t\t", "winTerminator", "output", hex(dkt.winTerminator,4))); } if (dkt.macTerminator > 0) { out.println(wrap("\t\t\t\t\t", "macTerminator", "output", hex(dkt.macTerminator,4))); } if (dkt.macStateId != null && dkt.macStateId.length() > 0) { out.println(wrap("\t\t\t\t\t", "macStateId", "state", dkt.macStateId)); } if (dkt.xkbOutput > 0) { out.println(wrap("\t\t\t\t\t", "xkbOutput", "output", hex(dkt.xkbOutput,4))); } if (dkt.xkbDeadKey != null && dkt.xkbDeadKey != XkbDeadKey.none) { out.println(wrap("\t\t\t\t\t", "xkbDeadKey", "keysym", dkt.xkbDeadKey.name())); } if (!dkt.keyMap.isEmpty()) { out.println("\t\t\t\t\t"); for (Map.Entry e : dkt.keyMap.entrySet()) { out.println(wrap("\t\t\t\t\t\t", "deadKeyEntry", "input", hex(e.getKey(),4), "output", hex(e.getValue(),4))); } out.println("\t\t\t\t\t"); } out.println("\t\t\t\t"); } private static void write(PrintWriter out, int[] lpo) { out.println("\t\t\t\t"); for (int output : lpo) { out.println(wrap("\t\t\t\t\t", "longPressEntry", "output", hex(output,4))); } out.println("\t\t\t\t"); } private static void writeKeymanConfig(PrintWriter out, KeyboardMapping km) { if (!any( km.keymanIdentifier, km.keymanName, km.keymanCopyright, km.keymanMessage, km.keymanWebHelpText, km.keymanVersion, km.keymanComments, km.keymanAuthor, km.keymanEmailAddress, km.keymanWebSite, km.keymanRightToLeft, km.keymanKey102, km.keymanDisplayUnderlying, km.keymanUseAltGr, km.keymanTargets, km.keymanPlatforms, km.keymanLanguages, km.keymanAttachments, km.keymanFileIds, km.keymanCpLabels, km.keymanFontFamily, km.keymanOSKFontFile, km.keymanDisplayFontFile, km.keymanDescription, km.keymanLicenseType, km.keymanLicenseText, km.keymanReadme, km.keymanHistory )) return; out.println(wrap("\t", "keymanIdentifier", km.keymanIdentifier)); out.println(wrap("\t", "keymanName", km.keymanName)); out.println(wrap("\t", "keymanCopyright", km.keymanCopyright)); out.println(wrap("\t", "keymanMessage", km.keymanMessage)); out.println(wrap("\t", "keymanWebHelpText", km.keymanWebHelpText)); out.println(wrap("\t", "keymanVersion", km.keymanVersion)); writeBlock(out, "\t", "keymanComments", km.keymanComments); out.println(wrap("\t", "keymanAuthor", km.keymanAuthor)); out.println(wrap("\t", "keymanEmailAddress", km.keymanEmailAddress)); out.println(wrap("\t", "keymanWebSite", km.keymanWebSite)); out.println(wrap("\t", "keymanRightToLeft", "value", (km.keymanRightToLeft ? "true" : "false"))); out.println(wrap("\t", "keymanKey102", "value", (km.keymanKey102 ? "true" : "false"))); out.println(wrap("\t", "keymanDisplayUnderlying", "value", (km.keymanDisplayUnderlying ? "true" : "false"))); out.println(wrap("\t", "keymanUseAltGr", "value", (km.keymanUseAltGr ? "true" : "false"))); out.println(wrap("\t", "keymanIgnoreCaps", "value", (km.keymanIgnoreCaps ? "true" : "false"))); out.print("\t"); out.print("\t"); out.println("\t"); for (Map.Entry e : km.keymanLanguages.entrySet()) { out.println(wrap("\t\t", "keymanLanguage", "tag", e.getKey(), "name", e.getValue())); } out.println("\t"); writeAttachments(out, "keymanAttachments", km.keymanAttachments); if (km.keymanFileIds != null && !km.keymanFileIds.isEmpty()) { out.println("\t"); for (Map.Entry e : km.keymanFileIds.entrySet()) { out.println(wrap("\t\t", "fileId", "name", e.getKey(), "id", e.getValue())); } out.println("\t"); } if (km.keymanCpLabels != null && !km.keymanCpLabels.isEmpty()) { out.println("\t"); for (Map.Entry e : km.keymanCpLabels.entrySet()) { out.println(wrap("\t\t", "cpLabel", "cp", hex(e.getKey(),4), "label", e.getValue())); } out.println("\t"); } if (km.keymanFontFamily != null && km.keymanFontFamily.length() > 0) { out.println(wrap("\t", "keymanFont", "family", km.keymanFontFamily)); } if (km.keymanOSKFontFile != null && km.keymanOSKFontFile.length() > 0) { out.println(wrap("\t", "keymanOSKFont", "file", km.keymanOSKFontFile)); } if (km.keymanDisplayFontFile != null && km.keymanDisplayFontFile.length() > 0) { out.println(wrap("\t", "keymanDisplayFont", "file", km.keymanDisplayFontFile)); } writeBlock(out, "\t", "keymanDescription", km.keymanDescription); writeBlock(out, "\t", "keymanLicense", "type", km.keymanLicenseType, km.keymanLicenseText); writeBlock(out, "\t", "keymanReadme", km.keymanReadme); writeBlock(out, "\t", "keymanHistory", km.keymanHistory); } private static void writeHTMLConfig(PrintWriter out, KeyboardMapping km) { boolean wroteHeader = false; if (km.htmlTitle != null && km.htmlTitle.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println(wrap("\t\t", "title", km.htmlTitle)); } if (km.htmlStyle != null && km.htmlStyle.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "style", km.htmlStyle); } if (km.htmlH1 != null && km.htmlH1.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println(wrap("\t\t", "h1", km.htmlH1)); } if (km.htmlH2 != null && km.htmlH2.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println(wrap("\t\t", "h2", km.htmlH2)); } if (km.htmlBody1 != null && km.htmlBody1.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "body1", km.htmlBody1); } if (km.htmlBody2 != null && km.htmlBody2.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "body2", km.htmlBody2); } if (km.htmlBody3 != null && km.htmlBody3.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "body3", km.htmlBody3); } if (km.htmlBody4 != null && km.htmlBody4.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "body4", km.htmlBody4); } if (km.htmlInstall != null && km.htmlInstall.length() > 0) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } writeCDATA(out, "\t\t", "install", km.htmlInstall); } if (km.htmlSquareChars != null && !km.htmlSquareChars.isEmpty()) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println(wrap("\t\t", "square", "chars", formatRanges(km.htmlSquareChars))); } if (km.htmlOutlineChars != null && !km.htmlOutlineChars.isEmpty()) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println(wrap("\t\t", "outline", "chars", formatRanges(km.htmlOutlineChars))); } boolean hasTdClasses = (km.htmlTdClasses != null && !km.htmlTdClasses.isEmpty()); boolean hasSpanClasses = (km.htmlSpanClasses != null && !km.htmlSpanClasses.isEmpty()); if (hasTdClasses || hasSpanClasses) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println("\t\t"); if (hasTdClasses) { for (Map.Entry e : km.htmlTdClasses.entrySet()) { out.println(wrap("\t\t\t", "td", "class", e.getKey(), "chars", formatRanges(e.getValue()))); } } if (hasSpanClasses) { for (Map.Entry e : km.htmlSpanClasses.entrySet()) { out.println(wrap("\t\t\t", "span", "class", e.getKey(), "chars", formatRanges(e.getValue()))); } } out.println("\t\t"); } if (km.htmlCpLabels != null && !km.htmlCpLabels.isEmpty()) { if (!wroteHeader) { out.println("\t"); wroteHeader = true; } out.println("\t\t"); for (Map.Entry e : km.htmlCpLabels.entrySet()) { out.println(wrap("\t\t\t", "cpLabel", "cp", hex(e.getKey(),4), "label", e.getValue())); } out.println("\t\t"); } if (wroteHeader) out.println("\t"); } private static void writeAttachments(PrintWriter out, String tag, Map attachments) { if (attachments != null && !attachments.isEmpty()) { out.println("\t<" + tag + ">"); for (Map.Entry e : attachments.entrySet()) { try { StringBuffer sb = new StringBuffer(); Base64OutputStream b64 = new Base64OutputStream(sb); b64.write(e.getValue()); b64.flush(); b64.close(); out.println( wrap("\t\t", "attachment", "name", e.getKey(), false) + sb.toString() + "" ); } catch (IOException ioe) { ioe.printStackTrace(); } } out.println("\t"); } } private static void writeCDATA(PrintWriter out, String prefix, String tag, String content) { out.println(prefix + "<" + tag + ">"); } private static void writeBlock(PrintWriter out, String prefix, String tag, String content) { if (content != null && content.length() > 0) { out.println(prefix + "<" + tag + ">"); for (String line : content.split("\r\n|\r|\n")) { out.println(prefix + "\t" + xmlEncode(line)); } out.println(prefix + ""); } } private static void writeBlock(PrintWriter out, String prefix, String tag, String attr, String value, String content) { if (content != null && content.length() > 0) { out.println(wrap(prefix, tag, attr, value, false)); for (String line : content.split("\r\n|\r|\n")) { out.println(prefix + "\t" + xmlEncode(line)); } out.println(prefix + ""); } } public static String formatRanges(BitSet bs) { if (bs == null || bs.isEmpty()) return null; int[] lastRange = null; List ranges = new ArrayList(); for (int i = 0; (i = bs.nextSetBit(i)) >= 0; i++) { if (lastRange != null && lastRange[1] == (i - 1)) lastRange[1]++; else ranges.add(lastRange = new int[]{i, i}); } boolean first = true; StringBuffer sb = new StringBuffer(); for (int[] range : ranges) { if (first) first = false; else sb.append(", "); sb.append(hex(range[0], 4).toUpperCase()); if (range[0] != range[1]) { sb.append("-"); sb.append(hex(range[1], 4).toUpperCase()); } } return sb.toString(); } private static String hex(int v, int n) { String h = Integer.toHexString(v); while (h.length() < n) h = "0" + h; return h; } private static String caps(CapsLockMapping clm, String unshifted, String shifted, String auto) { if (clm == null) return auto; if (clm == CapsLockMapping.UNSHIFTED) return unshifted; if (clm == CapsLockMapping.SHIFTED) return shifted; return auto; } private static String wrap(String prefix, String tag, boolean close) { return prefix + "<" + tag + (close ? "/>" : ">"); } private static String wrap(String prefix, String tag, String s) { return prefix + "<" + tag + ">" + xmlEncode(s) + ""; } private static String wrap(String prefix, String tag, String attr, String s) { return prefix + "<" + tag + " " + attr + "=\"" + xmlEncode(s) + "\"/>"; } private static String wrap(String prefix, String tag, String attr, String s, boolean close) { return prefix + "<" + tag + " " + attr + "=\"" + xmlEncode(s) + "\"" + (close ? "/>" : ">"); } private static String wrap(String prefix, String tag, String attr1, String s1, String attr2, String s2) { return prefix + "<" + tag + " " + attr1 + "=\"" + xmlEncode(s1) + "\" " + attr2 + "=\"" + xmlEncode(s2) + "\"/>"; } private static String xmlEncode(String s) { if (s == null) return ""; StringBuffer sb = new StringBuffer(); int i = 0; while (i < s.length()) { int ch = s.codePointAt(i); if ( ch < 0x20 || ch >= 0x7F || ch == '"' || ch == '\'' || ch == '&' || ch == '<' || ch == '>' ) { sb.append("&#" + ch + ";"); } else { sb.append((char)ch); } i += Character.charCount(ch); } return sb.toString(); } private static boolean any(Object... objects) { for (Object o : objects) { if (o == null) continue; else if (o instanceof String) { if (((String)o).length() > 0) return true; } else if (o instanceof Boolean) { if (((Boolean)o).booleanValue()) return true; } else if (o instanceof Collection) { if (((Collection)o).size() > 0) return true; } else if (o instanceof Map) { if (((Map)o).size() > 0) return true; } else throw new IllegalArgumentException(); } return false; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacCopy.java000066400000000000000000000021011506470510200271250ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; public class MacCopy { public static void main(String[] args) { if (args.length < 2) { System.out.println("Usage: MacCopy "); System.out.println(" MacCopy "); } else { String outPath = args[args.length-1]; File out = new File(outPath); if (args.length > 2 || outPath.endsWith("/") || out.isDirectory()) { out.mkdir(); for (int i = 0; i < args.length-1; i++) { try { KeyboardMapping km = MacReader.read(new File(args[i])); File output = new File(out, km.getNameNotEmpty() + ".keylayout"); MacWriter.write(output, km); } catch (IOException e) { System.err.println("Failed copying " + args[i] + ": " + e.getMessage()); } } } else { try { KeyboardMapping km = MacReader.read(new File(args[0])); MacWriter.write(new File(args[1]), km); } catch (IOException e) { System.err.println("Failed copying " + args[0] + ": " + e.getMessage()); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacIconSuite.java000066400000000000000000000623371506470510200301360ustar00rootroot00000000000000package com.kreative.keyedit; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import javax.imageio.ImageIO; public class MacIconSuite extends LinkedHashMap { private static final long serialVersionUID = 1L; public static final int icns = 0x69636E73; public static final int ICON = 0x49434F4E; // 16x12 classic public static final int icm$ = 0x69636D23; public static final int icm4 = 0x69636D34; public static final int icm8 = 0x69636D38; public static final int im32 = 0x696D3332; public static final int m8mk = 0x6D386D6B; // 16x16 classic public static final int ics$ = 0x69637323; public static final int ics4 = 0x69637334; public static final int ics8 = 0x69637338; public static final int is32 = 0x69733332; public static final int s8mk = 0x73386D6B; // 32x32 classic public static final int ICN$ = 0x49434E23; public static final int icl4 = 0x69636C34; public static final int icl8 = 0x69636C38; public static final int il32 = 0x696C3332; public static final int l8mk = 0x6C386D6B; // 48x48 classic public static final int ich$ = 0x69636823; public static final int ich4 = 0x69636834; public static final int ich8 = 0x69636838; public static final int ih32 = 0x69683332; public static final int h8mk = 0x68386D6B; // 128x128 classic public static final int ict$ = 0x69637423; public static final int ict4 = 0x69637434; public static final int ict8 = 0x69637438; public static final int it32 = 0x69743332; public static final int t8mk = 0x74386D6B; // 16x16, 32x32, 64x64 ARGB PackBits public static final int ic04 = 0x69633034; public static final int ic05 = 0x69633035; public static final int ic06 = 0x69633036; // 16x16, 32x32, 64x64 JPEG2000 / PNG public static final int icp4 = 0x69637034; public static final int icp5 = 0x69637035; public static final int icp6 = 0x69637036; // 128x128, 256x256, 512x512 JPEG2000 / PNG public static final int ic07 = 0x69633037; public static final int ic08 = 0x69633038; public static final int ic09 = 0x69633039; // 1024x1024 / 512x512@2x JPEG2000 / PNG public static final int ic10 = 0x69633130; // 16x16@2x, 32x32@2x, 128x128@2x, 256x256@2x JPEG2000 / PNG public static final int ic11 = 0x69633131; public static final int ic12 = 0x69633132; public static final int ic13 = 0x69633133; public static final int ic14 = 0x69633134; // 18x18, 36x36 (what is this used for?) public static final int icsb = 0x69637362; public static final int icsB = 0x69637342; // Metadata public static final int TOC = 0x544F4320; public static final int icnV = 0x69636E56; public static final int name = 0x6E616D65; public static final int info = 0x696E666F; public void read(DataInput in) throws IOException { if (in.readInt() != icns) throw new IOException("Bad magic number"); int fptr = 8; int flen = in.readInt(); if (flen < 8) throw new IOException("Bad file length"); while (fptr < flen) { int type = in.readInt(); int ilen = in.readInt(); if (ilen < 8) throw new IOException("Bad data length"); byte[] data = new byte[ilen - 8]; in.readFully(data); this.put(type, data); fptr += ilen; } } public void write(DataOutput out) throws IOException { int flen = this.size() * 8 + 8; for (byte[] data : this.values()) { flen += data.length; } out.writeInt(icns); out.writeInt(flen); for (Map.Entry e : this.entrySet()) { out.writeInt(e.getKey()); out.writeInt(e.getValue().length + 8); out.write(e.getValue()); } } public BufferedImage getImage() { for (int type : Arrays.asList( /* 1024x1024 */ ic10, /* 512x512 */ ic14, ic09, /* 256x256 */ ic13, ic08, /* 128x128 */ ic07, it32, ict8, ict4, ict$, /* 64x64 */ ic12, ic06, icp6, /* 48x48 */ ih32, ich8, ich4, ich$, /* 32x32 */ ic11, ic05, icp5, il32, icl8, icl4, ICN$, ICON, /* 16x16 */ ic04, icp4, is32, ics8, ics4, ics$, /* 16x12 */ im32, icm8, icm4, icm$ )) { if (containsKey(type)) { BufferedImage image = getImage(type); if (image != null) return image; } } return null; } public BufferedImage getImage(int type) { switch (type) { case ICON: return decode1Bit(32, 32, get(ICON), 0, null, 0); case icm$: return decode1Bit(16, 12, get(icm$), 0, get(icm$), 24); case icm4: return decode4Bit(16, 12, get(icm4), 0, get(icm$), 24); case icm8: return decode8Bit(16, 12, get(icm8), 0, get(icm$), 24); case im32: return decode32Bit(16, 12, get(im32), 0, get(m8mk), 0); case m8mk: return decode32Bit(16, 12, null, 0, get(m8mk), 0); case ics$: return decode1Bit(16, 16, get(ics$), 0, get(ics$), 32); case ics4: return decode4Bit(16, 16, get(ics4), 0, get(ics$), 32); case ics8: return decode8Bit(16, 16, get(ics8), 0, get(ics$), 32); case is32: return decode32Bit(16, 16, get(is32), 0, get(s8mk), 0); case s8mk: return decode32Bit(16, 16, null, 0, get(s8mk), 0); case ICN$: return decode1Bit(32, 32, get(ICN$), 0, get(ICN$), 128); case icl4: return decode4Bit(32, 32, get(icl4), 0, get(ICN$), 128); case icl8: return decode8Bit(32, 32, get(icl8), 0, get(ICN$), 128); case il32: return decode32Bit(32, 32, get(il32), 0, get(l8mk), 0); case l8mk: return decode32Bit(32, 32, null, 0, get(l8mk), 0); case ich$: return decode1Bit(48, 48, get(ich$), 0, get(ich$), 288); case ich4: return decode4Bit(48, 48, get(ich4), 0, get(ich$), 288); case ich8: return decode8Bit(48, 48, get(ich8), 0, get(ich$), 288); case ih32: return decode32Bit(48, 48, get(ih32), 0, get(h8mk), 0); case h8mk: return decode32Bit(48, 48, null, 0, get(h8mk), 0); case ict$: return decode1Bit(128, 128, get(ict$), 0, get(ict$), 2048); case ict4: return decode4Bit(128, 128, get(ict4), 0, get(ict$), 2048); case ict8: return decode8Bit(128, 128, get(ict8), 0, get(ict$), 2048); case it32: return decode32Bit(128, 128, get(it32), 4, get(t8mk), 0); case t8mk: return decode32Bit(128, 128, null, 0, get(t8mk), 0); case ic04: case icp4: return decodeCompressed(16, 16, get(type), 0); case ic05: case icp5: return decodeCompressed(32, 32, get(type), 0); case ic06: case icp6: return decodeCompressed(64, 64, get(type), 0); case ic07: return decodeCompressed(128, 128, get(type), 0); case ic08: return decodeCompressed(256, 256, get(type), 0); case ic09: return decodeCompressed(512, 512, get(type), 0); case ic10: return decodeCompressed(1024, 1024, get(type), 0); case ic11: return decodeCompressed(32, 32, get(type), 0); case ic12: return decodeCompressed(64, 64, get(type), 0); case ic13: return decodeCompressed(256, 256, get(type), 0); case ic14: return decodeCompressed(512, 512, get(type), 0); default: return null; } } public void putImage(BufferedImage image) { int w = image.getWidth(), h = image.getHeight(); if (w >= 1024 && h >= 1024) putImage(ic10, image); if (w >= 512 && h >= 512) putImage(ic09, image); if (w >= 256 && h >= 256) putImage(ic08, image); if (w >= 128 && h >= 128) { putImage(it32, image); putImage(t8mk, image); } if (w >= 48 && h >= 48) { putImage(ih32, image); putImage(h8mk, image); } if (w >= 32 && h >= 32) { putImage(il32, image); putImage(l8mk, image); } if (w >= 16 && h >= 16) { putImage(is32, image); putImage(s8mk, image); } } public void putImage(int type, BufferedImage image) { switch (type) { case ICON: put(type, encode1Bit(image, 32, 32, true, false)); break; case icm$: put(type, encode1Bit(image, 16, 12, true, true)); break; case icm4: put(type, encode4Bit(image, 16, 12)); break; case icm8: put(type, encode8Bit(image, 16, 12)); break; case im32: put(type, encode32Bit(image, 16, 12, 0, true, false)); break; case m8mk: put(type, encode32Bit(image, 16, 12, 0, false, true)); break; case ics$: put(type, encode1Bit(image, 16, 16, true, true)); break; case ics4: put(type, encode4Bit(image, 16, 16)); break; case ics8: put(type, encode8Bit(image, 16, 16)); break; case is32: put(type, encode32Bit(image, 16, 16, 0, true, false)); break; case s8mk: put(type, encode32Bit(image, 16, 16, 0, false, true)); break; case ICN$: put(type, encode1Bit(image, 32, 32, true, true)); break; case icl4: put(type, encode4Bit(image, 32, 32)); break; case icl8: put(type, encode8Bit(image, 32, 32)); break; case il32: put(type, encode32Bit(image, 32, 32, 0, true, false)); break; case l8mk: put(type, encode32Bit(image, 32, 32, 0, false, true)); break; case ich$: put(type, encode1Bit(image, 48, 48, true, true)); break; case ich4: put(type, encode4Bit(image, 48, 48)); break; case ich8: put(type, encode8Bit(image, 48, 48)); break; case ih32: put(type, encode32Bit(image, 48, 48, 0, true, false)); break; case h8mk: put(type, encode32Bit(image, 48, 48, 0, false, true)); break; case ict$: put(type, encode1Bit(image, 128, 128, true, true)); break; case ict4: put(type, encode4Bit(image, 128, 128)); break; case ict8: put(type, encode8Bit(image, 128, 128)); break; case it32: put(type, encode32Bit(image, 128, 128, 4, true, false)); break; case t8mk: put(type, encode32Bit(image, 128, 128, 0, false, true)); break; case ic04: put(type, encodeCompressed(image, 16, 16, "ARGB")); break; case ic05: put(type, encodeCompressed(image, 32, 32, "ARGB")); break; case ic06: put(type, encodeCompressed(image, 64, 64, "ARGB")); break; case icp4: put(type, encodeCompressed(image, 16, 16, "jpeg2000", "png")); break; case icp5: put(type, encodeCompressed(image, 32, 32, "jpeg2000", "png")); break; case icp6: put(type, encodeCompressed(image, 64, 64, "jpeg2000", "png")); break; case ic07: put(type, encodeCompressed(image, 128, 128, "jpeg2000", "png")); break; case ic08: put(type, encodeCompressed(image, 256, 256, "jpeg2000", "png")); break; case ic09: put(type, encodeCompressed(image, 512, 512, "jpeg2000", "png")); break; case ic10: put(type, encodeCompressed(image, 1024, 1024, "jpeg2000", "png")); break; case ic11: put(type, encodeCompressed(image, 32, 32, "jpeg2000", "png")); break; case ic12: put(type, encodeCompressed(image, 64, 64, "jpeg2000", "png")); break; case ic13: put(type, encodeCompressed(image, 256, 256, "jpeg2000", "png")); break; case ic14: put(type, encodeCompressed(image, 512, 512, "jpeg2000", "png")); break; } } public Integer getVersion() { byte[] d = get(icnV); if (d == null || d.length < 4) { return null; } else { int v = ((d[0] & 0xFF) << 24); v |= ((d[1] & 0xFF) << 16); v |= ((d[2] & 0xFF) << 8); v |= ((d[3] & 0xFF) << 0); return v; } } public void putVersion(Integer v) { if (v == null) { remove(icnV); } else { byte[] d = new byte[4]; d[0] = (byte)(v >> 24); d[1] = (byte)(v >> 16); d[2] = (byte)(v >> 8); d[3] = (byte)(v >> 0); put(icnV, d); } } private static final int[] COLORS_8BIT = { 0xFFFFFFFF, 0xFFFFFFCC, 0xFFFFFF99, 0xFFFFFF66, 0xFFFFFF33, 0xFFFFFF00, 0xFFFFCCFF, 0xFFFFCCCC, 0xFFFFCC99, 0xFFFFCC66, 0xFFFFCC33, 0xFFFFCC00, 0xFFFF99FF, 0xFFFF99CC, 0xFFFF9999, 0xFFFF9966, 0xFFFF9933, 0xFFFF9900, 0xFFFF66FF, 0xFFFF66CC, 0xFFFF6699, 0xFFFF6666, 0xFFFF6633, 0xFFFF6600, 0xFFFF33FF, 0xFFFF33CC, 0xFFFF3399, 0xFFFF3366, 0xFFFF3333, 0xFFFF3300, 0xFFFF00FF, 0xFFFF00CC, 0xFFFF0099, 0xFFFF0066, 0xFFFF0033, 0xFFFF0000, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFCCFF99, 0xFFCCFF66, 0xFFCCFF33, 0xFFCCFF00, 0xFFCCCCFF, 0xFFCCCCCC, 0xFFCCCC99, 0xFFCCCC66, 0xFFCCCC33, 0xFFCCCC00, 0xFFCC99FF, 0xFFCC99CC, 0xFFCC9999, 0xFFCC9966, 0xFFCC9933, 0xFFCC9900, 0xFFCC66FF, 0xFFCC66CC, 0xFFCC6699, 0xFFCC6666, 0xFFCC6633, 0xFFCC6600, 0xFFCC33FF, 0xFFCC33CC, 0xFFCC3399, 0xFFCC3366, 0xFFCC3333, 0xFFCC3300, 0xFFCC00FF, 0xFFCC00CC, 0xFFCC0099, 0xFFCC0066, 0xFFCC0033, 0xFFCC0000, 0xFF99FFFF, 0xFF99FFCC, 0xFF99FF99, 0xFF99FF66, 0xFF99FF33, 0xFF99FF00, 0xFF99CCFF, 0xFF99CCCC, 0xFF99CC99, 0xFF99CC66, 0xFF99CC33, 0xFF99CC00, 0xFF9999FF, 0xFF9999CC, 0xFF999999, 0xFF999966, 0xFF999933, 0xFF999900, 0xFF9966FF, 0xFF9966CC, 0xFF996699, 0xFF996666, 0xFF996633, 0xFF996600, 0xFF9933FF, 0xFF9933CC, 0xFF993399, 0xFF993366, 0xFF993333, 0xFF993300, 0xFF9900FF, 0xFF9900CC, 0xFF990099, 0xFF990066, 0xFF990033, 0xFF990000, 0xFF66FFFF, 0xFF66FFCC, 0xFF66FF99, 0xFF66FF66, 0xFF66FF33, 0xFF66FF00, 0xFF66CCFF, 0xFF66CCCC, 0xFF66CC99, 0xFF66CC66, 0xFF66CC33, 0xFF66CC00, 0xFF6699FF, 0xFF6699CC, 0xFF669999, 0xFF669966, 0xFF669933, 0xFF669900, 0xFF6666FF, 0xFF6666CC, 0xFF666699, 0xFF666666, 0xFF666633, 0xFF666600, 0xFF6633FF, 0xFF6633CC, 0xFF663399, 0xFF663366, 0xFF663333, 0xFF663300, 0xFF6600FF, 0xFF6600CC, 0xFF660099, 0xFF660066, 0xFF660033, 0xFF660000, 0xFF33FFFF, 0xFF33FFCC, 0xFF33FF99, 0xFF33FF66, 0xFF33FF33, 0xFF33FF00, 0xFF33CCFF, 0xFF33CCCC, 0xFF33CC99, 0xFF33CC66, 0xFF33CC33, 0xFF33CC00, 0xFF3399FF, 0xFF3399CC, 0xFF339999, 0xFF339966, 0xFF339933, 0xFF339900, 0xFF3366FF, 0xFF3366CC, 0xFF336699, 0xFF336666, 0xFF336633, 0xFF336600, 0xFF3333FF, 0xFF3333CC, 0xFF333399, 0xFF333366, 0xFF333333, 0xFF333300, 0xFF3300FF, 0xFF3300CC, 0xFF330099, 0xFF330066, 0xFF330033, 0xFF330000, 0xFF00FFFF, 0xFF00FFCC, 0xFF00FF99, 0xFF00FF66, 0xFF00FF33, 0xFF00FF00, 0xFF00CCFF, 0xFF00CCCC, 0xFF00CC99, 0xFF00CC66, 0xFF00CC33, 0xFF00CC00, 0xFF0099FF, 0xFF0099CC, 0xFF009999, 0xFF009966, 0xFF009933, 0xFF009900, 0xFF0066FF, 0xFF0066CC, 0xFF006699, 0xFF006666, 0xFF006633, 0xFF006600, 0xFF0033FF, 0xFF0033CC, 0xFF003399, 0xFF003366, 0xFF003333, 0xFF003300, 0xFF0000FF, 0xFF0000CC, 0xFF000099, 0xFF000066, 0xFF000033, 0xFFEE0000, 0xFFDD0000, 0xFFBB0000, 0xFFAA0000, 0xFF880000, 0xFF770000, 0xFF550000, 0xFF440000, 0xFF220000, 0xFF110000, 0xFF00EE00, 0xFF00DD00, 0xFF00BB00, 0xFF00AA00, 0xFF008800, 0xFF007700, 0xFF005500, 0xFF004400, 0xFF002200, 0xFF001100, 0xFF0000EE, 0xFF0000DD, 0xFF0000BB, 0xFF0000AA, 0xFF000088, 0xFF000077, 0xFF000055, 0xFF000044, 0xFF000022, 0xFF000011, 0xFFEEEEEE, 0xFFDDDDDD, 0xFFBBBBBB, 0xFFAAAAAA, 0xFF888888, 0xFF777777, 0xFF555555, 0xFF444444, 0xFF222222, 0xFF111111, 0xFF000000 }; private static final int[] COLORS_4BIT = { 0xFFFFFFFF, 0xFFFCF305, 0xFFFF6503, 0xFFDD0907, 0xFFF30885, 0xFF4700A5, 0xFF0000D4, 0xFF02ABEB, 0xFF1FB814, 0xFF006512, 0xFF562D05, 0xFF91713A, 0xFFC0C0C0, 0xFF808080, 0xFF404040, 0xFF000000 }; private static int closestColorIndex(int[] colors, int color) { int r = (color >> 16) & 0xFF; int g = (color >> 8) & 0xFF; int b = (color >> 0) & 0xFF; int index = -1, delta = Integer.MAX_VALUE; for (int i = 0; i < colors.length; i++) { int dr = r - ((colors[i] >> 16) & 0xFF); int dg = g - ((colors[i] >> 8) & 0xFF); int db = b - ((colors[i] >> 0) & 0xFF); int d = dr * dr + dg * dg + db * db; if (d < delta) { index = i; delta = d; } } return index; } private static void unpack(byte[] packed, int offset, int length, OutputStream out) throws IOException { while (length > 0) { int n = packed[offset++]; length--; if (n >= 0) { for (int i = n + 1; i > 0; i--) { int b = packed[offset++]; length--; out.write(b); } } else { int b = packed[offset++]; length--; for (int i = n + 131; i > 0; i--) { out.write(b); } } } } private static void packUncompressed(byte[] unpacked, OutputStream out) throws IOException { packUncompressed(unpacked, 0, unpacked.length, out); } private static void packUncompressed(byte[] unpacked, int offset, int length, OutputStream out) throws IOException { while (length >= 128) { out.write(127); out.write(unpacked, offset, 128); offset += 128; length -= 128; } if (length > 0) { out.write(length - 1); out.write(unpacked, offset, length); } } private static void pack(byte[] unpacked, OutputStream out) throws IOException { pack(unpacked, 0, unpacked.length, out); } private static void pack(byte[] unpacked, int offset, int length, OutputStream out) throws IOException { ByteArrayOutputStream run = new ByteArrayOutputStream(); while (length > 0) { int b = unpacked[offset++]; length--; int c = 1; while (length > 0 && unpacked[offset] == b) { offset++; length--; c++; if (c >= 130) break; } if (c < 3) { while (c > 0) { run.write(b); c--; } } else { packUncompressed(run.toByteArray(), out); out.write(c + 125); out.write(b); run = new ByteArrayOutputStream(); } } packUncompressed(run.toByteArray(), out); } private static boolean dataStartsWith(byte[] data, int offset, int... prefix) { for (int b : prefix) { if (offset >= data.length) return false; if (data[offset] != (byte)b) return false; offset++; } return true; } private static BufferedImage resizeImage(BufferedImage image, int width, int height) { if (image.getWidth() == width && image.getHeight() == height) return image; BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = resized.createGraphics(); g.drawImage(image, 0, 0, width, height, null); g.dispose(); return resized; } private static BufferedImage decode1Bit(int w, int h, byte[] data, int di, byte[] mask, int mi) { int[] pixels = new int[w * h]; if (data != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = data[di++]; for (int m = 0x80; m != 0; m >>= 1, pi++) { if ((b & m) == 0) pixels[pi] = 0x00FFFFFF; else pixels[pi] = 0xFF000000; } } } } if (mask != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = mask[mi++]; for (int m = 0x80; m != 0; m >>= 1, pi++) { if ((b & m) == 0) pixels[pi] &= 0x00FFFFFF; else pixels[pi] |= 0xFF000000; } } } } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, w, h, pixels, 0, w); return img; } private static BufferedImage decode4Bit(int w, int h, byte[] data, int di, byte[] mask, int mi) { int[] pixels = new int[w * h]; if (data != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 2) { int b = data[di++] & 0xFF; pixels[pi++] = COLORS_4BIT[b >> 4]; pixels[pi++] = COLORS_4BIT[b & 15]; } } } if (mask != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = mask[mi++]; for (int m = 0x80; m != 0; m >>= 1, pi++) { if ((b & m) == 0) pixels[pi] &= 0x00FFFFFF; else pixels[pi] |= 0xFF000000; } } } } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, w, h, pixels, 0, w); return img; } private static BufferedImage decode8Bit(int w, int h, byte[] data, int di, byte[] mask, int mi) { int[] pixels = new int[w * h]; if (data != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int b = data[di++] & 0xFF; pixels[pi++] = COLORS_8BIT[b]; } } } if (mask != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = mask[mi++]; for (int m = 0x80; m != 0; m >>= 1, pi++) { if ((b & m) == 0) pixels[pi] &= 0x00FFFFFF; else pixels[pi] |= 0xFF000000; } } } } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, w, h, pixels, 0, w); return img; } private static BufferedImage decode32Bit(int w, int h, byte[] data, int di, byte[] mask, int mi) { int[] pixels = new int[w * h]; if (data != null) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { unpack(data, di, data.length - di, out); } catch (IOException e) { e.printStackTrace(); } data = out.toByteArray(); di = 0; for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] = 0xFF000000 | (b << 16); } } for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] |= (b << 8); } } for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] |= b; } } } if (mask != null) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = mask[mi++] & 0xFF; pixels[pi] &= 0x00FFFFFF; pixels[pi] |= (b << 24); } } } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, w, h, pixels, 0, w); return img; } private static BufferedImage decodeCompressed(int w, int h, byte[] data, int di) { if (dataStartsWith(data, di, 'A', 'R', 'G', 'B')) { int[] pixels = new int[w * h]; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { unpack(data, di + 4, data.length - (di + 4), out); } catch (IOException e) { e.printStackTrace(); } data = out.toByteArray(); di = 0; for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] = (b << 24); } } for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] |= (b << 16); } } for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] |= (b << 8); } } for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { int b = data[di++] & 0xFF; pixels[pi] |= b; } } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, w, h, pixels, 0, w); return img; } try { return ImageIO.read(new ByteArrayInputStream(data, di, data.length - di)); } catch (Throwable t) { t.printStackTrace(); } return null; } private static byte[] encode1Bit(BufferedImage img, int w, int h, boolean data, boolean mask) { img = resizeImage(img, w, h); int[] pixels = new int[w * h]; img.getRGB(0, 0, w, h, pixels, 0, w); ByteArrayOutputStream out = new ByteArrayOutputStream(); if (data) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = 0; for (int m = 0x80; m != 0; m >>= 1, pi++) { int pa = (pixels[pi] >> 24) & 0xFF; int pr = (pixels[pi] >> 16) & 0xFF; int pg = (pixels[pi] >> 8) & 0xFF; int pb = (pixels[pi] >> 0) & 0xFF; int pk = pr * 30 + pg * 59 + pb * 11; if (pa >= 128 && pk < 12750) b |= m; } out.write(b); } } } if (mask) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 8) { int b = 0; for (int m = 0x80; m != 0; m >>= 1, pi++) { int pa = (pixels[pi] >> 24) & 0xFF; if (pa >= 128) b |= m; } out.write(b); } } } return out.toByteArray(); } private static byte[] encode4Bit(BufferedImage img, int w, int h) { img = resizeImage(img, w, h); int[] pixels = new int[w * h]; img.getRGB(0, 0, w, h, pixels, 0, w); ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x += 2) { int b = 0; if (pixels[pi] < 0) b |= closestColorIndex(COLORS_4BIT, pixels[pi]) << 4; pi++; if (pixels[pi] < 0) b |= closestColorIndex(COLORS_4BIT, pixels[pi]) << 0; pi++; out.write(b); } } return out.toByteArray(); } private static byte[] encode8Bit(BufferedImage img, int w, int h) { img = resizeImage(img, w, h); int[] pixels = new int[w * h]; img.getRGB(0, 0, w, h, pixels, 0, w); ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int b = 0; if (pixels[pi] < 0) b = closestColorIndex(COLORS_8BIT, pixels[pi]); pi++; out.write(b); } } return out.toByteArray(); } private static byte[] encode32Bit(BufferedImage img, int w, int h, int z, boolean data, boolean mask) { img = resizeImage(img, w, h); int[] pixels = new int[w * h]; img.getRGB(0, 0, w, h, pixels, 0, w); ByteArrayOutputStream out = new ByteArrayOutputStream(); while (z > 0) { out.write(0); z--; } if (data) { byte[] unpacked = new byte[w * h]; for (int s = 16; s >= 0; s -= 8) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { unpacked[pi] = (byte)(pixels[pi] >> s); } } try { pack(unpacked, out); } catch (IOException e) { e.printStackTrace(); } } } if (mask) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { out.write(pixels[pi] >> 24); } } } return out.toByteArray(); } private static byte[] encodeCompressed(BufferedImage img, int w, int h, String... formats) { img = resizeImage(img, w, h); ByteArrayOutputStream out = new ByteArrayOutputStream(); for (String format : formats) { if (format.equalsIgnoreCase("ARGB")) { int[] pixels = new int[w * h]; img.getRGB(0, 0, w, h, pixels, 0, w); out.write('A'); out.write('R'); out.write('G'); out.write('B'); byte[] unpacked = new byte[w * h]; for (int s = 24; s >= 0; s -= 8) { for (int pi = 0, y = 0; y < h; y++) { for (int x = 0; x < w; x++, pi++) { unpacked[pi] = (byte)(pixels[pi] >> s); } } try { pack(unpacked, out); } catch (IOException e) { e.printStackTrace(); } } break; } else { try { if (ImageIO.write(img, format, out)) break; } catch (IOException e) { e.printStackTrace(); } } } return out.toByteArray(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacKey.java000066400000000000000000000132541506470510200267560ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Arrays; import java.util.Collections; import java.util.List; public final class MacKey { public static final List KEYS = Collections.unmodifiableList(Arrays.asList( new MacKey( 0, Key.A, -1), new MacKey( 1, Key.S, -1), new MacKey( 2, Key.D, -1), new MacKey( 3, Key.F, -1), new MacKey( 4, Key.H, -1), new MacKey( 5, Key.G, -1), new MacKey( 6, Key.Z, -1), new MacKey( 7, Key.X, -1), new MacKey( 8, Key.C, -1), new MacKey( 9, Key.V, -1), new MacKey( 10, Key.SECTION, -1), new MacKey( 11, Key.B, -1), new MacKey( 12, Key.Q, -1), new MacKey( 13, Key.W, -1), new MacKey( 14, Key.E, -1), new MacKey( 15, Key.R, -1), new MacKey( 16, Key.Y, -1), new MacKey( 17, Key.T, -1), new MacKey( 18, Key.NUMROW_1, -1), new MacKey( 19, Key.NUMROW_2, -1), new MacKey( 20, Key.NUMROW_3, -1), new MacKey( 21, Key.NUMROW_4, -1), new MacKey( 22, Key.NUMROW_6, -1), new MacKey( 23, Key.NUMROW_5, -1), new MacKey( 24, Key.EQUALS_PLUS, -1), new MacKey( 25, Key.NUMROW_9, -1), new MacKey( 26, Key.NUMROW_7, -1), new MacKey( 27, Key.HYPHEN_UNDERSCORE, -1), new MacKey( 28, Key.NUMROW_8, -1), new MacKey( 29, Key.NUMROW_0, -1), new MacKey( 30, Key.RIGHT_BRACKET, -1), new MacKey( 31, Key.O, -1), new MacKey( 32, Key.U, -1), new MacKey( 33, Key.LEFT_BRACKET, -1), new MacKey( 34, Key.I, -1), new MacKey( 35, Key.P, -1), new MacKey( 36, null, 0x0D), new MacKey( 37, Key.L, -1), new MacKey( 38, Key.J, -1), new MacKey( 39, Key.QUOTE, -1), new MacKey( 40, Key.K, -1), new MacKey( 41, Key.SEMICOLON, -1), new MacKey( 42, Key.BACKSLASH, -1), new MacKey( 43, Key.COMMA, -1), new MacKey( 44, Key.SLASH, -1), new MacKey( 45, Key.N, -1), new MacKey( 46, Key.M, -1), new MacKey( 47, Key.PERIOD, -1), new MacKey( 48, null, 0x09), new MacKey( 49, Key.SPACE, -1), new MacKey( 50, Key.GRAVE_TILDE, -1), new MacKey( 51, null, 0x08), new MacKey( 52, null, 0x03), new MacKey( 53, null, 0x1B), new MacKey( 64, null, 0x10), new MacKey( 65, Key.NUMPAD_PERIOD, -1), new MacKey( 66, null, 0x1D), new MacKey( 67, Key.NUMPAD_TIMES, -1), new MacKey( 69, Key.NUMPAD_PLUS, -1), new MacKey( 70, null, 0x1C), new MacKey( 71, null, 0x1B), new MacKey( 72, null, 0x1F), new MacKey( 75, Key.NUMPAD_DIVIDE, -1), new MacKey( 76, null, 0x03), new MacKey( 77, null, 0x1E), new MacKey( 78, Key.NUMPAD_MINUS, -1), new MacKey( 79, null, 0x10), new MacKey( 80, null, 0x10), new MacKey( 81, Key.NUMPAD_EQUALS, -1), new MacKey( 82, Key.NUMPAD_0, -1), new MacKey( 83, Key.NUMPAD_1, -1), new MacKey( 84, Key.NUMPAD_2, -1), new MacKey( 85, Key.NUMPAD_3, -1), new MacKey( 86, Key.NUMPAD_4, -1), new MacKey( 87, Key.NUMPAD_5, -1), new MacKey( 88, Key.NUMPAD_6, -1), new MacKey( 89, Key.NUMPAD_7, -1), new MacKey( 90, null, 0x10), new MacKey( 91, Key.NUMPAD_8, -1), new MacKey( 92, Key.NUMPAD_9, -1), new MacKey( 93, Key.YEN, -1), new MacKey( 94, Key.UNDERSCORE, -1), new MacKey( 95, Key.NUMPAD_COMMA, -1), new MacKey( 96, null, 0x10), new MacKey( 97, null, 0x10), new MacKey( 98, null, 0x10), new MacKey( 99, null, 0x10), new MacKey(100, null, 0x10), new MacKey(101, null, 0x10), new MacKey(102, null, 0x10), new MacKey(103, null, 0x10), new MacKey(104, null, 0x10), new MacKey(105, null, 0x10), new MacKey(106, null, 0x10), new MacKey(107, null, 0x10), new MacKey(108, null, 0x10), new MacKey(109, null, 0x10), new MacKey(110, null, 0x10), new MacKey(111, null, 0x10), new MacKey(112, null, 0x10), new MacKey(113, null, 0x10), new MacKey(114, null, 0x05), new MacKey(115, null, 0x01), new MacKey(116, null, 0x0B), new MacKey(117, null, 0x7F), new MacKey(118, null, 0x10), new MacKey(119, null, 0x04), new MacKey(120, null, 0x10), new MacKey(121, null, 0x0C), new MacKey(122, null, 0x10), new MacKey(123, null, 0x1C), new MacKey(124, null, 0x1D), new MacKey(125, null, 0x1F), new MacKey(126, null, 0x1E) )); public final int keyCode; public final Key key; public final int output; private MacKey(int kc, Key key, int out) { this.keyCode = kc; this.key = key; this.output = out; } public static MacKey forKeyCode(int kc) { for (MacKey key : KEYS) { if (key.keyCode == kc) { return key; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacKeyboard.java000066400000000000000000000465571506470510200300020ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.ArrayList; import java.util.List; public class MacKeyboard { public final int group; public final int id; public final String name; public final int maxout; public final List layouts; public final List modifierMaps; public final List keyMapSets; public final List actions; public final List terminators; public MacKeyboard(int group, int id, String name, int maxout) { this.group = group; this.id = id; this.name = name; this.maxout = maxout; this.layouts = new ArrayList(); this.modifierMaps = new ArrayList(); this.keyMapSets = new ArrayList(); this.actions = new ArrayList(); this.terminators = new ArrayList(); } public Layouts layouts() { if (this.layouts.isEmpty()) { Layouts layouts = new Layouts(); this.layouts.add(layouts); return layouts; } else { int i = this.layouts.size() - 1; return this.layouts.get(i); } } public ModifierMap getModifierMap(String id) { for (ModifierMap modifierMap : this.modifierMaps) { if (modifierMap.id.equals(id)) { return modifierMap; } } return null; } public ModifierMap putModifierMap(ModifierMap modifierMap) { for (int i = 0; i < this.modifierMaps.size(); i++) { if (this.modifierMaps.get(i).id.equals(modifierMap.id)) { return this.modifierMaps.set(i, modifierMap); } } this.modifierMaps.add(modifierMap); return null; } public KeyMapSet getKeyMapSet(String id) { for (KeyMapSet keyMapSet : this.keyMapSets) { if (keyMapSet.id.equals(id)) { return keyMapSet; } } return null; } public KeyMapSet putKeyMapSet(KeyMapSet keyMapSet) { for (int i = 0; i < this.keyMapSets.size(); i++) { if (this.keyMapSets.get(i).id.equals(keyMapSet.id)) { return this.keyMapSets.set(i, keyMapSet); } } this.keyMapSets.add(keyMapSet); return null; } public Actions actions() { if (this.actions.isEmpty()) { Actions actions = new Actions(); this.actions.add(actions); return actions; } else { int i = this.actions.size() - 1; return this.actions.get(i); } } public Terminators terminators() { if (this.terminators.isEmpty()) { Terminators terminators = new Terminators(); this.terminators.add(terminators); return terminators; } else { int i = this.terminators.size() - 1; return this.terminators.get(i); } } public String startTag() { StringBuffer sb = new StringBuffer(); sb.append("= 0) { sb.append(" maxout=\"" + maxout + "\""); } sb.append(">"); return sb.toString(); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\n"); sb.append("\n"); sb.append(startTag() + "\n"); for (Layouts l : layouts) sb.append(l.toString()); for (ModifierMap m : modifierMaps) sb.append(m.toString()); for (KeyMapSet k : keyMapSets) sb.append(k.toString()); for (Actions a : actions) sb.append(a.toString()); for (Terminators t : terminators) sb.append(t.toString()); sb.append("\n"); return sb.toString(); } public static class Layouts extends ArrayList { private static final long serialVersionUID = 1L; public Layout getLayout(int i) { for (Layout layout : this) { if (i < 0 || (layout.first <= i && i <= layout.last)) { return layout; } } return null; } public void putLayout(Layout layout) { this.add(layout); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t\n"); for (Layout layout : this) { sb.append("\t\t" + layout.toString() + "\n"); } sb.append("\t\n"); return sb.toString(); } } public static class Layout { public final int first; public final int last; public final String modifiers; public final String mapSet; public Layout(int first, int last, String modifiers, String mapSet) { this.first = first; this.last = last; this.modifiers = modifiers; this.mapSet = mapSet; } public boolean equals(Object o) { if (o instanceof Layout) { Layout that = (Layout)o; return this.first == that.first && this.last == that.last && stringEquals(this.modifiers, that.modifiers) && stringEquals(this.mapSet, that.mapSet); } return false; } public int hashCode() { int hash = 0x6c61796f; hash *= 37; hash += first; hash *= 37; hash += last; hash *= 37; if (modifiers != null) hash += modifiers.hashCode(); hash *= 37; if (mapSet != null) hash += mapSet .hashCode(); return hash; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("= 0) { sb.append(" first=\"" + first + "\""); } if (last >= 0) { sb.append(" last=\"" + last + "\""); } if (modifiers != null) { String s = xmlEncode(modifiers); sb.append(" modifiers=\"" + s + "\""); } if (mapSet != null) { String s = xmlEncode(mapSet); sb.append(" mapSet=\"" + s + "\""); } sb.append(" />"); return sb.toString(); } } public static class ModifierMap extends ArrayList { private static final long serialVersionUID = 1L; public final String id; public final int defaultIndex; public ModifierMap(String id, int defaultIndex) { this.id = id; this.defaultIndex = defaultIndex; } public KeyMapSelect getKeyMapSelect(int mapIndex) { for (KeyMapSelect kms : this) { if (kms.mapIndex == mapIndex) { return kms; } } return null; } public KeyMapSelect putKeyMapSelect(KeyMapSelect kms) { for (int i = 0; i < this.size(); i++) { if (this.get(i).mapIndex == kms.mapIndex) { return this.set(i, kms); } } this.add(kms); return null; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t= 0) { sb.append(" defaultIndex=\"" + defaultIndex + "\""); } sb.append(">\n"); for (KeyMapSelect kms : this) { sb.append(kms.toString()); } sb.append("\t\n"); return sb.toString(); } public int mapIndexForState(boolean ctrl, boolean cmd, boolean opt, boolean shift, boolean caps) { for (KeyMapSelect kms : this) { if (kms.matchesState(ctrl, cmd, opt, shift, caps)) { return kms.mapIndex; } } return defaultIndex; } } public static class KeyMapSelect extends ArrayList { private static final long serialVersionUID = 1L; public final int mapIndex; public KeyMapSelect(int mapIndex) { this.mapIndex = mapIndex; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t\t= 0) { sb.append(" mapIndex=\"" + mapIndex + "\""); } sb.append(">\n"); for (Modifier mod : this) { sb.append("\t\t\t" + mod.toString() + "\n"); } sb.append("\t\t\n"); return sb.toString(); } public boolean matchesState(boolean ctrl, boolean cmd, boolean opt, boolean shift, boolean caps) { for (Modifier mod : this) { if (mod.matchesState(ctrl, cmd, opt, shift, caps)) { return true; } } return false; } } public static class Modifier { public static final Modifier UNSHIFTED = new Modifier(""); public static final Modifier CAPSLOCK = new Modifier("caps"); public static final Modifier SHIFTED = new Modifier("anyShift caps?"); public static final Modifier ALT_UNSHIFTED = new Modifier("anyOption"); public static final Modifier ALT_CAPSLOCK = new Modifier("anyOption caps"); public static final Modifier ALT_SHIFTED = new Modifier("anyOption anyShift caps?"); public static final Modifier COMMAND = new Modifier("command anyShift? caps?"); public static final Modifier COMMAND_OPTION = new Modifier("command anyOption caps?"); public static final Modifier COMMAND_OPTION_SHIFT = new Modifier("command anyOption anyShift caps?"); public static final Modifier CTRL = new Modifier("control command? anyOption? anyShift? caps?"); public static Modifier forState(Boolean ctrl, Boolean cmd, Boolean opt, Boolean shift, Boolean caps) { StringBuffer sb = new StringBuffer(); if (ctrl == null) sb.append(" control?" ); else if (ctrl .booleanValue()) sb.append(" control" ); if (cmd == null) sb.append(" command?" ); else if (cmd .booleanValue()) sb.append(" command" ); if (opt == null) sb.append(" anyOption?"); else if (opt .booleanValue()) sb.append(" anyOption"); if (shift == null) sb.append(" anyShift?" ); else if (shift.booleanValue()) sb.append(" anyShift" ); if (caps == null) sb.append(" caps?" ); else if (caps .booleanValue()) sb.append(" caps" ); return new Modifier(sb.toString().trim()); } public final String keys; public Modifier(String keys) { this.keys = keys; } public boolean equals(Object o) { if (o instanceof Modifier) { Modifier that = (Modifier)o; return stringEquals(this.keys, that.keys); } return false; } public int hashCode() { int hash = 0x6d6f6469; hash *= 37; if (keys != null) hash += keys.hashCode(); return hash; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(""); return sb.toString(); } public Boolean controlState() { return (keys == null || keys.contains("control?" )) ? null : keys.contains("control" ); } public Boolean commandState() { return (keys == null || keys.contains("command?" )) ? null : keys.contains("command" ); } public Boolean optionState() { return (keys == null || keys.contains("anyOption?")) ? null : keys.contains("anyOption"); } public Boolean shiftState() { return (keys == null || keys.contains("anyShift?" )) ? null : keys.contains("anyShift" ); } public Boolean capsState() { return (keys == null || keys.contains("caps?" )) ? null : keys.contains("caps" ); } public boolean matchesState(boolean ctrl, boolean cmd, boolean opt, boolean shift, boolean caps) { return ( (keys != null) && (keys.contains("control?" ) || (ctrl == keys.contains("control" ))) && (keys.contains("command?" ) || (cmd == keys.contains("command" ))) && (keys.contains("anyOption?") || (opt == keys.contains("anyOption"))) && (keys.contains("anyShift?" ) || (shift == keys.contains("anyShift" ))) && (keys.contains("caps?" ) || (caps == keys.contains("caps" ))) ); } } public static class KeyMapSet extends ArrayList { private static final long serialVersionUID = 1L; public final String id; public KeyMapSet(String id) { this.id = id; } public KeyMap getKeyMap(int index) { for (KeyMap keymap : this) { if (keymap.index == index) { return keymap; } } return null; } public KeyMap putKeyMap(KeyMap keymap) { for (int i = 0; i < this.size(); i++) { if (this.get(i).index == keymap.index) { return this.set(i, keymap); } } this.add(keymap); return null; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t\n"); for (KeyMap keymap : this) { sb.append(keymap.toString()); } sb.append("\t\n"); return sb.toString(); } } public static class KeyMap extends ArrayList { private static final long serialVersionUID = 1L; public final int index; public KeyMap(int index) { this.index = index; } public Key getKey(int code) { for (Key key : this) { if (key.code == code) { return key; } } return null; } public Key putKey(Key key) { for (int i = 0; i < this.size(); i++) { if (this.get(i).code == key.code) { return this.set(i, key); } } this.add(key); return null; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t\t= 0) { sb.append(" index=\"" + index + "\""); } sb.append(">\n"); for (Key key : this) { sb.append("\t\t\t" + key.toString() + "\n"); } sb.append("\t\t\n"); return sb.toString(); } } public static class Key { public final int code; public final String output; public final String action; public Key(int code, String output, String action) { this.code = code; this.output = output; this.action = action; } public boolean equals(Object o) { if (o instanceof Key) { Key that = (Key)o; return this.code == that.code && stringEquals(this.output, that.output) && stringEquals(this.action, that.action); } return false; } public int hashCode() { int hash = 0x6b657920; hash *= 37; hash += code; hash *= 37; if (output != null) hash += output.hashCode(); hash *= 37; if (action != null) hash += action.hashCode(); return hash; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("= 0) { String s = " code=\"" + code + "\""; while (s.length() < 11) s += " "; sb.append(s); } if (output != null) { String s = outputEncode(output); sb.append(" output=\"" + s + "\""); } if (action != null) { String s = xmlEncode(action); sb.append(" action=\"" + s + "\""); } sb.append(" />"); return sb.toString(); } } public static class Actions extends ArrayList { private static final long serialVersionUID = 1L; public Action getAction(String id) { for (Action action : this) { if (action.id.equals(id)) { return action; } } return null; } public Action putAction(Action action) { for (int i = 0; i < this.size(); i++) { if (this.get(i).id.equals(action.id)) { return this.set(i, action); } } this.add(action); return null; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\t\n"); for (Action action : this) { sb.append(action.toString()); } sb.append("\t\n"); return sb.toString(); } } public static class Action extends ArrayList { private static final long serialVersionUID = 1L; public final String id; public Action(String id) { this.id = id; } public When getWhen(String state) { for (When when : this) { if (when.state.equals(state)) { return when; } } return null; } public When putWhen(When when) { for (int i = 0; i < this.size(); i++) { if (this.get(i).state.equals(when.state)) { return this.set(i, when); } } this.add(when); return null; } public int stateIndent() { int indent = 0; for (When when : this) { if (when.state != null) { String s = xmlEncode(when.state); if (s.length() > indent) indent = s.length(); } } return indent; } public String toString() { int si = this.stateIndent(); StringBuffer sb = new StringBuffer(); sb.append("\t\t\n"); for (When when : this) { sb.append("\t\t\t" + when.toString(si) + "\n"); } sb.append("\t\t\n"); return sb.toString(); } } public static class When { public final String state; public final String through; public final String output; public final String multiplier; public final String next; public When(String state, String through, String output, String multiplier, String next) { this.state = state; this.through = through; this.output = output; this.multiplier = multiplier; this.next = next; } public boolean equals(Object o) { if (o instanceof When) { When that = (When)o; return stringEquals(this.state, that.state) && stringEquals(this.through, that.through) && stringEquals(this.output, that.output) && stringEquals(this.multiplier, that.multiplier) && stringEquals(this.next, that.next); } return false; } public int hashCode() { int hash = 0x7768656e; hash *= 37; if (state != null) hash += state .hashCode(); hash *= 37; if (through != null) hash += through .hashCode(); hash *= 37; if (output != null) hash += output .hashCode(); hash *= 37; if (multiplier != null) hash += multiplier.hashCode(); hash *= 37; if (next != null) hash += next .hashCode(); return hash; } public String toString() { return toString(0); } public String toString(int stateIndent) { StringBuffer sb = new StringBuffer(); sb.append(" 0) sb.append(spaces(ns)); } if (through != null) { String s = xmlEncode(through); sb.append(" through=\"" + s + "\""); } if (output != null) { String s = outputEncode(output); sb.append(" output=\"" + s + "\""); } if (multiplier != null) { String s = xmlEncode(multiplier); sb.append(" multiplier=\"" + s + "\""); } if (next != null) { String s = xmlEncode(next); sb.append(" next=\"" + s + "\""); } sb.append(" />"); return sb.toString(); } } public static class Terminators extends ArrayList { private static final long serialVersionUID = 1L; public When getWhen(String state) { for (When when : this) { if (when.state.equals(state)) { return when; } } return null; } public When putWhen(When when) { for (int i = 0; i < this.size(); i++) { if (this.get(i).state.equals(when.state)) { return this.set(i, when); } } this.add(when); return null; } public int stateIndent() { int indent = 0; for (When when : this) { if (when.state != null) { String s = xmlEncode(when.state); if (s.length() > indent) indent = s.length(); } } return indent; } public String toString() { int si = this.stateIndent(); StringBuffer sb = new StringBuffer(); sb.append("\t\n"); for (When when : this) { sb.append("\t\t" + when.toString(si) + "\n"); } sb.append("\t\n"); return sb.toString(); } } private static boolean stringEquals(String a, String b) { if (a == null) return (b == null); if (b == null) return (a == null); return a.equals(b); } private static String outputEncode(String s) { if (s.equals(" ")) return " "; return xmlEncode(s); } private static String xmlEncode(String s) { StringBuffer sb = new StringBuffer(); int i = 0; while (i < s.length()) { int ch = s.codePointAt(i); if ( ch < 0x20 || ch >= 0x7F || ch == '"' || ch == '\'' || ch == '&' || ch == '<' || ch == '>' ) { String h = Integer.toHexString(ch).toUpperCase(); while (h.length() < 4) h = "0" + h; sb.append("&#x" + h + ";"); } else { sb.append((char)ch); } i += Character.charCount(ch); } return sb.toString(); } private static String spaces(int n) { String s = " "; while (s.length() < n) s += s; return s.substring(0, n); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacKeyboardDiff.java000066400000000000000000000143571506470510200305640ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class MacKeyboardDiff { public static void main(String[] args) { if (args.length != 2) { System.out.println("Usage: MacKeyboardDiff "); } else { MacKeyboard left; MacKeyboard right; try { File leftFile = new File(args[0]); FileInputStream leftIn = new FileInputStream(leftFile); left = MacKeyboardParser.parse(leftFile.getName(), leftIn); leftIn.close(); } catch (IOException e) { System.err.println("Error: Failed to parse " + args[0] + ": " + e.getMessage()); return; } try { File rightFile = new File(args[1]); FileInputStream rightIn = new FileInputStream(rightFile); right = MacKeyboardParser.parse(rightFile.getName(), rightIn); rightIn.close(); } catch (IOException e) { System.err.println("Error: Failed to parse " + args[1] + ": " + e.getMessage()); return; } System.out.println("@@ Header @@"); printDiff(args[0], args[1], left.startTag(), right.startTag()); System.out.println("@@ Layouts @@"); List leftLayouts = collapse(left.layouts); List rightLayouts = collapse(right.layouts); printDiff(args[0], args[1], leftLayouts, rightLayouts); System.out.println("@@ Keymaps @@"); for (String layoutId : intersect(layoutIds(leftLayouts), layoutIds(rightLayouts))) { printKeymapDiff(args[0], args[1], left, right, layoutId); } System.out.println("@@ Actions @@"); printActionsDiff(args[0], args[1], collapse(left.actions), collapse(right.actions)); System.out.println("@@ Terminators @@"); printDiff(args[0], args[1], collapse(left.terminators), collapse(right.terminators)); } } private static boolean[] booleans = {false, true}; private static boolean stringEquals(String a, String b) { if (a == null) return (b == null); if (b == null) return (a == null); return a.equals(b); } private static List collapse(List> listList) { List collapsed = new ArrayList(); for (List list : listList) collapsed.addAll(list); return collapsed; } private static List subtract(Collection left, Collection right) { List diff = new ArrayList(); diff.addAll(left); diff.removeAll(right); return diff; } private static List intersect(Collection left, Collection right) { List inter = new ArrayList(); inter.addAll(left); inter.retainAll(right); return inter; } private static List layoutIds(List layouts) { List ids = new ArrayList(); for (MacKeyboard.Layout layout : layouts) { ids.add(layout.modifiers + "," + layout.mapSet); } return ids; } private static List actionIds(List actions) { List ids = new ArrayList(); for (MacKeyboard.Action action : actions) ids.add(action.id); return ids; } private static MacKeyboard.ModifierMap getModifierMap(MacKeyboard mk, String id) { for (MacKeyboard.ModifierMap mm : mk.modifierMaps) { if (stringEquals(mm.id, id)) { return mm; } } return null; } private static MacKeyboard.KeyMapSet getKeyMapSet(MacKeyboard mk, String id) { for (MacKeyboard.KeyMapSet kms : mk.keyMapSets) { if (stringEquals(kms.id, id)) { return kms; } } return null; } private static MacKeyboard.Action getAction(List actions, String id) { for (MacKeyboard.Action action : actions) { if (stringEquals(action.id, id)) { return action; } } return null; } private static String modifierString(boolean ctrl, boolean cmd, boolean opt, boolean shift, boolean caps) { StringBuffer sb = new StringBuffer(); if (ctrl) sb.append(" control"); if (cmd) sb.append(" command"); if (opt) sb.append(" option"); if (shift) sb.append(" shift"); if (caps) sb.append(" caps"); return "{" + sb.toString().trim().replaceAll(" ", ",") + "}"; } private static void printDiff(String l, String r, String left, String right) { if (stringEquals(left, right)) return; System.out.println("--- " + l + ":"); System.out.println("+++ " + r + ":"); System.out.println("- " + left); System.out.println("+ " + right); } private static void printDiff(String l, String r, List left, List right) { List leftDiff = subtract(left, right); List rightDiff = subtract(right, left); if (leftDiff.isEmpty() && rightDiff.isEmpty()) return; System.out.println("--- " + l + ":"); System.out.println("+++ " + r + ":"); for (T t : leftDiff) System.out.println("- " + t); for (T t : rightDiff) System.out.println("+ " + t); } private static void printKeymapDiff(String l, String r, MacKeyboard left, MacKeyboard right, String layoutId) { String[] ids = layoutId.split(","); MacKeyboard.ModifierMap lmm = getModifierMap(left, ids[0]); MacKeyboard.ModifierMap rmm = getModifierMap(right, ids[0]); MacKeyboard.KeyMapSet lkms = getKeyMapSet(left, ids[1]); MacKeyboard.KeyMapSet rkms = getKeyMapSet(right, ids[1]); for (boolean ctrl : booleans) { for (boolean cmd : booleans) { for (boolean opt : booleans) { for (boolean shift : booleans) { for (boolean caps : booleans) { String ms = modifierString(ctrl, cmd, opt, shift, caps); String ls = l + ":keymaps[" + layoutId + "," + ms + "]"; String rs = r + ":keymaps[" + layoutId + "," + ms + "]"; MacKeyboard.KeyMap lm = lkms.getKeyMap(lmm.mapIndexForState(ctrl, cmd, opt, shift, caps)); MacKeyboard.KeyMap rm = rkms.getKeyMap(rmm.mapIndexForState(ctrl, cmd, opt, shift, caps)); printDiff(ls, rs, lm, rm); } } } } } } private static void printActionsDiff(String l, String r, List left, List right) { List leftIds = actionIds(left); List rightIds = actionIds(right); printDiff(l, r, leftIds, rightIds); for (String actionId : intersect(leftIds, rightIds)) { String la = l + ":actions[" + actionId + "]"; String ra = r + ":actions[" + actionId + "]"; printDiff(la, ra, getAction(left, actionId), getAction(right, actionId)); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacKeyboardLint.java000066400000000000000000000010641506470510200306110ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class MacKeyboardLint { public static void main(String[] args) { for (String arg : args) { try { File file = new File(arg); FileInputStream in = new FileInputStream(file); MacKeyboard kbd = MacKeyboardParser.parse(arg, in); String xml = kbd.toString(); System.out.println(xml); in.close(); } catch (IOException e) { System.err.println("Error: Failed to parse " + arg + ": " + e.getMessage()); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacKeyboardParser.java000066400000000000000000000307661506470510200311520ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class MacKeyboardParser { public static MacKeyboard parse(String name, InputStream in) throws IOException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); // make sure the XML is valid factory.setExpandEntityReferences(false); // don't allow custom entities DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new KeylayoutEntityResolver()); builder.setErrorHandler(new KeylayoutErrorHandler(name)); Document document = builder.parse(new InputSource(fixStream(in))); return parseDocument(document); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException saxe) { throw new IOException(saxe); } } private static MacKeyboard parseDocument(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("#document")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("keyboard")) { if (child.hasAttributes() || child.hasChildNodes()) { return parseKeyboard(child); } } else { throw new IOException("Unknown element: " + ctype); } } throw new IOException("Empty document."); } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard parseKeyboard(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyboard")) { NamedNodeMap attr = node.getAttributes(); int group = parseInt(attr, "group", 126); int id = parseInt(attr, "id", -1); String name = parseString(attr, "name", true); int maxout = parseInt(attr, "maxout", 1); MacKeyboard kbd = new MacKeyboard(group, id, name, maxout); for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("layouts")) { kbd.layouts.add(parseLayouts(child)); } else if (ctype.equalsIgnoreCase("modifierMap")) { kbd.modifierMaps.add(parseModifierMap(child)); } else if (ctype.equalsIgnoreCase("keyMapSet")) { kbd.keyMapSets.add(parseKeyMapSet(child)); } else if (ctype.equalsIgnoreCase("actions")) { kbd.actions.add(parseActions(child)); } else if (ctype.equalsIgnoreCase("terminators")) { kbd.terminators.add(parseTerminators(child)); } else { throw new IOException("Unknown element: " + ctype); } } return kbd; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Layouts parseLayouts(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("layouts")) { MacKeyboard.Layouts layouts = new MacKeyboard.Layouts(); for (Node child : getChildren(node)) { layouts.add(parseLayout(child)); } return layouts; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Layout parseLayout(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("layout")) { NamedNodeMap attr = node.getAttributes(); int first = parseInt(attr, "first", 0); int last = parseInt(attr, "last", 255); String modifiers = parseString(attr, "modifiers", true); String mapSet = parseString(attr, "mapSet", true); return new MacKeyboard.Layout(first, last, modifiers, mapSet); } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.ModifierMap parseModifierMap(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("modifierMap")) { NamedNodeMap attr = node.getAttributes(); String id = parseString(attr, "id", true); int defaultIndex = parseInt(attr, "defaultIndex", 0); MacKeyboard.ModifierMap mm = new MacKeyboard.ModifierMap(id, defaultIndex); for (Node child : getChildren(node)) { mm.add(parseKeyMapSelect(child)); } return mm; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.KeyMapSelect parseKeyMapSelect(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyMapSelect")) { NamedNodeMap attr = node.getAttributes(); int mapIndex = parseInt(attr, "mapIndex", -1); MacKeyboard.KeyMapSelect kms = new MacKeyboard.KeyMapSelect(mapIndex); for (Node child : getChildren(node)) { kms.add(parseModifier(child)); } return kms; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Modifier parseModifier(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("modifier")) { NamedNodeMap attr = node.getAttributes(); String keys = parseString(attr, "keys", true); return new MacKeyboard.Modifier(keys); } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.KeyMapSet parseKeyMapSet(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyMapSet")) { NamedNodeMap attr = node.getAttributes(); String id = parseString(attr, "id", true); MacKeyboard.KeyMapSet kms = new MacKeyboard.KeyMapSet(id); for (Node child : getChildren(node)) { kms.add(parseKeyMap(child)); } return kms; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.KeyMap parseKeyMap(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("keyMap")) { NamedNodeMap attr = node.getAttributes(); int index = parseInt(attr, "index", -1); MacKeyboard.KeyMap keymap = new MacKeyboard.KeyMap(index); for (Node child : getChildren(node)) { keymap.add(parseKey(child)); } return keymap; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Key parseKey(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("key")) { NamedNodeMap attr = node.getAttributes(); int code = parseInt(attr, "code", -1); String output = parseString(attr, "output", false); String action = parseString(attr, "action", true); return new MacKeyboard.Key(code, output, action); } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Actions parseActions(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("actions")) { MacKeyboard.Actions actions = new MacKeyboard.Actions(); for (Node child : getChildren(node)) { actions.add(parseAction(child)); } return actions; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Action parseAction(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("action")) { NamedNodeMap attr = node.getAttributes(); String id = parseString(attr, "id", true); MacKeyboard.Action action = new MacKeyboard.Action(id); for (Node child : getChildren(node)) { action.add(parseWhen(child)); } return action; } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.When parseWhen(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("when")) { NamedNodeMap attr = node.getAttributes(); String state = parseString(attr, "state", true); String through = parseString(attr, "through", true); String output = parseString(attr, "output", false); String multiplier = parseString(attr, "multiplier", true); String next = parseString(attr, "next", true); return new MacKeyboard.When(state, through, output, multiplier, next); } else { throw new IOException("Unknown element: " + type); } } private static MacKeyboard.Terminators parseTerminators(Node node) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("terminators")) { MacKeyboard.Terminators terminators = new MacKeyboard.Terminators(); for (Node child : getChildren(node)) { terminators.add(parseWhen(child)); } return terminators; } else { throw new IOException("Unknown element: " + type); } } private static int parseInt(NamedNodeMap attr, String key, int def) { if (attr == null) return def; Node node = attr.getNamedItem(key); if (node == null) return def; String text = node.getTextContent(); if (text == null) return def; try { return Integer.parseInt(text.trim()); } catch (NumberFormatException nfe) { return def; } } private static String parseString(NamedNodeMap attr, String key, boolean trim) { if (attr == null) return null; Node node = attr.getNamedItem(key); if (node == null) return null; String text = node.getTextContent(); if (text == null) return null; text = unfixString(text); return trim ? text.trim() : text; } private static String unfixString(String s) { boolean unfixed = false; char[] ch = s.toCharArray(); for (int i = 0; i < ch.length; i++) { if (ch[i] >= 0xFDD0 && ch[i] <= 0xFDEF) { ch[i] -= 0xFDD0; unfixed = true; } } return unfixed ? String.valueOf(ch) : s; } private static List getChildren(Node node) { List list = new ArrayList(); if (node != null) { NodeList children = node.getChildNodes(); if (children != null) { int count = children.getLength(); for (int i = 0; i < count; i++) { Node child = children.item(i); if (child != null) { String type = child.getNodeName(); if (type.equalsIgnoreCase("#text") || type.equalsIgnoreCase("#comment")) { continue; } else { list.add(child); } } } } } return list; } private static final Pattern CHAR_REF_PATTERN = Pattern.compile("&#(x([0-9A-Fa-f]+)|([0-9]+));"); private static String fixString(String s) { StringBuffer sb = new StringBuffer(); Matcher m = CHAR_REF_PATTERN.matcher(s); while (m.find()) { int v = ( (m.group(2) != null && m.group(2).length() > 0) ? Integer.parseInt(m.group(2), 16) : (m.group(3) != null && m.group(3).length() > 0) ? Integer.parseInt(m.group(3), 10) : -1 ); if (v >= 0x00 && v < 0x20) { m.appendReplacement(sb, ("&#x" + Integer.toHexString(0xFDD0+v) + ";")); } else { m.appendReplacement(sb, m.group()); } } m.appendTail(sb); return sb.toString(); } private static Reader fixStream(InputStream in) { StringBuffer sb = new StringBuffer(); Scanner scan = new Scanner(in, "UTF-8"); while (scan.hasNextLine()) { sb.append(fixString(scan.nextLine())); sb.append("\n"); } scan.close(); return new StringReader(sb.toString()); } private static class KeylayoutEntityResolver implements EntityResolver { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (systemId.contains("KeyboardLayout.dtd")) { return new InputSource(MacKeyboardParser.class.getResourceAsStream("keylayout.dtd")); } else { return null; } } } private static class KeylayoutErrorHandler implements ErrorHandler { private final String name; public KeylayoutErrorHandler(String name) { this.name = name; } @Override public void error(SAXParseException e) throws SAXException { //System.err.print("Warning: Failed to parse " + name + ": "); //System.err.println("ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void fatalError(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("FATAL ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void warning(SAXParseException e) throws SAXException { //System.err.print("Warning: Failed to parse " + name + ": "); //System.err.println("WARNING on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacReader.java000066400000000000000000000172471506470510200274360ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class MacReader { public static KeyboardMapping read(File file) throws IOException { KeyboardMapping km = new KeyboardMapping(); read(file, km); String iname = stripSuffix(file.getName(), ".keylayout"); File ifile = new File(file.getParentFile(), iname + ".icns"); if (ifile.isFile()) { FileInputStream ifis = new FileInputStream(ifile); DataInputStream idis = new DataInputStream(ifis); MacIconSuite icns = new MacIconSuite(); icns.read(idis); km.icon = icns.getImage(); km.macIconVersion = icns.getVersion(); idis.close(); ifis.close(); } return km; } public static void read(File in, KeyboardMapping km) throws IOException { FileInputStream fis = new FileInputStream(in); read(in.getName(), fis, km); fis.close(); } public static void read(String name, InputStream in, KeyboardMapping km) throws IOException { transform(MacKeyboardParser.parse(name, in), km); } public static void transform(MacKeyboard mk, KeyboardMapping km) { km.macGroupNumber = mk.group; km.macIdNumber = mk.id; km.name = mk.name; km.macActionIds.clear(); MacKeyboard.Layout layout = getLayout(mk); if (layout == null) return; MacKeyboard.ModifierMap mm = mk.getModifierMap(layout.modifiers); if (mm == null) return; MacKeyboard.KeyMapSet kms = mk.getKeyMapSet(layout.mapSet); if (kms == null) return; // Get keymaps for the 6.2 states supported by KeyMapping. ctrl cmd opt shift caps MacKeyboard.KeyMap unshifted = kms.getKeyMap(mm.mapIndexForState(false, false, false, false, false)); MacKeyboard.KeyMap capslock = kms.getKeyMap(mm.mapIndexForState(false, false, false, false, true )); MacKeyboard.KeyMap shifted = kms.getKeyMap(mm.mapIndexForState(false, false, false, true, false)); MacKeyboard.KeyMap altUnshifted = kms.getKeyMap(mm.mapIndexForState(false, false, true, false, false)); MacKeyboard.KeyMap altCapslock = kms.getKeyMap(mm.mapIndexForState(false, false, true, false, true )); MacKeyboard.KeyMap altShifted = kms.getKeyMap(mm.mapIndexForState(false, false, true, true, false)); MacKeyboard.KeyMap command = kms.getKeyMap(mm.mapIndexForState(false, true, false, false, false)); MacKeyboard.KeyMap ctrl = kms.getKeyMap(mm.mapIndexForState(true, false, false, false, false)); // Set KeyMappings according to each keymap. for (MacKeyboard.Key key : unshifted ) new GetKey(km, mk, key).onUnshifted (getKeyMapping(key, km)); for (MacKeyboard.Key key : shifted ) new GetKey(km, mk, key).onShifted (getKeyMapping(key, km)); for (MacKeyboard.Key key : altUnshifted) new GetKey(km, mk, key).onAltUnshifted(getKeyMapping(key, km)); for (MacKeyboard.Key key : altShifted ) new GetKey(km, mk, key).onAltShifted (getKeyMapping(key, km)); for (MacKeyboard.Key key : command ) new GetKey(km, mk, key).onCommand (getKeyMapping(key, km)); for (MacKeyboard.Key key : ctrl ) new GetKey(km, mk, key).onCtrl (getKeyMapping(key, km)); for (MacKeyboard.Key key : capslock ) new GetCapsLockMapping(key, unshifted, shifted ).onCapsLock (getKeyMapping(key, km)); for (MacKeyboard.Key key : altCapslock ) new GetCapsLockMapping(key, altUnshifted, altShifted).onAltCapsLock(getKeyMapping(key, km)); } private static KeyMapping getKeyMapping(MacKeyboard.Key key, KeyboardMapping km) { MacKey k = MacKey.forKeyCode(key.code); if (k == null || k.key == null) return null; return km.map.get(k.key); } private static class GetCapsLockMapping { private final CapsLockMapping mapping; public GetCapsLockMapping(MacKeyboard.Key key, MacKeyboard.KeyMap unshifted, MacKeyboard.KeyMap shifted) { MacKeyboard.Key unshiftedKey = unshifted.getKey(key.code); MacKeyboard.Key shiftedKey = shifted.getKey(key.code); if (unshiftedKey.equals(shiftedKey)) mapping = CapsLockMapping.AUTO; else if (key.equals(unshiftedKey)) mapping = CapsLockMapping.UNSHIFTED; else if (key.equals(shiftedKey)) mapping = CapsLockMapping.SHIFTED; else mapping = CapsLockMapping.AUTO; } public void onCapsLock(KeyMapping m) { if (m == null) return; m.capsLockMapping = mapping; } public void onAltCapsLock(KeyMapping m) { if (m == null) return; m.altCapsLockMapping = mapping; } } private static class GetKey { private int output = -1; private DeadKeyTable deadKey = null; public GetKey(KeyboardMapping km, MacKeyboard mk, MacKeyboard.Key key) { if (key.output != null && key.output.length() > 0) { output = key.output.codePointAt(0); } if (key.action != null && key.action.length() > 0) { MacKeyboard.Action action = getAction(mk, key.action); if (action != null) { for (MacKeyboard.When when : action) { if (when.state.equals("none")) { if (when.output != null && when.output.length() > 0) { output = when.output.codePointAt(0); } if (when.next != null && when.next.length() > 0) { deadKey = getDeadKeyTable(km, mk, when.next); } } } } } } public void onCommand(KeyMapping m) { if (m == null) return; m.commandOutput = output; m.commandDeadKey = deadKey; } public void onUnshifted(KeyMapping m) { if (m == null) return; m.unshiftedOutput = output; m.unshiftedDeadKey = deadKey; } public void onShifted(KeyMapping m) { if (m == null) return; m.shiftedOutput = output; m.shiftedDeadKey = deadKey; } public void onCtrl(KeyMapping m) { if (m == null) return; m.ctrlOutput = output; m.ctrlDeadKey = deadKey; } public void onAltUnshifted(KeyMapping m) { if (m == null) return; m.altUnshiftedOutput = output; m.altUnshiftedDeadKey = deadKey; } public void onAltShifted(KeyMapping m) { if (m == null) return; m.altShiftedOutput = output; m.altShiftedDeadKey = deadKey; } } private static MacKeyboard.Action getAction(MacKeyboard mk, String actionId) { for (MacKeyboard.Actions actions : mk.actions) { for (MacKeyboard.Action action : actions) { if (action.id.equals(actionId)) { return action; } } } return null; } private static DeadKeyTable getDeadKeyTable(KeyboardMapping km, MacKeyboard mk, String state) { String t = getTerminatorOutput(mk, state); if (t == null || t.length() == 0) return null; DeadKeyTable dkt = new DeadKeyTable(t.codePointAt(0)); dkt.macStateId = state; for (MacKeyboard.Actions actions : mk.actions) { for (MacKeyboard.Action action : actions) { int noneOutput = -1; int deadOutput = -1; for (MacKeyboard.When when : action) { String o = when.output; if (o == null || o.length() == 0) continue; if (when.state.equals("none")) noneOutput = o.codePointAt(0); if (when.state.equals(state)) deadOutput = o.codePointAt(0); } if (noneOutput > 0 && deadOutput > 0) { dkt.keyMap.put(noneOutput, deadOutput); km.macActionIds.put(noneOutput, action.id); } } } return dkt; } private static String getTerminatorOutput(MacKeyboard mk, String state) { for (MacKeyboard.Terminators terms : mk.terminators) { for (MacKeyboard.When when : terms) { if (when.state.equals(state)) { return when.output; } } } return null; } private static MacKeyboard.Layout getLayout(MacKeyboard mk) { for (MacKeyboard.Layouts layouts : mk.layouts) { for (MacKeyboard.Layout layout : layouts) { return layout; } } return null; } private static String stripSuffix(String s, String suffix) { if (s.toLowerCase().endsWith(suffix.toLowerCase())) { return s.substring(0, s.length() - suffix.length()); } else { return s; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/MacWriter.java000066400000000000000000000271621506470510200275050ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; public class MacWriter { public static void write(File file, KeyboardMapping km) throws IOException { FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); write(pw, km); pw.flush(); pw.close(); fos.close(); if (km.icon != null) { String iname = stripSuffix(file.getName(), ".keylayout"); File ifile = new File(file.getParentFile(), iname + ".icns"); FileOutputStream ifos = new FileOutputStream(ifile); DataOutputStream idos = new DataOutputStream(ifos); MacIconSuite icns = new MacIconSuite(); icns.putImage(km.icon); icns.putVersion(km.macIconVersion); icns.write(idos); idos.flush(); idos.close(); ifos.close(); } if (!(km.macAttachments == null || km.macAttachments.isEmpty())) { File parentFile = file.getParentFile(); for (Map.Entry e : km.macAttachments.entrySet()) { fos = new FileOutputStream(new File(parentFile, e.getKey())); fos.write(e.getValue()); fos.flush(); fos.close(); } } } public static void write(PrintWriter out, KeyboardMapping km) { out.print(transform(km).toString()); } public static MacKeyboard transform(KeyboardMapping km) { MacKeyboard mk = new MacKeyboard(km.macGroupNumber, km.macIdNumber, km.getNameNotEmpty(), 1); // Create actions, terminators, and output map for dead keys. Map> dko = new TreeMap>(); for (KeyMapping k : km.map.values()) txDeadKey(k.unshiftedDeadKey, mk, dko); for (KeyMapping k : km.map.values()) txDeadKey(k.shiftedDeadKey, mk, dko); for (KeyMapping k : km.map.values()) txDeadKey(k.altUnshiftedDeadKey, mk, dko); for (KeyMapping k : km.map.values()) txDeadKey(k.altShiftedDeadKey, mk, dko); for (KeyMapping k : km.map.values()) txDeadKey(k.commandDeadKey, mk, dko); for (KeyMapping k : km.map.values()) txDeadKey(k.ctrlDeadKey, mk, dko); // Create actions for dead key output map. for (Map.Entry> e : dko.entrySet()) { String actionId = getActionId(km, e.getKey()); MacKeyboard.Action action = new MacKeyboard.Action(actionId); for (Map.Entry f : e.getValue().entrySet()) { String state = f.getKey(); String output = outputString(f.getValue()); action.putWhen(new MacKeyboard.When(state, null, output, null, null)); } mk.actions().putAction(action); } // Create keymaps. List unshifted = new ArrayList(); List capslock = new ArrayList(); List shifted = new ArrayList(); List altUnshifted = new ArrayList(); List altCapslock = new ArrayList(); List altShifted = new ArrayList(); List command = new ArrayList(); List commandOption = new ArrayList(); List commandOptionShift = new ArrayList(); List ctrl = new ArrayList(); for (MacKey key : MacKey.KEYS) { if (key.key == null) { String output = outputString(key.output); MacKeyboard.Key k = new MacKeyboard.Key(key.keyCode, output, null); unshifted.add(k); capslock.add(k); shifted.add(k); altUnshifted.add(k); altCapslock.add(k); altShifted.add(k); command.add(k); commandOption.add(k); commandOptionShift.add(k); ctrl.add(k); } else { KeyMapping m = km.map.get(key.key); TxKeyMemo defUnshiftedKM = txKey(key, key.key.defaultUnshifted, null, null, km, dko); TxKeyMemo defShiftedKM = txKey(key, key.key.defaultShifted, null, null, km, dko); TxKeyMemo defCtrlKM = txKey(key, key.key.defaultCtrl, null, defUnshiftedKM, km, dko); TxKeyMemo unshiftedKM = txKey(key, m.unshiftedOutput, m.unshiftedDeadKey, defUnshiftedKM, km, dko); TxKeyMemo shiftedKM = txKey(key, m.shiftedOutput, m.shiftedDeadKey, defShiftedKM, km, dko); TxKeyMemo capslockKM = capsLockKeyMemo(m.capsLockMapping, unshiftedKM, shiftedKM); TxKeyMemo altUnshiftedKM = txKey(key, m.altUnshiftedOutput, m.altUnshiftedDeadKey, unshiftedKM, km, dko); TxKeyMemo altShiftedKM = txKey(key, m.altShiftedOutput, m.altShiftedDeadKey, shiftedKM, km, dko); TxKeyMemo altCapslockKM = capsLockKeyMemo(m.altCapsLockMapping, altUnshiftedKM, altShiftedKM); TxKeyMemo commandKM = txKey(key, m.commandOutput, m.commandDeadKey, defUnshiftedKM, km, dko); TxKeyMemo commandOptionKM = undeadKeyMemo(altUnshiftedKM, km, dko); TxKeyMemo commandOptionShiftKM = undeadKeyMemo(altShiftedKM, km, dko); TxKeyMemo ctrlKM = txKey(key, m.ctrlOutput, m.ctrlDeadKey, defCtrlKM, km, dko); unshifted.add(unshiftedKM.key); capslock.add(capslockKM.key); shifted.add(shiftedKM.key); altUnshifted.add(altUnshiftedKM.key); altCapslock.add(altCapslockKM.key); altShifted.add(altShiftedKM.key); command.add(commandKM.key); commandOption.add(commandOptionKM.key); commandOptionShift.add(commandOptionShiftKM.key); ctrl.add(ctrlKM.key); } } // Dedupe keymaps. List> keymaps = new ArrayList>(); int unshiftedIndex = addKeyMap(keymaps, unshifted); int capslockIndex = addKeyMap(keymaps, capslock); int shiftedIndex = addKeyMap(keymaps, shifted); int altUnshiftedIndex = addKeyMap(keymaps, altUnshifted); int altCapslockIndex = addKeyMap(keymaps, altCapslock); int altShiftedIndex = addKeyMap(keymaps, altShifted); int commandIndex = addKeyMap(keymaps, command); int commandOptionIndex = addKeyMap(keymaps, commandOption); int commandOptionShiftIndex = addKeyMap(keymaps, commandOptionShift); int ctrlIndex = addKeyMap(keymaps, ctrl); // Create modifier map and key map set. MacKeyboard.ModifierMap mm = new MacKeyboard.ModifierMap("modifiers", unshiftedIndex); MacKeyboard.KeyMapSet kms = new MacKeyboard.KeyMapSet("ANSI"); for (int i = 0, n = keymaps.size(); i < n; i++) { MacKeyboard.KeyMapSelect kmsel = new MacKeyboard.KeyMapSelect(i); if (unshiftedIndex == i) kmsel.add(MacKeyboard.Modifier.UNSHIFTED); if (capslockIndex == i) kmsel.add(MacKeyboard.Modifier.CAPSLOCK); if (shiftedIndex == i) kmsel.add(MacKeyboard.Modifier.SHIFTED); if (altUnshiftedIndex == i) kmsel.add(MacKeyboard.Modifier.ALT_UNSHIFTED); if (altCapslockIndex == i) kmsel.add(MacKeyboard.Modifier.ALT_CAPSLOCK); if (altShiftedIndex == i) kmsel.add(MacKeyboard.Modifier.ALT_SHIFTED); if (commandIndex == i) kmsel.add(MacKeyboard.Modifier.COMMAND); if (commandOptionIndex == i) kmsel.add(MacKeyboard.Modifier.COMMAND_OPTION); if (commandOptionShiftIndex == i) kmsel.add(MacKeyboard.Modifier.COMMAND_OPTION_SHIFT); if (ctrlIndex == i) kmsel.add(MacKeyboard.Modifier.CTRL); mm.putKeyMapSelect(kmsel); MacKeyboard.KeyMap map = new MacKeyboard.KeyMap(i); map.addAll(keymaps.get(i)); kms.putKeyMap(map); } mk.putModifierMap(mm); mk.putKeyMapSet(kms); mk.layouts().putLayout(new MacKeyboard.Layout(0, 255, mm.id, kms.id)); return mk; } private static int addKeyMap(List> keymaps, List keymap) { int i = keymaps.indexOf(keymap); if (i >= 0) return i; i = keymaps.size(); keymaps.add(keymap); return i; } private static TxKeyMemo undeadKeyMemo(TxKeyMemo possiblyDead, KeyboardMapping km, Map> dko) { if (possiblyDead.deadKey == null) return possiblyDead; int code = possiblyDead.key.code; int out = possiblyDead.deadKey.macTerminator; if (dko.containsKey(out)) { String actionId = getActionId(km, out); MacKeyboard.Key k = new MacKeyboard.Key(code, null, actionId); return new TxKeyMemo(out, null, k); } else { String output = outputString(out); MacKeyboard.Key k = new MacKeyboard.Key(code, output, null); return new TxKeyMemo(out, null, k); } } private static TxKeyMemo capsLockKeyMemo(CapsLockMapping caps, TxKeyMemo unshifted, TxKeyMemo shifted) { if (caps == CapsLockMapping.UNSHIFTED) { return unshifted; } else if (caps == CapsLockMapping.SHIFTED) { return shifted; } else if (unshifted.deadKey != null && shifted.deadKey != null) { return isCasePair(unshifted.deadKey.macTerminator, shifted.deadKey.macTerminator) ? shifted : unshifted; } else if (unshifted.deadKey != null) { return (unshifted.deadKey.macTerminator == shifted.output) ? shifted : unshifted; } else if (shifted.deadKey != null) { return (shifted.deadKey.macTerminator == unshifted.output) ? shifted : unshifted; } else { return isCasePair(unshifted.output, shifted.output) ? shifted : unshifted; } } private static boolean isCasePair(int u, int s) { return (u != s) && (Character.toUpperCase(u) == s || Character.toLowerCase(s) == u); } private static TxKeyMemo txKey( MacKey key, int out, DeadKeyTable dead, TxKeyMemo def, KeyboardMapping km, Map> dko ) { if (dead != null) { MacKeyboard.Key k = new MacKeyboard.Key(key.keyCode, null, dead.macStateId); return new TxKeyMemo(out, dead, k); } if (out > 0) { if (dko.containsKey(out)) { String actionId = getActionId(km, out); MacKeyboard.Key k = new MacKeyboard.Key(key.keyCode, null, actionId); return new TxKeyMemo(out, dead, k); } else { String output = outputString(out); MacKeyboard.Key k = new MacKeyboard.Key(key.keyCode, output, null); return new TxKeyMemo(out, dead, k); } } return def; } private static class TxKeyMemo { public final int output; public final DeadKeyTable deadKey; public final MacKeyboard.Key key; public TxKeyMemo(int output, DeadKeyTable deadKey, MacKeyboard.Key key) { this.output = output; this.deadKey = deadKey; this.key = key; } } private static String getActionId(KeyboardMapping km, int cp) { if (km.macActionIds.containsKey(cp)) { return km.macActionIds.get(cp); } else { return XkbKeySym.MAP.getKeySym(cp); } } private static void txDeadKey(DeadKeyTable dkt, MacKeyboard mk, Map> dko) { if (dkt != null) { // If there is no state name invent one. String state = dkt.macStateId; if (state == null || state.length() == 0) { state = XkbKeySym.MAP.getKeySym(dkt.macTerminator); dkt.macStateId = state; } // Add action for dead key. MacKeyboard.Action action = new MacKeyboard.Action(state); action.putWhen(new MacKeyboard.When("none", null, null, null, state)); mk.actions().putAction(action); // Add terminator for dead key. String output = outputString(dkt.macTerminator); mk.terminators().putWhen(new MacKeyboard.When(state, null, output, null, null)); // Add dead key outputs to dead key output map. for (Map.Entry e : dkt.keyMap.entrySet()) { Map dka = dko.get(e.getKey()); if (dka == null) { dka = new LinkedHashMap(); dka.put("none", e.getKey()); dko.put(e.getKey(), dka); } dka.put(state, e.getValue()); } } } private static String outputString(int cp) { return (cp > 0) ? String.valueOf(Character.toChars(cp)) : null; } private static String stripSuffix(String s, String suffix) { if (s.toLowerCase().endsWith(suffix.toLowerCase())) { return s.substring(0, s.length() - suffix.length()); } else { return s; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/Main.java000066400000000000000000000036411506470510200264700ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { if (args.length == 0) { com.kreative.keyedit.edit.Main.main(args); } else { String arg0 = args[0].toLowerCase(); List arga = Arrays.asList(args); arga = arga.subList(1, arga.size()); args = arga.toArray(new String[arga.size()]); if (arg0.equals("edit")) { com.kreative.keyedit.edit.Main.main(args); } else if (arg0.equals("convert")) { ConvertKeyboard.main(args); } else if (arg0.equals("kkbcopy")) { KkbCopy.main(args); } else if (arg0.equals("kkbinfo")) { KkbInfo.main(args); } else if (arg0.equals("kkblint")) { KkbLint.main(args); } else if (arg0.equals("maccopy")) { MacCopy.main(args); } else if (arg0.equals("macdiff")) { MacKeyboardDiff.main(args); } else if (arg0.equals("maclint")) { MacKeyboardLint.main(args); } else if (arg0.equals("wincopy")) { WinCopy.main(args); } else if (arg0.equals("xkbcopy")) { XkbCopy.main(args); } else { printHelp(); } } } private static void printHelp() { System.out.println(); System.out.println("Usage:"); System.out.println(" java -jar KeyEdit.jar edit "); System.out.println(" java -jar KeyEdit.jar convert [-if ] [-of ] "); System.out.println(" java -jar KeyEdit.jar kkbcopy "); System.out.println(" java -jar KeyEdit.jar kkblint "); System.out.println(" java -jar KeyEdit.jar maccopy "); System.out.println(" java -jar KeyEdit.jar macdiff "); System.out.println(" java -jar KeyEdit.jar maclint "); System.out.println(" java -jar KeyEdit.jar wincopy "); System.out.println(" java -jar KeyEdit.jar xkbcopy [-k|-u] "); System.out.println(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinCopy.java000066400000000000000000000021041506470510200271650ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; public class WinCopy { public static void main(String[] args) { if (args.length < 2) { System.out.println("Usage: WinCopy "); System.out.println(" WinCopy "); } else { String outPath = args[args.length-1]; File out = new File(outPath); if (args.length > 2 || outPath.endsWith("/") || out.isDirectory()) { out.mkdir(); for (int i = 0; i < args.length-1; i++) { try { KeyboardMapping km = WinReader.read(new File(args[i])); File output = new File(out, km.getWinIdentifierNotEmpty() + ".klc"); WinWriter.write(output, km); } catch (IOException e) { System.err.println("Failed copying " + args[i] + ": " + e.getMessage()); } } } else { try { KeyboardMapping km = WinReader.read(new File(args[0])); WinWriter.write(new File(args[1]), km); } catch (IOException e) { System.err.println("Failed copying " + args[0] + ": " + e.getMessage()); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinIconDir.java000066400000000000000000000117711506470510200276140ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; public class WinIconDir extends ArrayList { private static final long serialVersionUID = 1L; private boolean isCursor; public WinIconDir() { this.isCursor = false; } public WinIconDir(boolean isCursor) { this.isCursor = isCursor; } public void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1 << 20]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.flush(); out.close(); read(out.toByteArray()); } public void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(bin); int reserved = Short.reverseBytes(din.readShort()); int type = Short.reverseBytes(din.readShort()); int count = Short.reverseBytes(din.readShort()); if (reserved != 0 || type < 1 || type > 2 || count < 1) { throw new IOException("invalid value in ico header"); } WinIconDirEntry[] entries = new WinIconDirEntry[count]; for (int i = 0; i < count; i++) { entries[i] = new WinIconDirEntry(type > 1); entries[i].readHeader(din); } for (int i = 0; i < count; i++) { entries[i].readData(din); } clear(type > 1); addAll(Arrays.asList(entries)); } public void write(OutputStream out) throws IOException { write(new DataOutputStream(out)); } public void write(DataOutputStream out) throws IOException { out.writeShort(Short.reverseBytes((short)0)); out.writeShort(Short.reverseBytes((short)(isCursor ? 2 : 1))); out.writeShort(Short.reverseBytes((short)size())); int offset = size() * 16 + 6; for (WinIconDirEntry e : this) { e.setDataOffset(offset); e.writeHeader(out); offset += e.getDataLength(); } for (WinIconDirEntry e : this) { out.write(e.getData()); } } @Override public boolean add(WinIconDirEntry e) { if (e.isCursor() != isCursor) { throw new IllegalArgumentException("cannot put a cursor in an icon file or vice versa"); } return super.add(e); } @Override public void add(int index, WinIconDirEntry e) { if (e.isCursor() != isCursor) { throw new IllegalArgumentException("cannot put a cursor in an icon file or vice versa"); } super.add(index, e); } @Override public boolean addAll(Collection c) { for (WinIconDirEntry e : c) { if (e.isCursor() != isCursor) { throw new IllegalArgumentException("cannot put a cursor in an icon file or vice versa"); } } return super.addAll(c); } @Override public boolean addAll(int index, Collection c) { for (WinIconDirEntry e : c) { if (e.isCursor() != isCursor) { throw new IllegalArgumentException("cannot put a cursor in an icon file or vice versa"); } } return super.addAll(index, c); } @Override public WinIconDirEntry set(int index, WinIconDirEntry e) { if (e.isCursor() != isCursor) { throw new IllegalArgumentException("cannot put a cursor in an icon file or vice versa"); } return super.set(index, e); } public void clear(boolean isCursor) { this.isCursor = isCursor; super.clear(); } public boolean isCursor() { return isCursor; } public WinIconDirEntry get(Integer wantWidth, Integer wantHeight, Integer wantBpp, Boolean wantPNG) { WinIconDirEntry best = null; int bestWidth = 0; int bestHeight = 0; int bestBpp = 0; boolean bestIsPNG = false; for (WinIconDirEntry e : this) { int eWidth = e.getWidth(); int eHeight = e.getHeight(); int eBpp = e.getBitsPerPixel(); boolean eIsPNG = e.isPNG(); if ( (wantWidth == null || wantWidth.intValue() == eWidth) && (eWidth >= bestWidth) && (wantHeight == null || wantHeight.intValue() == eHeight) && (eHeight >= bestHeight) && (wantBpp == null || wantBpp.intValue() == eBpp) && (eBpp >= bestBpp) && (wantPNG == null || wantPNG.booleanValue() == eIsPNG) && (eIsPNG || !bestIsPNG) ) { best = e; bestWidth = eWidth; bestHeight = eHeight; bestBpp = eBpp; bestIsPNG = eIsPNG; } } return best; } public List getAll(Integer wantWidth, Integer wantHeight, Integer wantBpp, Boolean wantPNG) { List matches = new ArrayList(); for (WinIconDirEntry e : this) { int eWidth = e.getWidth(); int eHeight = e.getHeight(); int eBpp = e.getBitsPerPixel(); boolean eIsPNG = e.isPNG(); if ( (wantWidth == null || wantWidth.intValue() == eWidth) && (wantHeight == null || wantHeight.intValue() == eHeight) && (wantBpp == null || wantBpp.intValue() == eBpp) && (wantPNG == null || wantPNG.booleanValue() == eIsPNG) ) { matches.add(e); } } return matches; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinIconDirEntry.java000066400000000000000000000371121506470510200306330ustar00rootroot00000000000000package com.kreative.keyedit; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.imageio.ImageIO; public class WinIconDirEntry { // IconDir Header private final boolean isCursor; // IconDirEntry Header private int icoWidth; private int icoHeight; private int icoColors; private int icoReserved; private int icoPlanes; private int icoBpp; private int dataLength; private int dataOffset; // IconDirEntry Data private byte[] data; private boolean isImageIO; private BufferedImage image; // BitmapInfoHeader private int bmpHeaderLength; private int bmpWidth; private int bmpHeight; private int bmpPlanes; private int bmpBpp; // private int bmpCompression; // private int bmpImageLength; // private int bmpXPPM; // private int bmpYPPM; private int bmpColors; // private int bmpImportantColors; public WinIconDirEntry() { this.isCursor = false; } public WinIconDirEntry(boolean isCursor) { this.isCursor = isCursor; } void readHeader(DataInputStream in) throws IOException { icoWidth = in.readUnsignedByte(); icoHeight = in.readUnsignedByte(); icoColors = in.readUnsignedByte(); icoReserved = in.readUnsignedByte(); icoPlanes = Short.reverseBytes(in.readShort()); icoBpp = Short.reverseBytes(in.readShort()); dataLength = Integer.reverseBytes(in.readInt()); dataOffset = Integer.reverseBytes(in.readInt()); } void readData(DataInputStream in) throws IOException { in.reset(); in.skipBytes(dataOffset); in.readFully((data = new byte[dataLength])); isImageIO = dataStartsWith(data, 0, 0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A); if (isImageIO) { try { image = ImageIO.read(new ByteArrayInputStream(data)); bmpHeaderLength = 0; bmpWidth = image.getWidth(); bmpHeight = image.getHeight() * 2; bmpPlanes = 0; bmpBpp = 0; // bmpCompression = 0; // bmpImageLength = 0; // bmpXPPM = 0; // bmpYPPM = 0; bmpColors = 0; // bmpImportantColors = 0; } catch (Exception e) { throw new IOException("error reading image: " + e, e); } } else { try { image = null; bmpHeaderLength = getInt32LE(data, 0); bmpWidth = getInt32LE(data, 4); bmpHeight = getInt32LE(data, 8); bmpPlanes = getInt16LE(data, 12); bmpBpp = getInt16LE(data, 14); // bmpCompression = getInt32LE(data, 16); // bmpImageLength = getInt32LE(data, 20); // bmpXPPM = getInt32LE(data, 24); // bmpYPPM = getInt32LE(data, 28); bmpColors = getInt32LE(data, 32); // bmpImportantColors = getInt32LE(data, 36); } catch (Exception e) { throw new IOException("error reading bitmap header: " + e, e); } } } void setDataOffset(int dataOffset) { this.dataOffset = dataOffset; } void writeHeader(DataOutputStream out) throws IOException { out.writeByte(icoWidth); out.writeByte(icoHeight); out.writeByte(icoColors); out.writeByte(icoReserved); out.writeShort(Short.reverseBytes((short)icoPlanes)); out.writeShort(Short.reverseBytes((short)icoBpp)); out.writeInt(Integer.reverseBytes(dataLength)); out.writeInt(Integer.reverseBytes(dataOffset)); } public boolean isCursor() { return isCursor; } public int getWidth() { if (icoWidth > 0) return icoWidth; if (bmpWidth > 0) return bmpWidth; return 0; } public int getHeight() { if (icoHeight > 0) return icoHeight; if (bmpHeight > 0) return bmpHeight / 2; return 0; } public int getPlanes() { if (icoPlanes > 0 && !isCursor) return icoPlanes; if (bmpPlanes > 0) return bmpPlanes; return 0; } public int getBitsPerPixel() { if (icoBpp > 0 && !isCursor) return icoBpp; if (bmpBpp > 0) return bmpBpp; return 0; } public int getColorCount() { if (icoColors > 0) return icoColors; if (icoBpp > 0 && !isCursor) { if (icoBpp < 1 || icoBpp > 8) return 0; return (1 << icoBpp); } if (bmpColors > 0) return bmpColors; if (bmpBpp < 1 || bmpBpp > 8) return 0; return (1 << bmpBpp); } public int[] getColorTable() { return getColorTable(data, bmpHeaderLength, getColorCount()); } public boolean hasAlphaChannel() { if (isImageIO) return true; int bpp = getBitsPerPixel(); return (bpp == 16 || bpp == 32); } public int getDataLength() { return dataLength; } public byte[] getData() { return data; } public boolean isPNG() { return isImageIO; } public BufferedImage getImage() { if (image != null) return image; int width = getWidth(); int height = getHeight(); int bpp = getBitsPerPixel(); int colors = getColorCount(); boolean mask = !hasAlphaChannel(); int[] pixels = new int[width * height]; decodeImage(data, bmpHeaderLength, pixels, width, height, bpp, colors, mask); image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); image.setRGB(0, 0, width, height, pixels, 0, width); return image; } public void setBMPImage(BufferedImage image, int bpp, int[] colorTable) { int width = image.getWidth(); int height = image.getHeight(); int[] pixels = new int[width * height]; image.getRGB(0, 0, width, height, pixels, 0, width); byte[] data = new byte[dataLength(40, width, height, bpp, colorTable.length, true)]; encodeImage(data, 40, pixels, width, height, bpp, colorTable, true); // IconDirEntry Header icoWidth = (width >= 256) ? 0 : width; icoHeight = (height >= 256) ? 0 : height; icoColors = (colorTable.length >= 256) ? 0 : colorTable.length; icoReserved = 0; if (!isCursor) { icoPlanes = 1; icoBpp = bpp; } dataLength = data.length; dataOffset = 0; // IconDirEntry Data this.data = data; this.isImageIO = false; this.image = null; // BitmapInfoHeader putInt32LE(data, 0, (bmpHeaderLength = 40)); putInt32LE(data, 4, (bmpWidth = width)); putInt32LE(data, 8, (bmpHeight = height * 2)); putInt16LE(data, 12, (bmpPlanes = 1)); putInt16LE(data, 14, (bmpBpp = bpp)); // putInt32LE(data, 16, (bmpCompression = 0)); // putInt32LE(data, 20, (bmpImageLength = 0)); // putInt32LE(data, 20, data.length - colorTable.length * 4 - 40); // putInt32LE(data, 24, (bmpXPPM = 0)); // putInt32LE(data, 28, (bmpYPPM = 0)); putInt32LE(data, 32, (bmpColors = colorTable.length)); // putInt32LE(data, 36, (bmpImportantColors = 0)); } public void setPNGImage(BufferedImage image) throws IOException { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageIO.write(image, "png", out); out.flush(); out.close(); byte[] data = out.toByteArray(); image = ImageIO.read(new ByteArrayInputStream(data)); int width = image.getWidth(); int height = image.getHeight(); // IconDirEntry Header icoWidth = (width >= 256) ? 0 : width; icoHeight = (height >= 256) ? 0 : height; icoColors = 0; icoReserved = 0; if (!isCursor) { icoPlanes = 1; icoBpp = 32; } dataLength = data.length; dataOffset = 0; // IconDirEntry Data this.data = data; this.isImageIO = true; this.image = image; // BitmapInfoHeader bmpHeaderLength = 0; bmpWidth = width; bmpHeight = height * 2; bmpPlanes = 0; bmpBpp = 0; // bmpCompression = 0; // bmpImageLength = 0; // bmpXPPM = 0; // bmpYPPM = 0; bmpColors = 0; // bmpImportantColors = 0; } catch (Exception e) { throw new IOException("error writing image: " + e, e); } } public Point getHotspot() { return isCursor ? new Point(icoPlanes, icoBpp) : null; } public void setHotspot(Point p) { if (isCursor) { icoPlanes = p.x; icoBpp = p.y; } } public void setHotspot(int x, int y) { if (isCursor) { icoPlanes = x; icoBpp = y; } } private static boolean dataStartsWith(byte[] data, int offset, int... prefix) { for (int b : prefix) { if (offset >= data.length) return false; if (data[offset] != (byte)b) return false; offset++; } return true; } private static int getInt32LE(byte[] data, int offset) { int v = (data[offset++] & 0xFF); v |= ((data[offset++] & 0xFF) << 8); v |= ((data[offset++] & 0xFF) << 16); v |= ((data[offset++] & 0xFF) << 24); return v; } private static int getInt24LE(byte[] data, int offset) { int v = (data[offset++] & 0xFF); v |= ((data[offset++] & 0xFF) << 8); v |= ((data[offset++] & 0xFF) << 16); return v; } private static int getInt16LE(byte[] data, int offset) { int v = (data[offset++] & 0xFF); v |= ((data[offset++] & 0xFF) << 8); return v; } private static void putInt32LE(byte[] data, int offset, int v) { data[offset++] = (byte)(v >> 0); data[offset++] = (byte)(v >> 8); data[offset++] = (byte)(v >> 16); data[offset++] = (byte)(v >> 24); } private static void putInt24LE(byte[] data, int offset, int v) { data[offset++] = (byte)(v >> 0); data[offset++] = (byte)(v >> 8); data[offset++] = (byte)(v >> 16); } private static void putInt16LE(byte[] data, int offset, int v) { data[offset++] = (byte)(v >> 0); data[offset++] = (byte)(v >> 8); } private static int[] getColorTable(byte[] data, int dp, int colors) { int[] colorTable = new int[colors]; for (int i = 0; i < colors; i++) { colorTable[i] = getInt32LE(data, dp) | 0xFF000000; dp += 4; } return colorTable; } private static void decodeImage(byte[] data, int dp, int[] pixels, int width, int height, int bpp, int colors, boolean mask) { int[] colorTable = new int[colors]; for (int i = 0; i < colors; i++) { colorTable[i] = getInt32LE(data, dp) | 0xFF000000; dp += 4; } int rowWidth = (((width * bpp) + 31) / 32) * 4; for (int pp = pixels.length, y = 0; y < height; y++) { pp -= width; decodeRow(data, dp, pixels, pp, width, bpp, colorTable); dp += rowWidth; } if (mask) { int maskRowWidth = ((width + 31) / 32) * 4; for (int pp = pixels.length, y = 0; y < height; y++) { pp -= width; decodeMaskRow(data, dp, pixels, pp, width); dp += maskRowWidth; } } } private static void encodeImage(byte[] data, int dp, int[] pixels, int width, int height, int bpp, int[] colorTable, boolean mask) { int adaptiveCount = 0; for (int color : colorTable) if (color == 0) adaptiveCount++; if (adaptiveCount > 0) { int[] adaptivePixels = new int[pixels.length]; for (int i = 0; i < pixels.length; i++) adaptivePixels[i] = pixels[i]; int[] adaptiveColors = ColorReducer.reduce(adaptivePixels, adaptiveCount); int adaptiveIndex = 0; int[] newColorTable = new int[colorTable.length]; for (int i = 0; i < colorTable.length; i++) { if (colorTable[i] != 0) { newColorTable[i] = colorTable[i]; } else if (adaptiveIndex < adaptiveColors.length) { newColorTable[i] = adaptiveColors[adaptiveIndex++]; } else { newColorTable[i] = -1; } } colorTable = newColorTable; } for (int color : colorTable) { putInt32LE(data, dp, (color & 0xFFFFFF)); dp += 4; } int rowWidth = (((width * bpp) + 31) / 32) * 4; for (int pp = pixels.length, y = 0; y < height; y++) { pp -= width; encodeRow(data, dp, pixels, pp, width, bpp, colorTable); dp += rowWidth; } if (mask) { int maskRowWidth = ((width + 31) / 32) * 4; for (int pp = pixels.length, y = 0; y < height; y++) { pp -= width; encodeMaskRow(data, dp, pixels, pp, width); dp += maskRowWidth; } } } private static int dataLength(int dp, int width, int height, int bpp, int colors, boolean mask) { dp += colors * 4; int rowWidth = (((width * bpp) + 31) / 32) * 4; dp += rowWidth * height; if (mask) { int maskRowWidth = ((width + 31) / 32) * 4; dp += maskRowWidth * height; } return dp; } private static void decodeRow(byte[] data, int dp, int[] pixels, int pp, int width, int bpp, int[] colorTable) { switch (bpp) { case 1: for (int x = 0; x < width;) { int b = data[dp++]; for (int s = (8-1); x < width && s >= 0; x++, s -= 1) { pixels[pp++] = colorTable[(b >> s) & 1]; } } break; case 2: for (int x = 0; x < width;) { int b = data[dp++]; for (int s = (8-2); x < width && s >= 0; x++, s -= 2) { pixels[pp++] = colorTable[(b >> s) & 3]; } } break; case 4: for (int x = 0; x < width;) { int b = data[dp++]; for (int s = (8-4); x < width && s >= 0; x++, s -= 4) { pixels[pp++] = colorTable[(b >> s) & 15]; } } break; case 8: for (int x = 0; x < width; x++, dp += 1) { int i = data[dp] & 0xFF; pixels[pp++] = colorTable[i]; } break; case 16: for (int x = 0; x < width; x++, dp += 2) { int i = getInt16LE(data, dp); int b = ((i >> 0) & 0x1F); b = (((b << 3) | (b >> 2)) << 0); int g = ((i >> 5) & 0x1F); g = (((g << 3) | (g >> 2)) << 8); int r = ((i >> 10) & 0x1F); r = (((r << 3) | (r >> 2)) << 16); int a = ((i >> 15) & 0x01); a = (( a * 0xFF ) << 24); pixels[pp++] = b | g | r | a; } break; case 24: for (int x = 0; x < width; x++, dp += 3) { int i = getInt24LE(data, dp); pixels[pp++] = i | 0xFF000000; } break; case 32: for (int x = 0; x < width; x++, dp += 4) { int i = getInt32LE(data, dp); pixels[pp++] = i; } break; } } private static void encodeRow(byte[] data, int dp, int[] pixels, int pp, int width, int bpp, int[] colorTable) { switch (bpp) { case 1: for (int x = 0; x < width;) { byte b = 0; for (int s = (8-1); x < width && s >= 0; x++, s -= 1) { b |= (closestColorIndex(colorTable, pixels[pp++]) << s); } data[dp++] = b; } break; case 2: for (int x = 0; x < width;) { byte b = 0; for (int s = (8-2); x < width && s >= 0; x++, s -= 2) { b |= (closestColorIndex(colorTable, pixels[pp++]) << s); } data[dp++] = b; } break; case 4: for (int x = 0; x < width;) { byte b = 0; for (int s = (8-4); x < width && s >= 0; x++, s -= 4) { b |= (closestColorIndex(colorTable, pixels[pp++]) << s); } data[dp++] = b; } break; case 8: for (int x = 0; x < width; x++, dp += 1) { int i = closestColorIndex(colorTable, pixels[pp++]); data[dp] = (byte)i; } break; case 16: for (int x = 0; x < width; x++, dp += 2) { int i = pixels[pp++]; int b = (((i >> 3) & 0x1F) << 0); int g = (((i >> 11) & 0x1F) << 5); int r = (((i >> 19) & 0x1F) << 10); int a = (((i >> 31) & 0x01) << 15); putInt16LE(data, dp, (b | g | r | a)); } break; case 24: for (int x = 0; x < width; x++, dp += 3) { int i = pixels[pp++]; putInt24LE(data, dp, i); } break; case 32: for (int x = 0; x < width; x++, dp += 4) { int i = pixels[pp++]; putInt32LE(data, dp, i); } break; } } private static int closestColorIndex(int[] colors, int color) { int r = (color >> 16) & 0xFF; int g = (color >> 8) & 0xFF; int b = (color >> 0) & 0xFF; int index = -1, delta = Integer.MAX_VALUE; for (int i = 0; i < colors.length; i++) { int dr = r - ((colors[i] >> 16) & 0xFF); int dg = g - ((colors[i] >> 8) & 0xFF); int db = b - ((colors[i] >> 0) & 0xFF); int d = dr * dr + dg * dg + db * db; if (d < delta) { index = i; delta = d; } } return index; } private static void decodeMaskRow(byte[] data, int dp, int[] pixels, int pp, int width) { for (int x = 0; x < width;) { int b = data[dp++]; for (int m = 0x80; x < width && m != 0; x++, m >>= 1) { if ((b & m) == 0) { pixels[pp++] |= 0xFF000000; } else { pixels[pp++] &= 0xFFFFFF; } } } } private static void encodeMaskRow(byte[] data, int dp, int[] pixels, int pp, int width) { for (int x = 0; x < width;) { byte b = 0; for (int m = 0x80; x < width && m != 0; x++, m >>= 1) { if (pixels[pp++] >= 0) { b |= m; } } data[dp++] = b; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinKey.java000066400000000000000000000054001506470510200270050ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Arrays; import java.util.Collections; import java.util.List; public final class WinKey { public static final List KEYS = Collections.unmodifiableList(Arrays.asList( new WinKey(0x02, "1", Key.NUMROW_1), new WinKey(0x03, "2", Key.NUMROW_2), new WinKey(0x04, "3", Key.NUMROW_3), new WinKey(0x05, "4", Key.NUMROW_4), new WinKey(0x06, "5", Key.NUMROW_5), new WinKey(0x07, "6", Key.NUMROW_6), new WinKey(0x08, "7", Key.NUMROW_7), new WinKey(0x09, "8", Key.NUMROW_8), new WinKey(0x0a, "9", Key.NUMROW_9), new WinKey(0x0b, "0", Key.NUMROW_0), new WinKey(0x0c, "OEM_MINUS", Key.HYPHEN_UNDERSCORE), new WinKey(0x0d, "OEM_PLUS", Key.EQUALS_PLUS), new WinKey(0x10, "Q", Key.Q), new WinKey(0x11, "W", Key.W), new WinKey(0x12, "E", Key.E), new WinKey(0x13, "R", Key.R), new WinKey(0x14, "T", Key.T), new WinKey(0x15, "Y", Key.Y), new WinKey(0x16, "U", Key.U), new WinKey(0x17, "I", Key.I), new WinKey(0x18, "O", Key.O), new WinKey(0x19, "P", Key.P), new WinKey(0x1a, "OEM_4", Key.LEFT_BRACKET), new WinKey(0x1b, "OEM_6", Key.RIGHT_BRACKET), new WinKey(0x1e, "A", Key.A), new WinKey(0x1f, "S", Key.S), new WinKey(0x20, "D", Key.D), new WinKey(0x21, "F", Key.F), new WinKey(0x22, "G", Key.G), new WinKey(0x23, "H", Key.H), new WinKey(0x24, "J", Key.J), new WinKey(0x25, "K", Key.K), new WinKey(0x26, "L", Key.L), new WinKey(0x27, "OEM_1", Key.SEMICOLON), new WinKey(0x28, "OEM_7", Key.QUOTE), new WinKey(0x29, "OEM_3", Key.GRAVE_TILDE), new WinKey(0x2b, "OEM_5", Key.BACKSLASH), new WinKey(0x2c, "Z", Key.Z), new WinKey(0x2d, "X", Key.X), new WinKey(0x2e, "C", Key.C), new WinKey(0x2f, "V", Key.V), new WinKey(0x30, "B", Key.B), new WinKey(0x31, "N", Key.N), new WinKey(0x32, "M", Key.M), new WinKey(0x33, "OEM_COMMA", Key.COMMA), new WinKey(0x34, "OEM_PERIOD", Key.PERIOD), new WinKey(0x35, "OEM_2", Key.SLASH), new WinKey(0x39, "SPACE", Key.SPACE), new WinKey(0x56, "OEM_102", Key.BACKSLASH_102), new WinKey(0x53, "DECIMAL", Key.NUMPAD_PERIOD) )); public final int scanCode; public final String vkConstant; public final Key key; private WinKey(int sc, String vk, Key key) { this.scanCode = sc; this.vkConstant = vk; this.key = key; } public static WinKey forScanCode(int sc) { for (WinKey key : KEYS) { if (key.scanCode == sc) { return key; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinLocale.java000066400000000000000000001506701506470510200274660ustar00rootroot00000000000000package com.kreative.keyedit; public enum WinLocale { AA (0x1000, "aa", "Afar"), AA_DJ (0x1000, "aa-DJ", "Afar (Djibouti)"), AA_ER (0x1000, "aa-ER", "Afar (Eritrea)"), AA_ET (0x1000, "aa-ET", "Afar (Ethiopia)"), AF (0x0036, "af", "Afrikaans"), AF_NA (0x1000, "af-NA", "Afrikaans (Namibia)"), AF_ZA (0x0436, "af-ZA", "Afrikaans (South Africa)"), AGQ (0x1000, "agq", "Aghem"), AGQ_CM (0x1000, "agq-CM", "Aghem (Cameroon)"), AK (0x1000, "ak", "Akan"), AK_GH (0x1000, "ak-GH", "Akan (Ghana)"), SQ (0x001C, "sq", "Albanian"), SQ_AL (0x041C, "sq-AL", "Albanian (Albania)"), SQ_XK (0x1000, "sq-XK", "Albanian (Kosovo)"), SQ_MK (0x1000, "sq-MK", "Albanian (Macedonia, FYRO)"), GSW (0x0084, "gsw", "Alsatian"), GSW_FR (0x0484, "gsw-FR", "Alsatian (France)"), GSW_LI (0x1000, "gsw-LI", "Alsatian (Liechtenstein)"), GSW_CH (0x1000, "gsw-CH", "Alsatian (Switzerland)"), AM (0x005E, "am", "Amharic"), AM_ET (0x045E, "am-ET", "Amharic (Ethiopia)"), AR (0x0001, "ar", "Arabic"), AR_DZ (0x1401, "ar-DZ", "Arabic (Algeria)"), AR_BH (0x3C01, "ar-BH", "Arabic (Bahrain)"), AR_TD (0x1000, "ar-TD", "Arabic (Chad)"), AR_KM (0x1000, "ar-KM", "Arabic (Comoros)"), AR_DJ (0x1000, "ar-DJ", "Arabic (Djibouti)"), AR_EG (0x0C01, "ar-EG", "Arabic (Egypt)"), AR_ER (0x1000, "ar-ER", "Arabic (Eritrea)"), AR_IQ (0x0801, "ar-IQ", "Arabic (Iraq)"), AR_IL (0x1000, "ar-IL", "Arabic (Israel)"), AR_JO (0x2C01, "ar-JO", "Arabic (Jordan)"), AR_KW (0x3401, "ar-KW", "Arabic (Kuwait)"), AR_LB (0x3001, "ar-LB", "Arabic (Lebanon)"), AR_LY (0x1001, "ar-LY", "Arabic (Libya)"), AR_MR (0x1000, "ar-MR", "Arabic (Mauritania)"), AR_MA (0x1801, "ar-MA", "Arabic (Morocco)"), AR_OM (0x2001, "ar-OM", "Arabic (Oman)"), AR_PS (0x1000, "ar-PS", "Arabic (Palestinian Authority)"), AR_QA (0x4001, "ar-QA", "Arabic (Qatar)"), AR_SA (0x0401, "ar-SA", "Arabic (Saudi Arabia)"), AR_SO (0x1000, "ar-SO", "Arabic (Somalia)"), AR_SS (0x1000, "ar-SS", "Arabic (South Sudan)"), AR_SD (0x1000, "ar-SD", "Arabic (Sudan)"), AR_SY (0x2801, "ar-SY", "Arabic (Syria)"), AR_TN (0x1C01, "ar-TN", "Arabic (Tunisia)"), AR_AE (0x3801, "ar-AE", "Arabic (U.A.E.)"), AR_001 (0x1000, "ar-001", "Arabic (World)"), AR_YE (0x2401, "ar-YE", "Arabic (Yemen)"), HY (0x002B, "hy", "Armenian"), HY_AM (0x042B, "hy-AM", "Armenian (Armenia)"), AS (0x004D, "as", "Assamese"), AS_IN (0x044D, "as-IN", "Assamese (India)"), AST (0x1000, "ast", "Asturian"), AST_ES (0x1000, "ast-ES", "Asturian (Spain)"), ASA (0x1000, "asa", "Asu"), ASA_TZ (0x1000, "asa-TZ", "Asu (Tanzania)"), AZ (0x002C, "az", "Azerbaijani"), AZ_CYRL (0x742C, "az-Cyrl", "Azerbaijani (Cyrillic)"), AZ_CYRL_AZ (0x082C, "az-Cyrl-AZ", "Azerbaijani (Cyrillic, Azerbaijan)"), AZ_LATN (0x782C, "az-Latn", "Azerbaijani (Latin)"), AZ_LATN_AZ (0x042C, "az-Latn-AZ", "Azerbaijani (Latin, Azerbaijan)"), KSF (0x1000, "ksf", "Bafia"), KSF_CM (0x1000, "ksf-CM", "Bafia (Cameroon)"), BM (0x1000, "bm", "Bambara"), BM_LATN (0x1000, "bm-Latn", "Bambara (Latin)"), BM_LATN_ML (0x1000, "bm-Latn-ML", "Bambara (Latin, Mali)"), BN (0x0045, "bn", "Bangla"), BN_BD (0x0845, "bn-BD", "Bangla (Bangladesh)"), BN_IN (0x0445, "bn-IN", "Bangla (India)"), BAS (0x1000, "bas", "Basaa"), BAS_CM (0x1000, "bas-CM", "Basaa (Cameroon)"), BA (0x006D, "ba", "Bashkir"), BA_RU (0x046D, "ba-RU", "Bashkir (Russia)"), EU (0x002D, "eu", "Basque"), EU_ES (0x042D, "eu-ES", "Basque (Basque)"), BE (0x0023, "be", "Belarusian"), BE_BY (0x0423, "be-BY", "Belarusian (Belarus)"), BEM (0x1000, "bem", "Bemba"), BEM_ZM (0x1000, "bem-ZM", "Bemba (Zambia)"), BEZ (0x1000, "bez", "Bena"), BEZ_TZ (0x1000, "bez-TZ", "Bena (Tanzania)"), BYN (0x1000, "byn", "Blin"), BYN_ER (0x1000, "byn-ER", "Blin (Eritrea)"), BRX (0x1000, "brx", "Bodo"), BRX_IN (0x1000, "brx-IN", "Bodo (India)"), BS (0x781A, "bs", "Bosnian"), BS_CYRL (0x641A, "bs-Cyrl", "Bosnian (Cyrillic)"), BS_CYRL_BA (0x201A, "bs-Cyrl-BA", "Bosnian (Cyrillic, Bosnia and Herzegovina)"), BS_LATN (0x681A, "bs-Latn", "Bosnian (Latin)"), BS_LATN_BA (0x141A, "bs-Latn-BA", "Bosnian (Latin, Bosnia and Herzegovina)"), BR (0x007E, "br", "Breton"), BR_FR (0x047E, "br-FR", "Breton (France)"), BG (0x0002, "bg", "Bulgarian"), BG_BG (0x0402, "bg-BG", "Bulgarian (Bulgaria)"), MY (0x0055, "my", "Burmese"), MY_MM (0x0455, "my-MM", "Burmese (Myanmar)"), CA (0x0003, "ca", "Catalan"), CA_AD (0x1000, "ca-AD", "Catalan (Andorra)"), CA_ES (0x0403, "ca-ES", "Catalan (Catalan)"), CA_FR (0x1000, "ca-FR", "Catalan (France)"), CA_IT (0x1000, "ca-IT", "Catalan (Italy)"), TZM_ARAB (0x1000, "tzm-Arab", "Central Atlas Tamazight (Arabic)"), TZM_ARAB_MA (0x045F, "tzm-Arab-MA", "Central Atlas Tamazight (Arabic, Morocco)"), TZM_LATN_MA (0x1000, "tzm-Latn-MA", "Central Atlas Tamazight (Latin, Morocco)"), TZM_TFNG_MA (0x105F, "tzm-Tfng-MA", "Central Atlas Tamazight (Tifinagh, Morocco)"), KU (0x0092, "ku", "Central Kurdish"), KU_ARAB (0x7C92, "ku-Arab", "Central Kurdish (Arabic)"), KU_ARAB_IQ (0x0492, "ku-Arab-IQ", "Central Kurdish (Iraq)"), CE (0x1000, "ce", "Chechen"), CE_RU (0x1000, "ce-RU", "Chechen (Russia)"), CHR (0x005C, "chr", "Cherokee"), CHR_CHER (0x7C5C, "chr-Cher", "Cherokee (Cherokee)"), CHR_CHER_US (0x045C, "chr-Cher-US", "Cherokee (Cherokee, United States)"), CGG (0x1000, "cgg", "Chiga"), CGG_UG (0x1000, "cgg-UG", "Chiga (Uganda)"), ZH (0x7804, "zh", "Chinese"), ZH_HANS_HK (0x1000, "zh-Hans-HK", "Chinese (Simplified Han, Hong Kong SAR)"), ZH_HANS_MO (0x1000, "zh-Hans-MO", "Chinese (Simplified Han, Macao SAR)"), ZH_HANS (0x0004, "zh-Hans", "Chinese (Simplified)"), ZH_CN (0x0804, "zh-CN", "Chinese (Simplified, PRC)"), ZH_SG (0x1004, "zh-SG", "Chinese (Simplified, Singapore)"), ZH_HANT (0x7C04, "zh-Hant", "Chinese (Traditional)"), ZH_HK (0x0C04, "zh-HK", "Chinese (Traditional, Hong Kong S.A.R.)"), ZH_MO (0x1404, "zh-MO", "Chinese (Traditional, Macao S.A.R.)"), ZH_TW (0x0404, "zh-TW", "Chinese (Traditional, Taiwan)"), CU (0x1000, "cu", "Church Slavic"), CU_RU (0x1000, "cu-RU", "Church Slavic (Russia)"), KSH (0x1000, "ksh", "Colognian"), KW (0x1000, "kw", "Cornish"), KW_GB (0x1000, "kw-GB", "Cornish (United Kingdom)"), CO (0x0083, "co", "Corsican"), CO_FR (0x0483, "co-FR", "Corsican (France)"), HR (0x001A, "hr", "Croatian"), HR_HR (0x041A, "hr-HR", "Croatian (Croatia)"), HR_BA (0x101A, "hr-BA", "Croatian (Latin, Bosnia and Herzegovina)"), CS (0x0005, "cs", "Czech"), CS_CZ (0x0405, "cs-CZ", "Czech (Czech Republic)"), DA (0x0006, "da", "Danish"), DA_DK (0x0406, "da-DK", "Danish (Denmark)"), DA_GL (0x1000, "da-GL", "Danish (Greenland)"), PRS (0x008C, "prs", "Dari"), PRS_AF (0x048C, "prs-AF", "Dari (Afghanistan)"), DV (0x0065, "dv", "Divehi"), DV_MV (0x0465, "dv-MV", "Divehi (Maldives)"), DUA (0x1000, "dua", "Duala"), DUA_CM (0x1000, "dua-CM", "Duala (Cameroon)"), NL (0x0013, "nl", "Dutch"), NL_AW (0x1000, "nl-AW", "Dutch (Aruba)"), NL_BE (0x0813, "nl-BE", "Dutch (Belgium)"), NL_BQ (0x1000, "nl-BQ", "Dutch (Bonaire, Sint Eustatius and Saba)"), NL_CW (0x1000, "nl-CW", "Dutch (Curaçao)"), NL_NL (0x0413, "nl-NL", "Dutch (Netherlands)"), NL_SX (0x1000, "nl-SX", "Dutch (Sint Maarten)"), NL_SR (0x1000, "nl-SR", "Dutch (Suriname)"), DZ (0x1000, "dz", "Dzongkha"), DZ_BT (0x0C51, "dz-BT", "Dzongkha (Bhutan)"), BIN (0x0066, "bin", "Edo"), BIN_NG (0x0466, "bin-NG", "Edo (Nigeria)"), EBU (0x1000, "ebu", "Embu"), EBU_KE (0x1000, "ebu-KE", "Embu (Kenya)"), EN (0x0009, "en", "English"), EN_AS (0x1000, "en-AS", "English (American Samoa)"), EN_AI (0x1000, "en-AI", "English (Anguilla)"), EN_AG (0x1000, "en-AG", "English (Antigua and Barbuda)"), EN_AU (0x0C09, "en-AU", "English (Australia)"), EN_AT (0x1000, "en-AT", "English (Austria)"), EN_BS (0x1000, "en-BS", "English (Bahamas)"), EN_BB (0x1000, "en-BB", "English (Barbados)"), EN_BE (0x1000, "en-BE", "English (Belgium)"), EN_BZ (0x2809, "en-BZ", "English (Belize)"), EN_BM (0x1000, "en-BM", "English (Bermuda)"), EN_BW (0x1000, "en-BW", "English (Botswana)"), EN_IO (0x1000, "en-IO", "English (British Indian Ocean Territory)"), EN_VG (0x1000, "en-VG", "English (British Virgin Islands)"), EN_BI (0x1000, "en-BI", "English (Burundi)"), EN_CM (0x1000, "en-CM", "English (Cameroon)"), EN_CA (0x1009, "en-CA", "English (Canada)"), EN_029 (0x2409, "en-029", "English (Caribbean)"), EN_KY (0x1000, "en-KY", "English (Cayman Islands)"), EN_CX (0x1000, "en-CX", "English (Christmas Island)"), EN_CC (0x1000, "en-CC", "English (Cocos [Keeling] Islands)"), EN_CK (0x1000, "en-CK", "English (Cook Islands)"), EN_CY (0x1000, "en-CY", "English (Cyprus)"), EN_DK (0x1000, "en-DK", "English (Denmark)"), EN_DM (0x1000, "en-DM", "English (Dominica)"), EN_ER (0x1000, "en-ER", "English (Eritrea)"), EN_150 (0x1000, "en-150", "English (Europe)"), EN_FK (0x1000, "en-FK", "English (Falkland Islands)"), EN_FJ (0x1000, "en-FJ", "English (Fiji)"), EN_FI (0x1000, "en-FI", "English (Finland)"), EN_GM (0x1000, "en-GM", "English (Gambia)"), EN_DE (0x1000, "en-DE", "English (Germany)"), EN_GH (0x1000, "en-GH", "English (Ghana)"), EN_GI (0x1000, "en-GI", "English (Gibraltar)"), EN_GD (0x1000, "en-GD", "English (Grenada)"), EN_GU (0x1000, "en-GU", "English (Guam)"), EN_GG (0x1000, "en-GG", "English (Guernsey)"), EN_GY (0x1000, "en-GY", "English (Guyana)"), EN_HK (0x3C09, "en-HK", "English (Hong Kong SAR)"), EN_IN (0x4009, "en-IN", "English (India)"), EN_ID (0x3809, "en-ID", "English (Indonesia)"), EN_IE (0x1809, "en-IE", "English (Ireland)"), EN_IM (0x1000, "en-IM", "English (Isle of Man)"), EN_IL (0x1000, "en-IL", "English (Israel)"), EN_JM (0x2009, "en-JM", "English (Jamaica)"), EN_JE (0x1000, "en-JE", "English (Jersey)"), EN_KE (0x1000, "en-KE", "English (Kenya)"), EN_KI (0x1000, "en-KI", "English (Kiribati)"), EN_LS (0x1000, "en-LS", "English (Lesotho)"), EN_LR (0x1000, "en-LR", "English (Liberia)"), EN_MO (0x1000, "en-MO", "English (Macao SAR)"), EN_MG (0x1000, "en-MG", "English (Madagascar)"), EN_MW (0x1000, "en-MW", "English (Malawi)"), EN_MY (0x4409, "en-MY", "English (Malaysia)"), EN_MT (0x1000, "en-MT", "English (Malta)"), EN_MH (0x1000, "en-MH", "English (Marshall Islands)"), EN_MU (0x1000, "en-MU", "English (Mauritius)"), EN_FM (0x1000, "en-FM", "English (Micronesia)"), EN_MS (0x1000, "en-MS", "English (Montserrat)"), EN_NA (0x1000, "en-NA", "English (Namibia)"), EN_NR (0x1000, "en-NR", "English (Nauru)"), EN_NL (0x1000, "en-NL", "English (Netherlands)"), EN_NZ (0x1409, "en-NZ", "English (New Zealand)"), EN_NG (0x1000, "en-NG", "English (Nigeria)"), EN_NU (0x1000, "en-NU", "English (Niue)"), EN_NF (0x1000, "en-NF", "English (Norfolk Island)"), EN_MP (0x1000, "en-MP", "English (Northern Mariana Islands)"), EN_PK (0x1000, "en-PK", "English (Pakistan)"), EN_PW (0x1000, "en-PW", "English (Palau)"), EN_PG (0x1000, "en-PG", "English (Papua New Guinea)"), EN_PH (0x3409, "en-PH", "English (Philippines)"), EN_PN (0x1000, "en-PN", "English (Pitcairn Islands)"), EN_PR (0x1000, "en-PR", "English (Puerto Rico)"), EN_RW (0x1000, "en-RW", "English (Rwanda)"), EN_KN (0x1000, "en-KN", "English (Saint Kitts and Nevis)"), EN_LC (0x1000, "en-LC", "English (Saint Lucia)"), EN_VC (0x1000, "en-VC", "English (Saint Vincent and the Grenadines)"), EN_WS (0x1000, "en-WS", "English (Samoa)"), EN_SC (0x1000, "en-SC", "English (Seychelles)"), EN_SL (0x1000, "en-SL", "English (Sierra Leone)"), EN_SG (0x4809, "en-SG", "English (Singapore)"), EN_SX (0x1000, "en-SX", "English (Sint Maarten)"), EN_SI (0x1000, "en-SI", "English (Slovenia)"), EN_SB (0x1000, "en-SB", "English (Solomon Islands)"), EN_ZA (0x1C09, "en-ZA", "English (South Africa)"), EN_SS (0x1000, "en-SS", "English (South Sudan)"), EN_SH (0x1000, "en-SH", "English (St Helena, Ascension, Tristan da Cunha)"), EN_SD (0x1000, "en-SD", "English (Sudan)"), EN_SZ (0x1000, "en-SZ", "English (Swaziland)"), EN_SE (0x1000, "en-SE", "English (Sweden)"), EN_CH (0x1000, "en-CH", "English (Switzerland)"), EN_TZ (0x1000, "en-TZ", "English (Tanzania)"), EN_TK (0x1000, "en-TK", "English (Tokelau)"), EN_TO (0x1000, "en-TO", "English (Tonga)"), EN_TT (0x2C09, "en-TT", "English (Trinidad and Tobago)"), EN_TC (0x1000, "en-TC", "English (Turks and Caicos Islands)"), EN_TV (0x1000, "en-TV", "English (Tuvalu)"), EN_UG (0x1000, "en-UG", "English (Uganda)"), EN_GB (0x0809, "en-GB", "English (United Kingdom)"), EN_US (0x0409, "en-US", "English (United States)"), EN_UM (0x1000, "en-UM", "English (US Minor Outlying Islands)"), EN_VI (0x1000, "en-VI", "English (US Virgin Islands)"), EN_VU (0x1000, "en-VU", "English (Vanuatu)"), EN_001 (0x1000, "en-001", "English (World)"), EN_ZM (0x1000, "en-ZM", "English (Zambia)"), EN_ZW (0x3009, "en-ZW", "English (Zimbabwe)"), EO (0x1000, "eo", "Esperanto"), EO_001 (0x1000, "eo-001", "Esperanto (World)"), ET (0x0025, "et", "Estonian"), ET_EE (0x0425, "et-EE", "Estonian (Estonia)"), EE (0x1000, "ee", "Ewe"), EE_GH (0x1000, "ee-GH", "Ewe (Ghana)"), EE_TG (0x1000, "ee-TG", "Ewe (Togo)"), EWO (0x1000, "ewo", "Ewondo"), EWO_CM (0x1000, "ewo-CM", "Ewondo (Cameroon)"), FO (0x0038, "fo", "Faroese"), FO_DK (0x1000, "fo-DK", "Faroese (Denmark)"), FO_FO (0x0438, "fo-FO", "Faroese (Faroe Islands)"), FIL (0x0064, "fil", "Filipino"), FIL_PH (0x0464, "fil-PH", "Filipino (Philippines)"), FI (0x000B, "fi", "Finnish"), FI_FI (0x040B, "fi-FI", "Finnish (Finland)"), FR (0x000C, "fr", "French"), FR_DZ (0x1000, "fr-DZ", "French (Algeria)"), FR_BE (0x080C, "fr-BE", "French (Belgium)"), FR_BJ (0x1000, "fr-BJ", "French (Benin)"), FR_BF (0x1000, "fr-BF", "French (Burkina Faso)"), FR_BI (0x1000, "fr-BI", "French (Burundi)"), FR_CM (0x2C0C, "fr-CM", "French (Cameroon)"), FR_CA (0x0C0C, "fr-CA", "French (Canada)"), FR_029 (0x1C0C, "fr-029", "French (Caribbean)"), FR_CF (0x1000, "fr-CF", "French (Central African Republic)"), FR_TD (0x1000, "fr-TD", "French (Chad)"), FR_KM (0x1000, "fr-KM", "French (Comoros)"), FR_CD (0x240C, "fr-CD", "French (Congo DRC)"), FR_CG (0x1000, "fr-CG", "French (Congo)"), FR_CI (0x300C, "fr-CI", "French (Côte d’Ivoire)"), FR_DJ (0x1000, "fr-DJ", "French (Djibouti)"), FR_GQ (0x1000, "fr-GQ", "French (Equatorial Guinea)"), FR_FR (0x040C, "fr-FR", "French (France)"), FR_GF (0x1000, "fr-GF", "French (French Guiana)"), FR_PF (0x1000, "fr-PF", "French (French Polynesia)"), FR_GA (0x1000, "fr-GA", "French (Gabon)"), FR_GP (0x1000, "fr-GP", "French (Guadeloupe)"), FR_GN (0x1000, "fr-GN", "French (Guinea)"), FR_HT (0x3C0C, "fr-HT", "French (Haiti)"), FR_LU (0x140C, "fr-LU", "French (Luxembourg)"), FR_MG (0x1000, "fr-MG", "French (Madagascar)"), FR_ML (0x340C, "fr-ML", "French (Mali)"), FR_MQ (0x1000, "fr-MQ", "French (Martinique)"), FR_MR (0x1000, "fr-MR", "French (Mauritania)"), FR_MU (0x1000, "fr-MU", "French (Mauritius)"), FR_YT (0x1000, "fr-YT", "French (Mayotte)"), FR_MC (0x180C, "fr-MC", "French (Monaco)"), FR_MA (0x380C, "fr-MA", "French (Morocco)"), FR_NC (0x1000, "fr-NC", "French (New Caledonia)"), FR_NE (0x1000, "fr-NE", "French (Niger)"), FR_RE (0x200C, "fr-RE", "French (Reunion)"), FR_RW (0x1000, "fr-RW", "French (Rwanda)"), FR_BL (0x1000, "fr-BL", "French (Saint Barthélemy)"), FR_MF (0x1000, "fr-MF", "French (Saint Martin)"), FR_PM (0x1000, "fr-PM", "French (Saint Pierre and Miquelon)"), FR_SN (0x280C, "fr-SN", "French (Senegal)"), FR_SC (0x1000, "fr-SC", "French (Seychelles)"), FR_CH (0x100C, "fr-CH", "French (Switzerland)"), FR_SY (0x1000, "fr-SY", "French (Syria)"), FR_TG (0x1000, "fr-TG", "French (Togo)"), FR_TN (0x1000, "fr-TN", "French (Tunisia)"), FR_VU (0x1000, "fr-VU", "French (Vanuatu)"), FR_WF (0x1000, "fr-WF", "French (Wallis and Futuna)"), FY (0x0062, "fy", "Frisian"), FY_NL (0x0462, "fy-NL", "Frisian (Netherlands)"), FUR (0x1000, "fur", "Friulian"), FUR_IT (0x1000, "fur-IT", "Friulian (Italy)"), FF (0x0067, "ff", "Fulah"), FF_CM (0x1000, "ff-CM", "Fulah (Cameroon)"), FF_GN (0x1000, "ff-GN", "Fulah (Guinea)"), FF_LATN (0x7C67, "ff-Latn", "Fulah (Latin)"), FF_LATN_SN (0x0867, "ff-Latn-SN", "Fulah (Latin, Senegal)"), FF_MR (0x1000, "ff-MR", "Fulah (Mauritania)"), FF_NG (0x0467, "ff-NG", "Fulah (Nigeria)"), GL (0x0056, "gl", "Galician"), GL_ES (0x0456, "gl-ES", "Galician (Galician)"), LG (0x1000, "lg", "Ganda"), LG_UG (0x1000, "lg-UG", "Ganda (Uganda)"), KA (0x0037, "ka", "Georgian"), KA_GE (0x0437, "ka-GE", "Georgian (Georgia)"), DE (0x0007, "de", "German"), DE_AT (0x0C07, "de-AT", "German (Austria)"), DE_BE (0x1000, "de-BE", "German (Belgium)"), DE_DE (0x0407, "de-DE", "German (Germany)"), DE_IT (0x1000, "de-IT", "German (Italy)"), DE_LI (0x1407, "de-LI", "German (Liechtenstein)"), DE_LU (0x1007, "de-LU", "German (Luxembourg)"), DE_CH (0x0807, "de-CH", "German (Switzerland)"), EL (0x0008, "el", "Greek"), EL_CY (0x1000, "el-CY", "Greek (Cyprus)"), EL_GR (0x0408, "el-GR", "Greek (Greece)"), KL (0x006F, "kl", "Greenlandic"), KL_GL (0x046F, "kl-GL", "Greenlandic (Greenland)"), GN (0x0074, "gn", "Guarani"), GN_PY (0x0474, "gn-PY", "Guarani (Paraguay)"), GU (0x0047, "gu", "Gujarati"), GU_IN (0x0447, "gu-IN", "Gujarati (India)"), GUZ (0x1000, "guz", "Gusii"), GUZ_KE (0x1000, "guz-KE", "Gusii (Kenya)"), HA (0x0068, "ha", "Hausa"), HA_LATN (0x7C68, "ha-Latn", "Hausa (Latin)"), HA_LATN_GH (0x1000, "ha-Latn-GH", "Hausa (Latin, Ghana)"), HA_LATN_NE (0x1000, "ha-Latn-NE", "Hausa (Latin, Niger)"), HA_LATN_NG (0x0468, "ha-Latn-NG", "Hausa (Latin, Nigeria)"), HAW (0x0075, "haw", "Hawaiian"), HAW_US (0x0475, "haw-US", "Hawaiian (United States)"), HE (0x000D, "he", "Hebrew"), HE_IL (0x040D, "he-IL", "Hebrew (Israel)"), HI (0x0039, "hi", "Hindi"), HI_IN (0x0439, "hi-IN", "Hindi (India)"), HU (0x000E, "hu", "Hungarian"), HU_HU (0x040E, "hu-HU", "Hungarian (Hungary)"), IBB (0x0069, "ibb", "Ibibio"), IBB_NG (0x0469, "ibb-NG", "Ibibio (Nigeria)"), IS (0x000F, "is", "Icelandic"), IS_IS (0x040F, "is-IS", "Icelandic (Iceland)"), IG (0x0070, "ig", "Igbo"), IG_NG (0x0470, "ig-NG", "Igbo (Nigeria)"), ID (0x0021, "id", "Indonesian"), ID_ID (0x0421, "id-ID", "Indonesian (Indonesia)"), IA (0x1000, "ia", "Interlingua"), IA_FR (0x1000, "ia-FR", "Interlingua (France)"), IA_001 (0x1000, "ia-001", "Interlingua (World)"), IU (0x005D, "iu", "Inuktitut"), IU_LATN (0x7C5D, "iu-Latn", "Inuktitut (Latin)"), IU_LATN_CA (0x085D, "iu-Latn-CA", "Inuktitut (Latin, Canada)"), IU_CANS (0x785D, "iu-Cans", "Inuktitut (Syllabics)"), IU_CANS_CA (0x045D, "iu-Cans-CA", "Inuktitut (Syllabics, Canada)"), GA (0x003C, "ga", "Irish"), GA_IE (0x083C, "ga-IE", "Irish (Ireland)"), IT (0x0010, "it", "Italian"), IT_IT (0x0410, "it-IT", "Italian (Italy)"), IT_SM (0x1000, "it-SM", "Italian (San Marino)"), IT_CH (0x0810, "it-CH", "Italian (Switzerland)"), IT_VA (0x1000, "it-VA", "Italian (Vatican City)"), JA (0x0011, "ja", "Japanese"), JA_JP (0x0411, "ja-JP", "Japanese (Japan)"), JV (0x1000, "jv", "Javanese"), JV_JAVA (0x1000, "jv-Java", "Javanese (Javanese)"), JV_JAVA_ID (0x1000, "jv-Java-ID", "Javanese (Javanese, Indonesia)"), JV_LATN (0x1000, "jv-Latn", "Javanese (Latin)"), JV_LATN_ID (0x1000, "jv-Latn-ID", "Javanese (Latin, Indonesia)"), DYO (0x1000, "dyo", "Jola-Fonyi"), DYO_SN (0x1000, "dyo-SN", "Jola-Fonyi (Senegal)"), KEA (0x1000, "kea", "Kabuverdianu"), KEA_CV (0x1000, "kea-CV", "Kabuverdianu (Cabo Verde)"), KAB (0x1000, "kab", "Kabyle"), KAB_DZ (0x1000, "kab-DZ", "Kabyle (Algeria)"), KKJ (0x1000, "kkj", "Kako"), KKJ_CM (0x1000, "kkj-CM", "Kako (Cameroon)"), KLN (0x1000, "kln", "Kalenjin"), KLN_KE (0x1000, "kln-KE", "Kalenjin (Kenya)"), KAM (0x1000, "kam", "Kamba"), KAM_KE (0x1000, "kam-KE", "Kamba (Kenya)"), KN (0x004B, "kn", "Kannada"), KN_IN (0x044B, "kn-IN", "Kannada (India)"), KR (0x0071, "kr", "Kanuri"), KR_NG (0x0471, "kr-NG", "Kanuri (Nigeria)"), KS (0x0060, "ks", "Kashmiri"), KS_DEVA (0x1000, "ks-Deva", "Kashmiri (Devanagari)"), KS_DEVA_IN (0x0860, "ks-Deva-IN", "Kashmiri (Devanagari, India)"), KS_ARAB (0x0460, "ks-Arab", "Kashmiri (Perso-Arabic)"), KS_ARAB_IN (0x1000, "ks-Arab-IN", "Kashmiri (Perso-Arabic, India)"), KK (0x003F, "kk", "Kazakh"), KK_KZ (0x043F, "kk-KZ", "Kazakh (Kazakhstan)"), KM (0x0053, "km", "Khmer"), KM_KH (0x0453, "km-KH", "Khmer (Cambodia)"), KI (0x1000, "ki", "Kikuyu"), KI_KE (0x1000, "ki-KE", "Kikuyu (Kenya)"), RW (0x0087, "rw", "Kinyarwanda"), RW_RW (0x0487, "rw-RW", "Kinyarwanda (Rwanda)"), SW (0x0041, "sw", "Kiswahili"), SW_CD (0x1000, "sw-CD", "Kiswahili (Congo DRC)"), SW_KE (0x0441, "sw-KE", "Kiswahili (Kenya)"), SW_TZ (0x1000, "sw-TZ", "Kiswahili (Tanzania)"), SW_UG (0x1000, "sw-UG", "Kiswahili (Uganda)"), KOK (0x0057, "kok", "Konkani"), KOK_IN (0x0457, "kok-IN", "Konkani (India)"), KO (0x0012, "ko", "Korean"), KO_KR (0x0412, "ko-KR", "Korean (Korea)"), KO_KP (0x1000, "ko-KP", "Korean (North Korea)"), KHQ (0x1000, "khq", "Koyra Chiini"), KHQ_ML (0x1000, "khq-ML", "Koyra Chiini (Mali)"), SES (0x1000, "ses", "Koyraboro Senni"), SES_ML (0x1000, "ses-ML", "Koyraboro Senni (Mali)"), KU_ARAB_IR (0x1000, "ku-Arab-IR", "Kurdish (Perso-Arabic, Iran)"), NMG (0x1000, "nmg", "Kwasio"), NMG_CM (0x1000, "nmg-CM", "Kwasio (Cameroon)"), KY (0x0040, "ky", "Kyrgyz"), KY_KG (0x0440, "ky-KG", "Kyrgyz (Kyrgyzstan)"), QUC (0x0086, "quc", "K’iche’"), QUC_LATN (0x7C86, "quc-Latn", "K’iche’ (Latin)"), QUC_LATN_GT (0x0486, "quc-Latn-GT", "K’iche’ (Latin, Guatemala)"), LKT (0x1000, "lkt", "Lakota"), LKT_US (0x1000, "lkt-US", "Lakota (United States)"), LAG (0x1000, "lag", "Langi"), LAG_TZ (0x1000, "lag-TZ", "Langi (Tanzania)"), LO (0x0054, "lo", "Lao"), LO_LA (0x0454, "lo-LA", "Lao (Lao P.D.R.)"), LA (0x0076, "la", "Latin"), LA_001 (0x0476, "la-001", "Latin (World)"), LV (0x0026, "lv", "Latvian"), LV_LV (0x0426, "lv-LV", "Latvian (Latvia)"), LN (0x1000, "ln", "Lingala"), LN_AO (0x1000, "ln-AO", "Lingala (Angola)"), LN_CF (0x1000, "ln-CF", "Lingala (Central African Republic)"), LN_CD (0x1000, "ln-CD", "Lingala (Congo DRC)"), LN_CG (0x1000, "ln-CG", "Lingala (Congo)"), LT (0x0027, "lt", "Lithuanian"), LT_LT (0x0427, "lt-LT", "Lithuanian (Lithuania)"), NDS (0x1000, "nds", "Low German"), NDS_DE (0x1000, "nds-DE", "Low German (Germany)"), NDS_NL (0x1000, "nds-NL", "Low German (Netherlands)"), DSB (0x7C2E, "dsb", "Lower Sorbian"), DSB_DE (0x082E, "dsb-DE", "Lower Sorbian (Germany)"), LU (0x1000, "lu", "Luba-Katanga"), LU_CD (0x1000, "lu-CD", "Luba-Katanga (Congo DRC)"), LUO (0x1000, "luo", "Luo"), LUO_KE (0x1000, "luo-KE", "Luo (Kenya)"), LB (0x006E, "lb", "Luxembourgish"), LB_LU (0x046E, "lb-LU", "Luxembourgish (Luxembourg)"), LUY (0x1000, "luy", "Luyia"), LUY_KE (0x1000, "luy-KE", "Luyia (Kenya)"), MK_MK (0x042F, "mk-MK", "Macedonian (Former Yugoslav Republic of Macedonia)"), MK (0x002F, "mk", "Macedonian (FYROM)"), JMC (0x1000, "jmc", "Machame"), JMC_TZ (0x1000, "jmc-TZ", "Machame (Tanzania)"), MGH (0x1000, "mgh", "Makhuwa-Meetto"), MGH_MZ (0x1000, "mgh-MZ", "Makhuwa-Meetto (Mozambique)"), KDE (0x1000, "kde", "Makonde"), KDE_TZ (0x1000, "kde-TZ", "Makonde (Tanzania)"), MG (0x1000, "mg", "Malagasy"), MG_MG (0x1000, "mg-MG", "Malagasy (Madagascar)"), MS (0x003E, "ms", "Malay"), MS_BN (0x083E, "ms-BN", "Malay (Brunei Darussalam)"), MS_SG (0x1000, "ms-SG", "Malay (Latin, Singapore)"), MS_MY (0x043E, "ms-MY", "Malay (Malaysia)"), ML (0x004C, "ml", "Malayalam"), ML_IN (0x044C, "ml-IN", "Malayalam (India)"), MT (0x003A, "mt", "Maltese"), MT_MT (0x043A, "mt-MT", "Maltese (Malta)"), MNI (0x0058, "mni", "Manipuri"), MNI_IN (0x0458, "mni-IN", "Manipuri (India)"), GV (0x1000, "gv", "Manx"), GV_IM (0x1000, "gv-IM", "Manx (Isle of Man)"), MI (0x0081, "mi", "Maori"), MI_NZ (0x0481, "mi-NZ", "Maori (New Zealand)"), ARN (0x007A, "arn", "Mapudungun"), ARN_CL (0x047A, "arn-CL", "Mapudungun (Chile)"), MR (0x004E, "mr", "Marathi"), MR_IN (0x044E, "mr-IN", "Marathi (India)"), MAS (0x1000, "mas", "Masai"), MAS_KE (0x1000, "mas-KE", "Masai (Kenya)"), MAS_TZ (0x1000, "mas-TZ", "Masai (Tanzania)"), MZN (0x1000, "mzn", "Mazanderani"), MZN_IR (0x1000, "mzn-IR", "Mazanderani (Iran)"), MER (0x1000, "mer", "Meru"), MER_KE (0x1000, "mer-KE", "Meru (Kenya)"), MGO (0x1000, "mgo", "Meta’"), MGO_CM (0x1000, "mgo-CM", "Meta’ (Cameroon)"), MOH (0x007C, "moh", "Mohawk"), MOH_CA (0x047C, "moh-CA", "Mohawk (Mohawk)"), MN (0x0050, "mn", "Mongolian"), MN_CYRL (0x7850, "mn-Cyrl", "Mongolian (Cyrillic)"), MN_MN (0x0450, "mn-MN", "Mongolian (Cyrillic, Mongolia)"), MN_MONG (0x7C50, "mn-Mong", "Mongolian (Traditional Mongolian)"), MN_MONG_MN (0x0C50, "mn-Mong-MN", "Mongolian (Traditional Mongolian, Mongolia)"), MN_MONG_CN (0x0850, "mn-Mong-CN", "Mongolian (Traditional Mongolian, PRC)"), MFE (0x1000, "mfe", "Morisyen"), MFE_MU (0x1000, "mfe-MU", "Morisyen (Mauritius)"), MUA (0x1000, "mua", "Mundang"), MUA_CM (0x1000, "mua-CM", "Mundang (Cameroon)"), NAQ (0x1000, "naq", "Nama"), NAQ_NA (0x1000, "naq-NA", "Nama (Namibia)"), NE (0x0061, "ne", "Nepali"), NE_IN (0x0861, "ne-IN", "Nepali (India)"), NE_NP (0x0461, "ne-NP", "Nepali (Nepal)"), NNH (0x1000, "nnh", "Ngiemboon"), NNH_CM (0x1000, "nnh-CM", "Ngiemboon (Cameroon)"), JGO (0x1000, "jgo", "Ngomba"), JGO_CM (0x1000, "jgo-CM", "Ngomba (Cameroon)"), ND (0x1000, "nd", "North Ndebele"), ND_ZW (0x1000, "nd-ZW", "North Ndebele (Zimbabwe)"), LRC (0x1000, "lrc", "Northern Luri"), LRC_IR (0x1000, "lrc-IR", "Northern Luri (Iran)"), LRC_IQ (0x1000, "lrc-IQ", "Northern Luri (Iraq)"), NO (0x0014, "no", "Norwegian"), NB (0x7C14, "nb", "Norwegian (Bokmål)"), NN (0x7814, "nn", "Norwegian (Nynorsk)"), NB_NO (0x0414, "nb-NO", "Norwegian, Bokmål (Norway)"), NB_SJ (0x1000, "nb-SJ", "Norwegian, Bokmål (Svalbard and Jan Mayen)"), NN_NO (0x0814, "nn-NO", "Norwegian, Nynorsk (Norway)"), NUS (0x1000, "nus", "Nuer"), NUS_SS (0x1000, "nus-SS", "Nuer (South Sudan)"), NYN (0x1000, "nyn", "Nyankole"), NYN_UG (0x1000, "nyn-UG", "Nyankole (Uganda)"), NQO (0x1000, "nqo", "N’ko"), NQO_GN (0x1000, "nqo-GN", "N’ko (Guinea)"), OC (0x0082, "oc", "Occitan"), OC_FR (0x0482, "oc-FR", "Occitan (France)"), OR (0x0048, "or", "Odia"), OR_IN (0x0448, "or-IN", "Odia (India)"), OM (0x0072, "om", "Oromo"), OM_ET (0x0472, "om-ET", "Oromo (Ethiopia)"), OM_KE (0x1000, "om-KE", "Oromo (Kenya)"), OS_GE (0x1000, "os-GE", "Ossetian (Cyrillic, Georgia)"), OS_RU (0x1000, "os-RU", "Ossetian (Cyrillic, Russia)"), OS (0x1000, "os", "Ossetic"), PAP (0x0079, "pap", "Papiamento"), PAP_029 (0x0479, "pap-029", "Papiamento (Caribbean)"), PS (0x0063, "ps", "Pashto"), PS_AF (0x0463, "ps-AF", "Pashto (Afghanistan)"), FA (0x0029, "fa", "Persian"), FA_IR (0x0429, "fa-IR", "Persian (Iran)"), PL (0x0015, "pl", "Polish"), PL_PL (0x0415, "pl-PL", "Polish (Poland)"), PT (0x0016, "pt", "Portuguese"), PT_AO (0x1000, "pt-AO", "Portuguese (Angola)"), PT_BR (0x0416, "pt-BR", "Portuguese (Brazil)"), PT_CV (0x1000, "pt-CV", "Portuguese (Cabo Verde)"), PT_GQ (0x1000, "pt-GQ", "Portuguese (Equatorial Guinea)"), PT_GW (0x1000, "pt-GW", "Portuguese (Guinea-Bissau)"), PT_LU (0x1000, "pt-LU", "Portuguese (Luxembourg)"), PT_MO (0x1000, "pt-MO", "Portuguese (Macao SAR)"), PT_MZ (0x1000, "pt-MZ", "Portuguese (Mozambique)"), PT_PT (0x0816, "pt-PT", "Portuguese (Portugal)"), PT_CH (0x1000, "pt-CH", "Portuguese (Switzerland)"), PT_ST (0x1000, "pt-ST", "Portuguese (São Tomé and Príncipe)"), PT_TL (0x1000, "pt-TL", "Portuguese (Timor-Leste)"), PRG (0x1000, "prg", "Prussian"), PRG_001 (0x1000, "prg-001", "Prussian (World)"), PA (0x0046, "pa", "Punjabi"), PA_ARAB (0x7C46, "pa-Arab", "Punjabi (Arabic)"), PA_IN (0x0446, "pa-IN", "Punjabi (India)"), PA_ARAB_PK (0x0846, "pa-Arab-PK", "Punjabi (Islamic Republic of Pakistan)"), QUZ (0x006B, "quz", "Quechua"), QUZ_BO (0x046B, "quz-BO", "Quechua (Bolivia)"), QUZ_EC (0x086B, "quz-EC", "Quechua (Ecuador)"), QUZ_PE (0x0C6B, "quz-PE", "Quechua (Peru)"), KSH_DE (0x1000, "ksh-DE", "Ripuarian (Germany)"), RO (0x0018, "ro", "Romanian"), RO_MD (0x0818, "ro-MD", "Romanian (Moldova)"), RO_RO (0x0418, "ro-RO", "Romanian (Romania)"), RM (0x0017, "rm", "Romansh"), RM_CH (0x0417, "rm-CH", "Romansh (Switzerland)"), ROF (0x1000, "rof", "Rombo"), ROF_TZ (0x1000, "rof-TZ", "Rombo (Tanzania)"), RN (0x1000, "rn", "Rundi"), RN_BI (0x1000, "rn-BI", "Rundi (Burundi)"), RU (0x0019, "ru", "Russian"), RU_BY (0x1000, "ru-BY", "Russian (Belarus)"), RU_KZ (0x1000, "ru-KZ", "Russian (Kazakhstan)"), RU_KG (0x1000, "ru-KG", "Russian (Kyrgyzstan)"), RU_MD (0x0819, "ru-MD", "Russian (Moldova)"), RU_RU (0x0419, "ru-RU", "Russian (Russia)"), RU_UA (0x1000, "ru-UA", "Russian (Ukraine)"), RWK (0x1000, "rwk", "Rwa"), RWK_TZ (0x1000, "rwk-TZ", "Rwa (Tanzania)"), SSY (0x1000, "ssy", "Saho"), SSY_ER (0x1000, "ssy-ER", "Saho (Eritrea)"), SAH (0x0085, "sah", "Sakha"), SAH_RU (0x0485, "sah-RU", "Sakha (Russia)"), SAQ (0x1000, "saq", "Samburu"), SAQ_KE (0x1000, "saq-KE", "Samburu (Kenya)"), SMN (0x703B, "smn", "Sami (Inari)"), SMJ (0x7C3B, "smj", "Sami (Lule)"), SE (0x003B, "se", "Sami (Northern)"), SMS (0x743B, "sms", "Sami (Skolt)"), SMA (0x783B, "sma", "Sami (Southern)"), SMN_FI (0x243B, "smn-FI", "Sami, Inari (Finland)"), SMJ_NO (0x103B, "smj-NO", "Sami, Lule (Norway)"), SMJ_SE (0x143B, "smj-SE", "Sami, Lule (Sweden)"), SE_FI (0x0C3B, "se-FI", "Sami, Northern (Finland)"), SE_NO (0x043B, "se-NO", "Sami, Northern (Norway)"), SE_SE (0x083B, "se-SE", "Sami, Northern (Sweden)"), SMS_FI (0x203B, "sms-FI", "Sami, Skolt (Finland)"), SMA_NO (0x183B, "sma-NO", "Sami, Southern (Norway)"), SMA_SE (0x1C3B, "sma-SE", "Sami, Southern (Sweden)"), SG (0x1000, "sg", "Sango"), SG_CF (0x1000, "sg-CF", "Sango (Central African Republic)"), SBP (0x1000, "sbp", "Sangu"), SBP_TZ (0x1000, "sbp-TZ", "Sangu (Tanzania)"), SA (0x004F, "sa", "Sanskrit"), SA_IN (0x044F, "sa-IN", "Sanskrit (India)"), GD (0x0091, "gd", "Scottish Gaelic"), GD_GB (0x0491, "gd-GB", "Scottish Gaelic (United Kingdom)"), SEH (0x1000, "seh", "Sena"), SEH_MZ (0x1000, "seh-MZ", "Sena (Mozambique)"), SR (0x7C1A, "sr", "Serbian"), SR_CYRL (0x6C1A, "sr-Cyrl", "Serbian (Cyrillic)"), SR_CYRL_BA (0x1C1A, "sr-Cyrl-BA", "Serbian (Cyrillic, Bosnia and Herzegovina)"), SR_CYRL_XK (0x1000, "sr-Cyrl-XK", "Serbian (Cyrillic, Kosovo)"), SR_CYRL_ME (0x301A, "sr-Cyrl-ME", "Serbian (Cyrillic, Montenegro)"), SR_CYRL_RS (0x281A, "sr-Cyrl-RS", "Serbian (Cyrillic, Serbia)"), SR_LATN (0x701A, "sr-Latn", "Serbian (Latin)"), SR_LATN_BA (0x181A, "sr-Latn-BA", "Serbian (Latin, Bosnia and Herzegovina)"), SR_LATN_XK (0x1000, "sr-Latn-XK", "Serbian (Latin, Kosovo)"), SR_LATN_ME (0x2C1A, "sr-Latn-ME", "Serbian (Latin, Montenegro)"), SR_LATN_RS (0x241A, "sr-Latn-RS", "Serbian (Latin, Serbia)"), ST_LS (0x1000, "st-LS", "Sesotho (Lesotho)"), NSO (0x006C, "nso", "Sesotho sa Leboa"), NSO_ZA (0x046C, "nso-ZA", "Sesotho sa Leboa (South Africa)"), TN (0x0032, "tn", "Setswana"), TN_BW (0x0832, "tn-BW", "Setswana (Botswana)"), TN_ZA (0x0432, "tn-ZA", "Setswana (South Africa)"), KSB (0x1000, "ksb", "Shambala"), KSB_TZ (0x1000, "ksb-TZ", "Shambala (Tanzania)"), SN (0x1000, "sn", "Shona"), SN_LATN (0x1000, "sn-Latn", "Shona (Latin)"), SN_LATN_ZW (0x1000, "sn-Latn-ZW", "Shona (Latin, Zimbabwe)"), SD (0x0059, "sd", "Sindhi"), SD_ARAB (0x7C59, "sd-Arab", "Sindhi (Arabic)"), SD_DEVA (0x1000, "sd-Deva", "Sindhi (Devanagari)"), SD_DEVA_IN (0x0459, "sd-Deva-IN", "Sindhi (Devanagari, India)"), SD_ARAB_PK (0x0859, "sd-Arab-PK", "Sindhi (Islamic Republic of Pakistan)"), SI (0x005B, "si", "Sinhala"), SI_LK (0x045B, "si-LK", "Sinhala (Sri Lanka)"), SK (0x001B, "sk", "Slovak"), SK_SK (0x041B, "sk-SK", "Slovak (Slovakia)"), SL (0x0024, "sl", "Slovenian"), SL_SI (0x0424, "sl-SI", "Slovenian (Slovenia)"), XOG (0x1000, "xog", "Soga"), XOG_UG (0x1000, "xog-UG", "Soga (Uganda)"), SO (0x0077, "so", "Somali"), SO_DJ (0x1000, "so-DJ", "Somali (Djibouti)"), SO_ET (0x1000, "so-ET", "Somali (Ethiopia)"), SO_KE (0x1000, "so-KE", "Somali (Kenya)"), SO_SO (0x0477, "so-SO", "Somali (Somalia)"), NR (0x1000, "nr", "South Ndebele"), NR_ZA (0x1000, "nr-ZA", "South Ndebele (South Africa)"), ST (0x0030, "st", "Southern Sotho"), ST_ZA (0x0430, "st-ZA", "Southern Sotho (South Africa)"), ES (0x000A, "es", "Spanish"), ES_AR (0x2C0A, "es-AR", "Spanish (Argentina)"), ES_BZ (0x1000, "es-BZ", "Spanish (Belize)"), ES_BO (0x400A, "es-BO", "Spanish (Bolivia)"), ES_BR (0x1000, "es-BR", "Spanish (Brazil)"), ES_CL (0x340A, "es-CL", "Spanish (Chile)"), ES_CO (0x240A, "es-CO", "Spanish (Colombia)"), ES_CR (0x140A, "es-CR", "Spanish (Costa Rica)"), ES_CU (0x5C0A, "es-CU", "Spanish (Cuba)"), ES_DO (0x1C0A, "es-DO", "Spanish (Dominican Republic)"), ES_EC (0x300A, "es-EC", "Spanish (Ecuador)"), ES_SV (0x440A, "es-SV", "Spanish (El Salvador)"), ES_GQ (0x1000, "es-GQ", "Spanish (Equatorial Guinea)"), ES_GT (0x100A, "es-GT", "Spanish (Guatemala)"), ES_HN (0x480A, "es-HN", "Spanish (Honduras)"), ES_419 (0x580A, "es-419", "Spanish (Latin America)"), ES_MX (0x080A, "es-MX", "Spanish (Mexico)"), ES_NI (0x4C0A, "es-NI", "Spanish (Nicaragua)"), ES_PA (0x180A, "es-PA", "Spanish (Panama)"), ES_PY (0x3C0A, "es-PY", "Spanish (Paraguay)"), ES_PE (0x280A, "es-PE", "Spanish (Peru)"), ES_PH (0x1000, "es-PH", "Spanish (Philippines)"), ES_PR (0x500A, "es-PR", "Spanish (Puerto Rico)"), ES_ES (0x0C0A, "es-ES", "Spanish (Spain)"), ES_US (0x540A, "es-US", "Spanish (United States)"), ES_UY (0x380A, "es-UY", "Spanish (Uruguay)"), ES_VE (0x200A, "es-VE", "Spanish (Venezuela)"), ZGH (0x1000, "zgh", "Standard Moroccan Tamazight"), ZGH_TFNG (0x1000, "zgh-Tfng", "Standard Moroccan Tamazight (Tifinagh)"), ZGH_TFNG_MA (0x1000, "zgh-Tfng-MA", "Standard Moroccan Tamazight (Tifinagh, Morocco)"), SS (0x1000, "ss", "Swati"), SS_ZA (0x1000, "ss-ZA", "Swati (South Africa)"), SS_SZ (0x1000, "ss-SZ", "Swati (Swaziland)"), SV (0x001D, "sv", "Swedish"), SV_FI (0x081D, "sv-FI", "Swedish (Finland)"), SV_SE (0x041D, "sv-SE", "Swedish (Sweden)"), SV_AX (0x1000, "sv-AX", "Swedish (Åland Islands)"), SYR (0x005A, "syr", "Syriac"), SYR_SY (0x045A, "syr-SY", "Syriac (Syria)"), SHI (0x1000, "shi", "Tachelhit"), SHI_LATN (0x1000, "shi-Latn", "Tachelhit (Latin)"), SHI_LATN_MA (0x1000, "shi-Latn-MA", "Tachelhit (Latin, Morocco)"), SHI_TFNG (0x1000, "shi-Tfng", "Tachelhit (Tifinagh)"), SHI_TFNG_MA (0x1000, "shi-Tfng-MA", "Tachelhit (Tifinagh, Morocco)"), DAV (0x1000, "dav", "Taita"), DAV_KE (0x1000, "dav-KE", "Taita (Kenya)"), TG (0x0028, "tg", "Tajik"), TG_CYRL (0x7C28, "tg-Cyrl", "Tajik (Cyrillic)"), TG_CYRL_TJ (0x0428, "tg-Cyrl-TJ", "Tajik (Cyrillic, Tajikistan)"), TZM (0x005F, "tzm", "Tamazight"), TZM_LATN (0x7C5F, "tzm-Latn", "Tamazight (Latin)"), TZM_LATN_DZ (0x085F, "tzm-Latn-DZ", "Tamazight (Latin, Algeria)"), TZM_TFNG (0x785F, "tzm-Tfng", "Tamazight (Tifinagh)"), TA (0x0049, "ta", "Tamil"), TA_IN (0x0449, "ta-IN", "Tamil (India)"), TA_MY (0x1000, "ta-MY", "Tamil (Malaysia)"), TA_SG (0x1000, "ta-SG", "Tamil (Singapore)"), TA_LK (0x0849, "ta-LK", "Tamil (Sri Lanka)"), TWQ (0x1000, "twq", "Tasawaq"), TWQ_NE (0x1000, "twq-NE", "Tasawaq (Niger)"), TT (0x0044, "tt", "Tatar"), TT_RU (0x0444, "tt-RU", "Tatar (Russia)"), TE (0x004A, "te", "Telugu"), TE_IN (0x044A, "te-IN", "Telugu (India)"), TEO (0x1000, "teo", "Teso"), TEO_KE (0x1000, "teo-KE", "Teso (Kenya)"), TEO_UG (0x1000, "teo-UG", "Teso (Uganda)"), TH (0x001E, "th", "Thai"), TH_TH (0x041E, "th-TH", "Thai (Thailand)"), BO (0x0051, "bo", "Tibetan"), BO_IN (0x1000, "bo-IN", "Tibetan (India)"), BO_CN (0x0451, "bo-CN", "Tibetan (PRC)"), TIG (0x1000, "tig", "Tigre"), TIG_ER (0x1000, "tig-ER", "Tigre (Eritrea)"), TI (0x0073, "ti", "Tigrinya"), TI_ER (0x0873, "ti-ER", "Tigrinya (Eritrea)"), TI_ET (0x0473, "ti-ET", "Tigrinya (Ethiopia)"), TO (0x1000, "to", "Tongan"), TO_TO (0x1000, "to-TO", "Tongan (Tonga)"), TS (0x0031, "ts", "Tsonga"), TS_ZA (0x0431, "ts-ZA", "Tsonga (South Africa)"), TR (0x001F, "tr", "Turkish"), TR_CY (0x1000, "tr-CY", "Turkish (Cyprus)"), TR_TR (0x041F, "tr-TR", "Turkish (Turkey)"), TK (0x0042, "tk", "Turkmen"), TK_TM (0x0442, "tk-TM", "Turkmen (Turkmenistan)"), UK (0x0022, "uk", "Ukrainian"), UK_UA (0x0422, "uk-UA", "Ukrainian (Ukraine)"), HSB (0x002E, "hsb", "Upper Sorbian"), HSB_DE (0x042E, "hsb-DE", "Upper Sorbian (Germany)"), UR (0x0020, "ur", "Urdu"), UR_IN (0x0820, "ur-IN", "Urdu (India)"), UR_PK (0x0420, "ur-PK", "Urdu (Islamic Republic of Pakistan)"), UG (0x0080, "ug", "Uyghur"), UG_CN (0x0480, "ug-CN", "Uyghur (PRC)"), UZ (0x0043, "uz", "Uzbek"), UZ_CYRL (0x7843, "uz-Cyrl", "Uzbek (Cyrillic)"), UZ_CYRL_UZ (0x0843, "uz-Cyrl-UZ", "Uzbek (Cyrillic, Uzbekistan)"), UZ_LATN (0x7C43, "uz-Latn", "Uzbek (Latin)"), UZ_LATN_UZ (0x0443, "uz-Latn-UZ", "Uzbek (Latin, Uzbekistan)"), UZ_ARAB (0x1000, "uz-Arab", "Uzbek (Perso-Arabic)"), UZ_ARAB_AF (0x1000, "uz-Arab-AF", "Uzbek (Perso-Arabic, Afghanistan)"), VAI (0x1000, "vai", "Vai"), VAI_LATN (0x1000, "vai-Latn", "Vai (Latin)"), VAI_LATN_LR (0x1000, "vai-Latn-LR", "Vai (Latin, Liberia)"), VAI_VAII (0x1000, "vai-Vaii", "Vai (Vai)"), VAI_VAII_LR (0x1000, "vai-Vaii-LR", "Vai (Vai, Liberia)"), CA_ES_VALENCIA(0x0803, "ca-ES-valencia", "Valencian (Spain)"), VE (0x0033, "ve", "Venda"), VE_ZA (0x0433, "ve-ZA", "Venda (South Africa)"), VI (0x002A, "vi", "Vietnamese"), VI_VN (0x042A, "vi-VN", "Vietnamese (Vietnam)"), VO (0x1000, "vo", "Volapük"), VO_001 (0x1000, "vo-001", "Volapük (World)"), VUN (0x1000, "vun", "Vunjo"), VUN_TZ (0x1000, "vun-TZ", "Vunjo (Tanzania)"), WAE (0x1000, "wae", "Walser"), WAE_CH (0x1000, "wae-CH", "Walser (Switzerland)"), CY (0x0052, "cy", "Welsh"), CY_GB (0x0452, "cy-GB", "Welsh (United Kingdom)"), WAL (0x1000, "wal", "Wolaytta"), WAL_ET (0x1000, "wal-ET", "Wolaytta (Ethiopia)"), WO (0x0088, "wo", "Wolof"), WO_SN (0x0488, "wo-SN", "Wolof (Senegal)"), XH (0x0034, "xh", "Xhosa"), XH_ZA (0x0434, "xh-ZA", "Xhosa (South Africa)"), YAV (0x1000, "yav", "Yangben"), YAV_CM (0x1000, "yav-CM", "Yangben (Cameroon)"), II (0x0078, "ii", "Yi"), II_CN (0x0478, "ii-CN", "Yi (PRC)"), YI (0x003D, "yi", "Yiddish"), YI_001 (0x043D, "yi-001", "Yiddish (World)"), YO (0x006A, "yo", "Yoruba"), YO_BJ (0x1000, "yo-BJ", "Yoruba (Benin)"), YO_NG (0x046A, "yo-NG", "Yoruba (Nigeria)"), DJE (0x1000, "dje", "Zarma"), DJE_NE (0x1000, "dje-NE", "Zarma (Niger)"), ZU (0x0035, "zu", "Zulu"), ZU_ZA (0x0435, "zu-ZA", "Zulu (South Africa)"); public final int lcid; public final String tag; public final String name; private WinLocale(int lcid, String tag, String name) { this.lcid = lcid; this.tag = tag; this.name = name; } public static WinLocale forTag(String tag, WinLocale def) { for (WinLocale locale : values()) { if (locale.tag.equalsIgnoreCase(tag)) { return locale; } } return def; } public static WinLocale forName(String name, WinLocale def) { for (WinLocale locale : values()) { if (locale.name.equalsIgnoreCase(name)) { return locale; } } return def; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinReader.java000066400000000000000000000110501506470510200274550ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class WinReader { public static KeyboardMapping read(File file) throws IOException { KeyboardMapping km = new KeyboardMapping(); read(file, km); return km; } public static void read(File in, KeyboardMapping km) throws IOException { Scanner scan = new Scanner(new FileInputStream(in), "UTF-16LE"); read(scan, km); scan.close(); } public static void read(Scanner in, KeyboardMapping km) { Map deadKeys = new HashMap(); boolean inLayout = false; DeadKeyTable inDeadKey = null; km.winAltGrEnable = false; km.winShiftLock = false; km.winLrmRlm = false; while (in.hasNextLine()) { String line = in.nextLine().trim(); int o = line.indexOf("//"); if (o >= 0) line = line.substring(0, o).trim(); if (line.length() == 0) continue; String[] fields = line.split("\t+"); String cmd = fields[0].trim(); if (cmd.equals("\uFEFFKBD") || cmd.equals("KBD")) { if (fields.length > 1) km.winIdentifier = fields[1].trim(); if (fields.length > 2) km.name = sq(fields[2].trim()); } else if (cmd.equals("COPYRIGHT")) { if (fields.length > 1) km.winCopyright = sq(fields[1].trim()); } else if (cmd.equals("COMPANY")) { if (fields.length > 1) km.winCompany = sq(fields[1].trim()); } else if (cmd.equals("LOCALENAME")) { if (fields.length > 1) km.winLocale = WinLocale.forTag(sq(fields[1].trim()), km.winLocale); } else if (cmd.equals("ALTGR")) { km.winAltGrEnable = true; } else if (cmd.equals("SHIFTLOCK")) { km.winShiftLock = true; } else if (cmd.equals("LRM_RLM")) { km.winLrmRlm = true; } else if (cmd.equals("LAYOUT")) { inLayout = true; inDeadKey = null; } else if (cmd.equals("DEADKEY")) { inLayout = false; inDeadKey = (fields.length > 1) ? deadKeys.get(parseCP(fields[1].trim())) : null; } else if (cmd.equals("KEYNAME")) { inLayout = false; inDeadKey = null; } else if (inLayout) { WinKey k = WinKey.forScanCode(parseHex(cmd)); if (k != null) { KeyMapping m = km.map.get(k.key); if (fields.length > 2) { int caps = parseHex(fields[2].trim()); m.capsLockMapping = ((caps & 1) == 0) ? CapsLockMapping.UNSHIFTED : CapsLockMapping.SHIFTED; m.altCapsLockMapping = ((caps & 4) == 0) ? CapsLockMapping.UNSHIFTED : CapsLockMapping.SHIFTED; } if (fields.length > 3) new ParseCPDK(fields[3].trim(), deadKeys).onUnshifted(m); if (fields.length > 4) new ParseCPDK(fields[4].trim(), deadKeys).onShifted(m); if (fields.length > 5) new ParseCPDK(fields[5].trim(), deadKeys).onCtrl(m); if (fields.length > 6) new ParseCPDK(fields[6].trim(), deadKeys).onAltUnshifted(m); if (fields.length > 7) new ParseCPDK(fields[7].trim(), deadKeys).onAltShifted(m); } } else if (inDeadKey != null) { int cp1 = (fields.length > 0) ? parseCP(fields[0].trim()) : -1; int cp2 = (fields.length > 1) ? parseCP(fields[1].trim()) : -1; if (cp1 > 0 && cp2 > 0) inDeadKey.keyMap.put(cp1, cp2); } } } private static String sq(String s) { if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) { return s.substring(1, s.length() - 1); } else { return s; } } private static int parseCP(String s) { if (s == null) return -1; if (s.length() == 0) return -1; if (s.length() == 1) return s.charAt(0); return parseHex(s); } private static int parseHex(String s) { try { return Integer.parseInt(s, 16); } catch (NumberFormatException nfe) { return -1; } } private static class ParseCPDK { private int output = -1; private DeadKeyTable deadKey = null; public ParseCPDK(String s, Map dk) { if (s.endsWith("@")) { s = s.substring(0, s.length()-1).trim(); output = parseCP(s); deadKey = new DeadKeyTable(output); dk.put(output, deadKey); } else { output = parseCP(s); deadKey = null; } } public void onUnshifted(KeyMapping m) { m.unshiftedOutput = output; m.unshiftedDeadKey = deadKey; } public void onShifted(KeyMapping m) { m.shiftedOutput = output; m.shiftedDeadKey = deadKey; } public void onCtrl(KeyMapping m) { m.ctrlOutput = output; m.ctrlDeadKey = deadKey; } public void onAltUnshifted(KeyMapping m) { m.altUnshiftedOutput = output; m.altUnshiftedDeadKey = deadKey; } public void onAltShifted(KeyMapping m) { m.altShiftedOutput = output; m.altShiftedDeadKey = deadKey; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/WinWriter.java000066400000000000000000000207261506470510200275410ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Map; import com.kreative.unicode.data.NameResolver; public class WinWriter { private static final String NONBMP_WARNING = "WARNING: Supplemental characters are assigned to altgr or dead keys.\nThese won't work natively on Windows. A third-party input method must be used."; public static void write(File file, KeyboardMapping km) throws IOException { if (!km.isWindowsNativeCompatible()) System.err.println(NONBMP_WARNING); FileOutputStream fos = new FileOutputStream(file); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-16LE"), true); write(pw, km); pw.flush(); pw.close(); fos.close(); if (!(km.winAttachments == null || km.winAttachments.isEmpty())) { File parentFile = file.getParentFile(); for (Map.Entry e : km.winAttachments.entrySet()) { fos = new FileOutputStream(new File(parentFile, e.getKey())); fos.write(e.getValue()); fos.flush(); fos.close(); } } } public static void write(PrintWriter out, KeyboardMapping km) { out.print("\uFEFF"); out.print("KBD\t" + km.getWinIdentifierNotEmpty() + "\t\"" + km.getNameNotEmpty() + "\"\r\n\r\n"); out.print("COPYRIGHT\t\"" + km.getWinCopyrightNotEmpty() + "\"\r\n\r\n"); out.print("COMPANY\t\"" + km.getWinCompanyNotEmpty() + "\"\r\n\r\n"); out.print("LOCALENAME\t\"" + km.getWinLocaleNotNull().tag + "\"\r\n\r\n"); out.print("LOCALEID\t\"" + hex(km.getWinLocaleNotNull().lcid,8) + "\"\r\n\r\n"); out.print("VERSION\t1.0\r\n\r\n"); if (km.winAltGrEnable || km.winShiftLock || km.winLrmRlm) { out.print("ATTRIBUTES\r\n"); if (km.winAltGrEnable) out.print("ALTGR\r\n"); if (km.winShiftLock) out.print("SHIFTLOCK\r\n"); if (km.winLrmRlm) out.print("LRM_RLM\r\n"); out.print("\r\n"); } out.print("SHIFTSTATE\r\n"); out.print("\r\n"); out.print("0\t//Column 4\r\n"); out.print("1\t//Column 5 : Shft\r\n"); out.print("2\t//Column 6 : Ctrl\r\n"); out.print("6\t//Column 7 : Ctrl Alt\r\n"); out.print("7\t//Column 8 : Shft Ctrl Alt\r\n"); out.print("\r\n"); out.print("LAYOUT\t\t;an extra '@' at the end is a dead key\r\n"); out.print("\r\n"); out.print("//SC\tVK_\t\tCap\t0\t1\t2\t6\t7\r\n"); out.print("//--\t----\t\t----\t----\t----\t----\t----\t----\r\n"); out.print("\r\n"); Map deadKeys = new LinkedHashMap(); for (WinKey k : WinKey.KEYS) { KeyMapping m = km.map.get(k.key); int u = getCP(m.unshiftedOutput, m.unshiftedDeadKey); int s = getCP(m.shiftedOutput, m.shiftedDeadKey); int c = getCP(m.ctrlOutput, m.ctrlDeadKey); int au = getCP(m.altUnshiftedOutput, m.altUnshiftedDeadKey); int as = getCP(m.altShiftedOutput, m.altShiftedDeadKey); int caps = 0; if (capsLockShifted(m.capsLockMapping, u, s )) caps |= 1; if (capsLockShifted(m.altCapsLockMapping, au, as)) caps |= 4; if (!(c == 0x1B || c == 0x1C || c == 0x1D || c == 0x20)) c = -1; out.print(hex(k.scanCode,2) + "\t"); out.print(k.vkConstant + ((k.vkConstant.length() >= 6) ? "\t" : "\t\t")); out.print(caps + "\t"); out.print(cpString(u, m.unshiftedDeadKey) + "\t"); out.print(cpString(s, m.shiftedDeadKey) + "\t"); out.print(cpString(c, m.ctrlDeadKey) + "\t"); out.print(cpString(au, m.altUnshiftedDeadKey) + "\t"); out.print(cpString(as, m.altShiftedDeadKey) + "\t"); out.print("\t// "); out.print(uniString(u) + ", "); out.print(uniString(s) + ", "); out.print(uniString(c) + ", "); out.print(uniString(au) + ", "); out.print(uniString(as) + "\r\n"); if (u > 0 && m.unshiftedDeadKey != null) deadKeys.put(u, m.unshiftedDeadKey); if (s > 0 && m.shiftedDeadKey != null) deadKeys.put(s, m.shiftedDeadKey); if (c > 0 && m.ctrlDeadKey != null) deadKeys.put(c, m.ctrlDeadKey); if (au > 0 && m.altUnshiftedDeadKey != null) deadKeys.put(au, m.altUnshiftedDeadKey); if (as > 0 && m.altShiftedDeadKey != null) deadKeys.put(as, m.altShiftedDeadKey); } if (!deadKeys.isEmpty()) { out.print("\r\n"); for (Map.Entry e : deadKeys.entrySet()) { out.print("\r\n"); out.print("DEADKEY\t" + cpString(e.getKey(), null) + "\r\n"); out.print("\r\n"); for (Map.Entry ee : e.getValue().keyMap.entrySet()) { out.print(hex(ee.getKey(),4) + "\t"); out.print(hex(ee.getValue(),4) + "\t"); out.print("// "); out.print(Character.toChars(ee.getKey())); out.print(" -> "); out.print(Character.toChars(ee.getValue())); out.print("\r\n"); } } } out.print("\r\n"); out.print("\r\n"); out.print("KEYNAME\r\n"); out.print("\r\n"); for (String s : KEYNAME) out.print(s); out.print("\r\n"); out.print("KEYNAME_EXT\r\n"); out.print("\r\n"); for (String s : KEYNAME_EXT) out.print(s); if (!deadKeys.isEmpty()) { out.print("\r\n"); out.print("KEYNAME_DEAD\r\n"); out.print("\r\n"); for (Map.Entry e : deadKeys.entrySet()) { out.print(cpString(e.getKey(), null) + "\t"); out.print("\"" + uniString(e.getKey()) + "\""); out.print("\r\n"); } out.print("\r\n"); } out.print("\r\n"); out.print("DESCRIPTIONS\r\n"); out.print("\r\n"); out.print(hex(km.getWinLocaleNotNull().lcid,4) + "\t" + km.getNameNotEmpty() + "\r\n"); out.print("\r\n"); out.print("LANGUAGENAMES\r\n"); out.print("\r\n"); out.print(hex(km.getWinLocaleNotNull().lcid,4) + "\t" + km.getWinLocaleNotNull().name + "\r\n"); out.print("\r\n"); out.print("ENDKBD\r\n"); } private static String hex(int v, int n) { String h = Integer.toHexString(v); while (h.length() < n) h = "0" + h; return h; } private static int getCP(int output, DeadKeyTable dead) { if (dead != null) { if (dead.winTerminator > 0) { return dead.winTerminator; } } if (output > 0) { return output; } return -1; } private static boolean isCasePair(int u, int s) { return (u != s) && (Character.toUpperCase(u) == s || Character.toLowerCase(s) == u); } private static boolean capsLockShifted(CapsLockMapping m, int u, int s) { if (m == CapsLockMapping.UNSHIFTED) return false; if (m == CapsLockMapping.SHIFTED) return true; return isCasePair(u, s); } private static String cpString(int cp, DeadKeyTable dead) { if (cp <= 0) return "-1"; String h; if (cp >= '0' && cp <= '9') h = Character.toString((char)cp); else if (cp >= 'A' && cp <= 'Z') h = Character.toString((char)cp); else if (cp >= 'a' && cp <= 'z') h = Character.toString((char)cp); else h = hex(cp,4); if (dead != null) h += "@"; return h; } private static String uniString(int cp) { if (cp <= 0) return ""; if (cp >= 0xE000 && cp < 0xF900) return "Private Use"; if (cp >= 0xF0000) return "Private Use"; return NameResolver.instance().getName(cp); } private static final String[] KEYNAME = { "01\tEsc\r\n", "0e\tBackspace\r\n", "0f\tTab\r\n", "1c\tEnter\r\n", "1d\tCtrl\r\n", "2a\tShift\r\n", "36\t\"Right Shift\"\r\n", "37\t\"Num *\"\r\n", "38\tAlt\r\n", "39\tSpace\r\n", "3a\t\"Caps Lock\"\r\n", "3b\tF1\r\n", "3c\tF2\r\n", "3d\tF3\r\n", "3e\tF4\r\n", "3f\tF5\r\n", "40\tF6\r\n", "41\tF7\r\n", "42\tF8\r\n", "43\tF9\r\n", "44\tF10\r\n", "45\tPause\r\n", "46\t\"Scroll Lock\"\r\n", "47\t\"Num 7\"\r\n", "48\t\"Num 8\"\r\n", "49\t\"Num 9\"\r\n", "4a\t\"Num -\"\r\n", "4b\t\"Num 4\"\r\n", "4c\t\"Num 5\"\r\n", "4d\t\"Num 6\"\r\n", "4e\t\"Num +\"\r\n", "4f\t\"Num 1\"\r\n", "50\t\"Num 2\"\r\n", "51\t\"Num 3\"\r\n", "52\t\"Num 0\"\r\n", "53\t\"Num Del\"\r\n", "54\t\"Sys Req\"\r\n", "57\tF11\r\n", "58\tF12\r\n", "7c\tF13\r\n", "7d\tF14\r\n", "7e\tF15\r\n", "7f\tF16\r\n", "80\tF17\r\n", "81\tF18\r\n", "82\tF19\r\n", "83\tF20\r\n", "84\tF21\r\n", "85\tF22\r\n", "86\tF23\r\n", "87\tF24\r\n", }; private static final String[] KEYNAME_EXT = { "1c\t\"Num Enter\"\r\n", "1d\t\"Right Ctrl\"\r\n", "35\t\"Num /\"\r\n", "37\t\"Prnt Scrn\"\r\n", "38\t\"Right Alt\"\r\n", "45\t\"Num Lock\"\r\n", "46\tBreak\r\n", "47\tHome\r\n", "48\tUp\r\n", "49\t\"Page Up\"\r\n", "4b\tLeft\r\n", "4d\tRight\r\n", "4f\tEnd\r\n", "50\tDown\r\n", "51\t\"Page Down\"\r\n", "52\tInsert\r\n", "53\tDelete\r\n", "54\t<00>\r\n", "56\tHelp\r\n", "5b\t\"Left Windows\"\r\n", "5c\t\"Right Windows\"\r\n", "5d\tApplication\r\n", }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbAltGrKey.java000066400000000000000000000013571506470510200277350ustar00rootroot00000000000000package com.kreative.keyedit; public enum XkbAltGrKey { none("None"), alt_switch("Either Alt"), lalt_switch("Left Alt"), ralt_switch("Right Alt"), win_switch("Either Windows"), lwin_switch("Left Windows"), rwin_switch("Right Windows"), menu_switch("Menu"), caps_switch("Caps Lock"), bksl_switch("Backslash"), lsgt_switch("Less/Greater"), enter_switch("Keypad Enter"); private final String label; private XkbAltGrKey(String label) { this.label = label; } public String toString() { return this.label; } public static XkbAltGrKey forInclude(String s) { if (s != null) { for (XkbAltGrKey key : values()) { if (s.equalsIgnoreCase("level3(" + key.name() + ")")) { return key; } } } return none; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbComposeKey.java000066400000000000000000000012271506470510200303250ustar00rootroot00000000000000package com.kreative.keyedit; public enum XkbComposeKey { none("None"), ralt("Right Alt"), lctrl("Left Control"), rctrl("Right Control"), lwin("Left Windows"), rwin("Right Windows"), menu("Menu"), caps("Caps Lock"), paus("Pause"), prsc("Print Screen"), sclk("Scroll Lock"); private final String label; private XkbComposeKey(String label) { this.label = label; } public String toString() { return this.label; } public static XkbComposeKey forInclude(String s) { if (s != null) { for (XkbComposeKey key : values()) { if (s.equalsIgnoreCase("compose(" + key.name() + ")")) { return key; } } } return none; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbCopy.java000066400000000000000000000023541506470510200271630ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class XkbCopy { public static void main(String[] args) { List files = new ArrayList(); boolean useKeySym = false; boolean parsingOptions = true; for (String arg : args) { if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) parsingOptions = false; else if (arg.equals("-k")) useKeySym = true; else if (arg.equals("-u")) useKeySym = false; else System.err.println("Invalid option: " + arg); } else { files.add(new File(arg)); } } if (files.size() < 2) { System.out.println("Usage: XkbCopy [-k|-u] "); System.out.println(" -k Output keysym constants for non-ASCII characters."); System.out.println(" -u Output keysym constants for ASCII characters only."); } else { File output = files.remove(files.size() - 1); for (File input : files) { try { KeyboardMapping km = XkbReader.read(input); km.xkbUseKeySym = useKeySym; XkbWriter.write(output, km); } catch (IOException e) { System.err.println("Failed copying " + input.getName() + ": " + e.getMessage()); } } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbDeadKey.java000066400000000000000000000116221506470510200275550ustar00rootroot00000000000000package com.kreative.keyedit; public enum XkbDeadKey { none, dead_grave, dead_acute, dead_circumflex, dead_tilde, dead_macron, dead_breve, dead_abovedot, dead_diaeresis, dead_abovering, dead_doubleacute, dead_caron, dead_cedilla, dead_ogonek, dead_iota, dead_voiced_sound, dead_semivoiced_sound, dead_belowdot, dead_hook, dead_horn, dead_stroke, dead_abovecomma, dead_abovereversedcomma, dead_doublegrave, dead_belowring, dead_belowmacron, dead_belowcircumflex, dead_belowtilde, dead_belowbreve, dead_belowdiaeresis, dead_invertedbreve, dead_belowcomma, dead_currency, dead_a, dead_A, dead_e, dead_E, dead_i, dead_I, dead_o, dead_O, dead_u, dead_U, dead_small_schwa, dead_capital_schwa, dead_greek, dead_lowline, dead_aboveverticalline, dead_belowverticalline, dead_longsolidusoverlay; public static XkbDeadKey forUnicode(int u) { switch (u) { case 0x0022: return dead_diaeresis; case 0x0024: return dead_currency; case 0x0027: return dead_abovedot; case 0x002F: return dead_stroke; case 0x0041: return dead_A; case 0x0045: return dead_E; case 0x0049: return dead_I; case 0x004F: return dead_O; case 0x0055: return dead_U; case 0x005E: return dead_circumflex; case 0x005F: return dead_lowline; case 0x0060: return dead_grave; case 0x0061: return dead_a; case 0x0065: return dead_e; case 0x0069: return dead_i; case 0x006F: return dead_o; case 0x0075: return dead_u; case 0x007E: return dead_tilde; case 0x00A2: return dead_currency; case 0x00A3: return dead_currency; case 0x00A4: return dead_currency; case 0x00A5: return dead_currency; case 0x00A8: return dead_diaeresis; case 0x00AF: return dead_macron; case 0x00B0: return dead_abovering; case 0x00B4: return dead_acute; case 0x00B8: return dead_cedilla; case 0x018F: return dead_capital_schwa; case 0x01DD: return dead_small_schwa; case 0x0259: return dead_small_schwa; case 0x02C6: return dead_circumflex; case 0x02C7: return dead_caron; case 0x02C8: return dead_aboveverticalline; case 0x02C9: return dead_macron; case 0x02CA: return dead_acute; case 0x02CB: return dead_grave; case 0x02CC: return dead_belowverticalline; case 0x02D8: return dead_breve; case 0x02D9: return dead_abovedot; case 0x02DA: return dead_abovering; case 0x02DB: return dead_ogonek; case 0x02DC: return dead_tilde; case 0x02DD: return dead_doubleacute; case 0x0300: return dead_grave; case 0x0301: return dead_acute; case 0x0302: return dead_circumflex; case 0x0303: return dead_tilde; case 0x0304: return dead_macron; case 0x0306: return dead_breve; case 0x0307: return dead_abovedot; case 0x0308: return dead_diaeresis; case 0x0309: return dead_hook; case 0x030A: return dead_abovering; case 0x030B: return dead_doubleacute; case 0x030C: return dead_caron; case 0x030D: return dead_aboveverticalline; case 0x030F: return dead_doublegrave; case 0x0311: return dead_invertedbreve; case 0x0313: return dead_abovecomma; case 0x0314: return dead_abovereversedcomma; case 0x031B: return dead_horn; case 0x0323: return dead_belowdot; case 0x0324: return dead_belowdiaeresis; case 0x0325: return dead_belowring; case 0x0326: return dead_belowcomma; case 0x0327: return dead_cedilla; case 0x0328: return dead_ogonek; case 0x0329: return dead_belowverticalline; case 0x032D: return dead_belowcircumflex; case 0x032E: return dead_belowbreve; case 0x0330: return dead_belowtilde; case 0x0331: return dead_belowmacron; case 0x0332: return dead_lowline; case 0x0335: return dead_stroke; case 0x0336: return dead_stroke; case 0x0337: return dead_stroke; case 0x0338: return dead_longsolidusoverlay; case 0x0345: return dead_iota; case 0x037A: return dead_iota; case 0x04D8: return dead_capital_schwa; case 0x04D9: return dead_small_schwa; case 0x058F: return dead_currency; case 0x060B: return dead_currency; case 0x07FE: return dead_currency; case 0x07FF: return dead_currency; case 0x09F2: return dead_currency; case 0x09F3: return dead_currency; case 0x09FB: return dead_currency; case 0x0AF1: return dead_currency; case 0x0BF9: return dead_currency; case 0x0E3F: return dead_currency; case 0x17DB: return dead_currency; case 0x2044: return dead_stroke; case 0x2215: return dead_stroke; case 0x3099: return dead_voiced_sound; case 0x309A: return dead_semivoiced_sound; case 0x309B: return dead_voiced_sound; case 0x309C: return dead_semivoiced_sound; case 0xA838: return dead_currency; case 0xFDFC: return dead_currency; default: if (u >= 0x0390 && u < 0x03CF) return dead_greek; if (u >= 0x20A0 && u <= 0x20CF) return dead_currency; return none; } } public static XkbDeadKey forKeySym(String s) { for (XkbDeadKey key : values()) { if (key.name().equals(s)) { return key; } } return none; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbKey.java000066400000000000000000000041011506470510200267710ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.Arrays; import java.util.Collections; import java.util.List; public final class XkbKey { public static final List KEYS = Collections.unmodifiableList(Arrays.asList( new XkbKey("TLDE", Key.GRAVE_TILDE), new XkbKey("AE01", Key.NUMROW_1), new XkbKey("AE02", Key.NUMROW_2), new XkbKey("AE03", Key.NUMROW_3), new XkbKey("AE04", Key.NUMROW_4), new XkbKey("AE05", Key.NUMROW_5), new XkbKey("AE06", Key.NUMROW_6), new XkbKey("AE07", Key.NUMROW_7), new XkbKey("AE08", Key.NUMROW_8), new XkbKey("AE09", Key.NUMROW_9), new XkbKey("AE10", Key.NUMROW_0), new XkbKey("AE11", Key.HYPHEN_UNDERSCORE), new XkbKey("AE12", Key.EQUALS_PLUS), null, new XkbKey("AD01", Key.Q), new XkbKey("AD02", Key.W), new XkbKey("AD03", Key.E), new XkbKey("AD04", Key.R), new XkbKey("AD05", Key.T), new XkbKey("AD06", Key.Y), new XkbKey("AD07", Key.U), new XkbKey("AD08", Key.I), new XkbKey("AD09", Key.O), new XkbKey("AD10", Key.P), new XkbKey("AD11", Key.LEFT_BRACKET), new XkbKey("AD12", Key.RIGHT_BRACKET), new XkbKey("BKSL", Key.BACKSLASH), null, new XkbKey("AC01", Key.A), new XkbKey("AC02", Key.S), new XkbKey("AC03", Key.D), new XkbKey("AC04", Key.F), new XkbKey("AC05", Key.G), new XkbKey("AC06", Key.H), new XkbKey("AC07", Key.J), new XkbKey("AC08", Key.K), new XkbKey("AC09", Key.L), new XkbKey("AC10", Key.SEMICOLON), new XkbKey("AC11", Key.QUOTE), null, new XkbKey("AB01", Key.Z), new XkbKey("AB02", Key.X), new XkbKey("AB03", Key.C), new XkbKey("AB04", Key.V), new XkbKey("AB05", Key.B), new XkbKey("AB06", Key.N), new XkbKey("AB07", Key.M), new XkbKey("AB08", Key.COMMA), new XkbKey("AB09", Key.PERIOD), new XkbKey("AB10", Key.SLASH), null, new XkbKey("SPCE", Key.SPACE) )); public final String id; public final Key key; private XkbKey(String id, Key key) { this.id = id; this.key = key; } public static XkbKey forId(String id) { for (XkbKey key : KEYS) { if (key != null && key.id.equalsIgnoreCase(id)) { return key; } } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbKeySym.java000066400000000000000000001321541506470510200274740ustar00rootroot00000000000000package com.kreative.keyedit; import java.util.HashMap; public final class XkbKeySym { public static final XkbKeySym MAP = new XkbKeySym(); private final HashMap u2n; private final HashMap n2u; private XkbKeySym() { this.u2n = new HashMap(); this.n2u = new HashMap(); // Latin 1 m(0x0020, "space"); m(0x0021, "exclam"); m(0x0022, "quotedbl"); m(0x0023, "numbersign"); m(0x0024, "dollar"); m(0x0025, "percent"); m(0x0026, "ampersand"); m(0x0027, "apostrophe"); m(0x0028, "parenleft"); m(0x0029, "parenright"); m(0x002A, "asterisk"); m(0x002B, "plus"); m(0x002C, "comma"); m(0x002D, "minus"); m(0x002E, "period"); m(0x002F, "slash"); m(0x0030, "0"); m(0x0031, "1"); m(0x0032, "2"); m(0x0033, "3"); m(0x0034, "4"); m(0x0035, "5"); m(0x0036, "6"); m(0x0037, "7"); m(0x0038, "8"); m(0x0039, "9"); m(0x003A, "colon"); m(0x003B, "semicolon"); m(0x003C, "less"); m(0x003D, "equal"); m(0x003E, "greater"); m(0x003F, "question"); m(0x0040, "at"); m(0x0041, "A"); m(0x0042, "B"); m(0x0043, "C"); m(0x0044, "D"); m(0x0045, "E"); m(0x0046, "F"); m(0x0047, "G"); m(0x0048, "H"); m(0x0049, "I"); m(0x004A, "J"); m(0x004B, "K"); m(0x004C, "L"); m(0x004D, "M"); m(0x004E, "N"); m(0x004F, "O"); m(0x0050, "P"); m(0x0051, "Q"); m(0x0052, "R"); m(0x0053, "S"); m(0x0054, "T"); m(0x0055, "U"); m(0x0056, "V"); m(0x0057, "W"); m(0x0058, "X"); m(0x0059, "Y"); m(0x005A, "Z"); m(0x005B, "bracketleft"); m(0x005C, "backslash"); m(0x005D, "bracketright"); m(0x005E, "asciicircum"); m(0x005F, "underscore"); m(0x0060, "grave"); m(0x0061, "a"); m(0x0062, "b"); m(0x0063, "c"); m(0x0064, "d"); m(0x0065, "e"); m(0x0066, "f"); m(0x0067, "g"); m(0x0068, "h"); m(0x0069, "i"); m(0x006A, "j"); m(0x006B, "k"); m(0x006C, "l"); m(0x006D, "m"); m(0x006E, "n"); m(0x006F, "o"); m(0x0070, "p"); m(0x0071, "q"); m(0x0072, "r"); m(0x0073, "s"); m(0x0074, "t"); m(0x0075, "u"); m(0x0076, "v"); m(0x0077, "w"); m(0x0078, "x"); m(0x0079, "y"); m(0x007A, "z"); m(0x007B, "braceleft"); m(0x007C, "bar"); m(0x007D, "braceright"); m(0x007E, "asciitilde"); m(0x00A0, "nobreakspace"); m(0x00A1, "exclamdown"); m(0x00A2, "cent"); m(0x00A3, "sterling"); m(0x00A4, "currency"); m(0x00A5, "yen"); m(0x00A6, "brokenbar"); m(0x00A7, "section"); m(0x00A8, "diaeresis"); m(0x00A9, "copyright"); m(0x00AA, "ordfeminine"); m(0x00AB, "guillemotleft"); m(0x00AC, "notsign"); rom(0x00AD, "hyphen"); m(0x00AE, "registered"); m(0x00AF, "macron"); m(0x00B0, "degree"); m(0x00B1, "plusminus"); m(0x00B2, "twosuperior"); m(0x00B3, "threesuperior"); m(0x00B4, "acute"); m(0x00B5, "mu"); m(0x00B6, "paragraph"); m(0x00B7, "periodcentered"); m(0x00B8, "cedilla"); m(0x00B9, "onesuperior"); m(0x00BA, "masculine"); m(0x00BB, "guillemotright"); m(0x00BC, "onequarter"); m(0x00BD, "onehalf"); m(0x00BE, "threequarters"); m(0x00BF, "questiondown"); m(0x00C0, "Agrave"); m(0x00C1, "Aacute"); m(0x00C2, "Acircumflex"); m(0x00C3, "Atilde"); m(0x00C4, "Adiaeresis"); m(0x00C5, "Aring"); m(0x00C6, "AE"); m(0x00C7, "Ccedilla"); m(0x00C8, "Egrave"); m(0x00C9, "Eacute"); m(0x00CA, "Ecircumflex"); m(0x00CB, "Ediaeresis"); m(0x00CC, "Igrave"); m(0x00CD, "Iacute"); m(0x00CE, "Icircumflex"); m(0x00CF, "Idiaeresis"); m(0x00D0, "ETH"); m(0x00D1, "Ntilde"); m(0x00D2, "Ograve"); m(0x00D3, "Oacute"); m(0x00D4, "Ocircumflex"); m(0x00D5, "Otilde"); m(0x00D6, "Odiaeresis"); m(0x00D7, "multiply"); m(0x00D8, "Oslash"); m(0x00D8, "Ooblique"); m(0x00D9, "Ugrave"); m(0x00DA, "Uacute"); m(0x00DB, "Ucircumflex"); m(0x00DC, "Udiaeresis"); m(0x00DD, "Yacute"); m(0x00DE, "THORN"); m(0x00DF, "ssharp"); m(0x00E0, "agrave"); m(0x00E1, "aacute"); m(0x00E2, "acircumflex"); m(0x00E3, "atilde"); m(0x00E4, "adiaeresis"); m(0x00E5, "aring"); m(0x00E6, "ae"); m(0x00E7, "ccedilla"); m(0x00E8, "egrave"); m(0x00E9, "eacute"); m(0x00EA, "ecircumflex"); m(0x00EB, "ediaeresis"); m(0x00EC, "igrave"); m(0x00ED, "iacute"); m(0x00EE, "icircumflex"); m(0x00EF, "idiaeresis"); m(0x00F0, "eth"); m(0x00F1, "ntilde"); m(0x00F2, "ograve"); m(0x00F3, "oacute"); m(0x00F4, "ocircumflex"); m(0x00F5, "otilde"); m(0x00F6, "odiaeresis"); m(0x00F7, "division"); m(0x00F8, "oslash"); m(0x00F8, "ooblique"); m(0x00F9, "ugrave"); m(0x00FA, "uacute"); m(0x00FB, "ucircumflex"); m(0x00FC, "udiaeresis"); m(0x00FD, "yacute"); m(0x00FE, "thorn"); m(0x00FF, "ydiaeresis"); // Latin 2 m(0x0104, "Aogonek"); m(0x02D8, "breve"); m(0x0141, "Lstroke"); m(0x013D, "Lcaron"); m(0x015A, "Sacute"); m(0x0160, "Scaron"); m(0x015E, "Scedilla"); m(0x0164, "Tcaron"); m(0x0179, "Zacute"); m(0x017D, "Zcaron"); m(0x017B, "Zabovedot"); m(0x0105, "aogonek"); m(0x02DB, "ogonek"); m(0x0142, "lstroke"); m(0x013E, "lcaron"); m(0x015B, "sacute"); m(0x02C7, "caron"); m(0x0161, "scaron"); m(0x015F, "scedilla"); m(0x0165, "tcaron"); m(0x017A, "zacute"); m(0x02DD, "doubleacute"); m(0x017E, "zcaron"); m(0x017C, "zabovedot"); m(0x0154, "Racute"); m(0x0102, "Abreve"); m(0x0139, "Lacute"); m(0x0106, "Cacute"); m(0x010C, "Ccaron"); m(0x0118, "Eogonek"); m(0x011A, "Ecaron"); m(0x010E, "Dcaron"); m(0x0110, "Dstroke"); m(0x0143, "Nacute"); m(0x0147, "Ncaron"); m(0x0150, "Odoubleacute"); m(0x0158, "Rcaron"); m(0x016E, "Uring"); m(0x0170, "Udoubleacute"); m(0x0162, "Tcedilla"); m(0x0155, "racute"); m(0x0103, "abreve"); m(0x013A, "lacute"); m(0x0107, "cacute"); m(0x010D, "ccaron"); m(0x0119, "eogonek"); m(0x011B, "ecaron"); m(0x010F, "dcaron"); m(0x0111, "dstroke"); m(0x0144, "nacute"); m(0x0148, "ncaron"); m(0x0151, "odoubleacute"); m(0x0159, "rcaron"); m(0x016F, "uring"); m(0x0171, "udoubleacute"); m(0x0163, "tcedilla"); m(0x02D9, "abovedot"); // Latin 3 m(0x0126, "Hstroke"); m(0x0124, "Hcircumflex"); m(0x0130, "Iabovedot"); m(0x011E, "Gbreve"); m(0x0134, "Jcircumflex"); m(0x0127, "hstroke"); m(0x0125, "hcircumflex"); m(0x0131, "idotless"); m(0x011F, "gbreve"); m(0x0135, "jcircumflex"); m(0x010A, "Cabovedot"); m(0x0108, "Ccircumflex"); m(0x0120, "Gabovedot"); m(0x011C, "Gcircumflex"); m(0x016C, "Ubreve"); m(0x015C, "Scircumflex"); m(0x010B, "cabovedot"); m(0x0109, "ccircumflex"); m(0x0121, "gabovedot"); m(0x011D, "gcircumflex"); m(0x016D, "ubreve"); m(0x015D, "scircumflex"); // Latin 4 m(0x0138, "kra"); m(0x0156, "Rcedilla"); m(0x0128, "Itilde"); m(0x013B, "Lcedilla"); m(0x0112, "Emacron"); m(0x0122, "Gcedilla"); m(0x0166, "Tslash"); m(0x0157, "rcedilla"); m(0x0129, "itilde"); m(0x013C, "lcedilla"); m(0x0113, "emacron"); m(0x0123, "gcedilla"); m(0x0167, "tslash"); m(0x014A, "ENG"); m(0x014B, "eng"); m(0x0100, "Amacron"); m(0x012E, "Iogonek"); m(0x0116, "Eabovedot"); m(0x012A, "Imacron"); m(0x0145, "Ncedilla"); m(0x014C, "Omacron"); m(0x0136, "Kcedilla"); m(0x0172, "Uogonek"); m(0x0168, "Utilde"); m(0x016A, "Umacron"); m(0x0101, "amacron"); m(0x012F, "iogonek"); m(0x0117, "eabovedot"); m(0x012B, "imacron"); m(0x0146, "ncedilla"); m(0x014D, "omacron"); m(0x0137, "kcedilla"); m(0x0173, "uogonek"); m(0x0169, "utilde"); m(0x016B, "umacron"); // Latin 8 m(0x0174, "Wcircumflex"); m(0x0175, "wcircumflex"); m(0x0176, "Ycircumflex"); m(0x0177, "ycircumflex"); m(0x1E02, "Babovedot"); m(0x1E03, "babovedot"); m(0x1E0A, "Dabovedot"); m(0x1E0B, "dabovedot"); m(0x1E1E, "Fabovedot"); m(0x1E1F, "fabovedot"); m(0x1E40, "Mabovedot"); m(0x1E41, "mabovedot"); m(0x1E56, "Pabovedot"); m(0x1E57, "pabovedot"); m(0x1E60, "Sabovedot"); m(0x1E61, "sabovedot"); m(0x1E6A, "Tabovedot"); m(0x1E6B, "tabovedot"); m(0x1E80, "Wgrave"); m(0x1E81, "wgrave"); m(0x1E82, "Wacute"); m(0x1E83, "wacute"); m(0x1E84, "Wdiaeresis"); m(0x1E85, "wdiaeresis"); m(0x1EF2, "Ygrave"); m(0x1EF3, "ygrave"); // Latin 9 m(0x0152, "OE"); m(0x0153, "oe"); m(0x0178, "Ydiaeresis"); // Katakana rom(0x203E, "overline"); rom(0x3002, "kana_fullstop"); rom(0x300C, "kana_openingbracket"); rom(0x300D, "kana_closingbracket"); rom(0x3001, "kana_comma"); rom(0x30FB, "kana_conjunctive"); rom(0x30F2, "kana_WO"); rom(0x30A1, "kana_a"); rom(0x30A3, "kana_i"); rom(0x30A5, "kana_u"); rom(0x30A7, "kana_e"); rom(0x30A9, "kana_o"); rom(0x30E3, "kana_ya"); rom(0x30E5, "kana_yu"); rom(0x30E7, "kana_yo"); rom(0x30C3, "kana_tsu"); rom(0x30FC, "prolongedsound"); rom(0x30A2, "kana_A"); rom(0x30A4, "kana_I"); rom(0x30A6, "kana_U"); rom(0x30A8, "kana_E"); rom(0x30AA, "kana_O"); rom(0x30AB, "kana_KA"); rom(0x30AD, "kana_KI"); rom(0x30AF, "kana_KU"); rom(0x30B1, "kana_KE"); rom(0x30B3, "kana_KO"); rom(0x30B5, "kana_SA"); rom(0x30B7, "kana_SHI"); rom(0x30B9, "kana_SU"); rom(0x30BB, "kana_SE"); rom(0x30BD, "kana_SO"); rom(0x30BF, "kana_TA"); rom(0x30C1, "kana_CHI"); rom(0x30C4, "kana_TSU"); rom(0x30C6, "kana_TE"); rom(0x30C8, "kana_TO"); rom(0x30CA, "kana_NA"); rom(0x30CB, "kana_NI"); rom(0x30CC, "kana_NU"); rom(0x30CD, "kana_NE"); rom(0x30CE, "kana_NO"); rom(0x30CF, "kana_HA"); rom(0x30D2, "kana_HI"); rom(0x30D5, "kana_FU"); rom(0x30D8, "kana_HE"); rom(0x30DB, "kana_HO"); rom(0x30DE, "kana_MA"); rom(0x30DF, "kana_MI"); rom(0x30E0, "kana_MU"); rom(0x30E1, "kana_ME"); rom(0x30E2, "kana_MO"); rom(0x30E4, "kana_YA"); rom(0x30E6, "kana_YU"); rom(0x30E8, "kana_YO"); rom(0x30E9, "kana_RA"); rom(0x30EA, "kana_RI"); rom(0x30EB, "kana_RU"); rom(0x30EC, "kana_RE"); rom(0x30ED, "kana_RO"); rom(0x30EF, "kana_WA"); rom(0x30F3, "kana_N"); rom(0x309B, "voicedsound"); rom(0x309C, "semivoicedsound"); // Arabic rom(0x06F0, "Farsi_0"); rom(0x06F1, "Farsi_1"); rom(0x06F2, "Farsi_2"); rom(0x06F3, "Farsi_3"); rom(0x06F4, "Farsi_4"); rom(0x06F5, "Farsi_5"); rom(0x06F6, "Farsi_6"); rom(0x06F7, "Farsi_7"); rom(0x06F8, "Farsi_8"); rom(0x06F9, "Farsi_9"); rom(0x066A, "Arabic_percent"); rom(0x0670, "Arabic_superscript_alef"); rom(0x0679, "Arabic_tteh"); rom(0x067E, "Arabic_peh"); rom(0x0686, "Arabic_tcheh"); rom(0x0688, "Arabic_ddal"); rom(0x0691, "Arabic_rreh"); rom(0x060C, "Arabic_comma"); rom(0x06D4, "Arabic_fullstop"); rom(0x0660, "Arabic_0"); rom(0x0661, "Arabic_1"); rom(0x0662, "Arabic_2"); rom(0x0663, "Arabic_3"); rom(0x0664, "Arabic_4"); rom(0x0665, "Arabic_5"); rom(0x0666, "Arabic_6"); rom(0x0667, "Arabic_7"); rom(0x0668, "Arabic_8"); rom(0x0669, "Arabic_9"); rom(0x061B, "Arabic_semicolon"); rom(0x061F, "Arabic_question_mark"); rom(0x0621, "Arabic_hamza"); rom(0x0622, "Arabic_maddaonalef"); rom(0x0623, "Arabic_hamzaonalef"); rom(0x0624, "Arabic_hamzaonwaw"); rom(0x0625, "Arabic_hamzaunderalef"); rom(0x0626, "Arabic_hamzaonyeh"); rom(0x0627, "Arabic_alef"); rom(0x0628, "Arabic_beh"); rom(0x0629, "Arabic_tehmarbuta"); rom(0x062A, "Arabic_teh"); rom(0x062B, "Arabic_theh"); rom(0x062C, "Arabic_jeem"); rom(0x062D, "Arabic_hah"); rom(0x062E, "Arabic_khah"); rom(0x062F, "Arabic_dal"); rom(0x0630, "Arabic_thal"); rom(0x0631, "Arabic_ra"); rom(0x0632, "Arabic_zain"); rom(0x0633, "Arabic_seen"); rom(0x0634, "Arabic_sheen"); rom(0x0635, "Arabic_sad"); rom(0x0636, "Arabic_dad"); rom(0x0637, "Arabic_tah"); rom(0x0638, "Arabic_zah"); rom(0x0639, "Arabic_ain"); rom(0x063A, "Arabic_ghain"); rom(0x0640, "Arabic_tatweel"); rom(0x0641, "Arabic_feh"); rom(0x0642, "Arabic_qaf"); rom(0x0643, "Arabic_kaf"); rom(0x0644, "Arabic_lam"); rom(0x0645, "Arabic_meem"); rom(0x0646, "Arabic_noon"); rom(0x0647, "Arabic_ha"); rom(0x0648, "Arabic_waw"); rom(0x0649, "Arabic_alefmaksura"); rom(0x064A, "Arabic_yeh"); rom(0x064B, "Arabic_fathatan"); rom(0x064C, "Arabic_dammatan"); rom(0x064D, "Arabic_kasratan"); rom(0x064E, "Arabic_fatha"); rom(0x064F, "Arabic_damma"); rom(0x0650, "Arabic_kasra"); rom(0x0651, "Arabic_shadda"); rom(0x0652, "Arabic_sukun"); rom(0x0653, "Arabic_madda_above"); rom(0x0654, "Arabic_hamza_above"); rom(0x0655, "Arabic_hamza_below"); rom(0x0698, "Arabic_jeh"); rom(0x06A4, "Arabic_veh"); rom(0x06A9, "Arabic_keheh"); rom(0x06AF, "Arabic_gaf"); rom(0x06BA, "Arabic_noon_ghunna"); rom(0x06BE, "Arabic_heh_doachashmee"); rom(0x06CC, "Farsi_yeh"); rom(0x06CC, "Arabic_farsi_yeh"); rom(0x06D2, "Arabic_yeh_baree"); rom(0x06C1, "Arabic_heh_goal"); // Cyrillic m(0x0492, "Cyrillic_GHE_bar"); m(0x0493, "Cyrillic_ghe_bar"); m(0x0496, "Cyrillic_ZHE_descender"); m(0x0497, "Cyrillic_zhe_descender"); m(0x049A, "Cyrillic_KA_descender"); m(0x049B, "Cyrillic_ka_descender"); m(0x049C, "Cyrillic_KA_vertstroke"); m(0x049D, "Cyrillic_ka_vertstroke"); m(0x04A2, "Cyrillic_EN_descender"); m(0x04A3, "Cyrillic_en_descender"); m(0x04AE, "Cyrillic_U_straight"); m(0x04AF, "Cyrillic_u_straight"); m(0x04B0, "Cyrillic_U_straight_bar"); m(0x04B1, "Cyrillic_u_straight_bar"); m(0x04B2, "Cyrillic_HA_descender"); m(0x04B3, "Cyrillic_ha_descender"); m(0x04B6, "Cyrillic_CHE_descender"); m(0x04B7, "Cyrillic_che_descender"); m(0x04B8, "Cyrillic_CHE_vertstroke"); m(0x04B9, "Cyrillic_che_vertstroke"); m(0x04BA, "Cyrillic_SHHA"); m(0x04BB, "Cyrillic_shha"); m(0x04D8, "Cyrillic_SCHWA"); m(0x04D9, "Cyrillic_schwa"); m(0x04E2, "Cyrillic_I_macron"); m(0x04E3, "Cyrillic_i_macron"); m(0x04E8, "Cyrillic_O_bar"); m(0x04E9, "Cyrillic_o_bar"); m(0x04EE, "Cyrillic_U_macron"); m(0x04EF, "Cyrillic_u_macron"); m(0x0452, "Serbian_dje"); m(0x0453, "Macedonia_gje"); m(0x0451, "Cyrillic_io"); m(0x0454, "Ukrainian_ie"); m(0x0455, "Macedonia_dse"); m(0x0456, "Ukrainian_i"); m(0x0457, "Ukrainian_yi"); m(0x0458, "Cyrillic_je"); m(0x0459, "Cyrillic_lje"); m(0x045A, "Cyrillic_nje"); m(0x045B, "Serbian_tshe"); m(0x045C, "Macedonia_kje"); m(0x0491, "Ukrainian_ghe_with_upturn"); m(0x045E, "Byelorussian_shortu"); m(0x045F, "Cyrillic_dzhe"); m(0x2116, "numerosign"); m(0x0402, "Serbian_DJE"); m(0x0403, "Macedonia_GJE"); m(0x0401, "Cyrillic_IO"); m(0x0404, "Ukrainian_IE"); m(0x0405, "Macedonia_DSE"); m(0x0406, "Ukrainian_I"); m(0x0407, "Ukrainian_YI"); m(0x0408, "Cyrillic_JE"); m(0x0409, "Cyrillic_LJE"); m(0x040A, "Cyrillic_NJE"); m(0x040B, "Serbian_TSHE"); m(0x040C, "Macedonia_KJE"); m(0x0490, "Ukrainian_GHE_WITH_UPTURN"); m(0x040E, "Byelorussian_SHORTU"); m(0x040F, "Cyrillic_DZHE"); m(0x044E, "Cyrillic_yu"); m(0x0430, "Cyrillic_a"); m(0x0431, "Cyrillic_be"); m(0x0446, "Cyrillic_tse"); m(0x0434, "Cyrillic_de"); m(0x0435, "Cyrillic_ie"); m(0x0444, "Cyrillic_ef"); m(0x0433, "Cyrillic_ghe"); m(0x0445, "Cyrillic_ha"); m(0x0438, "Cyrillic_i"); m(0x0439, "Cyrillic_shorti"); m(0x043A, "Cyrillic_ka"); m(0x043B, "Cyrillic_el"); m(0x043C, "Cyrillic_em"); m(0x043D, "Cyrillic_en"); m(0x043E, "Cyrillic_o"); m(0x043F, "Cyrillic_pe"); m(0x044F, "Cyrillic_ya"); m(0x0440, "Cyrillic_er"); m(0x0441, "Cyrillic_es"); m(0x0442, "Cyrillic_te"); m(0x0443, "Cyrillic_u"); m(0x0436, "Cyrillic_zhe"); m(0x0432, "Cyrillic_ve"); m(0x044C, "Cyrillic_softsign"); m(0x044B, "Cyrillic_yeru"); m(0x0437, "Cyrillic_ze"); m(0x0448, "Cyrillic_sha"); m(0x044D, "Cyrillic_e"); m(0x0449, "Cyrillic_shcha"); m(0x0447, "Cyrillic_che"); m(0x044A, "Cyrillic_hardsign"); m(0x042E, "Cyrillic_YU"); m(0x0410, "Cyrillic_A"); m(0x0411, "Cyrillic_BE"); m(0x0426, "Cyrillic_TSE"); m(0x0414, "Cyrillic_DE"); m(0x0415, "Cyrillic_IE"); m(0x0424, "Cyrillic_EF"); m(0x0413, "Cyrillic_GHE"); m(0x0425, "Cyrillic_HA"); m(0x0418, "Cyrillic_I"); m(0x0419, "Cyrillic_SHORTI"); m(0x041A, "Cyrillic_KA"); m(0x041B, "Cyrillic_EL"); m(0x041C, "Cyrillic_EM"); m(0x041D, "Cyrillic_EN"); m(0x041E, "Cyrillic_O"); m(0x041F, "Cyrillic_PE"); m(0x042F, "Cyrillic_YA"); m(0x0420, "Cyrillic_ER"); m(0x0421, "Cyrillic_ES"); m(0x0422, "Cyrillic_TE"); m(0x0423, "Cyrillic_U"); m(0x0416, "Cyrillic_ZHE"); m(0x0412, "Cyrillic_VE"); m(0x042C, "Cyrillic_SOFTSIGN"); m(0x042B, "Cyrillic_YERU"); m(0x0417, "Cyrillic_ZE"); m(0x0428, "Cyrillic_SHA"); m(0x042D, "Cyrillic_E"); m(0x0429, "Cyrillic_SHCHA"); m(0x0427, "Cyrillic_CHE"); m(0x042A, "Cyrillic_HARDSIGN"); // Greek m(0x0386, "Greek_ALPHAaccent"); m(0x0388, "Greek_EPSILONaccent"); m(0x0389, "Greek_ETAaccent"); m(0x038A, "Greek_IOTAaccent"); m(0x03AA, "Greek_IOTAdieresis"); m(0x038C, "Greek_OMICRONaccent"); m(0x038E, "Greek_UPSILONaccent"); m(0x03AB, "Greek_UPSILONdieresis"); m(0x038F, "Greek_OMEGAaccent"); m(0x0385, "Greek_accentdieresis"); m(0x2015, "Greek_horizbar"); m(0x03AC, "Greek_alphaaccent"); m(0x03AD, "Greek_epsilonaccent"); m(0x03AE, "Greek_etaaccent"); m(0x03AF, "Greek_iotaaccent"); m(0x03CA, "Greek_iotadieresis"); m(0x0390, "Greek_iotaaccentdieresis"); m(0x03CC, "Greek_omicronaccent"); m(0x03CD, "Greek_upsilonaccent"); m(0x03CB, "Greek_upsilondieresis"); m(0x03B0, "Greek_upsilonaccentdieresis"); m(0x03CE, "Greek_omegaaccent"); m(0x0391, "Greek_ALPHA"); m(0x0392, "Greek_BETA"); m(0x0393, "Greek_GAMMA"); m(0x0394, "Greek_DELTA"); m(0x0395, "Greek_EPSILON"); m(0x0396, "Greek_ZETA"); m(0x0397, "Greek_ETA"); m(0x0398, "Greek_THETA"); m(0x0399, "Greek_IOTA"); m(0x039A, "Greek_KAPPA"); m(0x039B, "Greek_LAMDA"); m(0x039B, "Greek_LAMBDA"); m(0x039C, "Greek_MU"); m(0x039D, "Greek_NU"); m(0x039E, "Greek_XI"); m(0x039F, "Greek_OMICRON"); m(0x03A0, "Greek_PI"); m(0x03A1, "Greek_RHO"); m(0x03A3, "Greek_SIGMA"); m(0x03A4, "Greek_TAU"); m(0x03A5, "Greek_UPSILON"); m(0x03A6, "Greek_PHI"); m(0x03A7, "Greek_CHI"); m(0x03A8, "Greek_PSI"); m(0x03A9, "Greek_OMEGA"); m(0x03B1, "Greek_alpha"); m(0x03B2, "Greek_beta"); m(0x03B3, "Greek_gamma"); m(0x03B4, "Greek_delta"); m(0x03B5, "Greek_epsilon"); m(0x03B6, "Greek_zeta"); m(0x03B7, "Greek_eta"); m(0x03B8, "Greek_theta"); m(0x03B9, "Greek_iota"); m(0x03BA, "Greek_kappa"); m(0x03BB, "Greek_lamda"); m(0x03BB, "Greek_lambda"); m(0x03BC, "Greek_mu"); m(0x03BD, "Greek_nu"); m(0x03BE, "Greek_xi"); m(0x03BF, "Greek_omicron"); m(0x03C0, "Greek_pi"); m(0x03C1, "Greek_rho"); m(0x03C3, "Greek_sigma"); m(0x03C2, "Greek_finalsmallsigma"); m(0x03C4, "Greek_tau"); m(0x03C5, "Greek_upsilon"); m(0x03C6, "Greek_phi"); m(0x03C7, "Greek_chi"); m(0x03C8, "Greek_psi"); m(0x03C9, "Greek_omega"); // Technical rom(0x23B7, "leftradical"); rom(0x2320, "topintegral"); rom(0x2321, "botintegral"); rom(0x23A1, "topleftsqbracket"); rom(0x23A3, "botleftsqbracket"); rom(0x23A4, "toprightsqbracket"); rom(0x23A6, "botrightsqbracket"); rom(0x239B, "topleftparens"); rom(0x239D, "botleftparens"); rom(0x239E, "toprightparens"); rom(0x23A0, "botrightparens"); rom(0x23A8, "leftmiddlecurlybrace"); rom(0x23AC, "rightmiddlecurlybrace"); m(0x2264, "lessthanequal"); m(0x2260, "notequal"); m(0x2265, "greaterthanequal"); m(0x222B, "integral"); rom(0x2234, "therefore"); rom(0x221D, "variation"); m(0x221E, "infinity"); m(0x2207, "nabla"); rom(0x223C, "approximate"); rom(0x2243, "similarequal"); rom(0x21D4, "ifonlyif"); rom(0x21D2, "implies"); rom(0x2261, "identical"); rom(0x221A, "radical"); rom(0x2282, "includedin"); rom(0x2283, "includes"); rom(0x2229, "intersection"); rom(0x222A, "union"); rom(0x2227, "logicaland"); rom(0x2228, "logicalor"); m(0x2202, "partialderivative"); rom(0x0192, "function"); rom(0x2190, "leftarrow"); rom(0x2191, "uparrow"); rom(0x2192, "rightarrow"); rom(0x2193, "downarrow"); // Special rom(0x25C6, "soliddiamond"); rom(0x2592, "checkerboard"); rom(0x2409, "ht"); rom(0x240C, "ff"); rom(0x240D, "cr"); rom(0x240A, "lf"); rom(0x2424, "nl"); rom(0x240B, "vt"); rom(0x2518, "lowrightcorner"); rom(0x2510, "uprightcorner"); rom(0x250C, "upleftcorner"); rom(0x2514, "lowleftcorner"); rom(0x253C, "crossinglines"); rom(0x23BA, "horizlinescan1"); rom(0x23BB, "horizlinescan3"); rom(0x2500, "horizlinescan5"); rom(0x23BC, "horizlinescan7"); rom(0x23BD, "horizlinescan9"); rom(0x251C, "leftt"); rom(0x2524, "rightt"); rom(0x2534, "bott"); rom(0x252C, "topt"); rom(0x2502, "vertbar"); // Publishing rom(0x2003, "emspace"); rom(0x2002, "enspace"); rom(0x2004, "em3space"); rom(0x2005, "em4space"); rom(0x2007, "digitspace"); rom(0x2008, "punctspace"); rom(0x2009, "thinspace"); rom(0x200A, "hairspace"); m(0x2014, "emdash"); m(0x2013, "endash"); m(0x2026, "ellipsis"); rom(0x2025, "doubbaselinedot"); rom(0x2153, "onethird"); rom(0x2154, "twothirds"); rom(0x2155, "onefifth"); rom(0x2156, "twofifths"); rom(0x2157, "threefifths"); rom(0x2158, "fourfifths"); rom(0x2159, "onesixth"); rom(0x215A, "fivesixths"); rom(0x2105, "careof"); rom(0x2012, "figdash"); rom(0x215B, "oneeighth"); rom(0x215C, "threeeighths"); rom(0x215D, "fiveeighths"); rom(0x215E, "seveneighths"); m(0x2122, "trademark"); m(0x2018, "leftsinglequotemark"); m(0x2019, "rightsinglequotemark"); m(0x201C, "leftdoublequotemark"); m(0x201D, "rightdoublequotemark"); rom(0x211E, "prescription"); rom(0x2030, "permille"); rom(0x2032, "minutes"); rom(0x2033, "seconds"); rom(0x271D, "latincross"); rom(0x2663, "club"); rom(0x2666, "diamond"); rom(0x2665, "heart"); rom(0x2720, "maltesecross"); m(0x2020, "dagger"); m(0x2021, "doubledagger"); rom(0x2713, "checkmark"); rom(0x2717, "ballotcross"); rom(0x266F, "musicalsharp"); rom(0x266D, "musicalflat"); rom(0x2642, "malesymbol"); rom(0x2640, "femalesymbol"); rom(0x260E, "telephone"); rom(0x2315, "telephonerecorder"); rom(0x2117, "phonographcopyright"); rom(0x2038, "caret"); m(0x201A, "singlelowquotemark"); m(0x201E, "doublelowquotemark"); // APL rom(0x22A4, "downtack"); rom(0x230A, "downstile"); rom(0x2218, "jot"); rom(0x2395, "quad"); rom(0x22A5, "uptack"); rom(0x25CB, "circle"); rom(0x2308, "upstile"); rom(0x22A3, "lefttack"); rom(0x22A2, "righttack"); // Hebrew rom(0x2017, "hebrew_doublelowline"); rom(0x05D0, "hebrew_aleph"); rom(0x05D1, "hebrew_bet"); rom(0x05D2, "hebrew_gimel"); rom(0x05D3, "hebrew_dalet"); rom(0x05D4, "hebrew_he"); rom(0x05D5, "hebrew_waw"); rom(0x05D6, "hebrew_zain"); rom(0x05D7, "hebrew_chet"); rom(0x05D8, "hebrew_tet"); rom(0x05D9, "hebrew_yod"); rom(0x05DA, "hebrew_finalkaph"); rom(0x05DB, "hebrew_kaph"); rom(0x05DC, "hebrew_lamed"); rom(0x05DD, "hebrew_finalmem"); rom(0x05DE, "hebrew_mem"); rom(0x05DF, "hebrew_finalnun"); rom(0x05E0, "hebrew_nun"); rom(0x05E1, "hebrew_samech"); rom(0x05E2, "hebrew_ayin"); rom(0x05E3, "hebrew_finalpe"); rom(0x05E4, "hebrew_pe"); rom(0x05E5, "hebrew_finalzade"); rom(0x05E6, "hebrew_zade"); rom(0x05E7, "hebrew_qoph"); rom(0x05E8, "hebrew_resh"); rom(0x05E9, "hebrew_shin"); rom(0x05EA, "hebrew_taw"); // Thai rom(0x0E01, "Thai_kokai"); rom(0x0E02, "Thai_khokhai"); rom(0x0E03, "Thai_khokhuat"); rom(0x0E04, "Thai_khokhwai"); rom(0x0E05, "Thai_khokhon"); rom(0x0E06, "Thai_khorakhang"); rom(0x0E07, "Thai_ngongu"); rom(0x0E08, "Thai_chochan"); rom(0x0E09, "Thai_choching"); rom(0x0E0A, "Thai_chochang"); rom(0x0E0B, "Thai_soso"); rom(0x0E0C, "Thai_chochoe"); rom(0x0E0D, "Thai_yoying"); rom(0x0E0E, "Thai_dochada"); rom(0x0E0F, "Thai_topatak"); rom(0x0E10, "Thai_thothan"); rom(0x0E11, "Thai_thonangmontho"); rom(0x0E12, "Thai_thophuthao"); rom(0x0E13, "Thai_nonen"); rom(0x0E14, "Thai_dodek"); rom(0x0E15, "Thai_totao"); rom(0x0E16, "Thai_thothung"); rom(0x0E17, "Thai_thothahan"); rom(0x0E18, "Thai_thothong"); rom(0x0E19, "Thai_nonu"); rom(0x0E1A, "Thai_bobaimai"); rom(0x0E1B, "Thai_popla"); rom(0x0E1C, "Thai_phophung"); rom(0x0E1D, "Thai_fofa"); rom(0x0E1E, "Thai_phophan"); rom(0x0E1F, "Thai_fofan"); rom(0x0E20, "Thai_phosamphao"); rom(0x0E21, "Thai_moma"); rom(0x0E22, "Thai_yoyak"); rom(0x0E23, "Thai_rorua"); rom(0x0E24, "Thai_ru"); rom(0x0E25, "Thai_loling"); rom(0x0E26, "Thai_lu"); rom(0x0E27, "Thai_wowaen"); rom(0x0E28, "Thai_sosala"); rom(0x0E29, "Thai_sorusi"); rom(0x0E2A, "Thai_sosua"); rom(0x0E2B, "Thai_hohip"); rom(0x0E2C, "Thai_lochula"); rom(0x0E2D, "Thai_oang"); rom(0x0E2E, "Thai_honokhuk"); rom(0x0E2F, "Thai_paiyannoi"); rom(0x0E30, "Thai_saraa"); rom(0x0E31, "Thai_maihanakat"); rom(0x0E32, "Thai_saraaa"); rom(0x0E33, "Thai_saraam"); rom(0x0E34, "Thai_sarai"); rom(0x0E35, "Thai_saraii"); rom(0x0E36, "Thai_saraue"); rom(0x0E37, "Thai_sarauee"); rom(0x0E38, "Thai_sarau"); rom(0x0E39, "Thai_sarauu"); rom(0x0E3A, "Thai_phinthu"); rom(0x0E3F, "Thai_baht"); rom(0x0E40, "Thai_sarae"); rom(0x0E41, "Thai_saraae"); rom(0x0E42, "Thai_sarao"); rom(0x0E43, "Thai_saraaimaimuan"); rom(0x0E44, "Thai_saraaimaimalai"); rom(0x0E45, "Thai_lakkhangyao"); rom(0x0E46, "Thai_maiyamok"); rom(0x0E47, "Thai_maitaikhu"); rom(0x0E48, "Thai_maiek"); rom(0x0E49, "Thai_maitho"); rom(0x0E4A, "Thai_maitri"); rom(0x0E4B, "Thai_maichattawa"); rom(0x0E4C, "Thai_thanthakhat"); rom(0x0E4D, "Thai_nikhahit"); rom(0x0E50, "Thai_leksun"); rom(0x0E51, "Thai_leknung"); rom(0x0E52, "Thai_leksong"); rom(0x0E53, "Thai_leksam"); rom(0x0E54, "Thai_leksi"); rom(0x0E55, "Thai_lekha"); rom(0x0E56, "Thai_lekhok"); rom(0x0E57, "Thai_lekchet"); rom(0x0E58, "Thai_lekpaet"); rom(0x0E59, "Thai_lekkao"); // Armenian m(0x0587, "Armenian_ligature_ew"); m(0x0589, "Armenian_full_stop"); m(0x0589, "Armenian_verjaket"); m(0x055D, "Armenian_separation_mark"); m(0x055D, "Armenian_but"); m(0x058A, "Armenian_hyphen"); m(0x058A, "Armenian_yentamna"); m(0x055C, "Armenian_exclam"); m(0x055C, "Armenian_amanak"); m(0x055B, "Armenian_accent"); m(0x055B, "Armenian_shesht"); m(0x055E, "Armenian_question"); m(0x055E, "Armenian_paruyk"); m(0x0531, "Armenian_AYB"); m(0x0561, "Armenian_ayb"); m(0x0532, "Armenian_BEN"); m(0x0562, "Armenian_ben"); m(0x0533, "Armenian_GIM"); m(0x0563, "Armenian_gim"); m(0x0534, "Armenian_DA"); m(0x0564, "Armenian_da"); m(0x0535, "Armenian_YECH"); m(0x0565, "Armenian_yech"); m(0x0536, "Armenian_ZA"); m(0x0566, "Armenian_za"); m(0x0537, "Armenian_E"); m(0x0567, "Armenian_e"); m(0x0538, "Armenian_AT"); m(0x0568, "Armenian_at"); m(0x0539, "Armenian_TO"); m(0x0569, "Armenian_to"); m(0x053A, "Armenian_ZHE"); m(0x056A, "Armenian_zhe"); m(0x053B, "Armenian_INI"); m(0x056B, "Armenian_ini"); m(0x053C, "Armenian_LYUN"); m(0x056C, "Armenian_lyun"); m(0x053D, "Armenian_KHE"); m(0x056D, "Armenian_khe"); m(0x053E, "Armenian_TSA"); m(0x056E, "Armenian_tsa"); m(0x053F, "Armenian_KEN"); m(0x056F, "Armenian_ken"); m(0x0540, "Armenian_HO"); m(0x0570, "Armenian_ho"); m(0x0541, "Armenian_DZA"); m(0x0571, "Armenian_dza"); m(0x0542, "Armenian_GHAT"); m(0x0572, "Armenian_ghat"); m(0x0543, "Armenian_TCHE"); m(0x0573, "Armenian_tche"); m(0x0544, "Armenian_MEN"); m(0x0574, "Armenian_men"); m(0x0545, "Armenian_HI"); m(0x0575, "Armenian_hi"); m(0x0546, "Armenian_NU"); m(0x0576, "Armenian_nu"); m(0x0547, "Armenian_SHA"); m(0x0577, "Armenian_sha"); m(0x0548, "Armenian_VO"); m(0x0578, "Armenian_vo"); m(0x0549, "Armenian_CHA"); m(0x0579, "Armenian_cha"); m(0x054A, "Armenian_PE"); m(0x057A, "Armenian_pe"); m(0x054B, "Armenian_JE"); m(0x057B, "Armenian_je"); m(0x054C, "Armenian_RA"); m(0x057C, "Armenian_ra"); m(0x054D, "Armenian_SE"); m(0x057D, "Armenian_se"); m(0x054E, "Armenian_VEV"); m(0x057E, "Armenian_vev"); m(0x054F, "Armenian_TYUN"); m(0x057F, "Armenian_tyun"); m(0x0550, "Armenian_RE"); m(0x0580, "Armenian_re"); m(0x0551, "Armenian_TSO"); m(0x0581, "Armenian_tso"); m(0x0552, "Armenian_VYUN"); m(0x0582, "Armenian_vyun"); m(0x0553, "Armenian_PYUR"); m(0x0583, "Armenian_pyur"); m(0x0554, "Armenian_KE"); m(0x0584, "Armenian_ke"); m(0x0555, "Armenian_O"); m(0x0585, "Armenian_o"); m(0x0556, "Armenian_FE"); m(0x0586, "Armenian_fe"); m(0x055A, "Armenian_apostrophe"); // Georgian rom(0x10D0, "Georgian_an"); rom(0x10D1, "Georgian_ban"); rom(0x10D2, "Georgian_gan"); rom(0x10D3, "Georgian_don"); rom(0x10D4, "Georgian_en"); rom(0x10D5, "Georgian_vin"); rom(0x10D6, "Georgian_zen"); rom(0x10D7, "Georgian_tan"); rom(0x10D8, "Georgian_in"); rom(0x10D9, "Georgian_kan"); rom(0x10DA, "Georgian_las"); rom(0x10DB, "Georgian_man"); rom(0x10DC, "Georgian_nar"); rom(0x10DD, "Georgian_on"); rom(0x10DE, "Georgian_par"); rom(0x10DF, "Georgian_zhar"); rom(0x10E0, "Georgian_rae"); rom(0x10E1, "Georgian_san"); rom(0x10E2, "Georgian_tar"); rom(0x10E3, "Georgian_un"); rom(0x10E4, "Georgian_phar"); rom(0x10E5, "Georgian_khar"); rom(0x10E6, "Georgian_ghan"); rom(0x10E7, "Georgian_qar"); rom(0x10E8, "Georgian_shin"); rom(0x10E9, "Georgian_chin"); rom(0x10EA, "Georgian_can"); rom(0x10EB, "Georgian_jil"); rom(0x10EC, "Georgian_cil"); rom(0x10ED, "Georgian_char"); rom(0x10EE, "Georgian_xan"); rom(0x10EF, "Georgian_jhan"); rom(0x10F0, "Georgian_hae"); rom(0x10F1, "Georgian_he"); rom(0x10F2, "Georgian_hie"); rom(0x10F3, "Georgian_we"); rom(0x10F4, "Georgian_har"); rom(0x10F5, "Georgian_hoe"); rom(0x10F6, "Georgian_fi"); // Caucasus m(0x1E8A, "Xabovedot"); m(0x012C, "Ibreve"); m(0x01B5, "Zstroke"); m(0x01E6, "Gcaron"); m(0x01D1, "Ocaron"); m(0x019F, "Obarred"); m(0x1E8B, "xabovedot"); m(0x012D, "ibreve"); m(0x01B6, "zstroke"); m(0x01E7, "gcaron"); m(0x01D2, "ocaron"); m(0x0275, "obarred"); m(0x018F, "SCHWA"); m(0x0259, "schwa"); m(0x01B7, "EZH"); m(0x0292, "ezh"); m(0x1E36, "Lbelowdot"); m(0x1E37, "lbelowdot"); // Vietnamese m(0x1EA0, "Abelowdot"); m(0x1EA1, "abelowdot"); m(0x1EA2, "Ahook"); m(0x1EA3, "ahook"); m(0x1EA4, "Acircumflexacute"); m(0x1EA5, "acircumflexacute"); m(0x1EA6, "Acircumflexgrave"); m(0x1EA7, "acircumflexgrave"); m(0x1EA8, "Acircumflexhook"); m(0x1EA9, "acircumflexhook"); m(0x1EAA, "Acircumflextilde"); m(0x1EAB, "acircumflextilde"); m(0x1EAC, "Acircumflexbelowdot"); m(0x1EAD, "acircumflexbelowdot"); m(0x1EAE, "Abreveacute"); m(0x1EAF, "abreveacute"); m(0x1EB0, "Abrevegrave"); m(0x1EB1, "abrevegrave"); m(0x1EB2, "Abrevehook"); m(0x1EB3, "abrevehook"); m(0x1EB4, "Abrevetilde"); m(0x1EB5, "abrevetilde"); m(0x1EB6, "Abrevebelowdot"); m(0x1EB7, "abrevebelowdot"); m(0x1EB8, "Ebelowdot"); m(0x1EB9, "ebelowdot"); m(0x1EBA, "Ehook"); m(0x1EBB, "ehook"); m(0x1EBC, "Etilde"); m(0x1EBD, "etilde"); m(0x1EBE, "Ecircumflexacute"); m(0x1EBF, "ecircumflexacute"); m(0x1EC0, "Ecircumflexgrave"); m(0x1EC1, "ecircumflexgrave"); m(0x1EC2, "Ecircumflexhook"); m(0x1EC3, "ecircumflexhook"); m(0x1EC4, "Ecircumflextilde"); m(0x1EC5, "ecircumflextilde"); m(0x1EC6, "Ecircumflexbelowdot"); m(0x1EC7, "ecircumflexbelowdot"); m(0x1EC8, "Ihook"); m(0x1EC9, "ihook"); m(0x1ECA, "Ibelowdot"); m(0x1ECB, "ibelowdot"); m(0x1ECC, "Obelowdot"); m(0x1ECD, "obelowdot"); m(0x1ECE, "Ohook"); m(0x1ECF, "ohook"); m(0x1ED0, "Ocircumflexacute"); m(0x1ED1, "ocircumflexacute"); m(0x1ED2, "Ocircumflexgrave"); m(0x1ED3, "ocircumflexgrave"); m(0x1ED4, "Ocircumflexhook"); m(0x1ED5, "ocircumflexhook"); m(0x1ED6, "Ocircumflextilde"); m(0x1ED7, "ocircumflextilde"); m(0x1ED8, "Ocircumflexbelowdot"); m(0x1ED9, "ocircumflexbelowdot"); m(0x1EDA, "Ohornacute"); m(0x1EDB, "ohornacute"); m(0x1EDC, "Ohorngrave"); m(0x1EDD, "ohorngrave"); m(0x1EDE, "Ohornhook"); m(0x1EDF, "ohornhook"); m(0x1EE0, "Ohorntilde"); m(0x1EE1, "ohorntilde"); m(0x1EE2, "Ohornbelowdot"); m(0x1EE3, "ohornbelowdot"); m(0x1EE4, "Ubelowdot"); m(0x1EE5, "ubelowdot"); m(0x1EE6, "Uhook"); m(0x1EE7, "uhook"); m(0x1EE8, "Uhornacute"); m(0x1EE9, "uhornacute"); m(0x1EEA, "Uhorngrave"); m(0x1EEB, "uhorngrave"); m(0x1EEC, "Uhornhook"); m(0x1EED, "uhornhook"); m(0x1EEE, "Uhorntilde"); m(0x1EEF, "uhorntilde"); m(0x1EF0, "Uhornbelowdot"); m(0x1EF1, "uhornbelowdot"); m(0x1EF4, "Ybelowdot"); m(0x1EF5, "ybelowdot"); m(0x1EF6, "Yhook"); m(0x1EF7, "yhook"); m(0x1EF8, "Ytilde"); m(0x1EF9, "ytilde"); m(0x01A0, "Ohorn"); m(0x01A1, "ohorn"); m(0x01AF, "Uhorn"); m(0x01B0, "uhorn"); // Currency rom(0x20A0, "EcuSign"); rom(0x20A1, "ColonSign"); rom(0x20A2, "CruzeiroSign"); rom(0x20A3, "FFrancSign"); rom(0x20A4, "LiraSign"); rom(0x20A5, "MillSign"); rom(0x20A6, "NairaSign"); rom(0x20A7, "PesetaSign"); rom(0x20A8, "RupeeSign"); rom(0x20A9, "WonSign"); rom(0x20AA, "NewSheqelSign"); rom(0x20AB, "DongSign"); m(0x20AC, "EuroSign"); // Mathematical rom(0x2070, "zerosuperior"); rom(0x2074, "foursuperior"); rom(0x2075, "fivesuperior"); rom(0x2076, "sixsuperior"); rom(0x2077, "sevensuperior"); rom(0x2078, "eightsuperior"); rom(0x2079, "ninesuperior"); rom(0x2080, "zerosubscript"); rom(0x2081, "onesubscript"); rom(0x2082, "twosubscript"); rom(0x2083, "threesubscript"); rom(0x2084, "foursubscript"); rom(0x2085, "fivesubscript"); rom(0x2086, "sixsubscript"); rom(0x2087, "sevensubscript"); rom(0x2088, "eightsubscript"); rom(0x2089, "ninesubscript"); rom(0x2202, "partdifferential"); rom(0x2205, "emptyset"); rom(0x2208, "elementof"); rom(0x2209, "notelementof"); rom(0x220B, "containsas"); m(0x221A, "squareroot"); rom(0x221B, "cuberoot"); rom(0x221C, "fourthroot"); rom(0x222C, "dintegral"); rom(0x222D, "tintegral"); rom(0x2235, "because"); rom(0x2245, "approxeq"); rom(0x2247, "notapproxeq"); rom(0x2262, "notidentical"); rom(0x2263, "stricteq"); // Braille rom(0x2800, "braille_blank"); rom(0x2801, "braille_dots_1"); rom(0x2802, "braille_dots_2"); rom(0x2803, "braille_dots_12"); rom(0x2804, "braille_dots_3"); rom(0x2805, "braille_dots_13"); rom(0x2806, "braille_dots_23"); rom(0x2807, "braille_dots_123"); rom(0x2808, "braille_dots_4"); rom(0x2809, "braille_dots_14"); rom(0x280a, "braille_dots_24"); rom(0x280b, "braille_dots_124"); rom(0x280c, "braille_dots_34"); rom(0x280d, "braille_dots_134"); rom(0x280e, "braille_dots_234"); rom(0x280f, "braille_dots_1234"); rom(0x2810, "braille_dots_5"); rom(0x2811, "braille_dots_15"); rom(0x2812, "braille_dots_25"); rom(0x2813, "braille_dots_125"); rom(0x2814, "braille_dots_35"); rom(0x2815, "braille_dots_135"); rom(0x2816, "braille_dots_235"); rom(0x2817, "braille_dots_1235"); rom(0x2818, "braille_dots_45"); rom(0x2819, "braille_dots_145"); rom(0x281a, "braille_dots_245"); rom(0x281b, "braille_dots_1245"); rom(0x281c, "braille_dots_345"); rom(0x281d, "braille_dots_1345"); rom(0x281e, "braille_dots_2345"); rom(0x281f, "braille_dots_12345"); rom(0x2820, "braille_dots_6"); rom(0x2821, "braille_dots_16"); rom(0x2822, "braille_dots_26"); rom(0x2823, "braille_dots_126"); rom(0x2824, "braille_dots_36"); rom(0x2825, "braille_dots_136"); rom(0x2826, "braille_dots_236"); rom(0x2827, "braille_dots_1236"); rom(0x2828, "braille_dots_46"); rom(0x2829, "braille_dots_146"); rom(0x282a, "braille_dots_246"); rom(0x282b, "braille_dots_1246"); rom(0x282c, "braille_dots_346"); rom(0x282d, "braille_dots_1346"); rom(0x282e, "braille_dots_2346"); rom(0x282f, "braille_dots_12346"); rom(0x2830, "braille_dots_56"); rom(0x2831, "braille_dots_156"); rom(0x2832, "braille_dots_256"); rom(0x2833, "braille_dots_1256"); rom(0x2834, "braille_dots_356"); rom(0x2835, "braille_dots_1356"); rom(0x2836, "braille_dots_2356"); rom(0x2837, "braille_dots_12356"); rom(0x2838, "braille_dots_456"); rom(0x2839, "braille_dots_1456"); rom(0x283a, "braille_dots_2456"); rom(0x283b, "braille_dots_12456"); rom(0x283c, "braille_dots_3456"); rom(0x283d, "braille_dots_13456"); rom(0x283e, "braille_dots_23456"); rom(0x283f, "braille_dots_123456"); rom(0x2840, "braille_dots_7"); rom(0x2841, "braille_dots_17"); rom(0x2842, "braille_dots_27"); rom(0x2843, "braille_dots_127"); rom(0x2844, "braille_dots_37"); rom(0x2845, "braille_dots_137"); rom(0x2846, "braille_dots_237"); rom(0x2847, "braille_dots_1237"); rom(0x2848, "braille_dots_47"); rom(0x2849, "braille_dots_147"); rom(0x284a, "braille_dots_247"); rom(0x284b, "braille_dots_1247"); rom(0x284c, "braille_dots_347"); rom(0x284d, "braille_dots_1347"); rom(0x284e, "braille_dots_2347"); rom(0x284f, "braille_dots_12347"); rom(0x2850, "braille_dots_57"); rom(0x2851, "braille_dots_157"); rom(0x2852, "braille_dots_257"); rom(0x2853, "braille_dots_1257"); rom(0x2854, "braille_dots_357"); rom(0x2855, "braille_dots_1357"); rom(0x2856, "braille_dots_2357"); rom(0x2857, "braille_dots_12357"); rom(0x2858, "braille_dots_457"); rom(0x2859, "braille_dots_1457"); rom(0x285a, "braille_dots_2457"); rom(0x285b, "braille_dots_12457"); rom(0x285c, "braille_dots_3457"); rom(0x285d, "braille_dots_13457"); rom(0x285e, "braille_dots_23457"); rom(0x285f, "braille_dots_123457"); rom(0x2860, "braille_dots_67"); rom(0x2861, "braille_dots_167"); rom(0x2862, "braille_dots_267"); rom(0x2863, "braille_dots_1267"); rom(0x2864, "braille_dots_367"); rom(0x2865, "braille_dots_1367"); rom(0x2866, "braille_dots_2367"); rom(0x2867, "braille_dots_12367"); rom(0x2868, "braille_dots_467"); rom(0x2869, "braille_dots_1467"); rom(0x286a, "braille_dots_2467"); rom(0x286b, "braille_dots_12467"); rom(0x286c, "braille_dots_3467"); rom(0x286d, "braille_dots_13467"); rom(0x286e, "braille_dots_23467"); rom(0x286f, "braille_dots_123467"); rom(0x2870, "braille_dots_567"); rom(0x2871, "braille_dots_1567"); rom(0x2872, "braille_dots_2567"); rom(0x2873, "braille_dots_12567"); rom(0x2874, "braille_dots_3567"); rom(0x2875, "braille_dots_13567"); rom(0x2876, "braille_dots_23567"); rom(0x2877, "braille_dots_123567"); rom(0x2878, "braille_dots_4567"); rom(0x2879, "braille_dots_14567"); rom(0x287a, "braille_dots_24567"); rom(0x287b, "braille_dots_124567"); rom(0x287c, "braille_dots_34567"); rom(0x287d, "braille_dots_134567"); rom(0x287e, "braille_dots_234567"); rom(0x287f, "braille_dots_1234567"); rom(0x2880, "braille_dots_8"); rom(0x2881, "braille_dots_18"); rom(0x2882, "braille_dots_28"); rom(0x2883, "braille_dots_128"); rom(0x2884, "braille_dots_38"); rom(0x2885, "braille_dots_138"); rom(0x2886, "braille_dots_238"); rom(0x2887, "braille_dots_1238"); rom(0x2888, "braille_dots_48"); rom(0x2889, "braille_dots_148"); rom(0x288a, "braille_dots_248"); rom(0x288b, "braille_dots_1248"); rom(0x288c, "braille_dots_348"); rom(0x288d, "braille_dots_1348"); rom(0x288e, "braille_dots_2348"); rom(0x288f, "braille_dots_12348"); rom(0x2890, "braille_dots_58"); rom(0x2891, "braille_dots_158"); rom(0x2892, "braille_dots_258"); rom(0x2893, "braille_dots_1258"); rom(0x2894, "braille_dots_358"); rom(0x2895, "braille_dots_1358"); rom(0x2896, "braille_dots_2358"); rom(0x2897, "braille_dots_12358"); rom(0x2898, "braille_dots_458"); rom(0x2899, "braille_dots_1458"); rom(0x289a, "braille_dots_2458"); rom(0x289b, "braille_dots_12458"); rom(0x289c, "braille_dots_3458"); rom(0x289d, "braille_dots_13458"); rom(0x289e, "braille_dots_23458"); rom(0x289f, "braille_dots_123458"); rom(0x28a0, "braille_dots_68"); rom(0x28a1, "braille_dots_168"); rom(0x28a2, "braille_dots_268"); rom(0x28a3, "braille_dots_1268"); rom(0x28a4, "braille_dots_368"); rom(0x28a5, "braille_dots_1368"); rom(0x28a6, "braille_dots_2368"); rom(0x28a7, "braille_dots_12368"); rom(0x28a8, "braille_dots_468"); rom(0x28a9, "braille_dots_1468"); rom(0x28aa, "braille_dots_2468"); rom(0x28ab, "braille_dots_12468"); rom(0x28ac, "braille_dots_3468"); rom(0x28ad, "braille_dots_13468"); rom(0x28ae, "braille_dots_23468"); rom(0x28af, "braille_dots_123468"); rom(0x28b0, "braille_dots_568"); rom(0x28b1, "braille_dots_1568"); rom(0x28b2, "braille_dots_2568"); rom(0x28b3, "braille_dots_12568"); rom(0x28b4, "braille_dots_3568"); rom(0x28b5, "braille_dots_13568"); rom(0x28b6, "braille_dots_23568"); rom(0x28b7, "braille_dots_123568"); rom(0x28b8, "braille_dots_4568"); rom(0x28b9, "braille_dots_14568"); rom(0x28ba, "braille_dots_24568"); rom(0x28bb, "braille_dots_124568"); rom(0x28bc, "braille_dots_34568"); rom(0x28bd, "braille_dots_134568"); rom(0x28be, "braille_dots_234568"); rom(0x28bf, "braille_dots_1234568"); rom(0x28c0, "braille_dots_78"); rom(0x28c1, "braille_dots_178"); rom(0x28c2, "braille_dots_278"); rom(0x28c3, "braille_dots_1278"); rom(0x28c4, "braille_dots_378"); rom(0x28c5, "braille_dots_1378"); rom(0x28c6, "braille_dots_2378"); rom(0x28c7, "braille_dots_12378"); rom(0x28c8, "braille_dots_478"); rom(0x28c9, "braille_dots_1478"); rom(0x28ca, "braille_dots_2478"); rom(0x28cb, "braille_dots_12478"); rom(0x28cc, "braille_dots_3478"); rom(0x28cd, "braille_dots_13478"); rom(0x28ce, "braille_dots_23478"); rom(0x28cf, "braille_dots_123478"); rom(0x28d0, "braille_dots_578"); rom(0x28d1, "braille_dots_1578"); rom(0x28d2, "braille_dots_2578"); rom(0x28d3, "braille_dots_12578"); rom(0x28d4, "braille_dots_3578"); rom(0x28d5, "braille_dots_13578"); rom(0x28d6, "braille_dots_23578"); rom(0x28d7, "braille_dots_123578"); rom(0x28d8, "braille_dots_4578"); rom(0x28d9, "braille_dots_14578"); rom(0x28da, "braille_dots_24578"); rom(0x28db, "braille_dots_124578"); rom(0x28dc, "braille_dots_34578"); rom(0x28dd, "braille_dots_134578"); rom(0x28de, "braille_dots_234578"); rom(0x28df, "braille_dots_1234578"); rom(0x28e0, "braille_dots_678"); rom(0x28e1, "braille_dots_1678"); rom(0x28e2, "braille_dots_2678"); rom(0x28e3, "braille_dots_12678"); rom(0x28e4, "braille_dots_3678"); rom(0x28e5, "braille_dots_13678"); rom(0x28e6, "braille_dots_23678"); rom(0x28e7, "braille_dots_123678"); rom(0x28e8, "braille_dots_4678"); rom(0x28e9, "braille_dots_14678"); rom(0x28ea, "braille_dots_24678"); rom(0x28eb, "braille_dots_124678"); rom(0x28ec, "braille_dots_34678"); rom(0x28ed, "braille_dots_134678"); rom(0x28ee, "braille_dots_234678"); rom(0x28ef, "braille_dots_1234678"); rom(0x28f0, "braille_dots_5678"); rom(0x28f1, "braille_dots_15678"); rom(0x28f2, "braille_dots_25678"); rom(0x28f3, "braille_dots_125678"); rom(0x28f4, "braille_dots_35678"); rom(0x28f5, "braille_dots_135678"); rom(0x28f6, "braille_dots_235678"); rom(0x28f7, "braille_dots_1235678"); rom(0x28f8, "braille_dots_45678"); rom(0x28f9, "braille_dots_145678"); rom(0x28fa, "braille_dots_245678"); rom(0x28fb, "braille_dots_1245678"); rom(0x28fc, "braille_dots_345678"); rom(0x28fd, "braille_dots_1345678"); rom(0x28fe, "braille_dots_2345678"); rom(0x28ff, "braille_dots_12345678"); // Sinhala m(0x0D82, "Sinh_ng"); m(0x0D83, "Sinh_h2"); m(0x0D85, "Sinh_a"); m(0x0D86, "Sinh_aa"); m(0x0D87, "Sinh_ae"); m(0x0D88, "Sinh_aee"); m(0x0D89, "Sinh_i"); m(0x0D8A, "Sinh_ii"); m(0x0D8B, "Sinh_u"); m(0x0D8C, "Sinh_uu"); m(0x0D8D, "Sinh_ri"); m(0x0D8E, "Sinh_rii"); m(0x0D8F, "Sinh_lu"); m(0x0D90, "Sinh_luu"); m(0x0D91, "Sinh_e"); m(0x0D92, "Sinh_ee"); m(0x0D93, "Sinh_ai"); m(0x0D94, "Sinh_o"); m(0x0D95, "Sinh_oo"); m(0x0D96, "Sinh_au"); m(0x0D9A, "Sinh_ka"); m(0x0D9B, "Sinh_kha"); m(0x0D9C, "Sinh_ga"); m(0x0D9D, "Sinh_gha"); m(0x0D9E, "Sinh_ng2"); m(0x0D9F, "Sinh_nga"); m(0x0DA0, "Sinh_ca"); m(0x0DA1, "Sinh_cha"); m(0x0DA2, "Sinh_ja"); m(0x0DA3, "Sinh_jha"); m(0x0DA4, "Sinh_nya"); m(0x0DA5, "Sinh_jnya"); m(0x0DA6, "Sinh_nja"); m(0x0DA7, "Sinh_tta"); m(0x0DA8, "Sinh_ttha"); m(0x0DA9, "Sinh_dda"); m(0x0DAA, "Sinh_ddha"); m(0x0DAB, "Sinh_nna"); m(0x0DAC, "Sinh_ndda"); m(0x0DAD, "Sinh_tha"); m(0x0DAE, "Sinh_thha"); m(0x0DAF, "Sinh_dha"); m(0x0DB0, "Sinh_dhha"); m(0x0DB1, "Sinh_na"); m(0x0DB3, "Sinh_ndha"); m(0x0DB4, "Sinh_pa"); m(0x0DB5, "Sinh_pha"); m(0x0DB6, "Sinh_ba"); m(0x0DB7, "Sinh_bha"); m(0x0DB8, "Sinh_ma"); m(0x0DB9, "Sinh_mba"); m(0x0DBA, "Sinh_ya"); m(0x0DBB, "Sinh_ra"); m(0x0DBD, "Sinh_la"); m(0x0DC0, "Sinh_va"); m(0x0DC1, "Sinh_sha"); m(0x0DC2, "Sinh_ssha"); m(0x0DC3, "Sinh_sa"); m(0x0DC4, "Sinh_ha"); m(0x0DC5, "Sinh_lla"); m(0x0DC6, "Sinh_fa"); m(0x0DCA, "Sinh_al"); m(0x0DCF, "Sinh_aa2"); m(0x0DD0, "Sinh_ae2"); m(0x0DD1, "Sinh_aee2"); m(0x0DD2, "Sinh_i2"); m(0x0DD3, "Sinh_ii2"); m(0x0DD4, "Sinh_u2"); m(0x0DD6, "Sinh_uu2"); m(0x0DD8, "Sinh_ru2"); m(0x0DD9, "Sinh_e2"); m(0x0DDA, "Sinh_ee2"); m(0x0DDB, "Sinh_ai2"); m(0x0DDC, "Sinh_o2"); m(0x0DDD, "Sinh_oo2"); m(0x0DDE, "Sinh_au2"); m(0x0DDF, "Sinh_lu2"); m(0x0DF2, "Sinh_ruu2"); m(0x0DF3, "Sinh_luu2"); m(0x0DF4, "Sinh_kunddaliya"); } private void m(int u, String n) { if (!u2n.containsKey(u)) u2n.put(u, n); if (!n2u.containsKey(n)) n2u.put(n, u); } private void rom(int u, String n) { if (!n2u.containsKey(n)) n2u.put(n, u); } public String getKeySym(int u) { if (u2n.containsKey(u)) return u2n.get(u); return getUKeySym(u); } public String getUKeySym(int u) { String s = Integer.toHexString(u).toUpperCase(); while (s.length() < 4) s = "0" + s; return "U" + s; } public int resolveKeySym(String n) { if (n2u.containsKey(n)) return n2u.get(n); if (!n.startsWith("U")) return -1; try { return Integer.parseInt(n.substring(1), 16); } catch (NumberFormatException nfe) { return -1; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbReader.java000066400000000000000000000236171506470510200274600ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class XkbReader { public static KeyboardMapping read(File file) throws IOException { KeyboardMapping km = new KeyboardMapping(); readEvdev(file, km); readSymbols(file, km); File icon = new File(file.getParentFile(), file.getName() + ".png"); if (icon.isFile()) km.icon = ImageIO.read(icon); return km; } public static void readEvdev(File file, KeyboardMapping km) throws IOException { StringBuffer sb = new StringBuffer(file.getName()); file = file.getParentFile(); while (file != null) { if (file.getName().equals("symbols")) { File rules = new File(file.getParentFile(), "rules"); if (rules.isDirectory()) { boolean found = false; for (File f : rules.listFiles()) { if (f.getName().toLowerCase().endsWith(".xml")) { readEvdev(sb.toString(), f, km); found = true; } } if (found) return; } } File f = new File(file, "evdev.xml"); if (f.isFile()) { readEvdev(sb.toString(), f, km); return; } sb.insert(0, "/"); sb.insert(0, file.getName()); file = file.getParentFile(); } } public static void readEvdev(String matchingPath, File file, KeyboardMapping km) throws IOException { FileInputStream in = new FileInputStream(file); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); // make sure the XML is valid factory.setExpandEntityReferences(false); // don't allow custom entities DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new EvdevEntityResolver()); builder.setErrorHandler(new EvdevErrorHandler(file.getName())); Document document = builder.parse(new InputSource(in)); parseDocument(matchingPath, document, km); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException saxe) { throw new IOException(saxe); } finally { in.close(); } } private static void parseDocument(String matchingPath, Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("#document")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("xkbConfigRegistry")) { if (child.hasAttributes() || child.hasChildNodes()) { parseXkbConfigRegistry(matchingPath, child, km); return; } } else { throw new IOException("Unknown element: " + ctype); } } throw new IOException("Empty document."); } else { throw new IOException("Unknown element: " + type); } } private static void parseXkbConfigRegistry(String matchingPath, Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("xkbConfigRegistry")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("layoutList")) { parseLayoutList(matchingPath, child, km); } } } else { throw new IOException("Unknown element: " + type); } } private static void parseLayoutList(String matchingPath, Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("layoutList")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("layout")) { parseLayout(matchingPath, child, km); } } } else { throw new IOException("Unknown element: " + type); } } private static void parseLayout(String matchingPath, Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("layout")) { for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("configItem")) { parseConfigItem(matchingPath, child, km); } } } else { throw new IOException("Unknown element: " + type); } } private static void parseConfigItem(String matchingPath, Node node, KeyboardMapping km) throws IOException { String type = node.getNodeName(); if (type.equalsIgnoreCase("configItem")) { String path = null; String label = null; String name = null; for (Node child : getChildren(node)) { String ctype = child.getNodeName(); if (ctype.equalsIgnoreCase("name")) { path = child.getTextContent(); } else if (ctype.equalsIgnoreCase("shortDescription")) { label = child.getTextContent(); } else if (ctype.equalsIgnoreCase("description")) { name = child.getTextContent(); } } if (matchingPath == null || matchingPath.equals(path)) { km.xkbPath = path; km.xkbLabel = label; km.name = name; } } else { throw new IOException("Unknown element: " + type); } } public static void readSymbols(File in, KeyboardMapping km) throws IOException { Scanner scan = new Scanner(new FileInputStream(in), "UTF-8"); readSymbols(scan, km); scan.close(); } public static void readSymbols(Scanner in, KeyboardMapping km) { km.xkbComment = null; km.xkbAltGrKey = XkbAltGrKey.none; km.xkbComposeKey = XkbComposeKey.none; while (in.hasNextLine()) { String line = in.nextLine().trim(); if (line.startsWith("//")) { line = line.substring(2).trim(); if (km.xkbComment == null) { km.xkbComment = line; } else { km.xkbComment += "\n"; km.xkbComment += line; } continue; } Matcher nameMatch = NAME_PATTERN.matcher(line); if (nameMatch.find()) { km.name = nameMatch.group(1); continue; } Matcher keyMatch = KEY_PATTERN.matcher(line); if (keyMatch.find()) { XkbKey key = XkbKey.forId(keyMatch.group(1)); if (key != null) { String[] fields = keyMatch.group(2).trim().split(","); String u = (fields.length > 0) ? fields[0].trim() : null; String s = (fields.length > 1) ? fields[1].trim() : null; String au = (fields.length > 2) ? fields[2].trim() : null; String as = (fields.length > 3) ? fields[3].trim() : null; KeyMapping k = km.map.get(key.key); k.unshiftedOutput = keysymOutput(u); k.shiftedOutput = keysymOutput(s); k.altUnshiftedOutput = keysymOutput(au); k.altShiftedOutput = keysymOutput(as); k.capsLockMapping = CapsLockMapping.AUTO; k.altCapsLockMapping = CapsLockMapping.AUTO; k.unshiftedDeadKey = keysymDeadKey(u); k.shiftedDeadKey = keysymDeadKey(s); k.altUnshiftedDeadKey = keysymDeadKey(au); k.altShiftedDeadKey = keysymDeadKey(as); } continue; } Matcher includeMatch = INCLUDE_PATTERN.matcher(line); if (includeMatch.find()) { String what = includeMatch.group(1); if (what.startsWith("level3")) km.xkbAltGrKey = XkbAltGrKey.forInclude(what); if (what.startsWith("compose")) km.xkbComposeKey = XkbComposeKey.forInclude(what); continue; } } } private static final Pattern NAME_PATTERN = Pattern.compile("^name[^=]*=[^\"]*\"([^\"]*)\"[^;]*;"); private static final Pattern KEY_PATTERN = Pattern.compile("^key[^<]*<([^>]*)>[^{]*\\{[^\\[]*\\[([^\\]]*)\\][^}]*\\}[^;]*;"); private static final Pattern INCLUDE_PATTERN = Pattern.compile("^include[^\"]*\"([^\"]*)\""); private static int keysymOutput(String s) { if (s == null || s.startsWith("dead_")) return -1; return XkbKeySym.MAP.resolveKeySym(s); } private static DeadKeyTable keysymDeadKey(String s) { if (s == null || !s.startsWith("dead_")) return null; XkbDeadKey dead = XkbDeadKey.forKeySym(s); if (dead == null || dead == XkbDeadKey.none) return null; DeadKeyTable dkt = new DeadKeyTable(); dkt.xkbDeadKey = dead; return dkt; } private static List getChildren(Node node) { List list = new ArrayList(); if (node != null) { NodeList children = node.getChildNodes(); if (children != null) { int count = children.getLength(); for (int i = 0; i < count; i++) { Node child = children.item(i); if (child != null) { String type = child.getNodeName(); if (type.equalsIgnoreCase("#text") || type.equalsIgnoreCase("#comment")) { continue; } else { list.add(child); } } } } } return list; } private static class EvdevEntityResolver implements EntityResolver { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (systemId.contains("xkb.dtd")) { return new InputSource(XkbReader.class.getResourceAsStream("xkb.dtd")); } else { return null; } } } private static class EvdevErrorHandler implements ErrorHandler { private final String name; public EvdevErrorHandler(String name) { this.name = name; } @Override public void error(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void fatalError(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("FATAL ERROR on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } @Override public void warning(SAXParseException e) throws SAXException { System.err.print("Warning: Failed to parse " + name + ": "); System.err.println("WARNING on "+e.getLineNumber()+":"+e.getColumnNumber()+": "+e.getMessage()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/XkbWriter.java000066400000000000000000000214501506470510200275230ustar00rootroot00000000000000package com.kreative.keyedit; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Scanner; import javax.imageio.ImageIO; public class XkbWriter { public static void write(File dir, KeyboardMapping km) throws IOException { dir.mkdir(); appendEvdev(dir, km); writeSymbols(dir, km); if (km.icon != null) { File icon = unixNewFile(dir, km.getXkbPathNotEmpty() + ".png"); ImageIO.write(km.icon, "png", icon); } if (!(km.xkbAttachments == null || km.xkbAttachments.isEmpty())) { for (Map.Entry e : km.xkbAttachments.entrySet()) { FileOutputStream fos = new FileOutputStream(unixNewFile(dir, e.getKey())); fos.write(e.getValue()); fos.flush(); fos.close(); } } writeInstall(new File(dir, "install.py"), km.getXkbPathNotEmpty(), km.getNameNotEmpty()); } public static void appendEvdev(File dir, KeyboardMapping km) throws IOException { File evdev = new File(dir, "evdev.xml"); if (evdev.isFile()) { List preLines = new ArrayList(); List postLines = new ArrayList(); boolean foundLayoutListEnd = false; Scanner scan = new Scanner(new FileInputStream(evdev), "UTF-8"); while (scan.hasNextLine()) { String line = scan.nextLine(); if (line.trim().equalsIgnoreCase("")) foundLayoutListEnd = true; (foundLayoutListEnd ? postLines : preLines).add(line); } scan.close(); FileOutputStream fos = new FileOutputStream(evdev); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); for (String line : preLines) pw.print(line + "\n"); writeEvdevLayout(pw, km); for (String line : postLines) pw.print(line + "\n"); pw.flush(); pw.close(); fos.close(); } else { FileOutputStream fos = new FileOutputStream(evdev); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); writeEvdev(pw, km); pw.flush(); pw.close(); fos.close(); } } public static void writeEvdev(PrintWriter out, KeyboardMapping km) { out.print("\n"); out.print("\n"); out.print("\n"); out.print(" \n"); writeEvdevLayout(out, km); out.print(" \n"); out.print("\n"); } public static void writeEvdevLayout(PrintWriter out, KeyboardMapping km) { out.print(" \n"); out.print(" \n"); out.print(" " + xmlEncode(km.getXkbPathNotEmpty()) + "\n"); out.print(" " + xmlEncode(km.getXkbLabelNotEmpty()) + "\n"); out.print(" " + xmlEncode(km.getNameNotEmpty()) + "\n"); out.print(" \n"); out.print(" \n"); out.print(" \n"); } public static void writeSymbols(File dir, KeyboardMapping km) throws IOException { FileOutputStream fos = new FileOutputStream(unixNewFile(dir, km.getXkbPathNotEmpty())); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); writeSymbols(pw, km); pw.flush(); pw.close(); fos.close(); } public static void writeSymbols(PrintWriter out, KeyboardMapping km) { out.print("default partial alphanumeric_keys modifier_keys\n"); out.print("xkb_symbols \"intl\" {\n"); out.print("\n"); out.print(" name[Group1]=\"" + km.getNameNotEmpty() + "\";\n"); out.print("\n"); if (km.xkbComment != null && km.xkbComment.length() > 0) { String[] lines = km.xkbComment.replaceAll("\r\n","\n").replaceAll("\r","\n").split("\n"); for (String line : lines) out.print(" // " + line + "\n"); out.print("\n"); } List unshifted = new ArrayList(); List shifted = new ArrayList(); List altUnshifted = new ArrayList(); List altShifted = new ArrayList(); for (XkbKey key : XkbKey.KEYS) { if (key == null) { unshifted.add(null); shifted.add(null); altUnshifted.add(null); altShifted.add(null); } else { KeyMapping k = km.map.get(key.key); String du = keysym(key.key.defaultUnshifted, null, km.xkbUseKeySym, null); String ds = keysym(key.key.defaultShifted, null, km.xkbUseKeySym, null); String u = keysym(k.unshiftedOutput, k.unshiftedDeadKey, km.xkbUseKeySym, du); String s = keysym(k.shiftedOutput, k.shiftedDeadKey, km.xkbUseKeySym, ds); String au = keysym(k.altUnshiftedOutput, k.altUnshiftedDeadKey, km.xkbUseKeySym, u); String as = keysym(k.altShiftedOutput, k.altShiftedDeadKey, km.xkbUseKeySym, s); unshifted.add(u); shifted.add(s); altUnshifted.add(au); altShifted.add(as); } } int ul = maxLength(unshifted); int sl = maxLength(shifted); int aul = maxLength(altUnshifted); int asl = maxLength(altShifted); for (int i = 0, n = XkbKey.KEYS.size(); i < n; i++) { XkbKey key = XkbKey.KEYS.get(i); if (key == null) { out.print("\n"); } else { String u = unshifted.get(i); String s = shifted.get(i); String au = altUnshifted.get(i); String as = altShifted.get(i); out.print(" key <" + key.id + "> { [ "); out.print(u + ", " + spaces(ul - u.length())); out.print(s + ", " + spaces(sl - s.length())); out.print(au + ", " + spaces(aul - au.length())); out.print(as + spaces(asl - as.length())); out.print(" ] };\n"); } } boolean altgr = (km.xkbAltGrKey != null && km.xkbAltGrKey != XkbAltGrKey.none); boolean compose = (km.xkbComposeKey != null && km.xkbComposeKey != XkbComposeKey.none); if (altgr || compose) { out.print("\n"); if (altgr) out.print(" include \"level3(" + km.xkbAltGrKey.name() + ")\"\n"); if (compose) out.print(" include \"compose(" + km.xkbComposeKey.name() + ")\"\n"); } out.print("\n"); out.print("};\n"); } public static void writeInstall(File install, String name, String dispName) throws IOException { FileOutputStream fos = new FileOutputStream(install); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"), true); writeInstall(pw, name, dispName); pw.flush(); pw.close(); fos.close(); try { String[] cmd = {"chmod", "+x", install.getAbsolutePath()}; Process p = Runtime.getRuntime().exec(cmd); try { p.waitFor(); } catch (InterruptedException e) {} } catch (IOException e) { // Ignored. } } public static void writeInstall(PrintWriter out, String name, String dispName) { Scanner scan = new Scanner(XkbWriter.class.getResourceAsStream("install.py"), "UTF-8"); while (scan.hasNextLine()) out.println(scan.nextLine()); scan.close(); out.println(); out.println(); out.println("main(" + quote(name) + ", " + quote(dispName) + ")"); out.println(); out.println(); } private static String quote(String s) { StringBuffer sb = new StringBuffer(); sb.append('\''); for (char ch : s.toCharArray()) { if (ch == '\\' || ch == '\'') sb.append('\\'); sb.append(ch); } sb.append('\''); return sb.toString(); } private static String keysym(int output, DeadKeyTable dead, boolean useKeySym, String def) { if (dead != null) { if (dead.xkbDeadKey != null && dead.xkbDeadKey != XkbDeadKey.none) { return dead.xkbDeadKey.name(); } if (dead.xkbOutput > 0) { if (useKeySym || (dead.xkbOutput <= 0xA0)) { return XkbKeySym.MAP.getKeySym(dead.xkbOutput); } else { return XkbKeySym.MAP.getUKeySym(dead.xkbOutput); } } } if (output > 0) { if (useKeySym || output <= 0xA0) { return XkbKeySym.MAP.getKeySym(output); } else { return XkbKeySym.MAP.getUKeySym(output); } } return def; } private static int maxLength(Iterable c) { int maxLength = 0; if (c != null) { for (String s : c) { if (s != null && s.length() > maxLength) { maxLength = s.length(); } } } return maxLength; } private static String spaces(int n) { String s = " "; while (s.length() < n) s += s; return s.substring(0, n); } private static String xmlEncode(String s) { if (s == null) return ""; StringBuffer sb = new StringBuffer(); int i = 0; while (i < s.length()) { int ch = s.codePointAt(i); if ( ch < 0x20 || ch >= 0x7F || ch == '"' || ch == '\'' || ch == '&' || ch == '<' || ch == '>' ) { String h = Integer.toHexString(ch).toUpperCase(); while (h.length() < 4) h = "0" + h; sb.append("&#x" + h + ";"); } else { sb.append((char)ch); } i += Character.charCount(ch); } return sb.toString(); } private static File unixNewFile(File dir, String path) { for (String name : path.split("/")) { dir.mkdir(); dir = new File(dir, name); } return dir; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/base-keymanphp.css000066400000000000000000000002371506470510200303550ustar00rootroot00000000000000th, td { padding: 1pt 12pt 1pt 0pt; text-align: left; } .hidden { display: none !important; } code { font-size: 10pt; font-weight: bold; padding: 4px; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/base.css000066400000000000000000000017051506470510200263640ustar00rootroot00000000000000/* BASE */ * { margin: 0; padding: 0; } body { font-family: Helvetica, sans-serif; font-size: 11pt; background: white; color: black; margin: 14pt; } h1, h2, h3, h4, h5, h6 { margin: 14pt 0pt; font-family: Futura, Helvetica, sans-serif; font-weight: bold; } h1 { font-size: 22pt; } h2 { font-size: 18pt; } h3 { font-size: 14pt; } h4 { font-size: 12pt; } h5 { font-size: 11pt; } h6 { font-size: 10pt; } p, pre, ul, ol, table, blockquote { margin: 12pt 0pt; font-size: 11pt; } th, td { padding: 1pt 12pt 1pt 0pt; text-align: left; } a:link { color: #9900cc; text-decoration: none; } a:visited { color: #cc00ff; text-decoration: none; } a:active { color: #ff0000; text-decoration: underline; } a:hover { color: #ff00ff; text-decoration: underline; } .center { text-align: center; } .center > * { margin-left: auto; margin-right: auto; } .hidden { display: none !important; } code { font-size: 10pt; font-weight: bold; padding: 4px; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/000077500000000000000000000000001506470510200256625ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/BufferedImageWell.java000066400000000000000000000101231506470510200320330ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Color; import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; import java.util.List; import javax.imageio.ImageIO; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JLabel; public class BufferedImageWell extends JLabel { private static final long serialVersionUID = 1L; private static final Color FOCUSED = new Color(0xFF6699CC); private BufferedImage image; public BufferedImageWell(BufferedImage image) { this.setHorizontalAlignment(JLabel.CENTER); this.setVerticalAlignment(JLabel.CENTER); this.setImage(image); this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); this.setFocusable(true); this.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, FOCUSED)); } public void focusLost(FocusEvent e) { setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); } }); this.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { requestFocusInWindow(); } }); this.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.isMetaDown() || e.isControlDown()) { switch (e.getKeyCode()) { case KeyEvent.VK_X: case KeyEvent.VK_CUT: cut(); break; case KeyEvent.VK_C: case KeyEvent.VK_COPY: copy(); break; case KeyEvent.VK_V: case KeyEvent.VK_PASTE: paste(); break; case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_DELETE: setImage(null); break; } } } }); new DropTarget(this, new DropTargetListener() { public void dragEnter(DropTargetDragEvent e) {} public void dragExit(DropTargetEvent e) {} public void dragOver(DropTargetDragEvent e) {} public void dropActionChanged(DropTargetDragEvent e) {} public void drop(DropTargetDropEvent e) { e.acceptDrop(e.getDropAction()); Transferable t = e.getTransferable(); try { if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image = (Image)t.getTransferData(DataFlavor.imageFlavor); if (image != null) { setImage(SwingUtils.toBufferedImage(image)); e.dropComplete(true); return; } } if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { List list = (List)t.getTransferData(DataFlavor.javaFileListFlavor); if (list != null && list.size() == 1) { BufferedImage image = ImageIO.read((File)list.get(0)); if (image != null) { setImage(image); e.dropComplete(true); return; } } } } catch (Exception e2) {} e.dropComplete(false); } }); } public BufferedImage getImage() { return this.image; } public void setImage(BufferedImage image) { this.image = image; this.setIcon((image != null) ? new ImageIcon(image) : null); } public void cut() { copy(); setImage(null); } public void copy() { if (image != null) { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); ImageSelection sel = new ImageSelection(image); cb.setContents(sel, sel); } } public void paste() { try { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(DataFlavor.imageFlavor)) { Object data = cb.getData(DataFlavor.imageFlavor); if (data instanceof Image) { Image image = (Image)data; setImage(SwingUtils.toBufferedImage(image)); } } } catch (Exception ex) { ex.printStackTrace(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/CodePointClassTableModel.java000066400000000000000000000045511506470510200333350ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import java.util.Map; import javax.swing.table.AbstractTableModel; import com.kreative.keyedit.KkbReader; import com.kreative.keyedit.KkbWriter; public class CodePointClassTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final List entries; public CodePointClassTableModel(Map map) { this.entries = new ArrayList(); for (Map.Entry e : map.entrySet()) { Entry entry = new Entry(); entry.className = e.getKey(); entry.codepoints = new BitSet(); entry.codepoints.or(e.getValue()); this.entries.add(entry); } } public void addEntry(String className, BitSet codepoints) { int i = entries.size(); Entry entry = new Entry(); entry.className = className; entry.codepoints = new BitSet(); entry.codepoints.or(codepoints); entries.add(entry); fireTableRowsInserted(i, i); } public void deleteEntry(int i) { entries.remove(i); fireTableRowsDeleted(i, i); } public void toMap(Map map) { map.clear(); for (Entry e : entries) { BitSet bs = map.get(e.className); if (bs == null) map.put(e.className, (bs = new BitSet())); bs.or(e.codepoints); } } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Class Name"; case 1: return "Code Points"; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { Entry e = entries.get(row); switch (col) { case 0: return e.className; case 1: return KkbWriter.formatRanges(e.codepoints); default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object value, int row, int col) { Entry e = entries.get(row); switch (col) { case 0: e.className = value.toString().trim(); break; case 1: e.codepoints = KkbReader.parseRanges(value.toString()); break; default: break; } } private static class Entry { private String className; private BitSet codepoints; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/CodePointLabelTableModel.java000066400000000000000000000061501506470510200333040ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.swing.table.AbstractTableModel; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class CodePointLabelTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final NameDatabase ndb; private final String labelType; private final List entries; public CodePointLabelTableModel(Map map, String labelType) { this.ndb = NameDatabase.instance(); this.labelType = labelType; this.entries = new ArrayList(); for (Map.Entry e : map.entrySet()) { Entry entry = new Entry(); entry.codepoint = e.getKey(); entry.label = e.getValue(); this.entries.add(entry); } } public void addEntry(int codepoint, String label) { int i = entries.size(); Entry entry = new Entry(); entry.codepoint = codepoint; entry.label = label; entries.add(entry); fireTableRowsInserted(i, i); } public void deleteEntry(int i) { entries.remove(i); fireTableRowsDeleted(i, i); } public void toMap(Map map) { map.clear(); for (Entry e : entries) { map.put(e.codepoint, e.label); } } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Code Point"; case 1: return "Character"; case 2: return "Character Name"; case 3: return labelType; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { Entry e = entries.get(row); switch (col) { case 0: if (e.codepoint < 0) return null; String h = Integer.toHexString(e.codepoint); while (h.length() < 4) h = "0" + h; return h.toUpperCase(); case 1: if (e.codepoint < 0) return null; return String.valueOf(Character.toChars(e.codepoint)); case 2: if (e.codepoint < 0) return null; return NameResolver.instance(e.codepoint).getName(e.codepoint); case 3: return e.label; default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object value, int row, int col) { Entry e = entries.get(row); switch (col) { case 0: try { int cp = Integer.parseInt(value.toString().trim(), 16); if (cp > 0) e.codepoint = cp; } catch (NumberFormatException nfe) { // Ignored } break; case 1: String s = value.toString(); if (s.length() > 0) e.codepoint = s.codePointAt(0); break; case 2: NameDatabase.NameEntry ne = ndb.find(value.toString().trim()); if (ne != null) e.codepoint = ne.codePoint; break; case 3: String a = value.toString().trim(); if (a.length() > 0) e.label = a; break; default: break; } fireTableRowsUpdated(row, row); } private static class Entry { private int codepoint; private String label; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/CodePointTableModel.java000066400000000000000000000103701506470510200323430ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class CodePointTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final NameDatabase ndb; private final List entries; public CodePointTableModel() { this.ndb = NameDatabase.instance(); this.entries = new ArrayList(); } public CodePointTableModel(List entries) { this(); if (entries != null) this.entries.addAll(entries); } public CodePointTableModel(Integer[] entries) { this(); if (entries != null) for (int e : entries) this.entries.add(e); } public CodePointTableModel(int[] entries) { this(); if (entries != null) for (int e : entries) this.entries.add(e); } public void addEntry(int codepoint) { int i = entries.size(); entries.add(codepoint); fireTableRowsInserted(i, i); } public void deleteEntry(int i) { entries.remove(i); fireTableRowsDeleted(i, i); } public void moveEntry(int i, int dir) { if (dir < 0 && i > 0) { Integer e = entries.remove(i); i -= 1; entries.add(i, e); fireTableRowsUpdated(i, i + 1); } if (dir > 0 && i < (entries.size() - 1)) { Integer e = entries.remove(i); i += 1; entries.add(i, e); fireTableRowsUpdated(i - 1, i); } } public void addEntries(List entries) { if (entries != null && entries.size() > 0) { int i = this.entries.size(); int j = i + entries.size() - 1; this.entries.addAll(entries); fireTableRowsInserted(i, j); } } public void addEntries(Integer[] entries) { if (entries != null && entries.length > 0) { int i = this.entries.size(); int j = i + entries.length - 1; for (int e : entries) this.entries.add(e); fireTableRowsInserted(i, j); } } public void addEntries(int[] entries) { if (entries != null && entries.length > 0) { int i = this.entries.size(); int j = i + entries.length - 1; for (int e : entries) this.entries.add(e); fireTableRowsInserted(i, j); } } public void clearEntries() { int i = entries.size(); if (i > 0) { entries.clear(); fireTableRowsDeleted(0, i - 1); } } public boolean isEmpty() { return entries.isEmpty(); } public int size() { return entries.size(); } public void toList(List entries) { entries.clear(); entries.addAll(this.entries); } public Integer[] toIntegerArray() { return entries.toArray(new Integer[entries.size()]); } public int[] toIntArray() { Integer[] A = toIntegerArray(); int[] a = new int[A.length]; for (int i = 0; i < A.length; i++) a[i] = A[i]; return a; } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 3; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Code Point"; case 1: return "Character"; case 2: return "Character Name"; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { int cp = entries.get(row); switch (col) { case 0: if (cp < 0) return null; String h = Integer.toHexString(cp); while (h.length() < 4) h = "0" + h; return h.toUpperCase(); case 1: if (cp < 0) return null; return String.valueOf(Character.toChars(cp)); case 2: if (cp < 0) return null; return NameResolver.instance(cp).getName(cp); default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object value, int row, int col) { switch (col) { case 0: try { int cp = Integer.parseInt(value.toString().trim(), 16); if (cp > 0) entries.set(row, cp); } catch (NumberFormatException nfe) { // Ignored } break; case 1: String s = value.toString(); if (s.length() > 0) entries.set(row, s.codePointAt(0)); break; case 2: NameDatabase.NameEntry ne = ndb.find(value.toString().trim()); if (ne != null) entries.set(row, ne.codePoint); break; default: break; } fireTableRowsUpdated(row, row); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/DeadKeyMapTableModel.java000066400000000000000000000100431506470510200324200ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.swing.table.AbstractTableModel; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class DeadKeyMapTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final NameDatabase ndb; private final List entries; public DeadKeyMapTableModel(Map map) { this.ndb = NameDatabase.instance(); this.entries = new ArrayList(); for (Map.Entry e : map.entrySet()) { Entry entry = new Entry(); entry.input = e.getKey(); entry.output = e.getValue(); this.entries.add(entry); } } public void addEntry(int input, int output) { int i = entries.size(); Entry entry = new Entry(); entry.input = input; entry.output = output; entries.add(entry); fireTableRowsInserted(i, i); } public void deleteEntry(int i) { entries.remove(i); fireTableRowsDeleted(i, i); } public void moveEntry(int i, int dir) { if (dir < 0 && i > 0) { Entry e = entries.remove(i); i -= 1; entries.add(i, e); fireTableRowsUpdated(i, i + 1); } if (dir > 0 && i < (entries.size() - 1)) { Entry e = entries.remove(i); i += 1; entries.add(i, e); fireTableRowsUpdated(i - 1, i); } } public void toMap(Map map) { map.clear(); for (Entry e : entries) { map.put(e.input, e.output); } } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 6; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Input Code"; case 1: return "Input Char"; case 2: return "Input Character Name"; case 3: return "Output Code"; case 4: return "Output Char"; case 5: return "Output Character Name"; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { Entry e = entries.get(row); switch (col) { case 0: if (e.input < 0) return null; String ih = Integer.toHexString(e.input); while (ih.length() < 4) ih = "0" + ih; return ih.toUpperCase(); case 1: if (e.input < 0) return null; return String.valueOf(Character.toChars(e.input)); case 2: if (e.input < 0) return null; return NameResolver.instance(e.input).getName(e.input); case 3: if (e.output < 0) return null; String oh = Integer.toHexString(e.output); while (oh.length() < 4) oh = "0" + oh; return oh.toUpperCase(); case 4: if (e.output < 0) return null; return String.valueOf(Character.toChars(e.output)); case 5: if (e.output < 0) return null; return NameResolver.instance(e.output).getName(e.output); default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object value, int row, int col) { Entry e = entries.get(row); switch (col) { case 0: try { int cp = Integer.parseInt(value.toString().trim(), 16); if (cp > 0) e.input = cp; } catch (NumberFormatException nfe) { // Ignored } break; case 1: String is = value.toString(); if (is.length() > 0) e.input = is.codePointAt(0); break; case 2: NameDatabase.NameEntry ine = ndb.find(value.toString().trim()); if (ine != null) e.input = ine.codePoint; break; case 3: try { int cp = Integer.parseInt(value.toString().trim(), 16); if (cp > 0) e.output = cp; } catch (NumberFormatException nfe) { // Ignored } break; case 4: String os = value.toString(); if (os.length() > 0) e.output = os.codePointAt(0); break; case 5: NameDatabase.NameEntry one = ndb.find(value.toString().trim()); if (one != null) e.output = one.codePoint; break; default: break; } fireTableRowsUpdated(row, row); } private static class Entry { private int input; private int output; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/DeadKeyTableFrame.java000066400000000000000000000042141506470510200317570ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import com.kreative.keyedit.DeadKeyTable; public class DeadKeyTableFrame extends JDialog { private static final long serialVersionUID = 1L; private final DeadKeyTablePanel panel; private final List listeners; public DeadKeyTableFrame(Frame parent, DeadKeyTable dead) { super(parent, "Edit Dead Key"); this.panel = new DeadKeyTablePanel(dead); this.listeners = new ArrayList(); JButton cancelButton = new JButton("Cancel"); JButton okButton = new JButton("OK"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(cancelButton); buttonPanel.add(okButton); JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(this.panel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDefaultButton(getRootPane(), okButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.commit(); dispose(); for (KeyEditListener l : listeners) l.keyMappingChanged(); } }); setSize(900, 600); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } public void addListener(KeyEditListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyEditListener listener) { if (listener != null) listeners.remove(listener); } public KeyEditListener[] getListeners() { return listeners.toArray(new KeyEditListener[listeners.size()]); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/DeadKeyTablePanel.java000066400000000000000000000164071506470510200317730ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.table.TableColumn; import com.kreative.keyedit.DeadKeyTable; import com.kreative.keyedit.XkbDeadKey; public class DeadKeyTablePanel extends JPanel { private static final long serialVersionUID = 1L; private final DeadKeyTable dead; private final OutputPanel winTerminator; private final OutputPanel macTerminator; private final JTextField macStateId; private final OutputPanel xkbOutput; private final JComboBox xkbDeadKey; private final DeadKeyMapTableModel keyMapModel; private final JTable keyMapTable; private final JScrollPane keyMapPane; private final JButton keyMapAdd; private final JButton keyMapDelete; private final JButton keyMapUp; private final JButton keyMapDown; public DeadKeyTablePanel(DeadKeyTable dead) { this.dead = dead; this.winTerminator = new OutputPanel(dead.winTerminator); this.macTerminator = new OutputPanel(dead.macTerminator); this.macStateId = new JTextField(dead.macStateId); this.xkbOutput = new OutputPanel(dead.xkbOutput); this.xkbDeadKey = new JComboBox(XkbDeadKey.values()); this.xkbDeadKey.setEditable(false); this.xkbDeadKey.setSelectedItem(dead.xkbDeadKey); this.keyMapModel = new DeadKeyMapTableModel(dead.keyMap); this.keyMapTable = new JTable(this.keyMapModel); this.keyMapPane = scrollWrap(this.keyMapTable); this.keyMapAdd = square(new JButton("+")); this.keyMapAdd.addActionListener(new AddKeyMapActionListener()); this.keyMapDelete = square(new JButton("\u2212")); this.keyMapDelete.addActionListener(new DeleteKeyMapActionListener()); this.keyMapUp = square(new JButton("\u2191")); this.keyMapUp.addActionListener(new MoveUpKeyMapActionListener()); this.keyMapDown = square(new JButton("\u2193")); this.keyMapDown.addActionListener(new MoveDownKeyMapActionListener()); setColumnWidth(keyMapTable, 0, 80); setColumnWidth(keyMapTable, 1, 80); setColumnWidth(keyMapTable, 3, 80); setColumnWidth(keyMapTable, 4, 80); JPanel labels = verticalStack( l("Terminator (Win):", "The default output on Windows. Windows only allows some characters to be used as terminators."), l("Terminator (Mac):", "The default output on Mac OS X. Mac OS X allows any character to be used as a terminator."), l("State ID (Mac):", "The identifier to be used for this dead key state."), l("Xkb Keysym:", "The dead key to engage on Linux. If “none” is selected, use “Xkb Output” instead. Linux ignores all other settings, including the key map."), l("Xkb Output:", "The output on Linux, if “none” is selected above.") ); JPanel fields = verticalStack(winTerminator, macTerminator, macStateId, leftAlign(xkbDeadKey), xkbOutput); JPanel keymap = topSxS(new JLabel("Key Map:"), keyMapPane, 4); JPanel button = leftAlign(horizontalStack(keyMapAdd, keyMapDelete, keyMapUp, keyMapDown)); JPanel panel = verticalSxS(leftSxS(labels, fields, 8), keymap, button, 8); setLayout(new GridLayout(1,1,0,0)); add(panel); } private static JLabel l(String label, String tooltip) { JLabel c = new JLabel(label); c.setToolTipText(tooltip); return c; } private static JPanel verticalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(0,1,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel horizontalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel leftAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.LINE_START); return p; } private static JPanel leftSxS(Component l, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(l, BorderLayout.LINE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel topSxS(Component t, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel verticalSxS(Component t, Component c, Component b, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); p.add(b, BorderLayout.PAGE_END); return p; } private static C square(C c) { Dimension d = c.getPreferredSize(); d.width = (d.height += 8); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); c.putClientProperty("JButton.buttonType", "bevel"); return c; } private static JScrollPane scrollWrap(Component c) { return new JScrollPane( c, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); } private static void setColumnWidth(JTable t, int col, int w) { TableColumn column = t.getColumnModel().getColumn(col); column.setMinWidth(w); column.setPreferredWidth(w); column.setMaxWidth(w); } public void commit() { dead.winTerminator = this.winTerminator.getOutput(); dead.macTerminator = this.macTerminator.getOutput(); dead.macStateId = this.macStateId.getText(); dead.xkbOutput = this.xkbOutput.getOutput(); dead.xkbDeadKey = (XkbDeadKey)this.xkbDeadKey.getSelectedItem(); this.keyMapModel.toMap(dead.keyMap); } private class AddKeyMapActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = keyMapModel.getRowCount(); keyMapModel.addEntry(32, ( (dead.macTerminator > 0) ? dead.macTerminator : (dead.winTerminator > 0) ? dead.winTerminator : (dead.xkbOutput > 0) ? dead.xkbOutput : 32 )); SwingUtilities.invokeLater(new Runnable() { public void run() { keyMapTable.getSelectionModel().setSelectionInterval(i, i); JScrollBar vsb = keyMapPane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); } } private class DeleteKeyMapActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { int[] rows = keyMapTable.getSelectedRows(); for (int i = rows.length - 1; i >= 0; i--) { keyMapModel.deleteEntry(rows[i]); } } } private class MoveUpKeyMapActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = keyMapTable.getSelectedRow(); if (i < 1) return; keyMapModel.moveEntry(i, -1); SwingUtilities.invokeLater(new Runnable() { public void run() { keyMapTable.getSelectionModel().setSelectionInterval(i-1, i-1); } }); } } private class MoveDownKeyMapActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = keyMapTable.getSelectedRow(); if (i < 0 || i >= (keyMapModel.getRowCount()-1)) return; keyMapModel.moveEntry(i, +1); SwingUtilities.invokeLater(new Runnable() { public void run() { keyMapTable.getSelectionModel().setSelectionInterval(i+1, i+1); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/FixedGridBagConstraints.java000066400000000000000000000010341506470510200332320ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.io.Serializable; public class FixedGridBagConstraints implements Cloneable, Serializable { private static final long serialVersionUID = 1L; public int gridx = 0; public int gridy = 0; public int gridwidth = 1; public int gridheight = 1; @Override public FixedGridBagConstraints clone() { FixedGridBagConstraints c = new FixedGridBagConstraints(); c.gridx = this.gridx; c.gridy = this.gridy; c.gridwidth = this.gridwidth; c.gridheight = this.gridheight; return c; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/FixedGridBagLayout.java000066400000000000000000000127541506470510200322130ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.io.Serializable; import java.util.IdentityHashMap; public class FixedGridBagLayout implements LayoutManager2, Serializable { private static final long serialVersionUID = 1L; private IdentityHashMap cons; private int totalGridWidth; private int totalGridHeight; private int maxMinW; private int maxMinH; private int maxPrefW; private int maxPrefH; private int minMaxW; private int minMaxH; public FixedGridBagLayout() { this.cons = new IdentityHashMap(); this.totalGridWidth = -1; this.totalGridHeight = -1; this.maxMinW = -1; this.maxMinH = -1; this.maxPrefW = -1; this.maxPrefH = -1; this.minMaxW = -1; this.minMaxH = -1; } @Override public void addLayoutComponent(String name, Component c) { this.cons.remove(c); } @Override public void addLayoutComponent(Component c, Object con) { this.cons.remove(c); if (con instanceof FixedGridBagConstraints) { this.cons.put(c, ((FixedGridBagConstraints)con).clone()); } } @Override public void removeLayoutComponent(Component c) { this.cons.remove(c); } @Override public void invalidateLayout(Container parent) { this.totalGridWidth = -1; this.totalGridHeight = -1; this.maxMinW = -1; this.maxMinH = -1; this.maxPrefW = -1; this.maxPrefH = -1; this.minMaxW = -1; this.minMaxH = -1; } private int scale64(int m, int n, int d) { long q = (long)m * (long)n / (long)d; return (q < Integer.MAX_VALUE) ? (int)q : Integer.MAX_VALUE; } private void check(Container parent) { if (totalGridWidth < 0 || totalGridHeight < 0) { for (FixedGridBagConstraints con : cons.values()) { int maxX = con.gridx + con.gridwidth; int maxY = con.gridy + con.gridheight; if (maxX > totalGridWidth) totalGridWidth = maxX; if (maxY > totalGridHeight) totalGridHeight = maxY; } } if (maxMinW < 0 || maxMinH < 0 || maxPrefW < 0 || maxPrefH < 0 || minMaxW < 0 || minMaxH < 0) { maxMinW = Math.max(totalGridWidth, 0); maxMinH = Math.max(totalGridHeight, 0); maxPrefW = Math.max(totalGridWidth, 0); maxPrefH = Math.max(totalGridHeight, 0); minMaxW = Integer.MAX_VALUE; minMaxH = Integer.MAX_VALUE; for (int i = 0, n = parent.getComponentCount(); i < n; i++) { Component c = parent.getComponent(i); Dimension min = c.getMinimumSize(); Dimension pref = c.getPreferredSize(); Dimension max = c.getMaximumSize(); if (totalGridWidth > 0 && totalGridHeight > 0) { FixedGridBagConstraints con = cons.get(c); if (con != null) { min.width = scale64(min.width, totalGridWidth, con.gridwidth); min.height = scale64(min.height, totalGridHeight, con.gridheight); pref.width = scale64(pref.width, totalGridWidth, con.gridwidth); pref.height = scale64(pref.height, totalGridHeight, con.gridheight); max.width = scale64(max.width, totalGridWidth, con.gridwidth); max.height = scale64(max.height, totalGridHeight, con.gridheight); } } if (min.width > maxMinW) maxMinW = min.width; if (min.height > maxMinH) maxMinH = min.height; if (pref.width > maxPrefW) maxPrefW = pref.width; if (pref.height > maxPrefH) maxPrefH = pref.height; if (max.width < minMaxW) minMaxW = max.width; if (max.height < minMaxH) minMaxH = max.height; } } } @Override public Dimension minimumLayoutSize(Container parent) { check(parent); Dimension d = new Dimension(maxMinW, maxMinH); Insets insets = parent.getInsets(); d.width += insets.left + insets.right; if (d.width < 0) d.width = Integer.MAX_VALUE; d.height += insets.top + insets.bottom; if (d.height < 0) d.height = Integer.MAX_VALUE; return d; } @Override public Dimension preferredLayoutSize(Container parent) { check(parent); Dimension d = new Dimension(maxPrefW, maxPrefH); Insets insets = parent.getInsets(); d.width += insets.left + insets.right; if (d.width < 0) d.width = Integer.MAX_VALUE; d.height += insets.top + insets.bottom; if (d.height < 0) d.height = Integer.MAX_VALUE; return d; } @Override public Dimension maximumLayoutSize(Container parent) { check(parent); Dimension d = new Dimension(minMaxW, minMaxH); Insets insets = parent.getInsets(); d.width += insets.left + insets.right; if (d.width < 0) d.width = Integer.MAX_VALUE; d.height += insets.top + insets.bottom; if (d.height < 0) d.height = Integer.MAX_VALUE; return d; } @Override public void layoutContainer(Container parent) { check(parent); Insets insets = parent.getInsets(); int width = parent.getWidth() - insets.left - insets.right; int height = parent.getHeight() - insets.top - insets.bottom; for (int i = 0, n = parent.getComponentCount(); i < n; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { int x = insets.left, y = insets.top, w = width, h = height; if (totalGridWidth > 0 && totalGridHeight > 0) { FixedGridBagConstraints con = cons.get(c); if (con != null) { x += width * con.gridx / totalGridWidth; y += height * con.gridy / totalGridHeight; w = width * con.gridwidth / totalGridWidth; h = height * con.gridheight / totalGridHeight; } } c.setBounds(x, y, w, h); } } } @Override public float getLayoutAlignmentX(Container parent) { return 0.5f; } @Override public float getLayoutAlignmentY(Container parent) { return 0.5f; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/ImageSelection.java000066400000000000000000000017661506470510200314270ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Image; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; public class ImageSelection implements ClipboardOwner, Transferable { private Image myImage; public ImageSelection(Image image) { myImage = image; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (DataFlavor.imageFlavor.equals(flavor)) { return myImage; } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.imageFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return (DataFlavor.imageFlavor.equals(flavor)); } public void lostOwnership(Clipboard clipboard, Transferable contents) { //nothing } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyEditController.java000066400000000000000000000203221506470510200321260ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import com.kreative.keyedit.CapsLockMapping; import com.kreative.keyedit.DeadKeyTable; import com.kreative.keyedit.Key; import com.kreative.keyedit.KeyMapping; import com.kreative.keyedit.KeyboardMapping; public class KeyEditController { private final KeyEditFrame parent; private final KeyboardMappingPanel kmp; private final List listeners; private Key key = null; private boolean alt = false; private boolean shift = false; public KeyEditController(KeyEditFrame parent, KeyboardMappingPanel kmp) { this.parent = parent; (this.kmp = kmp).addListener(new MyKeyboardMappingPanelListener()); this.listeners = new ArrayList(); } public Key getSelectedKey() { return key; } public boolean isAltSelected() { return alt; } public boolean isShiftSelected() { return shift; } public void setSelectedKey(Key key, boolean alt, boolean shift) { kmp.setSelectedKey(key, alt, shift); } public int getOutput(Key key, boolean alt, boolean shift) { return kmp.getKeyMappingPanel(key).getOutput(alt, shift); } public void setOutput(Key key, boolean alt, boolean shift, int output) { KeyMapping km = kmp.getKeyMappingPanel(key).getKeyMapping(); if (alt) { if (shift) km.altShiftedOutput = output; else km.altUnshiftedOutput = output; km.altCapsLockMapping = CapsLockMapping.AUTO; } else { if (shift) km.shiftedOutput = output; else km.unshiftedOutput = output; km.capsLockMapping = CapsLockMapping.AUTO; } DeadKeyTable dead; if (alt) { if (shift) dead = km.altShiftedDeadKey; else dead = km.altUnshiftedDeadKey; } else { if (shift) dead = km.shiftedDeadKey; else dead = km.unshiftedDeadKey; } if (dead != null) dead.setTerminator(output); for (KeyEditListener l : listeners) l.keyMappingChanged(); } public KeyInfoFrame getKeyMappingFrame(Key key, boolean alt, boolean shift) { KeyMapping km = kmp.getKeyMappingPanel(key).getKeyMapping(); KeyInfoFrame f = new KeyInfoFrame(parent, key, km, this); f.addListener(new MyKeyEditListener()); return f; } public DeadKeyTable getDeadKey(Key key, boolean alt, boolean shift) { return kmp.getKeyMappingPanel(key).getDeadKey(alt, shift); } public void setDeadKey(Key key, boolean alt, boolean shift, DeadKeyTable dead) { KeyMapping km = kmp.getKeyMappingPanel(key).getKeyMapping(); if (alt) { if (shift) km.altShiftedDeadKey = dead; else km.altUnshiftedDeadKey = dead; } else { if (shift) km.shiftedDeadKey = dead; else km.unshiftedDeadKey = dead; } for (KeyEditListener l : listeners) l.keyMappingChanged(); } public DeadKeyTableFrame getDeadKeyTableFrame(Key key, boolean alt, boolean shift) { DeadKeyTable dead = getDeadKey(key, alt, shift); if (dead == null) { int output = getOutput(key, alt, shift); dead = new DeadKeyTable(output); dead.keyMap.put(32, output); setDeadKey(key, alt, shift, dead); } DeadKeyTableFrame f = new DeadKeyTableFrame(parent, dead); f.addListener(new MyKeyEditListener()); return f; } public int[] getLongPressOutput(Key key, boolean alt, boolean shift) { return kmp.getKeyMappingPanel(key).getLongPressOutput(alt, shift); } public void setLongPressOutput(Key key, boolean alt, boolean shift, int[] lpo) { KeyMapping km = kmp.getKeyMappingPanel(key).getKeyMapping(); if (alt) { if (shift) km.altShiftedLongPressOutput = lpo; else km.altUnshiftedLongPressOutput = lpo; } else { if (shift) km.shiftedLongPressOutput = lpo; else km.unshiftedLongPressOutput = lpo; } for (KeyEditListener l : listeners) l.keyMappingChanged(); } public LongPressTableFrame getLongPressTableFrame(Key key, boolean alt, boolean shift) { Promise autoLPO = new MyAutoLongPressOutputPromise(key, alt, shift); int[] lpo = getLongPressOutput(key, alt, shift); LongPressTableFrame f = new LongPressTableFrame(parent, autoLPO, lpo); f.addListener(new MyLongPressTableListener(key, alt, shift)); return f; } public void swapAlt(Key key) { kmp.getKeyMappingPanel(key).getKeyMapping().swapAlt(); for (KeyEditListener l : listeners) l.keyMappingChanged(); } public LayoutInfoFrame getKeyboardMappingInfoFrame() { KeyboardMapping km = kmp.getKeyboardMapping(); LayoutInfoFrame f = new LayoutInfoFrame(parent, km); f.addListener(new MyKeyEditListener()); return f; } public void addListener(KeyEditListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyEditListener listener) { if (listener != null) listeners.remove(listener); } public KeyEditListener[] getListeners() { return listeners.toArray(new KeyEditListener[listeners.size()]); } private class MyKeyboardMappingPanelListener implements KeyboardMappingPanelListener { public void focusGained(FocusEvent e, Key key, boolean alt, boolean shift) { KeyEditController.this.key = key; KeyEditController.this.alt = alt; KeyEditController.this.shift = shift; } public void keyPressed(KeyEvent e, Key key, boolean alt, boolean shift) { KeyEditController.this.key = key; KeyEditController.this.alt = alt; KeyEditController.this.shift = shift; switch (e.getKeyCode()) { case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_DELETE: if (e.isMetaDown() || e.isControlDown()) { setDeadKey(key, alt, shift, null); } else if (e.isAltDown() || e.isAltGraphDown()) { setLongPressOutput(key, alt, shift, null); } else { setOutput(key, alt, shift, -1); } break; case KeyEvent.VK_ENTER: if (e.isMetaDown() || e.isControlDown()) { getDeadKeyTableFrame(key, alt, shift).setVisible(true); } else if (e.isAltDown() || e.isAltGraphDown()) { getLongPressTableFrame(key, alt, shift).setVisible(true); } else { getKeyMappingFrame(key, alt, shift).setVisible(true); } break; } } public void keyTyped(KeyEvent e, Key key, boolean alt, boolean shift) { KeyEditController.this.key = key; KeyEditController.this.alt = alt; KeyEditController.this.shift = shift; if (e.isMetaDown() || e.isControlDown()) return; char ch = e.getKeyChar(); if (ch == KeyEvent.CHAR_UNDEFINED) return; if (ch < 32 || (ch >= 127 && ch < 160)) return; if (ch >= 0xD800 && ch < 0xE000) return; setOutput(key, alt, shift, ch); } public void mouseClicked(MouseEvent e, Key key, boolean alt, boolean shift) { KeyEditController.this.key = key; KeyEditController.this.alt = alt; KeyEditController.this.shift = shift; if (e.getClickCount() > 1) { getKeyMappingFrame(key, alt, shift).setVisible(true); } } public void focusLost(FocusEvent e, Key key, boolean alt, boolean shift) {} public void keyReleased(KeyEvent e, Key key, boolean alt, boolean shift) {} public void mouseEntered(MouseEvent e, Key key, boolean alt, boolean shift) {} public void mouseExited(MouseEvent e, Key key, boolean alt, boolean shift) {} public void mousePressed(MouseEvent e, Key key, boolean alt, boolean shift) {} public void mouseReleased(MouseEvent e, Key key, boolean alt, boolean shift) {} } private class MyKeyEditListener implements KeyEditListener { public void metadataChanged() { for (KeyEditListener l : listeners) l.metadataChanged(); } public void keyMappingChanged() { for (KeyEditListener l : listeners) l.keyMappingChanged(); } } private class MyAutoLongPressOutputPromise implements Promise { private final Key key; private final boolean alt; private final boolean shift; private MyAutoLongPressOutputPromise(Key key, boolean alt, boolean shift) { this.key = key; this.alt = alt; this.shift = shift; } public int[] resolve() { return kmp.getKeyboardMapping().getAutoLongPressOutput(getOutput(key, alt, shift)); } } private class MyLongPressTableListener implements LongPressTableListener { private final Key key; private final boolean alt; private final boolean shift; private MyLongPressTableListener(Key key, boolean alt, boolean shift) { this.key = key; this.alt = alt; this.shift = shift; } public void longPressOutputChanged(int[] lpo) { setLongPressOutput(key, alt, shift, lpo); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyEditFrame.java000066400000000000000000000061661506470510200310470ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JOptionPane; import com.kreative.keyedit.KeyboardFormat; import com.kreative.keyedit.KeyboardMapping; import com.kreative.keyedit.KkbWriter; public class KeyEditFrame extends JFrame { private static final long serialVersionUID = 1L; private File file; private boolean changed; private final KeyboardMapping mapping; private final KeyboardMappingPanel keyboardPanel; private final KeyEditController controller; public KeyEditFrame(File file, KeyboardMapping mapping) { this.file = file; this.changed = false; this.mapping = mapping; this.keyboardPanel = new KeyboardMappingPanel(mapping); this.controller = new KeyEditController(this, keyboardPanel); setContentPane(keyboardPanel); setJMenuBar(new KeyEditMenuBar(this, this, controller)); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); updateWindow(); controller.addListener(new MyKeyEditListener()); addWindowListener(new MyWindowListener()); } public boolean save() { if (file == null) { return saveAs(); } else try { KkbWriter.write(file, mapping); changed = false; updateWindow(); return true; } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); updateWindow(); return false; } } public boolean saveAs() { File newFile = Main.getSaveFile(".kkbx"); if (newFile == null) return false; file = newFile; return save(); } public boolean export(KeyboardFormat format) { File newFile = Main.getSaveFile(format.getSuffix()); if (newFile == null) { return false; } else try { format.write(newFile, mapping); return true; } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while exporting this file.", "Export", JOptionPane.ERROR_MESSAGE ); return false; } } private void updateWindow() { if (OSUtils.IS_MAC_OS) { getRootPane().putClientProperty("Window.documentFile", file); getRootPane().putClientProperty("Window.documentModified", changed); setTitle(mapping.getNameNotEmpty()); } else if (changed) { setTitle(mapping.getNameNotEmpty() + " \u2022"); } else { setTitle(mapping.getNameNotEmpty()); } } private class MyKeyEditListener implements KeyEditListener { public void metadataChanged() { changed = true; updateWindow(); keyboardPanel.updateModifiers(); } public void keyMappingChanged() { changed = true; updateWindow(); keyboardPanel.updateKeys(); } } private class MyWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { if (changed) { String name = mapping.getNameNotEmpty(); switch (new SaveChangesDialog(KeyEditFrame.this, name).showDialog()) { case CANCEL: return; case DONT_SAVE: break; case SAVE: if (save()) break; else return; } } dispose(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyEditListener.java000066400000000000000000000002131506470510200315650ustar00rootroot00000000000000package com.kreative.keyedit.edit; public interface KeyEditListener { public void metadataChanged(); public void keyMappingChanged(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyEditMenuBar.java000066400000000000000000000406221506470510200313410ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.keyedit.Key; import com.kreative.keyedit.KeyBlock; import com.kreative.keyedit.KeyboardFormat; import com.kreative.unicode.fontmap.FontMapController; public class KeyEditMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public static final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); public KeyEditMenuBar(KeyEditFrame f, Window w, KeyEditController ctrl) { add(new FileMenu(f, w, ctrl)); add(new EditMenu(ctrl)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(KeyEditFrame f, Window w, KeyEditController ctrl) { super("File"); add(new NewMappingMenuItem()); add(new OpenMappingMenuItem()); add(new CloseMenuItem(w)); addSeparator(); add(new SaveMenuItem(f)); add(new SaveAsMenuItem(f)); add(new ExportMenu(f)); addSeparator(); add(new LayoutInfoMenuItem(ctrl)); if (!OSUtils.IS_MAC_OS) { addSeparator(); add(new ExitMenuItem()); } } } public static class NewMappingMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewMappingMenuItem() { super("New"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.newMapping(); } }); } } public static class OpenMappingMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenMappingMenuItem() { super("Open..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.openMapping(); } }); } } public static class CloseMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CloseMenuItem(final Window window) { super("Close Window"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); } }); } } public static class SaveMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveMenuItem(final KeyEditFrame f) { super("Save"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.save(); } }); } } public static class SaveAsMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveAsMenuItem(final KeyEditFrame f) { super("Save As..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.saveAs(); } }); } } public static class ExportMenu extends JMenu { private static final long serialVersionUID = 1L; public ExportMenu(final KeyEditFrame f) { super("Export"); for (KeyboardFormat format : KeyboardFormat.values()) { if (format != KeyboardFormat.KKB) { add(new ExportMenuItem(f, format)); } } } } public static class ExportMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ExportMenuItem(final KeyEditFrame f, final KeyboardFormat format) { super(format.getName() + "..."); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.export(format); } }); } } public static class LayoutInfoMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public LayoutInfoMenuItem(final KeyEditController ctrl) { super("Layout Info"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ctrl.getKeyboardMappingInfoFrame().setVisible(true); } }); } } public static class ExitMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ExitMenuItem() { super("Exit"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) return; } } System.exit(0); } }); } } public static class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(KeyEditController ctrl) { super("Edit"); add(new CutMenuItem(ctrl)); add(new CopyMenuItem(ctrl)); add(new PasteMenuItem(ctrl)); add(new ClearMenuItem(ctrl)); addSeparator(); add(new EditKeyMenuItem(ctrl)); add(new EditDeadKeyMenuItem(ctrl)); add(new DeleteDeadKeyMenuItem(ctrl)); add(new EditLongPressOutputMenuItem(ctrl)); addSeparator(); add(new BulkActionMenu(ctrl)); addSeparator(); add(new FontMapMenuItem()); } } public static class CutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CutMenuItem(final KeyEditController ctrl) { super("Cut"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); int output = ctrl.getOutput(key, alt, shift); if (output <= 0) return; String content = String.valueOf(Character.toChars(output)); Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new StringSelection(content), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); ctrl.setOutput(key, alt, shift, -1); } }); } } public static class CopyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CopyMenuItem(final KeyEditController ctrl) { super("Copy"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); int output = ctrl.getOutput(key, alt, shift); if (output <= 0) return; String content = String.valueOf(Character.toChars(output)); Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new StringSelection(content), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); } }); } } public static class PasteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PasteMenuItem(final KeyEditController ctrl) { super("Paste"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); try { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(DataFlavor.stringFlavor)) { String content = cb.getData(DataFlavor.stringFlavor).toString(); int output = (content == null || content.length() == 0) ? (-1) : content.codePointAt(0); ctrl.setOutput(key, alt, shift, output); } } catch (Exception ex) { ex.printStackTrace(); } } }); } } public static class ClearMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ClearMenuItem(final KeyEditController ctrl) { super("Clear"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); ctrl.setOutput(key, alt, shift, -1); } }); } } public static class EditKeyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public EditKeyMenuItem(final KeyEditController ctrl) { super("Edit Key"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); ctrl.getKeyMappingFrame(key, alt, shift).setVisible(true); } }); } } public static class EditDeadKeyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public EditDeadKeyMenuItem(final KeyEditController ctrl) { super("Edit Dead Key"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); ctrl.getDeadKeyTableFrame(key, alt, shift).setVisible(true); } }); } } public static class DeleteDeadKeyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public DeleteDeadKeyMenuItem(final KeyEditController ctrl) { super("Delete Dead Key"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); ctrl.setDeadKey(key, alt, shift, null); } }); } } public static class EditLongPressOutputMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public EditLongPressOutputMenuItem(final KeyEditController ctrl) { super("Edit Long Press Output"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Key key = ctrl.getSelectedKey(); if (key == null) return; boolean alt = ctrl.isAltSelected(); boolean shift = ctrl.isShiftSelected(); ctrl.getLongPressTableFrame(key, alt, shift).setVisible(true); } }); } } public static class BulkActionMenu extends JMenu { private static final long serialVersionUID = 1L; public BulkActionMenu(KeyEditController ctrl) { super("Bulk Actions"); add(new CopyUnshiftedToShiftedMenuItem(ctrl)); add(new CopyShiftedToUnshiftedMenuItem(ctrl)); add(new CopyNormalToAltMenuItem(ctrl)); add(new CopyAltToNormalMenuItem(ctrl)); add(new ClearNormalMenuItem(ctrl)); add(new ClearAltMenuItem(ctrl)); add(new SwapNormalAndAltMenuItem(ctrl)); } } public static abstract class BulkActionMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public BulkActionMenuItem(final String title, final KeyEditController ctrl) { super(title); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { boolean shiftDown = ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0); for (Key key : Key.values()) { if (shiftDown || key.keyBlock == KeyBlock.ALPHA) { BulkActionMenuItem.this.actionPerformed(e, ctrl, key); } } } }); } public abstract void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key); } public static class CopyUnshiftedToShiftedMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public CopyUnshiftedToShiftedMenuItem(KeyEditController ctrl) { super("Copy Unshifted to Shifted", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { int nu = ctrl.getOutput(key, false, false); int ns = ctrl.getOutput(key, false, true); if (ns <= 0) ctrl.setOutput(key, false, true, Character.toUpperCase(nu)); int au = ctrl.getOutput(key, true, false); int as = ctrl.getOutput(key, true, true); if (as <= 0) ctrl.setOutput(key, true, true, Character.toUpperCase(au)); } } public static class CopyShiftedToUnshiftedMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public CopyShiftedToUnshiftedMenuItem(KeyEditController ctrl) { super("Copy Shifted to Unshifted", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { int ns = ctrl.getOutput(key, false, true); int nu = ctrl.getOutput(key, false, false); if (nu <= 0) ctrl.setOutput(key, false, false, Character.toLowerCase(ns)); int as = ctrl.getOutput(key, true, true); int au = ctrl.getOutput(key, true, false); if (au <= 0) ctrl.setOutput(key, true, false, Character.toLowerCase(as)); } } public static class CopyNormalToAltMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public CopyNormalToAltMenuItem(KeyEditController ctrl) { super("Copy Normal to Alt", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { int nu = ctrl.getOutput(key, false, false); int au = ctrl.getOutput(key, true, false); if (au <= 0) ctrl.setOutput(key, true, false, nu); int ns = ctrl.getOutput(key, false, true); int as = ctrl.getOutput(key, true, true); if (as <= 0) ctrl.setOutput(key, true, true, ns); } } public static class CopyAltToNormalMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public CopyAltToNormalMenuItem(KeyEditController ctrl) { super("Copy Alt to Normal", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { int au = ctrl.getOutput(key, true, false); int nu = ctrl.getOutput(key, false, false); if (nu <= 0) ctrl.setOutput(key, false, false, au); int as = ctrl.getOutput(key, true, true); int ns = ctrl.getOutput(key, false, true); if (ns <= 0) ctrl.setOutput(key, false, true, as); } } public static class ClearNormalMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public ClearNormalMenuItem(KeyEditController ctrl) { super("Clear Normal", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { ctrl.setOutput(key, false, false, -1); ctrl.setOutput(key, false, true, -1); } } public static class ClearAltMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public ClearAltMenuItem(KeyEditController ctrl) { super("Clear Alt", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { ctrl.setOutput(key, true, false, -1); ctrl.setOutput(key, true, true, -1); } } public static class SwapNormalAndAltMenuItem extends BulkActionMenuItem { private static final long serialVersionUID = 1L; public SwapNormalAndAltMenuItem(KeyEditController ctrl) { super("Swap Normal and Alt", ctrl); } public void actionPerformed(ActionEvent e, KeyEditController ctrl, Key key) { ctrl.swapAlt(key); } } public static class FontMapMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public FontMapMenuItem() { super("Font Map"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontMapController.getInstance().getFrame().setVisible(true); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyInfoFrame.java000066400000000000000000000052441506470510200310510ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import com.kreative.keyedit.Key; import com.kreative.keyedit.KeyMapping; public class KeyInfoFrame extends JDialog { private static final long serialVersionUID = 1L; private final KeyInfoPanel panel; private final List listeners; public KeyInfoFrame(Frame parent, Key key, KeyMapping km, final KeyEditController controller) { super(parent, "Edit Key"); this.panel = new KeyInfoPanel(key, km, controller); this.listeners = new ArrayList(); JButton cancelButton = new JButton("Cancel"); JButton okButton = new JButton("OK"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(cancelButton); buttonPanel.add(okButton); JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(this.panel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDefaultButton(getRootPane(), okButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.commit(); dispose(); for (KeyEditListener l : listeners) l.keyMappingChanged(); } }); pack(); // setSize(900, 600); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); final KeyEditListener ul = new KeyEditListener() { public void metadataChanged() { panel.update(); } public void keyMappingChanged() { panel.update(); } }; controller.addListener(ul); final WindowAdapter wl = new WindowAdapter() { public void windowClosed(WindowEvent e) { controller.removeListener(ul); } }; this.addWindowListener(wl); } public void addListener(KeyEditListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyEditListener listener) { if (listener != null) listeners.remove(listener); } public KeyEditListener[] getListeners() { return listeners.toArray(new KeyEditListener[listeners.size()]); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyInfoPanel.java000066400000000000000000000207131506470510200310540ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Component; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.keyedit.CapsLockMapping; import com.kreative.keyedit.Key; import com.kreative.keyedit.KeyMapping; public class KeyInfoPanel extends JPanel { private static final long serialVersionUID = 1L; private final Key key; private final KeyMapping km; private final KeyEditController controller; private final OutputPanel uop; private final JButton uadd, uedit, udel, ulpo; private final OutputPanel sop; private final JButton sadd, sedit, sdel, slpo; private final JComboBox caps; private final OutputPanel auop; private final JButton auadd, auedit, audel, aulpo; private final OutputPanel asop; private final JButton asadd, asedit, asdel, aslpo; private final JComboBox acaps; private final OutputPanel ctrl; private final OutputPanel cmd; public KeyInfoPanel(Key key, KeyMapping km, KeyEditController controller) { this.key = key; this.km = km; this.controller = controller; this.uop = new OutputPanel(km.unshiftedOutput); this.uadd = new JButton("Add"); this.uedit = new JButton("Edit"); this.udel = new JButton("Delete"); this.ulpo = new JButton("Edit Long Press Output"); this.sop = new OutputPanel(km.shiftedOutput); this.sadd = new JButton("Add"); this.sedit = new JButton("Edit"); this.sdel = new JButton("Delete"); this.slpo = new JButton("Edit Long Press Output"); this.caps = new JComboBox(new String[] {"Auto", "Unshifted", "Shifted"}); this.caps.setSelectedIndex(km.capsLockMapping.ordinal()); this.auop = new OutputPanel(km.altUnshiftedOutput); this.auadd = new JButton("Add"); this.auedit = new JButton("Edit"); this.audel = new JButton("Delete"); this.aulpo = new JButton("Edit Long Press Output"); this.asop = new OutputPanel(km.altShiftedOutput); this.asadd = new JButton("Add"); this.asedit = new JButton("Edit"); this.asdel = new JButton("Delete"); this.aslpo = new JButton("Edit Long Press Output"); this.acaps = new JComboBox(new String[] {"Auto", "Alt Unshifted", "Alt Shifted"}); this.acaps.setSelectedIndex(km.altCapsLockMapping.ordinal()); this.ctrl = new OutputPanel(km.ctrlOutput); this.cmd = new OutputPanel(km.commandOutput); update(); JPanel labels = verticalStack( l("Unshifted:", "Output without any modifier keys pressed."), l("Shifted:", "Output with Shift pressed."), l("Caps Lock:", "Output with Caps Lock pressed."), l("Alt Unshifted:", "AltGr on Windows and Linux. Option on Mac OS X."), l("Alt Shifted:", "AltGr + Shift on Windows and Linux. Option + Shift on Mac OS X."), l("Alt Caps Lock:", "AltGr + Caps Lock on Windows and Linux. Option + Caps Lock on Mac OS X."), l("Control:", "Control on Mac OS X. Should be a corresponding control character. Usually best left alone."), l("Command:", "Command on Mac OS X. Should be an unshifted ASCII character. Usually best left alone.") ); JPanel fields = verticalStack( uop, sop, leftAlign(caps), auop, asop, leftAlign(acaps), ctrl, cmd ); JPanel dklbls = verticalStack( "Dead Key:", "Dead Key:", "", "Dead Key:", "Dead Key:", "", "", "" ); JPanel dkbtns = verticalStack( horizontalStack(uadd, uedit, udel), horizontalStack(sadd, sedit, sdel), new JPanel(), horizontalStack(auadd, auedit, audel), horizontalStack(asadd, asedit, asdel), new JPanel(), new JPanel(), new JPanel() ); JPanel lpobtns = verticalStack( ulpo, slpo, new JPanel(), aulpo, aslpo, new JPanel(), new JPanel(), new JPanel() ); JPanel left = leftSxS(labels, fields, 8); JPanel right1 = leftSxS(dklbls, dkbtns, 8); JPanel right = rightSxS(right1, lpobtns, 8); JPanel panel = topAlign(rightSxS(left, right, 8)); setLayout(new GridLayout(1,1,0,0)); add(panel); uadd.addActionListener(new EditDeadKeyActionListener(false, false)); uedit.addActionListener(new EditDeadKeyActionListener(false, false)); udel.addActionListener(new DeleteDeadKeyActionListener(false, false)); ulpo.addActionListener(new EditLongPressActionListener(false, false)); sadd.addActionListener(new EditDeadKeyActionListener(false, true)); sedit.addActionListener(new EditDeadKeyActionListener(false, true)); sdel.addActionListener(new DeleteDeadKeyActionListener(false, true)); slpo.addActionListener(new EditLongPressActionListener(false, true)); auadd.addActionListener(new EditDeadKeyActionListener(true, false)); auedit.addActionListener(new EditDeadKeyActionListener(true, false)); audel.addActionListener(new DeleteDeadKeyActionListener(true, false)); aulpo.addActionListener(new EditLongPressActionListener(true, false)); asadd.addActionListener(new EditDeadKeyActionListener(true, true)); asedit.addActionListener(new EditDeadKeyActionListener(true, true)); asdel.addActionListener(new DeleteDeadKeyActionListener(true, true)); aslpo.addActionListener(new EditLongPressActionListener(true, true)); } private static JLabel l(String label, String tooltip) { JLabel c = new JLabel(label); c.setToolTipText(tooltip); return c; } private static JPanel verticalStack(String... labels) { JPanel p = new JPanel(new GridLayout(0,1,4,4)); for (String s : labels) p.add(new JLabel(s)); return p; } private static JPanel verticalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(0,1,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel horizontalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel leftAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.LINE_START); return p; } private static JPanel leftSxS(Component l, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(l, BorderLayout.LINE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel rightSxS(Component c, Component r, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(c, BorderLayout.CENTER); p.add(r, BorderLayout.LINE_END); return p; } private static JPanel topAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.PAGE_START); return p; } public void update() { uadd.setEnabled(km.unshiftedDeadKey == null); uedit.setEnabled(km.unshiftedDeadKey != null); udel.setEnabled(km.unshiftedDeadKey != null); sadd.setEnabled(km.shiftedDeadKey == null); sedit.setEnabled(km.shiftedDeadKey != null); sdel.setEnabled(km.shiftedDeadKey != null); auadd.setEnabled(km.altUnshiftedDeadKey == null); auedit.setEnabled(km.altUnshiftedDeadKey != null); audel.setEnabled(km.altUnshiftedDeadKey != null); asadd.setEnabled(km.altShiftedDeadKey == null); asedit.setEnabled(km.altShiftedDeadKey != null); asdel.setEnabled(km.altShiftedDeadKey != null); } public void commit() { km.unshiftedOutput = uop.getOutput(); km.shiftedOutput = sop.getOutput(); km.capsLockMapping = CapsLockMapping.values()[caps.getSelectedIndex()]; km.altUnshiftedOutput = auop.getOutput(); km.altShiftedOutput = asop.getOutput(); km.altCapsLockMapping = CapsLockMapping.values()[acaps.getSelectedIndex()]; km.ctrlOutput = ctrl.getOutput(); km.commandOutput = cmd.getOutput(); } private class EditDeadKeyActionListener implements ActionListener { private final boolean alt; private final boolean shift; public EditDeadKeyActionListener(boolean alt, boolean shift) { this.alt = alt; this.shift = shift; } public void actionPerformed(ActionEvent e) { controller.getDeadKeyTableFrame(key, alt, shift).setVisible(true); } } private class DeleteDeadKeyActionListener implements ActionListener { private final boolean alt; private final boolean shift; public DeleteDeadKeyActionListener(boolean alt, boolean shift) { this.alt = alt; this.shift = shift; } public void actionPerformed(ActionEvent e) { controller.setDeadKey(key, alt, shift, null); } } private class EditLongPressActionListener implements ActionListener { private final boolean alt; private final boolean shift; public EditLongPressActionListener(boolean alt, boolean shift) { this.alt = alt; this.shift = shift; } public void actionPerformed(ActionEvent e) { controller.getLongPressTableFrame(key, alt, shift).setVisible(true); } } } KeyManAttachmentListModel.java000066400000000000000000000034241506470510200334630ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/editpackage com.kreative.keyedit.edit; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.swing.AbstractListModel; public class KeyManAttachmentListModel extends AbstractListModel { private static final long serialVersionUID = 1L; private final List entries; public KeyManAttachmentListModel(Map map) { this.entries = new ArrayList(); for (Map.Entry e : map.entrySet()) { Entry entry = new Entry(); entry.name = e.getKey(); entry.data = e.getValue(); this.entries.add(entry); } } public void addEntry(File file) throws IOException { ByteArrayOutputStream ba = new ByteArrayOutputStream(); FileInputStream in = new FileInputStream(file); byte[] buf = new byte[65536]; int n; while ((n = in.read(buf)) > 0) ba.write(buf, 0, n); in.close(); ba.close(); addEntry(file.getName(), ba.toByteArray()); } public void addEntry(String name, byte[] data) { int i = entries.size(); Entry entry = new Entry(); entry.name = name; entry.data = data; entries.add(entry); fireIntervalAdded(this, i, i); } public void deleteEntry(int i) { entries.remove(i); fireIntervalRemoved(this, i, i); } public void renameEntry(int i, String name) { entries.get(i).name = name; fireContentsChanged(this, i, i); } public void toMap(Map map) { map.clear(); for (Entry e : entries) { map.put(e.name, e.data); } } @Override public Object getElementAt(int row) { return entries.get(row).name; } @Override public int getSize() { return entries.size(); } private static class Entry { private String name; private byte[] data; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyManAttachmentPanel.java000066400000000000000000000123021506470510200327000ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; public class KeyManAttachmentPanel extends JPanel { private static final long serialVersionUID = 1L; private final List listeners; private final KeyManAttachmentListModel model; private final JList list; private final JScrollPane pane; private final JButton add; private final JButton delete; private final JButton rename; public KeyManAttachmentPanel(Map attachments) { this.listeners = new ArrayList(); this.model = new KeyManAttachmentListModel(attachments); this.list = new JList(this.model); this.list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.pane = scrollWrap(this.list); this.add = square(new JButton("+")); this.add.addActionListener(new AddActionListener()); this.delete = square(new JButton("\u2212")); this.delete.addActionListener(new DeleteActionListener()); this.rename = new JButton("Rename"); this.rename.addActionListener(new RenameActionListener()); setLayout(new BorderLayout(8, 8)); add(topSxS(new JLabel("Attachments:"), pane, 4), BorderLayout.CENTER); JPanel buttons1 = horizontalStack(add, delete); JPanel buttons2 = horizontalStack(rename); add(leftAlign(leftSxS(buttons1, buttons2, 4)), BorderLayout.PAGE_END); } public void addListener(KeyManAttachmentPanelListener listener) { this.listeners.add(listener); } public void removeListener(KeyManAttachmentPanelListener listener) { this.listeners.remove(listener); } public void toMap(Map attachments) { this.model.toMap(attachments); } private static JPanel horizontalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel leftAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.LINE_START); return p; } private static JPanel leftSxS(Component l, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(l, BorderLayout.LINE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel topSxS(Component t, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); return p; } private static C square(C c) { Dimension d = c.getPreferredSize(); d.width = (d.height += 8); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); c.putClientProperty("JButton.buttonType", "bevel"); return c; } private static JScrollPane scrollWrap(Component c) { return new JScrollPane( c, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); } private class AddActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { File file = Main.getOpenFile(); if (file == null) return; try { final int i = model.getSize(); model.addEntry(file); SwingUtilities.invokeLater(new Runnable() { public void run() { list.setSelectedIndex(i); JScrollBar vsb = pane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); for (KeyManAttachmentPanelListener l : listeners) { l.attachmentsChanged(model); } } catch (IOException ioe) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); } } } private class DeleteActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { int[] rows = list.getSelectedIndices(); if (rows.length < 1) { Toolkit.getDefaultToolkit().beep(); return; } for (int i = rows.length - 1; i >= 0; i--) { model.deleteEntry(rows[i]); } for (KeyManAttachmentPanelListener l : listeners) { l.attachmentsChanged(model); } } } private class RenameActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { int[] rows = list.getSelectedIndices(); if (rows.length != 1) { Toolkit.getDefaultToolkit().beep(); return; } String name = model.getElementAt(rows[0]).toString(); Object input = JOptionPane.showInputDialog( null, "Enter a new name for " + name + ":", "Rename", JOptionPane.QUESTION_MESSAGE, null, null, name ); if (input != null && !input.equals(name)) { if ((name = input.toString()).length() > 0) { model.renameEntry(rows[0], name); for (KeyManAttachmentPanelListener l : listeners) { l.attachmentsChanged(model); } } } } } } KeyManAttachmentPanelListener.java000066400000000000000000000002421506470510200343270ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/editpackage com.kreative.keyedit.edit; public interface KeyManAttachmentPanelListener { public abstract void attachmentsChanged(KeyManAttachmentListModel model); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyManLanguageTableModel.java000066400000000000000000000066571506470510200333240ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import javax.swing.table.AbstractTableModel; import com.kreative.keyedit.WinLocale; public class KeyManLanguageTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private final List entries; public KeyManLanguageTableModel(Map map) { this.entries = new ArrayList(); for (Map.Entry e : map.entrySet()) { Entry entry = new Entry(); entry.tag = e.getKey(); entry.name = e.getValue(); this.entries.add(entry); } } public void addEntry(String tag, String name) { int i = entries.size(); Entry entry = new Entry(); entry.tag = tag; entry.name = name; entries.add(entry); fireTableRowsInserted(i, i); } public void deleteEntry(int i) { entries.remove(i); fireTableRowsDeleted(i, i); } public void moveEntry(int i, int dir) { if (dir < 0 && i > 0) { Entry e = entries.remove(i); i -= 1; entries.add(i, e); fireTableRowsUpdated(i, i + 1); } if (dir > 0 && i < (entries.size() - 1)) { Entry e = entries.remove(i); i += 1; entries.add(i, e); fireTableRowsUpdated(i - 1, i); } } public void addEntries(Map entries) { if (entries != null && entries.size() > 0) { int i = this.entries.size(); int j = i + entries.size() - 1; for (Map.Entry e : entries.entrySet()) { Entry entry = new Entry(); entry.tag = e.getKey(); entry.name = e.getValue(); this.entries.add(entry); } fireTableRowsInserted(i, j); } } public void clearEntries() { int i = entries.size(); if (i > 0) { entries.clear(); fireTableRowsDeleted(0, i - 1); } } public void sortEntries() { int i = entries.size(); if (i > 0) { Collections.sort(entries, new Comparator() { public int compare(Entry a, Entry b) { String as = (a.name != null) ? a.name : ""; String bs = (b.name != null) ? b.name : ""; return as.compareToIgnoreCase(bs); } }); fireTableRowsUpdated(0, i - 1); } } public void toMap(Map map) { map.clear(); for (Entry e : entries) { map.put(e.tag, e.name); } } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int col) { switch (col) { case 0: return "ID"; case 1: return "Name"; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { switch (col) { case 0: return entries.get(row).tag; case 1: return entries.get(row).name; default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object value, int row, int col) { Entry e = entries.get(row); switch (col) { case 0: e.tag = value.toString().trim(); WinLocale loc0 = WinLocale.forTag(e.tag, null); e.name = (loc0 != null) ? loc0.name : e.tag; break; case 1: e.name = value.toString().trim(); WinLocale loc1 = WinLocale.forName(e.name, null); if (loc1 != null) e.tag = loc1.tag; break; } fireTableRowsUpdated(row, row); } private static class Entry { private String tag; private String name; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyMappingPanel.java000066400000000000000000000323141506470510200315540ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.keyedit.DeadKeyTable; import com.kreative.keyedit.KeyMapping; import com.kreative.unicode.data.NameResolver; import com.kreative.unicode.fontmap.FontMapController; import com.kreative.unicode.fontmap.FontMapEntry; public class KeyMappingPanel extends JPanel { private static final long serialVersionUID = 1L; private static final Color BG_LD = new Color(0xFFFFCC00); private static final Color FG_LD = Color.black; private static final Color BG_DK = new Color(0xFFFFDD55); private static final Color FG_DK = Color.black; private static final Color BG_LP = new Color(0xFFFFEEAA); private static final Color FG_LP = Color.black; private static final Color BG_NG = new Color(0xFFDDDDDD); private static final Color FG_NG = new Color(0xFFDDDDDD); private static final Color BG_CC = new Color(204, 255, 204); private static final Color FG_CC = Color.black; private static final Color BG_PU = new Color(238, 204, 255); private static final Color FG_PU = Color.black; private static final Color BG_OK = Color.white; private static final Color FG_OK = Color.black; private static final Color BLURRED = new Color(0xFFBBBBBB); private static final Color FOCUSED = new Color(0xFF6699CC); private static final Color INFOCUS = new Color(0xFF99CCFF); private final KeyMapping km; private final JLabel unshifted; private final JLabel shifted; private final JLabel altUnshifted; private final JLabel altShifted; private final JPanel innerPanel; private final Font defaultFont; private final List listeners; public KeyMappingPanel(KeyMapping keymapping) { km = keymapping; unshifted = makeField("unshifted", false, false); shifted = makeField("shifted", false, true); altUnshifted = makeField("alt, unshifted", true, false); altShifted = makeField("alt, shifted", true, true); innerPanel = new JPanel(new GridLayout(2, 2, 0, 0)); innerPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, BLURRED)); innerPanel.add(shifted); innerPanel.add(altShifted); innerPanel.add(unshifted); innerPanel.add(altUnshifted); defaultFont = unshifted.getFont(); listeners = new ArrayList(); update(); JPanel panel = new JPanel(new GridLayout(1, 1, 0, 0)); panel.add(innerPanel); panel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); panel.setPreferredSize(new Dimension(60, 60)); setLayout(new GridLayout(1, 1, 0, 0)); add(panel); } private JLabel makeField(String tooltip, boolean alt, boolean shift) { JLabel f = new JLabel(); f.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); f.setFocusable(true); f.setHorizontalAlignment(JLabel.CENTER); f.setOpaque(true); f.setToolTipText(tooltip); MyListener ml = new MyListener(f, alt, shift); f.addFocusListener(ml); f.addKeyListener(ml); f.addMouseListener(ml); return f; } public void update() { update(false, false); update(false, true); update(true, false); update(true, true); } public void update(boolean alt, boolean shift) { JLabel field = getTextField(alt, shift); int output = getOutput(alt, shift); if (output > 0) { field.setText(cpString(output)); FontMapEntry fme = FontMapController.getInstance().entryForCodePoint(output); field.setFont((fme != null) ? fme.getFont() : defaultFont); } else { field.setText(" "); field.setFont(defaultFont); } int[] lpo = getLongPressOutput(alt, shift); boolean hasLongPress = (lpo != null && lpo.length > 0); boolean hasDeadKey = (getDeadKey(alt, shift) != null); if (hasDeadKey && hasLongPress) { field.setBackground(BG_LD); field.setForeground(FG_LD); } else if (hasDeadKey) { field.setBackground(BG_DK); field.setForeground(FG_DK); } else if (hasLongPress) { field.setBackground(BG_LP); field.setForeground(FG_LP); } else if (output <= 0) { field.setBackground(BG_NG); field.setForeground(FG_NG); } else if (output < 0x20 || (output >= 0x7F && output < 0xA0)) { field.setBackground(BG_CC); field.setForeground(FG_CC); } else if ((output >= 0xE000 && output < 0xF900) || output >= 0xF0000) { field.setBackground(BG_PU); field.setForeground(FG_PU); } else { field.setBackground(BG_OK); field.setForeground(FG_OK); } } public KeyMapping getKeyMapping() { return km; } public JLabel getTextField(boolean alt, boolean shift) { return alt ? (shift ? altShifted : altUnshifted) : (shift ? shifted : unshifted); } public int getOutput(boolean alt, boolean shift) { int output = alt ? (shift ? km.altShiftedOutput : km.altUnshiftedOutput) : (shift ? km.shiftedOutput : km.unshiftedOutput); DeadKeyTable dead = getDeadKey(alt, shift); if (dead != null) { if (dead.macTerminator > 0) output = dead.macTerminator; else if (dead.winTerminator > 0) output = dead.winTerminator; else if (dead.xkbOutput > 0) output = dead.xkbOutput; } return output; } public DeadKeyTable getDeadKey(boolean alt, boolean shift) { return alt ? (shift ? km.altShiftedDeadKey : km.altUnshiftedDeadKey) : (shift ? km.shiftedDeadKey : km.unshiftedDeadKey); } public int[] getLongPressOutput(boolean alt, boolean shift) { return alt ? (shift ? km.altShiftedLongPressOutput : km.altUnshiftedLongPressOutput) : (shift ? km.shiftedLongPressOutput : km.unshiftedLongPressOutput); } public void addListener(KeyMappingPanelListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyMappingPanelListener listener) { if (listener != null) listeners.remove(listener); } public KeyMappingPanelListener[] getListeners() { return listeners.toArray(new KeyMappingPanelListener[listeners.size()]); } private class MyListener implements FocusListener, KeyListener, MouseListener { private final JLabel field; private final boolean alt; private final boolean shift; public MyListener(JLabel field, boolean alt, boolean shift) { this.field = field; this.alt = alt; this.shift = shift; } public void focusGained(FocusEvent e) { innerPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, FOCUSED)); field.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, INFOCUS)); for (KeyMappingPanelListener l : listeners) l.focusGained(e, alt, shift); } public void focusLost(FocusEvent e) { innerPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, BLURRED)); field.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); for (KeyMappingPanelListener l : listeners) l.focusLost(e, alt, shift); } public void keyPressed(KeyEvent e) { for (KeyMappingPanelListener l : listeners) l.keyPressed(e, alt, shift); } public void keyReleased(KeyEvent e) { for (KeyMappingPanelListener l : listeners) l.keyReleased(e, alt, shift); } public void keyTyped(KeyEvent e) { for (KeyMappingPanelListener l : listeners) l.keyTyped(e, alt, shift); } public void mouseClicked(MouseEvent e) { for (KeyMappingPanelListener l : listeners) l.mouseClicked(e, alt, shift); } public void mouseEntered(MouseEvent e) { for (KeyMappingPanelListener l : listeners) l.mouseEntered(e, alt, shift); } public void mouseExited(MouseEvent e) { for (KeyMappingPanelListener l : listeners) l.mouseExited(e, alt, shift); } public void mousePressed(MouseEvent e) { field.requestFocusInWindow(); for (KeyMappingPanelListener l : listeners) l.mousePressed(e, alt, shift); } public void mouseReleased(MouseEvent e) { for (KeyMappingPanelListener l : listeners) l.mouseReleased(e, alt, shift); } } private static String cpString(int output) { if (output >= 0xFE00 && output <= 0xFE0F) return "vs" + (output - 0xFE00 + 1); if (output >= 0xE0100 && output <= 0xE01EF) return "vs" + (output - 0xE0100 + 17); switch (output) { case 0x00: return "nul"; case 0x01: return "soh"; case 0x02: return "stx"; case 0x03: return "etx"; case 0x04: return "eot"; case 0x05: return "enq"; case 0x06: return "ack"; case 0x07: return "bel"; case 0x08: return "bs"; case 0x09: return "ht"; case 0x0A: return "lf"; case 0x0B: return "vt"; case 0x0C: return "ff"; case 0x0D: return "cr"; case 0x0E: return "so"; case 0x0F: return "si"; case 0x10: return "dle"; case 0x11: return "dc1"; case 0x12: return "dc2"; case 0x13: return "dc3"; case 0x14: return "dc4"; case 0x15: return "nak"; case 0x16: return "syn"; case 0x17: return "etb"; case 0x18: return "can"; case 0x19: return "em"; case 0x1A: return "sub"; case 0x1B: return "esc"; case 0x1C: return "fs"; case 0x1D: return "gs"; case 0x1E: return "rs"; case 0x1F: return "us"; case 0x20: return "space"; case 0x7F: return "del"; case 0x80: return "pad"; case 0x81: return "hop"; case 0x82: return "bph"; case 0x83: return "nbh"; case 0x84: return "ind"; case 0x85: return "nel"; case 0x86: return "ssa"; case 0x87: return "esa"; case 0x88: return "hts"; case 0x89: return "htj"; case 0x8A: return "vts"; case 0x8B: return "pld"; case 0x8C: return "plu"; case 0x8D: return "ri"; case 0x8E: return "ss2"; case 0x8F: return "ss3"; case 0x90: return "dcs"; case 0x91: return "pu1"; case 0x92: return "pu2"; case 0x93: return "sts"; case 0x94: return "cch"; case 0x95: return "mw"; case 0x96: return "spa"; case 0x97: return "epa"; case 0x98: return "sos"; case 0x99: return "sgc"; case 0x9A: return "sci"; case 0x9B: return "csi"; case 0x9C: return "st"; case 0x9D: return "osc"; case 0x9E: return "pm"; case 0x9F: return "apc"; case 0xA0: return "nbsp"; case 0xAD: return "-"; case 0x02DE: return "◌˞"; case 0x034F: return "cgj"; case 0x061C: return "alm"; case 0x070F: return "sam"; case 0x115F: return "hcf"; case 0x1160: return "hjf"; case 0x17B4: return "kivaq"; case 0x17B5: return "kivaa"; case 0x180B: return "fvs1"; case 0x180C: return "fvs2"; case 0x180D: return "fvs3"; case 0x180E: return "mvs"; case 0x180F: return "fvs4"; case 0x2000: return "nqsp"; case 0x2001: return "mqsp"; case 0x2002: return "ensp"; case 0x2003: return "emsp"; case 0x2004: return "3/msp"; case 0x2005: return "4/msp"; case 0x2006: return "6/msp"; case 0x2007: return "fsp"; case 0x2008: return "psp"; case 0x2009: return "thsp"; case 0x200A: return "hsp"; case 0x200B: return "zwsp"; case 0x200C: return "zwnj"; case 0x200D: return "zwj"; case 0x200E: return "lrm"; case 0x200F: return "rlm"; case 0x2028: return "lsep"; case 0x2029: return "psep"; case 0x202A: return "lre"; case 0x202B: return "rle"; case 0x202C: return "pdf"; case 0x202D: return "lro"; case 0x202E: return "rlo"; case 0x202F: return "nnbsp"; case 0x205F: return "mmsp"; case 0x2060: return "wj"; case 0x2066: return "lri"; case 0x2067: return "rli"; case 0x2068: return "fsi"; case 0x2069: return "pdi"; case 0x206A: return "iss"; case 0x206B: return "ass"; case 0x206C: return "iafs"; case 0x206D: return "aafs"; case 0x206E: return "nads"; case 0x206F: return "nods"; case 0x3000: return "idsp"; case 0x3164: return "hf"; case 0xFEFF: return "zwnbsp"; case 0xFFA0: return "hwhf"; case 0xFFF0: return "cd"; case 0xFFF1: return "rd"; case 0xFFF2: return "pd"; case 0xFFF3: return "sd"; case 0xFFF9: return "iaa"; case 0xFFFA: return "ias"; case 0xFFFB: return "iat"; case 0xFFFC: return "obj"; case 0x1107F: return "bnj"; case 0x16FE4: return "kssf"; case 0x1BC9D: return "dtls"; case 0x1D159: return "msnn"; case 0x1D173: return "msbb"; case 0x1D174: return "mseb"; case 0x1D175: return "msbt"; case 0x1D176: return "mset"; case 0x1D177: return "msbs"; case 0x1D178: return "mses"; case 0x1D179: return "msbp"; case 0x1D17A: return "msep"; case 0x1DA9B: return "swf2"; case 0x1DA9C: return "swf3"; case 0x1DA9D: return "swf4"; case 0x1DA9E: return "swf5"; case 0x1DA9F: return "swf6"; case 0x1DAA1: return "swr2"; case 0x1DAA2: return "swr3"; case 0x1DAA3: return "swr4"; case 0x1DAA4: return "swr5"; case 0x1DAA5: return "swr6"; case 0x1DAA6: return "swr7"; case 0x1DAA7: return "swr8"; case 0x1DAA8: return "swr9"; case 0x1DAA9: return "swr10"; case 0x1DAAA: return "swr11"; case 0x1DAAB: return "swr12"; case 0x1DAAC: return "swr13"; case 0x1DAAD: return "swr14"; case 0x1DAAE: return "swr15"; case 0x1DAAF: return "swr16"; } String s = String.valueOf(Character.toChars(output)); NameResolver r = NameResolver.instance(output); if (r.getCategory(output).startsWith("M")) { // Combining Mark s = "◌" + s; String ccc = r.getCombiningClass(output); if (ccc.equals("233") || ccc.equals("234")) { // Double Combining Mark s = s + "◌"; } } return s; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyMappingPanelListener.java000066400000000000000000000015621506470510200332630ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; public interface KeyMappingPanelListener { public void focusGained (FocusEvent e, boolean alt, boolean shift); public void focusLost (FocusEvent e, boolean alt, boolean shift); public void keyPressed (KeyEvent e, boolean alt, boolean shift); public void keyReleased (KeyEvent e, boolean alt, boolean shift); public void keyTyped (KeyEvent e, boolean alt, boolean shift); public void mouseClicked (MouseEvent e, boolean alt, boolean shift); public void mouseEntered (MouseEvent e, boolean alt, boolean shift); public void mouseExited (MouseEvent e, boolean alt, boolean shift); public void mousePressed (MouseEvent e, boolean alt, boolean shift); public void mouseReleased(MouseEvent e, boolean alt, boolean shift); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/KeyboardMappingPanel.java000066400000000000000000000365351506470510200325750ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Window; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.keyedit.Key; import com.kreative.keyedit.KeyboardMapping; import com.kreative.keyedit.XkbAltGrKey; import com.kreative.keyedit.XkbComposeKey; public class KeyboardMappingPanel extends JPanel { private static final long serialVersionUID = 1L; private final KeyboardMapping km; private final Map keyPanels; private final Set modifierPanels; private final List listeners; public KeyboardMappingPanel(KeyboardMapping keyboard) { km = keyboard; keyPanels = new HashMap(); modifierPanels = new HashSet(); listeners = new ArrayList(); JPanel panel = new JPanel(new FixedGridBagLayout()); FixedGridBagConstraints gbc = new FixedGridBagConstraints(); gbc.gridheight = 4; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 4; addKeys( panel, gbc, Key.GRAVE_TILDE, Key.NUMROW_1, Key.NUMROW_2, Key.NUMROW_3, Key.NUMROW_4, Key.NUMROW_5, Key.NUMROW_6, Key.NUMROW_7, Key.NUMROW_8, Key.NUMROW_9, Key.NUMROW_0, Key.HYPHEN_UNDERSCORE, Key.EQUALS_PLUS ); gbc.gridwidth = 8; addModifier(panel, gbc, (OSUtils.IS_MAC_OS ? "delete" : "backspace"), null); gbc.gridx = 0; gbc.gridy = 4; gbc.gridwidth = 6; addModifier(panel, gbc, "tab", null); gbc.gridwidth = 4; addKeys( panel, gbc, Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P, Key.LEFT_BRACKET, Key.RIGHT_BRACKET ); gbc.gridwidth = 6; addKeys(panel, gbc, Key.BACKSLASH); gbc.gridx = 0; gbc.gridy = 8; gbc.gridwidth = 7; addModifier(panel, gbc, "caps lock", XkbComposeKey.caps, XkbAltGrKey.caps_switch); gbc.gridwidth = 4; addKeys( panel, gbc, Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L, Key.SEMICOLON, Key.QUOTE ); gbc.gridwidth = 9; addModifier(panel, gbc, (OSUtils.IS_MAC_OS ? "return" : "enter"), null); gbc.gridx = 0; gbc.gridy = 12; gbc.gridwidth = 9; addModifier(panel, gbc, "shift", null); gbc.gridwidth = 4; addKeys( panel, gbc, Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M, Key.COMMA, Key.PERIOD, Key.SLASH ); gbc.gridwidth = 11; addModifier(panel, gbc, "shift", null); gbc.gridx = 0; gbc.gridy = 16; if (OSUtils.IS_MAC_OS) { gbc.gridwidth = 6; addModifier(panel, gbc, "control", null); gbc.gridwidth = 5; addModifier(panel, gbc, "option", null); gbc.gridwidth = 6; addModifier(panel, gbc, "command", null); gbc.gridwidth = 26; addKeys(panel, gbc, Key.SPACE); gbc.gridwidth = 6; addModifier(panel, gbc, "command", null); gbc.gridwidth = 5; addModifier(panel, gbc, "option", null); gbc.gridwidth = 6; addModifier(panel, gbc, "control", null); } else { gbc.gridwidth = 6; addModifier(panel, gbc, "ctrl", XkbComposeKey.lctrl); gbc.gridwidth = 5; addModifier(panel, gbc, "❖", XkbComposeKey.lwin, XkbAltGrKey.lwin_switch, XkbAltGrKey.win_switch); addModifier(panel, gbc, "alt", null, XkbAltGrKey.lalt_switch, XkbAltGrKey.alt_switch); gbc.gridwidth = 23; addKeys(panel, gbc, Key.SPACE); gbc.gridwidth = 5; addModifier(panel, gbc, "alt", XkbComposeKey.ralt, XkbAltGrKey.ralt_switch, XkbAltGrKey.alt_switch); addModifier(panel, gbc, "❖", XkbComposeKey.rwin, XkbAltGrKey.rwin_switch, XkbAltGrKey.win_switch); addModifier(panel, gbc, "▤", XkbComposeKey.menu, XkbAltGrKey.menu_switch); gbc.gridwidth = 6; addModifier(panel, gbc, "ctrl", XkbComposeKey.rctrl); } gbc.gridwidth = 4; gbc.gridx = 62; gbc.gridy = 0; addModifier(panel, gbc, (OSUtils.IS_MAC_OS ? "clear" : "numlk"), null); addKeys(panel, gbc, Key.NUMPAD_EQUALS, Key.NUMPAD_DIVIDE, Key.NUMPAD_TIMES); gbc.gridx = 62; gbc.gridy = 4; addKeys(panel, gbc, Key.NUMPAD_7, Key.NUMPAD_8, Key.NUMPAD_9, Key.NUMPAD_MINUS); gbc.gridx = 62; gbc.gridy = 8; addKeys(panel, gbc, Key.NUMPAD_4, Key.NUMPAD_5, Key.NUMPAD_6, Key.NUMPAD_PLUS); gbc.gridx = 62; gbc.gridy = 12; addKeys(panel, gbc, Key.NUMPAD_1, Key.NUMPAD_2, Key.NUMPAD_3); gbc.gridheight = 8; addModifier(panel, gbc, "enter", null, XkbAltGrKey.enter_switch); gbc.gridheight = 4; gbc.gridx = 62; gbc.gridy = 16; addKeys(panel, gbc, Key.NUMPAD_0, Key.NUMPAD_COMMA, Key.NUMPAD_PERIOD); gbc.gridy = 22; gbc.gridx = 0; addKeys(panel, gbc, Key.SECTION); gbc.gridx = 5; addKeys(panel, gbc, Key.BACKSLASH_102); gbc.gridx = 52; addKeys(panel, gbc, Key.YEN); addKeys(panel, gbc, Key.UNDERSCORE); gbc.gridheight = 2; gbc.gridy = 20; gbc.gridx = 0; addLabel(panel, gbc, "Mac ISO"); gbc.gridx = 5; addLabel(panel, gbc, "Win 102"); gbc.gridx = 52; gbc.gridwidth = 8; addLabel(panel, gbc, "Mac JIS"); update(); panel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30)); setLayout(new GridLayout(1, 1, 0, 0)); add(panel); } private void addKeys(JPanel panel, FixedGridBagConstraints gbc, Key... keys) { for (Key key : keys) { KeyMappingPanel kmp = new KeyMappingPanel(km.map.get(key)); kmp.addListener(new MyListener(key)); keyPanels.put(key, kmp); Dimension d = new Dimension(gbc.gridwidth*15, gbc.gridheight*15); kmp.setMinimumSize(d); kmp.setPreferredSize(d); kmp.setMaximumSize(d); panel.add(kmp, gbc); gbc.gridx += gbc.gridwidth; } } private void addModifier(JPanel panel, FixedGridBagConstraints gbc, String label, XkbComposeKey compose, XkbAltGrKey... altgr) { ModifierKeyPanel mkp = new ModifierKeyPanel(km, gbc.gridwidth, label, compose, altgr); modifierPanels.add(mkp); Dimension d = new Dimension(gbc.gridwidth*15, gbc.gridheight*15); mkp.setMinimumSize(d); mkp.setPreferredSize(d); mkp.setMaximumSize(d); panel.add(mkp, gbc); gbc.gridx += gbc.gridwidth; } private void addLabel(JPanel panel, FixedGridBagConstraints gbc, String text) { JLabel label = new JLabel(text); label.setHorizontalAlignment(JLabel.CENTER); Dimension d = new Dimension(gbc.gridwidth*15, gbc.gridheight*15); label.setMinimumSize(d); label.setPreferredSize(d); label.setMaximumSize(d); panel.add(label, gbc); gbc.gridx += gbc.gridwidth; } public void update() { updateKeys(); updateModifiers(); } public void updateKeys() { for (KeyMappingPanel p : keyPanels.values()) p.update(); } public void updateModifiers() { for (ModifierKeyPanel p : modifierPanels) p.update(); } public KeyboardMapping getKeyboardMapping() { return km; } public KeyMappingPanel getKeyMappingPanel(Key key) { return keyPanels.get(key); } public void setSelectedKey(Key key, boolean alt, boolean shift) { keyPanels.get(key).getTextField(alt, shift).requestFocusInWindow(); } public void addListener(KeyboardMappingPanelListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyboardMappingPanelListener listener) { if (listener != null) listeners.remove(listener); } public KeyboardMappingPanelListener[] getListeners() { return listeners.toArray(new KeyboardMappingPanelListener[listeners.size()]); } private class MyListener implements KeyMappingPanelListener { private final Key key; public MyListener(Key key) { this.key = key; } public void focusGained(FocusEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.focusGained(e, key, alt, shift); } public void focusLost(FocusEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.focusLost(e, key, alt, shift); } public void keyPressed(KeyEvent e, boolean alt, boolean shift) { Key key = MyListener.this.key; switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: alt = !alt; if (alt) key = getKeyLeftwards(key); if (key == null) return; setSelectedKey(key, alt, shift); return; case KeyEvent.VK_RIGHT: alt = !alt; if (!alt) key = getKeyRightwards(key); if (key == null) return; setSelectedKey(key, alt, shift); return; case KeyEvent.VK_UP: shift = !shift; if (!shift) { KeyAndAlt kaa = getKeyAbove(key, alt); if (kaa == null) return; key = kaa.key; alt = kaa.alt; } setSelectedKey(key, alt, shift); return; case KeyEvent.VK_DOWN: shift = !shift; if (shift) { KeyAndAlt kaa = getKeyBelow(key, alt); if (kaa == null) return; key = kaa.key; alt = kaa.alt; } setSelectedKey(key, alt, shift); return; case KeyEvent.VK_ESCAPE: case KeyEvent.VK_CLEAR: Component c = KeyboardMappingPanel.this; while (c != null) { if (c instanceof Window) { c.requestFocusInWindow(); return; } else { c = c.getParent(); } } return; } for (KeyboardMappingPanelListener l : listeners) l.keyPressed(e, key, alt, shift); } public void keyReleased(KeyEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.keyReleased(e, key, alt, shift); } public void keyTyped(KeyEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.keyTyped(e, key, alt, shift); } public void mouseClicked(MouseEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.mouseClicked(e, key, alt, shift); } public void mouseEntered(MouseEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.mouseEntered(e, key, alt, shift); } public void mouseExited(MouseEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.mouseExited(e, key, alt, shift); } public void mousePressed(MouseEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.mousePressed(e, key, alt, shift); } public void mouseReleased(MouseEvent e, boolean alt, boolean shift) { for (KeyboardMappingPanelListener l : listeners) l.mouseReleased(e, key, alt, shift); } } private static final List LEFT_RIGHT_ORDER = Arrays.asList( // NUM ROW null, Key.GRAVE_TILDE, Key.NUMROW_1, Key.NUMROW_2, Key.NUMROW_3, Key.NUMROW_4, Key.NUMROW_5, Key.NUMROW_6, Key.NUMROW_7, Key.NUMROW_8, Key.NUMROW_9, Key.NUMROW_0, Key.HYPHEN_UNDERSCORE, Key.EQUALS_PLUS, Key.NUMPAD_EQUALS, Key.NUMPAD_DIVIDE, Key.NUMPAD_TIMES, // TOP ROW null, Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P, Key.LEFT_BRACKET, Key.RIGHT_BRACKET, Key.BACKSLASH, Key.NUMPAD_7, Key.NUMPAD_8, Key.NUMPAD_9, Key.NUMPAD_MINUS, // HOME ROW null, Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L, Key.SEMICOLON, Key.QUOTE, Key.NUMPAD_4, Key.NUMPAD_5, Key.NUMPAD_6, Key.NUMPAD_PLUS, // BOT ROW null, Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M, Key.COMMA, Key.PERIOD, Key.SLASH, Key.NUMPAD_1, Key.NUMPAD_2, Key.NUMPAD_3, // SPACE ETC null, Key.SPACE, Key.NUMPAD_0, Key.NUMPAD_COMMA, Key.NUMPAD_PERIOD, null, Key.SECTION, Key.BACKSLASH_102, Key.YEN, Key.UNDERSCORE, null ); private static Key getKeyLeftwards(Key key) { if (key == null) return null; int i = LEFT_RIGHT_ORDER.indexOf(key); return LEFT_RIGHT_ORDER.get(i - 1); } private static Key getKeyRightwards(Key key) { if (key == null) return null; int i = LEFT_RIGHT_ORDER.indexOf(key); return LEFT_RIGHT_ORDER.get(i + 1); } private static final class KeyAndAlt { private final Key key; private final boolean alt; private KeyAndAlt(Key key, boolean alt) { this.key = key; this.alt = alt; } public boolean equals(Object o) { if (o instanceof KeyAndAlt) { KeyAndAlt that = (KeyAndAlt)o; return this.key == that.key && this.alt == that.alt; } return false; } public int hashCode() { int hash = key.hashCode(); if (alt) hash = ~hash; return hash; } } private static KeyAndAlt P(Key key) { return new KeyAndAlt(key, false); } private static KeyAndAlt A(Key key) { return new KeyAndAlt(key, true); } private static final List UP_DOWN_ORDER = Arrays.asList( // These must come first for navigation away from space, alt space, // and alt backslash to align with the keys along their centers. null, P(Key.NUMROW_5), A(Key.R), A(Key.F), P(Key.V), P(Key.SPACE), null, P(Key.NUMROW_8), A(Key.U), A(Key.J), P(Key.M), A(Key.SPACE), null, A(Key.BACKSLASH), P(Key.UNDERSCORE), // LEFT HALF null, P(Key.GRAVE_TILDE), P(Key.SECTION), null, A(Key.GRAVE_TILDE), A(Key.SECTION), null, P(Key.NUMROW_1), P(Key.BACKSLASH_102), null, A(Key.NUMROW_1), P(Key.Q), P(Key.A), A(Key.BACKSLASH_102), null, P(Key.NUMROW_2), A(Key.Q), A(Key.A), P(Key.Z), null, A(Key.NUMROW_2), P(Key.W), P(Key.S), A(Key.Z), null, P(Key.NUMROW_3), A(Key.W), A(Key.S), P(Key.X), null, A(Key.NUMROW_3), P(Key.E), P(Key.D), A(Key.X), null, P(Key.NUMROW_4), A(Key.E), A(Key.D), P(Key.C), P(Key.SPACE), null, A(Key.NUMROW_4), P(Key.R), P(Key.F), A(Key.C), P(Key.SPACE), // CENTER null, A(Key.NUMROW_5), P(Key.T), P(Key.G), A(Key.V), P(Key.SPACE), null, P(Key.NUMROW_6), A(Key.T), A(Key.G), P(Key.B), P(Key.SPACE), null, A(Key.NUMROW_6), P(Key.Y), P(Key.H), A(Key.B), P(Key.SPACE), null, P(Key.NUMROW_7), A(Key.Y), A(Key.H), P(Key.N), A(Key.SPACE), null, A(Key.NUMROW_7), P(Key.U), P(Key.J), A(Key.N), A(Key.SPACE), // RIGHT HALF null, A(Key.NUMROW_8), P(Key.I), P(Key.K), A(Key.M), A(Key.SPACE), null, P(Key.NUMROW_9), A(Key.I), A(Key.K), P(Key.COMMA), A(Key.SPACE), null, A(Key.NUMROW_9), P(Key.O), P(Key.L), A(Key.COMMA), A(Key.SPACE), null, P(Key.NUMROW_0), A(Key.O), A(Key.L), P(Key.PERIOD), null, A(Key.NUMROW_0), P(Key.P), P(Key.SEMICOLON), A(Key.PERIOD), null, P(Key.HYPHEN_UNDERSCORE), A(Key.P), A(Key.SEMICOLON), P(Key.SLASH), null, A(Key.HYPHEN_UNDERSCORE), P(Key.LEFT_BRACKET), P(Key.QUOTE), A(Key.SLASH), null, P(Key.EQUALS_PLUS), A(Key.LEFT_BRACKET), A(Key.QUOTE), null, A(Key.EQUALS_PLUS), P(Key.RIGHT_BRACKET), null, A(Key.RIGHT_BRACKET), P(Key.YEN), null, P(Key.BACKSLASH), A(Key.YEN), null, A(Key.BACKSLASH), A(Key.UNDERSCORE), // NUM PAD null, P(Key.NUMPAD_7), P(Key.NUMPAD_4), P(Key.NUMPAD_1), P(Key.NUMPAD_0), null, A(Key.NUMPAD_7), A(Key.NUMPAD_4), A(Key.NUMPAD_1), A(Key.NUMPAD_0), null, P(Key.NUMPAD_EQUALS), P(Key.NUMPAD_8), P(Key.NUMPAD_5), P(Key.NUMPAD_2), P(Key.NUMPAD_COMMA), null, A(Key.NUMPAD_EQUALS), A(Key.NUMPAD_8), A(Key.NUMPAD_5), A(Key.NUMPAD_2), A(Key.NUMPAD_COMMA), null, P(Key.NUMPAD_DIVIDE), P(Key.NUMPAD_9), P(Key.NUMPAD_6), P(Key.NUMPAD_3), P(Key.NUMPAD_PERIOD), null, A(Key.NUMPAD_DIVIDE), A(Key.NUMPAD_9), A(Key.NUMPAD_6), A(Key.NUMPAD_3), A(Key.NUMPAD_PERIOD), null, P(Key.NUMPAD_TIMES), P(Key.NUMPAD_MINUS), P(Key.NUMPAD_PLUS), null, A(Key.NUMPAD_TIMES), A(Key.NUMPAD_MINUS), A(Key.NUMPAD_PLUS), null ); private static KeyAndAlt getKeyAbove(Key key, boolean alt) { if (key == null) return null; int i = UP_DOWN_ORDER.indexOf(new KeyAndAlt(key, alt)); return UP_DOWN_ORDER.get(i - 1); } private static KeyAndAlt getKeyBelow(Key key, boolean alt) { if (key == null) return null; int i = UP_DOWN_ORDER.indexOf(new KeyAndAlt(key, alt)); return UP_DOWN_ORDER.get(i + 1); } } KeyboardMappingPanelListener.java000066400000000000000000000017621506470510200342160ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/editpackage com.kreative.keyedit.edit; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import com.kreative.keyedit.Key; public interface KeyboardMappingPanelListener { public void focusGained (FocusEvent e, Key key, boolean alt, boolean shift); public void focusLost (FocusEvent e, Key key, boolean alt, boolean shift); public void keyPressed (KeyEvent e, Key key, boolean alt, boolean shift); public void keyReleased (KeyEvent e, Key key, boolean alt, boolean shift); public void keyTyped (KeyEvent e, Key key, boolean alt, boolean shift); public void mouseClicked (MouseEvent e, Key key, boolean alt, boolean shift); public void mouseEntered (MouseEvent e, Key key, boolean alt, boolean shift); public void mouseExited (MouseEvent e, Key key, boolean alt, boolean shift); public void mousePressed (MouseEvent e, Key key, boolean alt, boolean shift); public void mouseReleased(MouseEvent e, Key key, boolean alt, boolean shift); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/LayoutInfoFrame.java000066400000000000000000000042031506470510200315700ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import com.kreative.keyedit.KeyboardMapping; public class LayoutInfoFrame extends JDialog { private static final long serialVersionUID = 1L; private final LayoutInfoPanel panel; private final List listeners; public LayoutInfoFrame(Frame parent, KeyboardMapping km) { super(parent, "Layout Info"); this.panel = new LayoutInfoPanel(km); this.listeners = new ArrayList(); JButton cancelButton = new JButton("Cancel"); JButton okButton = new JButton("OK"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(cancelButton); buttonPanel.add(okButton); JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(this.panel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDefaultButton(getRootPane(), okButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { panel.commit(); dispose(); for (KeyEditListener l : listeners) l.metadataChanged(); } }); setSize(1200, 720); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } public void addListener(KeyEditListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(KeyEditListener listener) { if (listener != null) listeners.remove(listener); } public KeyEditListener[] getListeners() { return listeners.toArray(new KeyEditListener[listeners.size()]); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/LayoutInfoPanel.java000066400000000000000000001354021506470510200316030ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.SystemColor; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.LinkedHashMap; import java.util.Scanner; import java.util.TreeSet; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.text.AbstractDocument; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DocumentFilter; import com.kreative.keyedit.HTMLWriterUtility; import com.kreative.keyedit.KeyManPlatform; import com.kreative.keyedit.KeyManProjectWriter; import com.kreative.keyedit.KeyManTarget; import com.kreative.keyedit.KeyManWriterUtility; import com.kreative.keyedit.KeyboardMapping; import com.kreative.keyedit.KkbReader; import com.kreative.keyedit.KkbWriter; import com.kreative.keyedit.WinLocale; import com.kreative.keyedit.XkbAltGrKey; import com.kreative.keyedit.XkbComposeKey; import com.kreative.unicode.data.NameResolver; public class LayoutInfoPanel extends JPanel { private static final long serialVersionUID = 1L; private final KeyboardMapping km; private final JTextField name; private final JTextField winIdentifier; private final JTextField winCopyright; private final JTextField winCompany; private final WinLocaleTableModel winLocaleModel; private final JTable winLocaleTable; private final JScrollPane winLocalePane; private final JCheckBox winAltGrEnable; private final JCheckBox winShiftLock; private final JCheckBox winLrmRlm; private final SpinnerNumberModel macGroupNumber; private final SpinnerNumberModel macIdNumber; private final JTextField xkbPath; private final JTextField xkbLabel; private final JTextArea xkbComment; private final JComboBox xkbAltGrKey; private final JComboBox xkbComposeKey; private final BufferedImageWell icon; private final JTextField macIconVersion; private final CodePointLabelTableModel macActionIdsModel; private final JTable macActionIdsTable; private final JScrollPane macActionIdsPane; private final JButton macActionIdsAdd; private final JButton macActionIdsDelete; private final JTextField keymanIdentifier; private final JTextField keymanName; private final JTextField keymanCopyright; private final JTextField keymanMessage; private final JTextField keymanWebHelpText; private final JTextField keymanVersion; private final JTextArea keymanComments; private final JTextField keymanAuthor; private final JTextField keymanEmailAddress; private final JTextField keymanWebSite; private final JCheckBox keymanRightToLeft; private final JCheckBox keymanKey102; private final JCheckBox keymanDisplayUnderlying; private final JCheckBox keymanUseAltGr; private final JCheckBox keymanIgnoreCaps; private final JCheckBox[] keymanTargets; private final JCheckBox[] keymanPlatforms; private final KeyManLanguageTableModel keymanLanguagesModel; private final JTable keymanLanguagesTable; private final JScrollPane keymanLanguagesPane; private final JButton keymanLanguagesAdd; private final JButton keymanLanguagesDelete; private final JButton keymanLanguagesClear; private final JButton keymanLanguagesCopy; private final JButton keymanLanguagesPaste; private final JButton keymanLanguagesSort; private final KeyManAttachmentPanel keymanAttachments; private final CodePointLabelTableModel keymanCpLabelsModel; private final JTable keymanCpLabelsTable; private final JScrollPane keymanCpLabelsPane; private final JButton keymanCpLabelsAdd; private final JButton keymanCpLabelsDelete; private final JTextField keymanFontFamily; private final JComboBox keymanOSKFontFile; private final JComboBox keymanDisplayFontFile; private final JTextField keymanDescription; private final JTextField keymanLicenseType; private final JTextArea keymanLicenseText; private final JButton keymanLicenseDefault; private final JTextArea keymanReadme; private final JButton keymanReadmeDefault; private final JTextArea keymanHistory; private final JButton keymanHistoryDefault; private final JTextField htmlTitle; private final JTextArea htmlStyle; private final JTextField htmlH1; private final JTextField htmlH2; private final JTextArea htmlBody1; private final JTextArea htmlBody2; private final JTextArea htmlBody3; private final JTextArea htmlBody4; private final JTextArea htmlInstall; private final JButton htmlInstallDefault; private final JTextField htmlSquareChars; private final JTextField htmlOutlineChars; private final CodePointClassTableModel htmlTdClassesModel; private final JTable htmlTdClassesTable; private final JScrollPane htmlTdClassesPane; private final JButton htmlTdClassesAdd; private final JButton htmlTdClassesDelete; private final CodePointClassTableModel htmlSpanClassesModel; private final JTable htmlSpanClassesTable; private final JScrollPane htmlSpanClassesPane; private final JButton htmlSpanClassesAdd; private final JButton htmlSpanClassesDelete; private final CodePointLabelTableModel htmlCpLabelsModel; private final JTable htmlCpLabelsTable; private final JScrollPane htmlCpLabelsPane; private final JButton htmlCpLabelsAdd; private final JButton htmlCpLabelsDelete; private final KeyManAttachmentPanel winAttachments; private final KeyManAttachmentPanel macAttachments; private final KeyManAttachmentPanel xkbAttachments; private final JCheckBox charsIncludeDeadKeys; private final JCheckBox charsIncludeLongPress; private final JCheckBox charsVerbose; private final JTextArea chars; public LayoutInfoPanel(KeyboardMapping km) { this.km = km; this.name = new JTextField(km.name); this.winIdentifier = new JTextField(km.winIdentifier, 8); ((AbstractDocument)this.winIdentifier.getDocument()).setDocumentFilter(new LimitingDocumentFilter(8)); this.winCopyright = new JTextField(km.winCopyright); this.winCompany = new JTextField(km.winCompany); int wli = km.getWinLocaleNotNull().ordinal(); this.winLocaleModel = new WinLocaleTableModel(); this.winLocaleTable = new JTable(this.winLocaleModel); this.winLocaleTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.winLocaleTable.getSelectionModel().setSelectionInterval(wli, wli); this.winLocalePane = scrollWrap(this.winLocaleTable); setColumnWidth(this.winLocaleTable, 0, 80); setColumnWidth(this.winLocaleTable, 1, 120); SwingUtilities.invokeLater(new Runnable() { public void run() { int i = winLocaleTable.getSelectedRow(); Rectangle r = winLocaleTable.getCellRect(i, 0, true); winLocaleTable.scrollRectToVisible(r); } }); this.winAltGrEnable = new JCheckBox("Treat Right Alt as Ctrl+Alt (AltGr)"); this.winAltGrEnable.setSelected(km.winAltGrEnable); this.winShiftLock = new JCheckBox("Disable Caps Lock when Shift is pressed (ShiftLock)"); this.winShiftLock.setSelected(km.winShiftLock); this.winLrmRlm = new JCheckBox("Left Shift + Backspace = LRM, Right Shift + Backspace = RLM"); this.winLrmRlm.setSelected(km.winLrmRlm); this.macGroupNumber = new SpinnerNumberModel(km.macGroupNumber, 0, 127, 1); this.macIdNumber = new SpinnerNumberModel(km.macIdNumber, -32768, 32767, 1); this.xkbPath = new JTextField(km.xkbPath); this.xkbLabel = new JTextField(km.xkbLabel, 4); this.xkbComment = mono(new JTextArea(km.xkbComment)); this.xkbAltGrKey = new JComboBox(XkbAltGrKey.values()); this.xkbAltGrKey.setEditable(false); this.xkbAltGrKey.setMaximumRowCount(32); this.xkbAltGrKey.setSelectedItem(km.xkbAltGrKey); this.xkbComposeKey = new JComboBox(XkbComposeKey.values()); this.xkbComposeKey.setEditable(false); this.xkbComposeKey.setMaximumRowCount(32); this.xkbComposeKey.setSelectedItem(km.xkbComposeKey); this.keymanIdentifier = new JTextField(km.keymanIdentifier); this.keymanName = new JTextField(km.keymanName); this.keymanCopyright = new JTextField(km.keymanCopyright); this.keymanMessage = new JTextField(km.keymanMessage); this.keymanWebHelpText = new JTextField(km.keymanWebHelpText); this.keymanVersion = new JTextField(km.keymanVersion); this.keymanComments = new JTextArea(km.keymanComments); this.keymanAuthor = new JTextField(km.keymanAuthor); this.keymanEmailAddress = new JTextField(km.keymanEmailAddress); this.keymanWebSite = new JTextField(km.keymanWebSite); this.keymanRightToLeft = new JCheckBox("Keyboard is right-to-left"); this.keymanRightToLeft.setSelected(km.keymanRightToLeft); this.keymanKey102 = new JCheckBox("Display 102nd Key (as on European keyboards)"); this.keymanKey102.setSelected(km.keymanKey102); this.keymanDisplayUnderlying = new JCheckBox("Display underlying layout characters"); this.keymanDisplayUnderlying.setSelected(km.keymanDisplayUnderlying); this.keymanUseAltGr = new JCheckBox("Distinguish between left and right Ctrl/Alt"); this.keymanUseAltGr.setSelected(km.keymanUseAltGr); this.keymanIgnoreCaps = new JCheckBox("Disable Caps Lock"); this.keymanIgnoreCaps.setSelected(km.keymanIgnoreCaps); KeyManTarget[] targets = KeyManTarget.values(); this.keymanTargets = new JCheckBox[targets.length]; for (int i = 0; i < targets.length; i++) { this.keymanTargets[i] = new JCheckBox(targets[i].toString()); this.keymanTargets[i].setSelected(km.keymanTargets.contains(targets[i])); } KeyManPlatform[] platforms = KeyManPlatform.values(); this.keymanPlatforms = new JCheckBox[platforms.length]; for (int i = 0; i < platforms.length; i++) { this.keymanPlatforms[i] = new JCheckBox(platforms[i].toString()); this.keymanPlatforms[i].setSelected(km.keymanPlatforms.contains(platforms[i])); } this.keymanLanguagesModel = new KeyManLanguageTableModel(km.keymanLanguages); this.keymanLanguagesTable = new JTable(this.keymanLanguagesModel); this.keymanLanguagesTable.setDefaultRenderer(String.class, new KeyManLanguageTableCellRenderer(keymanLanguagesModel)); this.keymanLanguagesPane = scrollWrap(this.keymanLanguagesTable); this.keymanLanguagesAdd = square(new JButton("+")); this.keymanLanguagesAdd.addActionListener(new AddKeyManLanguageActionListener(keymanLanguagesModel, keymanLanguagesTable, keymanLanguagesPane)); this.keymanLanguagesDelete = square(new JButton("\u2212")); this.keymanLanguagesDelete.addActionListener(new DeleteKeyManLanguageActionListener(keymanLanguagesModel, keymanLanguagesTable)); this.keymanLanguagesClear = new JButton("Clear All"); this.keymanLanguagesClear.addActionListener(new ClearKeyManLanguageActionListener(keymanLanguagesModel)); this.keymanLanguagesCopy = new JButton("Copy All"); this.keymanLanguagesCopy.addActionListener(new CopyKeyManLanguageActionListener(keymanLanguagesModel)); this.keymanLanguagesPaste = new JButton("Paste All"); this.keymanLanguagesPaste.addActionListener(new PasteKeyManLanguageActionListener(keymanLanguagesModel)); this.keymanLanguagesSort = new JButton("Sort All"); this.keymanLanguagesSort.addActionListener(new SortKeyManLanguageActionListener(keymanLanguagesModel)); setColumnWidth(keymanLanguagesTable, 0, 80); this.keymanAttachments = new KeyManAttachmentPanel(km.keymanAttachments); this.keymanAttachments.addListener(new KeyManAttachmentPanelListener() { public void attachmentsChanged(KeyManAttachmentListModel model) { updateKeymanFonts(model); } }); this.keymanCpLabelsModel = new CodePointLabelTableModel(km.keymanCpLabels, "Label"); this.keymanCpLabelsTable = new JTable(this.keymanCpLabelsModel); this.keymanCpLabelsPane = scrollWrap(this.keymanCpLabelsTable); this.keymanCpLabelsAdd = square(new JButton("+")); this.keymanCpLabelsAdd.addActionListener(new AddCodePointLabelActionListener(keymanCpLabelsModel, keymanCpLabelsTable, keymanCpLabelsPane)); this.keymanCpLabelsDelete = square(new JButton("\u2212")); this.keymanCpLabelsDelete.addActionListener(new DeleteCodePointLabelActionListener(keymanCpLabelsModel, keymanCpLabelsTable)); setColumnWidth(keymanCpLabelsTable, 0, 80); setColumnWidth(keymanCpLabelsTable, 1, 80); this.keymanFontFamily = new JTextField(km.keymanFontFamily); this.keymanOSKFontFile = new JComboBox(new String[0]); this.keymanOSKFontFile.setEditable(false); this.keymanOSKFontFile.setMaximumRowCount(32); this.keymanDisplayFontFile = new JComboBox(new String[0]); this.keymanDisplayFontFile.setEditable(false); this.keymanDisplayFontFile.setMaximumRowCount(32); updateKeymanFonts(null); this.keymanDescription = new JTextField(km.keymanDescription); this.keymanLicenseType = mono(new JTextField(km.keymanLicenseType, 8)); this.keymanLicenseText = mono(new JTextArea(km.keymanLicenseText)); this.keymanLicenseDefault = new JButton("Generate Default License"); this.keymanLicenseDefault.addActionListener(new KeymanDefaultActionListener("keyman-license.md", keymanLicenseText)); this.keymanReadme = mono(new JTextArea(km.keymanReadme)); this.keymanReadmeDefault = new JButton("Generate Default Readme"); this.keymanReadmeDefault.addActionListener(new KeymanDefaultActionListener("keyman-readme.md", keymanReadme)); this.keymanHistory = mono(new JTextArea(km.keymanHistory)); this.keymanHistoryDefault = new JButton("Generate Default History"); this.keymanHistoryDefault.addActionListener(new KeymanDefaultActionListener("keyman-history.md", keymanHistory)); this.icon = size(new BufferedImageWell(km.icon), 36, 36); String miv = null; if (km.macIconVersion != null) { miv = "00000000" + Integer.toHexString(km.macIconVersion); miv = miv.substring(miv.length() - 8).toUpperCase(); } this.macIconVersion = new JTextField(miv, 8); this.macActionIdsModel = new CodePointLabelTableModel(km.macActionIds, "Action ID"); this.macActionIdsTable = new JTable(this.macActionIdsModel); this.macActionIdsPane = scrollWrap(this.macActionIdsTable); this.macActionIdsAdd = square(new JButton("+")); this.macActionIdsAdd.addActionListener(new AddCodePointLabelActionListener(macActionIdsModel, macActionIdsTable, macActionIdsPane)); this.macActionIdsDelete = square(new JButton("\u2212")); this.macActionIdsDelete.addActionListener(new DeleteCodePointLabelActionListener(macActionIdsModel, macActionIdsTable)); setColumnWidth(macActionIdsTable, 0, 80); setColumnWidth(macActionIdsTable, 1, 80); this.htmlTitle = new JTextField(km.htmlTitle); this.htmlStyle = mono(new JTextArea(km.htmlStyle)); this.htmlH1 = new JTextField(km.htmlH1); this.htmlH2 = new JTextField(km.htmlH2); this.htmlBody1 = mono(new JTextArea(km.htmlBody1)); this.htmlBody2 = mono(new JTextArea(km.htmlBody2)); this.htmlBody3 = mono(new JTextArea(km.htmlBody3)); this.htmlBody4 = mono(new JTextArea(km.htmlBody4)); this.htmlInstall = mono(new JTextArea(km.htmlInstall)); this.htmlInstallDefault = new JButton("Generate Default Instructions"); this.htmlInstallDefault.addActionListener(new HTMLInstallDefaultActionListener()); this.htmlSquareChars = new JTextField(KkbWriter.formatRanges(km.htmlSquareChars)); this.htmlOutlineChars = new JTextField(KkbWriter.formatRanges(km.htmlOutlineChars)); this.htmlTdClassesModel = new CodePointClassTableModel(km.htmlTdClasses); this.htmlTdClassesTable = new JTable(this.htmlTdClassesModel); this.htmlTdClassesPane = scrollWrap(this.htmlTdClassesTable); this.htmlTdClassesAdd = square(new JButton("+")); this.htmlTdClassesAdd.addActionListener(new AddCodePointClassActionListener(htmlTdClassesModel, htmlTdClassesTable, htmlTdClassesPane)); this.htmlTdClassesDelete = square(new JButton("\u2212")); this.htmlTdClassesDelete.addActionListener(new DeleteCodePointClassActionListener(htmlTdClassesModel, htmlTdClassesTable)); setColumnWidth(htmlTdClassesTable, 0, 80); this.htmlSpanClassesModel = new CodePointClassTableModel(km.htmlSpanClasses); this.htmlSpanClassesTable = new JTable(this.htmlSpanClassesModel); this.htmlSpanClassesPane = scrollWrap(this.htmlSpanClassesTable); this.htmlSpanClassesAdd = square(new JButton("+")); this.htmlSpanClassesAdd.addActionListener(new AddCodePointClassActionListener(htmlSpanClassesModel, htmlSpanClassesTable, htmlSpanClassesPane)); this.htmlSpanClassesDelete = square(new JButton("\u2212")); this.htmlSpanClassesDelete.addActionListener(new DeleteCodePointClassActionListener(htmlSpanClassesModel, htmlSpanClassesTable)); setColumnWidth(htmlSpanClassesTable, 0, 80); this.htmlCpLabelsModel = new CodePointLabelTableModel(km.htmlCpLabels, "Label"); this.htmlCpLabelsTable = new JTable(this.htmlCpLabelsModel); this.htmlCpLabelsPane = scrollWrap(this.htmlCpLabelsTable); this.htmlCpLabelsAdd = square(new JButton("+")); this.htmlCpLabelsAdd.addActionListener(new AddCodePointLabelActionListener(htmlCpLabelsModel, htmlCpLabelsTable, htmlCpLabelsPane)); this.htmlCpLabelsDelete = square(new JButton("\u2212")); this.htmlCpLabelsDelete.addActionListener(new DeleteCodePointLabelActionListener(htmlCpLabelsModel, htmlCpLabelsTable)); setColumnWidth(htmlCpLabelsTable, 0, 80); setColumnWidth(htmlCpLabelsTable, 1, 80); this.winAttachments = new KeyManAttachmentPanel(km.winAttachments); this.macAttachments = new KeyManAttachmentPanel(km.macAttachments); this.xkbAttachments = new KeyManAttachmentPanel(km.xkbAttachments); this.charsIncludeDeadKeys = new JCheckBox("Include Dead Keys"); this.charsIncludeDeadKeys.setSelected(true); this.charsIncludeDeadKeys.addActionListener(new UpdateCharsActionListener()); this.charsIncludeLongPress = new JCheckBox("Include Long Press"); this.charsIncludeLongPress.addActionListener(new UpdateCharsActionListener()); this.charsVerbose = new JCheckBox("Show Details"); this.charsVerbose.addActionListener(new UpdateCharsActionListener()); this.chars = mono(new JTextArea()); this.chars.setEditable(false); this.chars.setLineWrap(true); new UpdateCharsActionListener().actionPerformed(null); JPanel iconPanel = leftSxS(new JLabel("Icon:"), icon, 8); JPanel namePanel = leftSxS(new JLabel("Name:"), name, 8); JPanel topPanel = leftSxS(iconPanel, verticalCenter(namePanel), 16); JPanel winLabels = verticalStack("Short Name:", "Copyright:", "Company:"); JPanel winFields = verticalStack(leftAlign(winIdentifier), winCopyright, winCompany); JPanel winLocSel = topSxS(new JLabel("Locale:"), winLocalePane, 4); JPanel winChecks = verticalStack(winAltGrEnable, winShiftLock, winLrmRlm); JPanel winPanel1 = verticalSxS(leftSxS(winLabels, winFields, 8), winLocSel, winChecks, 8); JPanel winPanel = left2Right1(winPanel1, winAttachments, 20); JPanel macLabels = verticalStack("Group Number:", "ID Number:", "Icon Version:"); JPanel macFields = verticalStack(leftAlign(macGroupNumber), leftAlign(macIdNumber), leftAlign(macIconVersion)); JPanel macActIDs = topSxS(new JLabel("Action IDs:"), macActionIdsPane, 4); JPanel macButton = leftAlign(horizontalStack(macActionIdsAdd, macActionIdsDelete)); JPanel macPanel1 = verticalSxS(leftSxS(macLabels, macFields, 8), macActIDs, macButton, 8); JPanel macPanel = left2Right1(macPanel1, macAttachments, 20); JPanel xkbLabel1 = verticalStack("Path:", "Label:"); JPanel xkbField1 = verticalStack(xkbPath, leftAlign(xkbLabel)); JPanel xkbCommnt = topSxS(new JLabel("Comment:"), scrollWrap(xkbComment), 4); JPanel xkbLabel2 = verticalStack("AltGr Key:", "Compose Key:"); JPanel xkbField2 = leftAlign(verticalStack(xkbAltGrKey, xkbComposeKey)); JPanel xkbPanel1 = verticalSxS(leftSxS(xkbLabel1, xkbField1, 8), xkbCommnt, leftSxS(xkbLabel2, xkbField2, 8), 8); JPanel xkbPanel = left2Right1(xkbPanel1, xkbAttachments, 20); JPanel kmnLabels = verticalStack("ID:", "Name:", "Copyright:", "Message:", "Web Help Text:", "Keyboard Version:", "Author:", "Email Address:", "Web Site:"); JPanel kmnFields = verticalStack(keymanIdentifier, keymanName, keymanCopyright, keymanMessage, keymanWebHelpText, keymanVersion, keymanAuthor, keymanEmailAddress, keymanWebSite); JPanel kmnCommts = topSxS(new JLabel("Comments:"), scrollWrap(keymanComments), 4); JPanel kmnPanelL = topSxS(leftSxS(kmnLabels, kmnFields, 8), kmnCommts, 8); JPanel kmnChecks = verticalStack(keymanRightToLeft, keymanKey102, keymanDisplayUnderlying, keymanUseAltGr, keymanIgnoreCaps); JPanel kmnTarget = topSxS(new JLabel("Targets:"), scrollWrap(topAlign(verticalStack(0, keymanTargets))), 4); JPanel kmnPlatfm = topSxS(new JLabel("Platforms:"), scrollWrap(topAlign(verticalStack(0, keymanPlatforms))), 4); JPanel kmnTgtPfm = horizontalStack(12, kmnTarget, kmnPlatfm); JPanel kmnLangsB = leftAlign(leftSxS(horizontalStack(keymanLanguagesAdd, keymanLanguagesDelete), horizontalStack(keymanLanguagesClear, keymanLanguagesCopy, keymanLanguagesPaste, keymanLanguagesSort), 4)); JPanel kmnLangsP = verticalSxS(new JLabel("Languages:"), keymanLanguagesPane, kmnLangsB, 4); JPanel kmnPanelR = topSxS(kmnChecks, verticalStack(8, kmnTgtPfm, kmnLangsP), 8); JPanel kmnPanel = horizontalStack(20, kmnPanelL, kmnPanelR); JPanel kmnFontLb = verticalStack("Editor Font:", "OSK Font:", "Display Font:"); JPanel kmnFontFd = verticalStack(keymanFontFamily, keymanOSKFontFile, keymanDisplayFontFile); JPanel kmnFontFm = leftSxS(kmnFontLb, kmnFontFd, 8); JPanel kmnCpLabs = topSxS(new JLabel("Code Point Labels:"), keymanCpLabelsPane, 4); JPanel kmnCpBtns = leftAlign(horizontalStack(keymanCpLabelsAdd, keymanCpLabelsDelete)); JPanel kmnFontP1 = verticalSxS(kmnFontFm, kmnCpLabs, kmnCpBtns, 8); JPanel kmnFontP = left2Right1(kmnFontP1, keymanAttachments, 20); JPanel kmnRMDesc = leftSxS(new JLabel("Description:"), keymanDescription, 8); JPanel kmnRMText = verticalSxS(new JLabel("Readme Markdown:"), scrollWrap(keymanReadme), leftAlign(keymanReadmeDefault), 4); JPanel kmnRMPane = topSxS(kmnRMDesc, kmnRMText, 8); JPanel kmnLicTyp = leftSxS(new JLabel("License Type:"), leftAlign(keymanLicenseType), 8); JPanel kmnLicTxt = verticalSxS(new JLabel("License Markdown:"), scrollWrap(keymanLicenseText), leftAlign(keymanLicenseDefault), 4); JPanel kmnLicPnl = topSxS(kmnLicTyp, kmnLicTxt, 8); JPanel kmnHistP = verticalSxS(new JLabel("History Markdown:"), scrollWrap(keymanHistory), leftAlign(keymanHistoryDefault), 4); JPanel htmHLabel = verticalStack("Title:", "H1:", "H2:"); JPanel htmHField = verticalStack(htmlTitle, htmlH1, htmlH2); JPanel htmStyles = topSxS(new JLabel("Stylesheet:"), scrollWrap(htmlStyle), 4); JPanel htmLLabel = verticalStack("Square Chars:", "Outline Chars:"); JPanel htmLField = verticalStack(htmlSquareChars, htmlOutlineChars); JPanel htmTcLabs = topSxS(new JLabel("Cell Classes:"), htmlTdClassesPane, 4); JPanel htmTcBtns = leftAlign(horizontalStack(htmlTdClassesAdd, htmlTdClassesDelete)); JPanel htmScLabs = topSxS(new JLabel("Span Classes:"), htmlSpanClassesPane, 4); JPanel htmScBtns = leftAlign(horizontalStack(htmlSpanClassesAdd, htmlSpanClassesDelete)); JPanel htmCpLabs = topSxS(new JLabel("Code Point Labels:"), htmlCpLabelsPane, 4); JPanel htmCpBtns = leftAlign(horizontalStack(htmlCpLabelsAdd, htmlCpLabelsDelete)); JPanel htmXxLabs = horizontalStack(htmTcLabs, htmScLabs, htmCpLabs); JPanel htmXxBtns = horizontalStack(htmTcBtns, htmScBtns, htmCpBtns); JPanel htmPanelH = topSxS(leftSxS(htmHLabel, htmHField, 8), htmStyles, 8); JPanel htmPanelL = verticalSxS(leftSxS(htmLLabel, htmLField, 8), htmXxLabs, htmXxBtns, 8); JPanel htmPanel1 = topSxS(new JLabel("Body HTML below header:"), scrollWrap(htmlBody1), 4); JPanel htmPanel2 = topSxS(new JLabel("Body HTML above layout:"), scrollWrap(htmlBody2), 4); JPanel htmPanel3 = topSxS(new JLabel("Body HTML below layout:"), scrollWrap(htmlBody3), 4); JPanel htmPanelI = verticalSxS(new JLabel("Installation instructions HTML:"), scrollWrap(htmlInstall), leftAlign(htmlInstallDefault), 4); JPanel htmPanel4 = topSxS(new JLabel("Footer HTML:"), scrollWrap(htmlBody4), 4); JPanel charsBtns = horizontalStack(12, charsIncludeDeadKeys, charsIncludeLongPress, charsVerbose); JPanel charsHead = rightSxS(new JLabel("Characters generated by layout:"), charsBtns, 12); JPanel charsPnl = topSxS(charsHead, scrollWrap(chars), 4); JTabbedPane tabs = new JTabbedPane(JTabbedPane.LEFT); tabs.add("Windows (MSKLC)", addBorder(winPanel, 20)); tabs.add("Mac OS X", addBorder(macPanel, 20)); tabs.add("Linux (XKB)", addBorder(xkbPanel, 20)); tabs.add("Keyman", addBorder(kmnPanel, 20)); tabs.add("Keyman Fonts", addBorder(kmnFontP, 20)); tabs.add("Keyman Readme", addBorder(kmnRMPane, 20)); tabs.add("Keyman License", addBorder(kmnLicPnl, 20)); tabs.add("Keyman History", addBorder(kmnHistP, 20)); tabs.add("HTML Header", addBorder(htmPanelH, 20)); tabs.add("HTML Layout", addBorder(htmPanelL, 20)); tabs.add("HTML Body 1", addBorder(htmPanel1, 20)); tabs.add("HTML Body 2", addBorder(htmPanel2, 20)); tabs.add("HTML Body 3", addBorder(htmPanel3, 20)); tabs.add("HTML Install", addBorder(htmPanelI, 20)); tabs.add("HTML Footer", addBorder(htmPanel4, 20)); tabs.add("Characters", addBorder(charsPnl, 20)); JPanel mainPanel = topSxS(topPanel, tabs, 16); setLayout(new GridLayout(1,1,0,0)); add(mainPanel); } private static JPanel verticalCenter(Component c) { JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); p.add(Box.createVerticalGlue()); p.add(c); p.add(Box.createVerticalGlue()); return p; } private static JPanel verticalStack(String... labels) { JPanel p = new JPanel(new GridLayout(0,1,4,4)); for (String s : labels) p.add(new JLabel(s)); return p; } private static JPanel verticalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(0,1,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel verticalStack(int gap, Component... comps) { JPanel p = new JPanel(new GridLayout(0,1,gap,gap)); for (Component c : comps) p.add(c); return p; } private static JPanel horizontalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel horizontalStack(int gap, Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,gap,gap)); for (Component c : comps) p.add(c); return p; } private static JPanel leftAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.LINE_START); return p; } private static JPanel leftAlign(SpinnerNumberModel snm) { JPanel p = new JPanel(new BorderLayout()); p.add(new JSpinner(snm), BorderLayout.LINE_START); return p; } private static JPanel leftSxS(Component l, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(l, BorderLayout.LINE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel rightSxS(Component c, Component r, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(c, BorderLayout.CENTER); p.add(r, BorderLayout.LINE_END); return p; } private static JPanel left2Right1(JComponent l, JComponent r, int gap) { JPanel p = new JPanel(new FixedGridBagLayout()); FixedGridBagConstraints gbc = new FixedGridBagConstraints(); gbc.gridwidth = 2; p.add(addBorder(l, 0, 0, 0, gap/2), gbc); gbc.gridx = 2; gbc.gridwidth = 1; p.add(addBorder(r, 0, gap/2, 0, 0), gbc); return p; } private static JPanel topAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.PAGE_START); return p; } private static JPanel topSxS(Component t, Component c, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); return p; } private static JPanel verticalSxS(Component t, Component c, Component b, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); p.add(b, BorderLayout.PAGE_END); return p; } private static C addBorder(C c, int b) { c.setBorder(BorderFactory.createEmptyBorder(b, b, b, b)); return c; } private static C addBorder(C c, int t, int l, int b, int r) { c.setBorder(BorderFactory.createEmptyBorder(t, l, b, r)); return c; } private static C mono(C c) { c.setFont(new Font("Monospaced", Font.PLAIN, 12)); return c; } private static C size(C c, int w, int h) { Dimension d = new Dimension(w, h); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); return c; } private static C square(C c) { Dimension d = c.getPreferredSize(); d.width = (d.height += 8); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); c.putClientProperty("JButton.buttonType", "bevel"); return c; } private static JScrollPane scrollWrap(Component c) { return new JScrollPane( c, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); } private static void setColumnWidth(JTable t, int col, int w) { TableColumn column = t.getColumnModel().getColumn(col); column.setMinWidth(w); column.setPreferredWidth(w); column.setMaxWidth(w); } private static boolean hasExt(String name, String... exts) { name = name.toLowerCase(); for (String ext : exts) if (name.endsWith(ext)) return true; return false; } private void updateKeymanFonts(KeyManAttachmentListModel alm) { String currentOSKFont; String currentDisplayFont; if (alm == null) { currentOSKFont = (km.keymanOSKFontFile != null && km.keymanOSKFontFile.length() > 0) ? km.keymanOSKFontFile : null; currentDisplayFont = (km.keymanDisplayFontFile != null && km.keymanDisplayFontFile.length() > 0) ? km.keymanDisplayFontFile : null; } else { currentOSKFont = (this.keymanOSKFontFile.getSelectedIndex() > 0) ? this.keymanOSKFontFile.getSelectedItem().toString() : null; currentDisplayFont = (this.keymanDisplayFontFile.getSelectedIndex() > 0) ? this.keymanDisplayFontFile.getSelectedItem().toString() : null; } ArrayList options = new ArrayList(); options.add("None"); if (alm == null) { for (String name : km.keymanAttachments.keySet()) { if (hasExt(name, ".ttf", ".otf", ".eot", ".woff", ".woff2")) { options.add(name); } } } else { for (int i = 0, n = alm.getSize(); i < n; i++) { String name = alm.getElementAt(i).toString(); if (hasExt(name, ".ttf", ".otf", ".eot", ".woff", ".woff2")) { options.add(name); } } } this.keymanOSKFontFile.setModel(new DefaultComboBoxModel(options.toArray())); this.keymanDisplayFontFile.setModel(new DefaultComboBoxModel(options.toArray())); this.keymanOSKFontFile.setSelectedIndex(0); this.keymanDisplayFontFile.setSelectedIndex(0); if (currentOSKFont != null) this.keymanOSKFontFile.setSelectedItem(currentOSKFont); if (currentDisplayFont != null) this.keymanDisplayFontFile.setSelectedItem(currentDisplayFont); } public void commit() { km.name = this.name.getText(); km.winIdentifier = this.winIdentifier.getText(); km.winCopyright = this.winCopyright.getText(); km.winCompany = this.winCompany.getText(); km.winLocale = WinLocale.values()[this.winLocaleTable.getSelectedRow()]; km.winAltGrEnable = this.winAltGrEnable.isSelected(); km.winShiftLock = this.winShiftLock.isSelected(); km.winLrmRlm = this.winLrmRlm.isSelected(); km.macGroupNumber = this.macGroupNumber.getNumber().intValue(); km.macIdNumber = this.macIdNumber.getNumber().intValue(); km.xkbPath = this.xkbPath.getText(); km.xkbLabel = this.xkbLabel.getText(); km.xkbComment = this.xkbComment.getText(); km.xkbAltGrKey = (XkbAltGrKey)this.xkbAltGrKey.getSelectedItem(); km.xkbComposeKey = (XkbComposeKey)this.xkbComposeKey.getSelectedItem(); km.keymanIdentifier = this.keymanIdentifier.getText(); km.keymanName = this.keymanName.getText(); km.keymanCopyright = this.keymanCopyright.getText(); km.keymanMessage = this.keymanMessage.getText(); km.keymanWebHelpText = this.keymanWebHelpText.getText(); km.keymanVersion = this.keymanVersion.getText(); km.keymanComments = this.keymanComments.getText(); km.keymanAuthor = this.keymanAuthor.getText(); km.keymanEmailAddress = this.keymanEmailAddress.getText(); km.keymanWebSite = this.keymanWebSite.getText(); km.keymanRightToLeft = this.keymanRightToLeft.isSelected(); km.keymanKey102 = this.keymanKey102.isSelected(); km.keymanDisplayUnderlying = this.keymanDisplayUnderlying.isSelected(); km.keymanUseAltGr = this.keymanUseAltGr.isSelected(); km.keymanIgnoreCaps = this.keymanIgnoreCaps.isSelected(); KeyManTarget[] targets = KeyManTarget.values(); for (int i = 0; i < targets.length; i++) { if (this.keymanTargets[i].isSelected()) km.keymanTargets.add(targets[i]); else km.keymanTargets.remove(targets[i]); } KeyManPlatform[] platforms = KeyManPlatform.values(); for (int i = 0; i < platforms.length; i++) { if (this.keymanPlatforms[i].isSelected()) km.keymanPlatforms.add(platforms[i]); else km.keymanPlatforms.remove(platforms[i]); } this.keymanLanguagesModel.toMap(km.keymanLanguages); this.keymanAttachments.toMap(km.keymanAttachments); KeyManProjectWriter.updateFileIds(km); this.keymanCpLabelsModel.toMap(km.keymanCpLabels); km.keymanFontFamily = this.keymanFontFamily.getText(); km.keymanOSKFontFile = ( (this.keymanOSKFontFile.getSelectedIndex() > 0) ? this.keymanOSKFontFile.getSelectedItem().toString() : null ); km.keymanDisplayFontFile = ( (this.keymanDisplayFontFile.getSelectedIndex() > 0) ? this.keymanDisplayFontFile.getSelectedItem().toString() : null ); km.keymanDescription = this.keymanDescription.getText(); km.keymanLicenseType = this.keymanLicenseType.getText(); km.keymanLicenseText = this.keymanLicenseText.getText(); km.keymanReadme = this.keymanReadme.getText(); km.keymanHistory = this.keymanHistory.getText(); km.icon = this.icon.getImage(); try { km.macIconVersion = Integer.parseInt(this.macIconVersion.getText(), 16); } catch (NumberFormatException nfe) { km.macIconVersion = null; } this.macActionIdsModel.toMap(km.macActionIds); km.htmlTitle = this.htmlTitle.getText(); km.htmlStyle = this.htmlStyle.getText(); km.htmlH1 = this.htmlH1.getText(); km.htmlH2 = this.htmlH2.getText(); km.htmlBody1 = this.htmlBody1.getText(); km.htmlBody2 = this.htmlBody2.getText(); km.htmlBody3 = this.htmlBody3.getText(); km.htmlBody4 = this.htmlBody4.getText(); km.htmlInstall = this.htmlInstall.getText(); km.htmlSquareChars = KkbReader.parseRanges(this.htmlSquareChars.getText()); km.htmlOutlineChars = KkbReader.parseRanges(this.htmlOutlineChars.getText()); this.htmlTdClassesModel.toMap(km.htmlTdClasses); this.htmlSpanClassesModel.toMap(km.htmlSpanClasses); this.htmlCpLabelsModel.toMap(km.htmlCpLabels); this.winAttachments.toMap(km.winAttachments); this.macAttachments.toMap(km.macAttachments); this.xkbAttachments.toMap(km.xkbAttachments); } private class LimitingDocumentFilter extends DocumentFilter { private int limit; public LimitingDocumentFilter(int limit) { this.limit = limit; } public void insertString(FilterBypass fb, int offset, String text, AttributeSet a) throws BadLocationException { int currentLength = fb.getDocument().getLength(); int overLimit = currentLength + text.length() - limit; if (overLimit > 0) text = text.substring(0, text.length() - overLimit); if (text.length() > 0) super.insertString(fb, offset, text, a); } public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet a) throws BadLocationException { int currentLength = fb.getDocument().getLength(); int overLimit = currentLength + text.length() - length - limit; if (overLimit > 0) text = text.substring(0, text.length() - overLimit); if (text.length() > 0) super.replace(fb, offset, length, text, a); } } private class KeymanDefaultActionListener implements ActionListener { private final String template; private final JTextArea textArea; private KeymanDefaultActionListener(String template, JTextArea textArea) { this.template = template; this.textArea = textArea; } public void actionPerformed(ActionEvent e) { StringBuffer sb = new StringBuffer(); Scanner scan = KeyManWriterUtility.getTemplate(template); while (scan.hasNextLine()) { if (sb.length() > 0) sb.append("\n"); sb.append(KeyManWriterUtility.replaceFields(scan.nextLine(), km)); } scan.close(); textArea.setText(sb.toString()); if (textArea == keymanLicenseText) { keymanLicenseType.setText("mit"); } } } private class HTMLInstallDefaultActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { StringBuffer sb = new StringBuffer(); String rn = km.isWindowsNativeCompatible() ? "install.html" : "install-nonbmp.html"; Scanner scan = HTMLWriterUtility.getTemplate(rn); while (scan.hasNextLine()) { if (sb.length() > 0) sb.append("\n"); sb.append(HTMLWriterUtility.replaceFields(scan.nextLine(), km)); } scan.close(); htmlInstall.setText(sb.toString()); } } private static class AddCodePointLabelActionListener implements ActionListener { private final CodePointLabelTableModel model; private final JTable table; private final JScrollPane pane; private AddCodePointLabelActionListener(CodePointLabelTableModel model, JTable table, JScrollPane pane) { this.model = model; this.table = table; this.pane = pane; } public void actionPerformed(ActionEvent e) { final int i = model.getRowCount(); model.addEntry(32, "space"); SwingUtilities.invokeLater(new Runnable() { public void run() { table.getSelectionModel().setSelectionInterval(i, i); JScrollBar vsb = pane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); } } private static class DeleteCodePointLabelActionListener implements ActionListener { private final CodePointLabelTableModel model; private final JTable table; private DeleteCodePointLabelActionListener(CodePointLabelTableModel model, JTable table) { this.model = model; this.table = table; } public void actionPerformed(ActionEvent e) { int[] rows = table.getSelectedRows(); for (int i = rows.length - 1; i >= 0; i--) { model.deleteEntry(rows[i]); } } } private static class AddCodePointClassActionListener implements ActionListener { private final CodePointClassTableModel model; private final JTable table; private final JScrollPane pane; private AddCodePointClassActionListener(CodePointClassTableModel model, JTable table, JScrollPane pane) { this.model = model; this.table = table; this.pane = pane; } public void actionPerformed(ActionEvent e) { final int i = model.getRowCount(); model.addEntry("", new BitSet()); SwingUtilities.invokeLater(new Runnable() { public void run() { table.getSelectionModel().setSelectionInterval(i, i); JScrollBar vsb = pane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); } } private static class DeleteCodePointClassActionListener implements ActionListener { private final CodePointClassTableModel model; private final JTable table; private DeleteCodePointClassActionListener(CodePointClassTableModel model, JTable table) { this.model = model; this.table = table; } public void actionPerformed(ActionEvent e) { int[] rows = table.getSelectedRows(); for (int i = rows.length - 1; i >= 0; i--) { model.deleteEntry(rows[i]); } } } private static class KeyManLanguageTableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private final KeyManLanguageTableModel model; private KeyManLanguageTableCellRenderer(KeyManLanguageTableModel model) { this.model = model; } public Component getTableCellRendererComponent(JTable table, Object value, boolean sel, boolean focus, int row, int col) { Component c = super.getTableCellRendererComponent(table, value, sel, focus, row, col); if (!sel) { Object v0 = model.getValueAt(row, 0); Object v1 = model.getValueAt(row, 1); if (v0 == null || v1 == null) { c.setBackground(Color.red); c.setForeground(Color.white); } else { String s0 = v0.toString(); String s1 = v1.toString(); if (s0 == null || s1 == null || s0.trim().length() == 0 || s1.trim().length() == 0) { c.setBackground(Color.red); c.setForeground(Color.white); } else { WinLocale loc0 = WinLocale.forTag(s0, null); WinLocale loc1 = WinLocale.forName(s1, null); if (loc0 != loc1) { c.setBackground(Color.orange); c.setForeground(Color.black); } else if (loc0 == null) { c.setBackground(Color.yellow); c.setForeground(Color.black); } else { c.setBackground(SystemColor.text); c.setForeground(SystemColor.textText); } } } } return c; } } private static class AddKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private final JTable table; private final JScrollPane pane; private AddKeyManLanguageActionListener(KeyManLanguageTableModel model, JTable table, JScrollPane pane) { this.model = model; this.table = table; this.pane = pane; } public void actionPerformed(ActionEvent e) { final int i = model.getRowCount(); model.addEntry("en", "English"); SwingUtilities.invokeLater(new Runnable() { public void run() { table.getSelectionModel().setSelectionInterval(i, i); JScrollBar vsb = pane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); } } private static class DeleteKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private final JTable table; private DeleteKeyManLanguageActionListener(KeyManLanguageTableModel model, JTable table) { this.model = model; this.table = table; } public void actionPerformed(ActionEvent e) { int[] rows = table.getSelectedRows(); for (int i = rows.length - 1; i >= 0; i--) { model.deleteEntry(rows[i]); } } } private static class ClearKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private ClearKeyManLanguageActionListener(KeyManLanguageTableModel model) { this.model = model; } public void actionPerformed(ActionEvent e) { model.clearEntries(); } } private static class CopyKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private CopyKeyManLanguageActionListener(KeyManLanguageTableModel model) { this.model = model; } public void actionPerformed(ActionEvent e) { StringBuffer sb = new StringBuffer(); for (int i = 0, n = model.getRowCount(); i < n; i++) { sb.append(model.getValueAt(i, 0)); sb.append('\t'); sb.append(model.getValueAt(i, 1)); sb.append('\n'); } Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection sel = new StringSelection(sb.toString()); cb.setContents(sel, sel); } } private static class PasteKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private PasteKeyManLanguageActionListener(KeyManLanguageTableModel model) { this.model = model; } public void actionPerformed(ActionEvent e) { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(DataFlavor.stringFlavor)) { try { String s = cb.getData(DataFlavor.stringFlavor).toString(); s = s.replace("\r\n|\r|\n", "\n"); // Parse copied data from hyperglot s = s.replaceAll("ISO code: (\\w+)(\nautonym: .+(\n.+)*)?\nname: (.+)(\n.+)*", "$1\t$4"); LinkedHashMap langs = new LinkedHashMap(); lines: for (String line : s.trim().split("\n")) { if ((line = line.trim()).length() > 0) { WinLocale loc = WinLocale.forTag(line, null); if (loc != null) { langs.put(loc.tag, loc.name); continue lines; } loc = WinLocale.forName(line, null); if (loc != null) { langs.put(loc.tag, loc.name); continue lines; } String[] tabbed = line.split("\t"); String[] space2 = line.split("\\s+", 2); String[] spaced = line.split("\\s+"); for (String[] fields : Arrays.asList(tabbed, space2, spaced)) { for (String field : fields) { if ((field = field.trim()).length() > 0) { loc = WinLocale.forTag(field, null); if (loc != null) { langs.put(loc.tag, loc.name); continue lines; } loc = WinLocale.forName(field, null); if (loc != null) { langs.put(loc.tag, loc.name); continue lines; } } } } for (String[] fields : Arrays.asList(tabbed, space2, spaced)) { if (fields.length == 2) { langs.put(fields[0].trim(), fields[1].trim()); continue lines; } } langs.put(line, line); } } if (!langs.isEmpty()) { model.clearEntries(); model.addEntries(langs); return; } } catch (UnsupportedFlavorException e1) {} catch (IOException e1) {} } Toolkit.getDefaultToolkit().beep(); } } private static class SortKeyManLanguageActionListener implements ActionListener { private final KeyManLanguageTableModel model; private SortKeyManLanguageActionListener(KeyManLanguageTableModel model) { this.model = model; } public void actionPerformed(ActionEvent e) { model.sortEntries(); } } private class UpdateCharsActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { boolean includeDeadKeys = charsIncludeDeadKeys.isSelected(); boolean includeLongPress = charsIncludeLongPress.isSelected(); boolean verbose = charsVerbose.isSelected(); TreeSet all = new TreeSet(); km.getAllOutputs(all, includeDeadKeys, includeLongPress); StringBuffer sb = new StringBuffer(); for (int output : all) { if (output >= 32) { if (verbose) { String h = Integer.toHexString(output); while (h.length() < 4) h = "0" + h; sb.append("U+" + h.toUpperCase() + "\t"); } sb.append(Character.toChars(output)); if (verbose) { String n = NameResolver.instance(output).getName(output); sb.append("\t" + n + "\n"); } } } chars.setText(sb.toString()); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/LongPressTableFrame.java000066400000000000000000000043211506470510200323640ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; public class LongPressTableFrame extends JDialog { private static final long serialVersionUID = 1L; private final LongPressTablePanel panel; private final List listeners; public LongPressTableFrame(Frame parent, Promise autoLPO, int[] lpo) { super(parent, "Edit Long Press Output"); this.panel = new LongPressTablePanel(autoLPO, lpo); this.listeners = new ArrayList(); JButton cancelButton = new JButton("Cancel"); JButton okButton = new JButton("OK"); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(cancelButton); buttonPanel.add(okButton); JPanel mainPanel = new JPanel(new BorderLayout(12, 12)); mainPanel.add(this.panel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDefaultButton(getRootPane(), okButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int[] lpo = panel.getLongPressOutput(); dispose(); for (LongPressTableListener l : listeners) l.longPressOutputChanged(lpo); } }); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } public void addListener(LongPressTableListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(LongPressTableListener listener) { if (listener != null) listeners.remove(listener); } public LongPressTableListener[] getListeners() { return listeners.toArray(new LongPressTableListener[listeners.size()]); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/LongPressTableListener.java000066400000000000000000000002001506470510200331070ustar00rootroot00000000000000package com.kreative.keyedit.edit; public interface LongPressTableListener { public void longPressOutputChanged(int[] lpo); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/LongPressTablePanel.java000066400000000000000000000146741506470510200324050ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableColumn; public class LongPressTablePanel extends JPanel { private static final long serialVersionUID = 1L; private final Promise autoLPO; private final JRadioButton autoButton; private final JRadioButton noneButton; private final JRadioButton customButton; private final CodePointTableModel cpModel; private final JTable cpTable; private final JScrollPane cpPane; private final JButton cpAdd; private final JButton cpDelete; private final JButton cpUp; private final JButton cpDown; private boolean locked = false; public LongPressTablePanel(Promise autoLPO, int[] lpo) { this.autoLPO = autoLPO; this.autoButton = new JRadioButton("Auto"); this.autoButton.setSelected(lpo == null); this.autoButton.addActionListener(new AutoButtonActionListener()); this.noneButton = new JRadioButton("None"); this.noneButton.setSelected(lpo != null && lpo.length == 0); this.noneButton.addActionListener(new NoneButtonActionListener()); this.customButton = new JRadioButton("Custom"); this.customButton.setSelected(lpo != null && lpo.length > 0); ButtonGroup bg = new ButtonGroup(); bg.add(autoButton); bg.add(noneButton); bg.add(customButton); if (lpo == null && autoLPO != null) lpo = autoLPO.resolve(); this.cpModel = new CodePointTableModel(lpo); this.cpModel.addTableModelListener(new EditCodePointActionListener()); this.cpTable = new JTable(this.cpModel); this.cpPane = scrollWrap(this.cpTable); this.cpAdd = square(new JButton("+")); this.cpAdd.addActionListener(new AddCodePointActionListener()); this.cpDelete = square(new JButton("\u2212")); this.cpDelete.addActionListener(new DeleteCodePointActionListener()); this.cpUp = square(new JButton("\u2191")); this.cpUp.addActionListener(new MoveUpCodePointActionListener()); this.cpDown = square(new JButton("\u2193")); this.cpDown.addActionListener(new MoveDownCodePointActionListener()); setColumnWidth(cpTable, 0, 80); setColumnWidth(cpTable, 1, 80); JPanel radios = horizontalStack(autoButton, noneButton, customButton); JPanel button = leftAlign(horizontalStack(cpAdd, cpDelete, cpUp, cpDown)); JPanel panel = verticalSxS(radios, cpPane, button, 8); setLayout(new GridLayout(1,1,0,0)); add(panel); } public int[] getLongPressOutput() { if (customButton.isSelected()) return cpModel.toIntArray(); if (noneButton.isSelected()) return new int[0]; return null; } private static JPanel horizontalStack(Component... comps) { JPanel p = new JPanel(new GridLayout(1,0,4,4)); for (Component c : comps) p.add(c); return p; } private static JPanel leftAlign(Component c) { JPanel p = new JPanel(new BorderLayout()); p.add(c, BorderLayout.LINE_START); return p; } private static JPanel verticalSxS(Component t, Component c, Component b, int gap) { JPanel p = new JPanel(new BorderLayout(gap, gap)); p.add(t, BorderLayout.PAGE_START); p.add(c, BorderLayout.CENTER); p.add(b, BorderLayout.PAGE_END); return p; } private static C square(C c) { Dimension d = c.getPreferredSize(); d.width = (d.height += 8); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); c.putClientProperty("JButton.buttonType", "bevel"); return c; } private static JScrollPane scrollWrap(Component c) { return new JScrollPane( c, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); } private static void setColumnWidth(JTable t, int col, int w) { TableColumn column = t.getColumnModel().getColumn(col); column.setMinWidth(w); column.setPreferredWidth(w); column.setMaxWidth(w); } private class AutoButtonActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (locked) return; locked = true; cpModel.clearEntries(); if (autoLPO != null) { int[] lpo = autoLPO.resolve(); if (lpo != null) cpModel.addEntries(lpo); } locked = false; } } private class NoneButtonActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (locked) return; locked = true; cpModel.clearEntries(); locked = false; } } private class EditCodePointActionListener implements TableModelListener { public void tableChanged(TableModelEvent e) { if (locked) return; locked = true; autoButton.setSelected(false); noneButton.setSelected(cpModel.isEmpty()); customButton.setSelected(!cpModel.isEmpty()); locked = false; } } private class AddCodePointActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = cpModel.getRowCount(); cpModel.addEntry(32); SwingUtilities.invokeLater(new Runnable() { public void run() { cpTable.getSelectionModel().setSelectionInterval(i, i); JScrollBar vsb = cpPane.getVerticalScrollBar(); vsb.setValue(vsb.getMaximum()); } }); } } private class DeleteCodePointActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { int[] rows = cpTable.getSelectedRows(); for (int i = rows.length - 1; i >= 0; i--) { cpModel.deleteEntry(rows[i]); } } } private class MoveUpCodePointActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = cpTable.getSelectedRow(); if (i < 1) return; cpModel.moveEntry(i, -1); SwingUtilities.invokeLater(new Runnable() { public void run() { cpTable.getSelectionModel().setSelectionInterval(i-1, i-1); } }); } } private class MoveDownCodePointActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { final int i = cpTable.getSelectedRow(); if (i < 0 || i >= (cpModel.getRowCount()-1)) return; cpModel.moveEntry(i, +1); SwingUtilities.invokeLater(new Runnable() { public void run() { cpTable.getSelectionModel().setSelectionInterval(i+1, i+1); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/Main.java000066400000000000000000000100561506470510200274130ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Toolkit; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.swing.JOptionPane; import javax.swing.UIManager; import com.kreative.keyedit.KeyboardFormat; import com.kreative.keyedit.KeyboardMapping; public class Main { public static void main(String[] args) { try { System.setProperty("com.apple.mrj.application.apple.menu.about.name", "KeyEdit"); } catch (Exception e) {} try { System.setProperty("apple.laf.useScreenMenuBar", "true"); } catch (Exception e) {} try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) {} try { Method getModule = Class.class.getMethod("getModule"); Object javaDesktop = getModule.invoke(Toolkit.getDefaultToolkit().getClass()); Object allUnnamed = getModule.invoke(Main.class); Class module = Class.forName("java.lang.Module"); Method addOpens = module.getMethod("addOpens", String.class, module); addOpens.invoke(javaDesktop, "sun.awt.X11", allUnnamed); } catch (Exception e) {} try { Toolkit tk = Toolkit.getDefaultToolkit(); Field aacn = tk.getClass().getDeclaredField("awtAppClassName"); aacn.setAccessible(true); aacn.set(tk, "KeyEdit"); } catch (Exception e) {} if (OSUtils.IS_MAC_OS) { try { Class.forName("com.kreative.keyedit.edit.mac.MacDummyWindow").newInstance(); } catch (Exception e) { e.printStackTrace(); } } if (args.length == 0) { newMapping(); } else { for (String arg : args) { openMapping(new File(arg)); } } if (OSUtils.IS_MAC_OS) { try { Class.forName("com.kreative.keyedit.edit.mac.MyApplicationListener").newInstance(); } catch (Exception e) { e.printStackTrace(); } } } public static KeyEditFrame newMapping() { KeyboardMapping km = new KeyboardMapping(); KeyEditFrame f = new KeyEditFrame(null, km); f.setVisible(true); return f; } private static String lastOpenDirectory = null; public static File getOpenFile() { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Open", FileDialog.LOAD); if (lastOpenDirectory != null) fd.setDirectory(lastOpenDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; return new File((lastOpenDirectory = ds), fs); } public static KeyEditFrame openMapping() { File file = getOpenFile(); if (file == null) return null; return openMapping(file); } public static KeyEditFrame openMapping(File file) { if (file == null) return openMapping(); KeyboardFormat fmt = KeyboardFormat.forInputFile(file); if (fmt == null) { JOptionPane.showMessageDialog( null, "The selected file was not recognized as a keyboard layout file readable by KeyEdit.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } try { KeyboardMapping km = fmt.read(file); if (km == null) { JOptionPane.showMessageDialog( null, "The selected file was not recognized as a keyboard layout file readable by KeyEdit.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } if (fmt != KeyboardFormat.KKB) file = null; KeyEditFrame f = new KeyEditFrame(file, km); f.setVisible(true); return f; } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } private static String lastSaveDirectory = null; public static File getSaveFile(String suffix) { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Save", FileDialog.SAVE); if (lastSaveDirectory != null) fd.setDirectory(lastSaveDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; if (!fs.toLowerCase().endsWith(suffix.toLowerCase())) fs += suffix; return new File((lastSaveDirectory = ds), fs); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/ModifierKeyPanel.java000066400000000000000000000045731506470510200317250ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.keyedit.KeyboardMapping; import com.kreative.keyedit.XkbAltGrKey; import com.kreative.keyedit.XkbComposeKey; public class ModifierKeyPanel extends JPanel { private static final long serialVersionUID = 1L; private static final Color BG = new Color(0xFFCCCCCC); private static final Color FG = Color.black; private static final Color BORDER = new Color(0xFFBBBBBB); private final KeyboardMapping km; private final JLabel top; private final JLabel bot; private final String label; private final XkbComposeKey compose; private final XkbAltGrKey[] altgr; public ModifierKeyPanel(KeyboardMapping km, int w, String label, XkbComposeKey compose, XkbAltGrKey... altgr) { this.km = km; this.top = new JLabel(" "); this.bot = new JLabel(label); this.label = label; this.compose = compose; this.altgr = altgr; top.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0)); bot.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0)); top.setHorizontalAlignment(JLabel.CENTER); bot.setHorizontalAlignment(JLabel.CENTER); top.setOpaque(true); bot.setOpaque(true); top.setBackground(BG); bot.setBackground(BG); top.setForeground(FG); bot.setForeground(FG); JPanel innerPanel = new JPanel(new GridLayout(2, 1, 0, 0)); innerPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, BORDER)); innerPanel.add(top); innerPanel.add(bot); update(); JPanel panel = new JPanel(new GridLayout(1, 1, 0, 0)); panel.add(innerPanel); panel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); panel.setPreferredSize(new Dimension(w * 15, 60)); setLayout(new GridLayout(1, 1, 0, 0)); add(panel); } public void update() { if (OSUtils.IS_MAC_OS) { bot.setText(label); } else if (OSUtils.IS_WINDOWS) { boolean isRightAlt = (compose == XkbComposeKey.ralt); boolean isAltGr = isRightAlt && km.winAltGrEnable; bot.setText(isAltGr ? "alt gr" : label); } else { if (compose != null && km.xkbComposeKey == compose) { bot.setText("compose"); } else { boolean isAltGr = false; for (XkbAltGrKey a : altgr) { if (km.xkbAltGrKey == a) { isAltGr = true; } } bot.setText(isAltGr ? "alt gr" : label); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/OSUtils.java000066400000000000000000000013671506470510200300760ustar00rootroot00000000000000package com.kreative.keyedit.edit; public class OSUtils { public static final boolean IS_MAC_OS; public static final boolean IS_WINDOWS; static { boolean isMacOS; boolean isWindows; try { String os = System.getProperty("os.name").toUpperCase(); isMacOS = os.contains("MAC OS"); isWindows = os.contains("WINDOWS"); } catch (Exception e) { isMacOS = false; isWindows = false; } try { String os = System.getProperty("com.kreative.keyedit.os.name"); if (os != null) { os = os.trim().toUpperCase(); if (os.length() > 0) { isMacOS = os.contains("MAC OS"); isWindows = os.contains("WINDOWS"); } } } catch (Exception e) { // Ignored } IS_MAC_OS = isMacOS; IS_WINDOWS = isWindows; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/OutputPanel.java000066400000000000000000000117451506470510200310150ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class OutputPanel extends JPanel { private static final long serialVersionUID = 1L; private final NameDatabase ndb; private final List listeners; private final JTextField codeField; private final JTextField charField; private final JTextField nameField; private boolean lock = false; private int output = -1; public OutputPanel(int output) { this.ndb = NameDatabase.instance(); this.listeners = new ArrayList(); this.codeField = new JTextField(8); this.charField = new JTextField(4); this.nameField = new JTextField(20); this.internalSetOutput(null, output); JPanel innerPanel = new JPanel(new BorderLayout(4,4)); innerPanel.add(nameField, BorderLayout.CENTER); innerPanel.add(charField, BorderLayout.LINE_START); JPanel outerPanel = new JPanel(new BorderLayout(4,4)); outerPanel.add(innerPanel, BorderLayout.CENTER); outerPanel.add(codeField, BorderLayout.LINE_START); setLayout(new BorderLayout(0,0)); add(outerPanel, BorderLayout.CENTER); new CodeDocumentListener().on(codeField); new CharDocumentListener().on(charField); new NameDocumentListener().on(nameField); } public void addListener(OutputPanelListener l) { this.listeners.add(l); } public void removeListener(OutputPanelListener l) { this.listeners.remove(l); } public OutputPanelListener[] getListeners() { return this.listeners.toArray(new OutputPanelListener[this.listeners.size()]); } public int getOutput() { return this.output; } public void setOutput(int output) { this.internalSetOutput(null, output); } private void internalSetOutput(Component src, int output) { this.lock = true; if (src != codeField) { if (output < 0) codeField.setText(null); else { String h = Integer.toHexString(output); while (h.length() < 4) h = "0" + h; codeField.setText(h.toUpperCase()); } } if (src != charField) { if (output < 0) charField.setText(null); else { char[] ch = Character.toChars(output); charField.setText(String.valueOf(ch)); } } if (src != nameField) { if (output < 0) nameField.setText(null); else nameField.setText(NameResolver.instance(output).getName(output)); } this.lock = false; if (this.output != output) { this.output = output; for (OutputPanelListener l : this.listeners) l.outputChanged(output); } } private class CodeDocumentListener implements DocumentListener, FocusListener { public void changedUpdate(DocumentEvent e) { doIt(codeField); } public void insertUpdate(DocumentEvent e) { doIt(codeField); } public void removeUpdate(DocumentEvent e) { doIt(codeField); } public void focusGained(FocusEvent e) {} public void focusLost(FocusEvent e) { doIt(null); } private void doIt(Component c) { if (lock) return; String s = codeField.getText().trim(); if (s.length() == 0) { internalSetOutput(c, -1); } else { try { internalSetOutput(c, Integer.parseInt(s, 16)); } catch (NumberFormatException nfe) {} } } public void on(JTextField f) { f.getDocument().addDocumentListener(this); f.addFocusListener(this); } } private class CharDocumentListener implements DocumentListener, FocusListener { public void changedUpdate(DocumentEvent e) { doIt(charField); } public void insertUpdate(DocumentEvent e) { doIt(charField); } public void removeUpdate(DocumentEvent e) { doIt(charField); } public void focusGained(FocusEvent e) {} public void focusLost(FocusEvent e) { doIt(null); } private void doIt(Component c) { if (lock) return; String s = charField.getText(); if (s.length() == 0) { internalSetOutput(c, -1); } else { internalSetOutput(c, s.codePointAt(0)); } } public void on(JTextField f) { f.getDocument().addDocumentListener(this); f.addFocusListener(this); } } private class NameDocumentListener implements DocumentListener, FocusListener { public void changedUpdate(DocumentEvent e) { /* doIt(nameField); */ } public void insertUpdate(DocumentEvent e) { /* doIt(nameField); */ } public void removeUpdate(DocumentEvent e) { /* doIt(nameField); */ } public void focusGained(FocusEvent e) {} public void focusLost(FocusEvent e) { doIt(null); } private void doIt(Component c) { if (lock) return; String s = nameField.getText().trim(); if (s.length() == 0) { internalSetOutput(c, -1); } else { NameDatabase.NameEntry ne = ndb.find(s); if (ne != null) internalSetOutput(c, ne.codePoint); } } public void on(JTextField f) { f.getDocument().addDocumentListener(this); f.addFocusListener(this); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/OutputPanelListener.java000066400000000000000000000001651506470510200325150ustar00rootroot00000000000000package com.kreative.keyedit.edit; public interface OutputPanelListener { public void outputChanged(int output); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/Promise.java000066400000000000000000000001311506470510200301360ustar00rootroot00000000000000package com.kreative.keyedit.edit; public interface Promise { public T resolve(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/SaveChangesDialog.java000066400000000000000000000054051506470510200320400ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; public class SaveChangesDialog extends JDialog { private static final long serialVersionUID = 1L; public static enum Action { SAVE, CANCEL, DONT_SAVE } private JLabel label; private JButton dontSaveButton; private JButton cancelButton; private JButton saveButton; private Action action; public SaveChangesDialog(Dialog parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Frame parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Window parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } private void make(String name) { label = new JLabel("Save changes to \u201C" + name + "\u201D before closing?"); dontSaveButton = new JButton("Don\u2019t Save"); cancelButton = new JButton("Cancel"); saveButton = new JButton("Save"); JPanel leftButtonPanel = new JPanel(new FlowLayout()); leftButtonPanel.add(dontSaveButton); JPanel rightButtonPanel = new JPanel(new FlowLayout()); rightButtonPanel.add(cancelButton); rightButtonPanel.add(saveButton); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.add(leftButtonPanel, BorderLayout.WEST); buttonPanel.add(rightButtonPanel, BorderLayout.EAST); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(label, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDontSaveButton(getRootPane(), dontSaveButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), saveButton); setResizable(false); pack(); setLocationRelativeTo(null); saveButton.requestFocusInWindow(); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.SAVE; dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.CANCEL; dispose(); } }); dontSaveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.DONT_SAVE; dispose(); } }); } public Action showDialog() { action = Action.CANCEL; setVisible(true); return action; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/SwingUtils.java000066400000000000000000000047611506470510200306450ustar00rootroot00000000000000package com.kreative.keyedit.edit; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JRootPane; import javax.swing.KeyStroke; public class SwingUtils { public static void setDefaultButton(final JRootPane rp, final JButton b) { rp.setDefaultButton(b); } public static void setCancelButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); rp.getActionMap().put("cancel", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } public static void setDontSaveButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "dontSave"); rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, rp.getToolkit().getMenuShortcutKeyMask()), "dontSave"); rp.getActionMap().put("dontSave", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } public static BufferedImage toBufferedImage(Image image) { if (image == null) return null; // Prepare Toolkit tk = Toolkit.getDefaultToolkit(); boolean prepared = false; for (int attempts = 0; attempts < 10; attempts++) { prepared = tk.prepareImage(image, -1, -1, null); if (prepared) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } if (!prepared) return null; // Get Size int w = -1, h = -1; for (int attempts = 0; attempts < 10; attempts++) { w = image.getWidth(null); h = image.getHeight(null); if (w > 0 && h > 0) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } if (w < 1 || h < 1) return null; // Render BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); boolean drawn = false; for (int attempts = 0; attempts < 10; attempts++) { drawn = g.drawImage(image, 0, 0, null); if (drawn) break; try { Thread.sleep(10); } catch (InterruptedException ie) { break; } } g.dispose(); if (!drawn) return null; // Return return bi; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/WinLocaleTableModel.java000066400000000000000000000021141506470510200323310ustar00rootroot00000000000000package com.kreative.keyedit.edit; import javax.swing.table.AbstractTableModel; import com.kreative.keyedit.WinLocale; public class WinLocaleTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private static final WinLocale[] LOCALES = WinLocale.values(); @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 3; } @Override public String getColumnName(int col) { switch (col) { case 0: return "LCID"; case 1: return "Tag"; case 2: return "Locale"; default: return null; } } @Override public int getRowCount() { return LOCALES.length; } @Override public Object getValueAt(int row, int col) { WinLocale locale = LOCALES[row]; switch (col) { case 0: String h = "0000" + Integer.toHexString(locale.lcid); return h.substring(h.length() - 4).toUpperCase(); case 1: return locale.tag; case 2: return locale.name; default: return null; } } @Override public boolean isCellEditable(int row, int col) { return false; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/mac/000077500000000000000000000000001506470510200264225ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/mac/MacDummyWindow.java000066400000000000000000000016231506470510200321730ustar00rootroot00000000000000package com.kreative.keyedit.edit.mac; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import com.kreative.keyedit.edit.KeyEditMenuBar; public class MacDummyWindow extends JFrame { public static final long serialVersionUID = 1L; public MacDummyWindow() { JMenu fileMenu = new JMenu("File"); fileMenu.add(new KeyEditMenuBar.NewMappingMenuItem()); fileMenu.add(new KeyEditMenuBar.OpenMappingMenuItem()); JMenu editMenu = new JMenu("Edit"); editMenu.add(new KeyEditMenuBar.FontMapMenuItem()); JMenuBar mb = new JMenuBar(); mb.add(fileMenu); mb.add(editMenu); setJMenuBar(mb); setUndecorated(true); setResizable(false); setMinimumSize(new Dimension(0,0)); setPreferredSize(new Dimension(0,0)); setMaximumSize(new Dimension(0,0)); setSize(new Dimension(0,0)); setLocation(-1000000, -1000000); setVisible(true); } } MyApplicationListener.java000066400000000000000000000050731506470510200334720ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/edit/macpackage com.kreative.keyedit.edit.mac; import java.awt.Window; import java.awt.desktop.OpenFilesEvent; import java.awt.desktop.OpenFilesHandler; import java.awt.desktop.PrintFilesEvent; import java.awt.desktop.PrintFilesHandler; import java.awt.desktop.QuitEvent; import java.awt.desktop.QuitHandler; import java.awt.desktop.QuitResponse; import java.awt.event.WindowEvent; import java.io.File; import java.lang.reflect.Method; import com.kreative.keyedit.edit.Main; public class MyApplicationListener { private static final String[][] classAndMethodNames = { { "java.awt.Desktop", "getDesktop" }, { "com.kreative.ual.eawt.NewApplicationAdapter", "getInstance" }, { "com.kreative.ual.eawt.OldApplicationAdapter", "getInstance" }, }; public MyApplicationListener() { for (String[] classAndMethodName : classAndMethodNames) { try { Class cls = Class.forName(classAndMethodName[0]); Method getInstance = cls.getMethod(classAndMethodName[1]); Object instance = getInstance.invoke(null); cls.getMethod("setOpenFileHandler", OpenFilesHandler.class).invoke(instance, open); cls.getMethod("setPrintFileHandler", PrintFilesHandler.class).invoke(instance, print); cls.getMethod("setQuitHandler", QuitHandler.class).invoke(instance, quit); System.out.println("Registered app event handlers through " + classAndMethodName[0]); return; } catch (Exception e) { System.out.println("Failed to register app event handlers through " + classAndMethodName[0] + ": " + e); } } } private final OpenFilesHandler open = new OpenFilesHandler() { @Override public void openFiles(final OpenFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openMapping((File)o); } } }.start(); } }; private final PrintFilesHandler print = new PrintFilesHandler() { @Override public void printFiles(final PrintFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openMapping((File)o); } } }.start(); } }; private final QuitHandler quit = new QuitHandler() { @Override public void handleQuitRequestWith(final QuitEvent e, final QuitResponse r) { new Thread() { public void run() { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) { r.cancelQuit(); return; } } } r.performQuit(); System.exit(0); } }.start(); } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/install-nonbmp.html000066400000000000000000000022511506470510200305600ustar00rootroot00000000000000

Installation on Mac OS X

Copy {{name}}.keylayout and {{name}}.icns to either
~/Library/Keyboard Layouts/ or /Library/Keyboard Layouts/.

Open System Preferences, search for "keyboard layout,"
and add the {{name}} keyboard layout or input method.

Select {{name}} from the keyboard menu and start typing.

Installation on Windows

This layout requires Keyman Desktop to be used on Windows.

Download and install Keyman Desktop.

From the Keyman directory, open and install the {{name}}.kmp file.

Select {{name}} from the Keyman system tray menu and start typing.

Installation on Linux

Open a terminal in the Linux directory and run sudo python install.py.

Restart the window server by logging out and in again.

Open the settings application, search for "keyboard layout,"
and add the {{name}} keyboard layout or input method.

Select {{name}} from the keyboard menu and start typing.

Enjoy!

bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/install.html000066400000000000000000000024701506470510200272740ustar00rootroot00000000000000

Installation on Mac OS X

Copy {{name}}.keylayout and {{name}}.icns to either
~/Library/Keyboard Layouts/ or /Library/Keyboard Layouts/.

Open System Preferences, search for "keyboard layout,"
and add the {{name}} keyboard layout or input method.

Select {{name}} from the keyboard menu and start typing.

Installation on Windows

From the Windows directory, run setup.exe and follow the prompts.

Select {{name}} from the language bar and start typing.

Installation on Windows (Alternative Method)

Download and install Keyman Desktop.

From the Keyman directory, open and install the {{name}}.kmp file.

Select {{name}} from the Keyman system tray menu and start typing.

Installation on Linux

Open a terminal in the Linux directory and run sudo python install.py.

Restart the window server by logging out and in again.

Open the settings application, search for "keyboard layout,"
and add the {{name}} keyboard layout or input method.

Select {{name}} from the keyboard menu and start typing.

Enjoy!

bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/install.py000066400000000000000000000067601506470510200267660ustar00rootroot00000000000000#!/usr/bin/env python import os import re import shutil import sys def getlayout(evdev, name): with open(evdev, 'r') as f: contents = f.read() pattern = re.compile(r'^\s+\s+\s+' + name + r'.+?\n', re.M | re.S) match = pattern.search(contents) if match: return match.group(0) else: return None def rmlayout(evdev, name): with open(evdev, 'r') as f: contents = f.read() pattern = re.compile(r'^\s+\s+\s+' + name + r'.+?\n', re.M | re.S) return pattern.sub('', contents) def addlayout(evdev, layout): with open(evdev, 'r') as f: contents = f.read() pattern = re.compile(r'^\s+\n', re.M) def repl(m): return layout + m.group(0) return pattern.sub(repl, contents) def rmifexists(path): if os.path.exists(path): os.remove(path) def cpmkdir(src, dst): if os.path.exists(src): try: shutil.copy(src, dst) except (IOError, OSError): os.makedirs(os.path.dirname(dst)) shutil.copy(src, dst) def doremove(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName): try: contents = rmlayout(sysEvdev, name) with open(sysEvdev, 'w') as f: f.write(contents) rmifexists(os.path.join(sysSymbols, name)) rmifexists(os.path.join(sysSymbols, name + '.png')) print('Successfully removed %s.' % dispName) except (IOError, OSError) as err: print('Could not remove %s: %s' % (dispName, err)) print('(Try running as root.)') def doinstall(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName): try: cpmkdir(os.path.join(localSymbols, name), os.path.join(sysSymbols, name)) cpmkdir(os.path.join(localSymbols, name + '.png'), os.path.join(sysSymbols, name + '.png')) layout = getlayout(localEvdev, name) contents = addlayout(sysEvdev, layout) with open(sysEvdev, 'w') as f: f.write(contents) print('Successfully installed %s.' % dispName) except (IOError, OSError) as err: print('Could not install %s: %s' % (dispName, err)) print('(Try running as root.)') def dointeractive(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName): if getlayout(sysEvdev, name): print('The %s layout is currently installed.' % dispName) print('Remove it? [y/N]') a = sys.stdin.readline().strip().lower() if a == 'y' or a == 'yes': doremove(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName) else: print('The %s layout is currently NOT installed.' % dispName) print('Install it? [Y/n]') a = sys.stdin.readline().strip().lower() if a != 'n' and a != 'no': doinstall(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName) def doargv(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName): if len(sys.argv) < 2: dointeractive(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName) elif len(sys.argv) == 2: if sys.argv[1].lower() == 'check': if getlayout(sysEvdev, name): print('The %s layout is currently installed.' % dispName) else: print('The %s layout is currently NOT installed.' % dispName) elif sys.argv[1].lower() == 'install': doinstall(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName) elif sys.argv[1].lower() == 'remove': doremove(sysEvdev, localEvdev, sysSymbols, localSymbols, name, dispName) else: print('Usage: %s [check|install|remove]' % sys.argv[0]) else: print('Usage: %s [check|install|remove]' % sys.argv[0]) def main(name, dispName): doargv('/usr/share/X11/xkb/rules/evdev.xml', 'evdev.xml', '/usr/share/X11/xkb/symbols', '.', name, dispName) bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/keyboard.css000066400000000000000000000012761506470510200272550ustar00rootroot00000000000000/* KEYBOARD */ table.k { font-family: "Georgia", "Times New Roman", serif; font-size: 16px; border-collapse: collapse; table-layout: fixed; width: 842px; } table.k td { padding: 2px; text-align: center; vertical-align: middle; height: 23px; } table.k td.t, table.k td.tl, table.k td.tr { border-top: solid 2px black; } table.k td.b, table.k td.bl, table.k td.br { border-bottom: solid 2px black; } table.k td.t, table.k td.b, table.k td.tl, table.k td.bl { border-left: solid 2px black; } table.k td.t, table.k td.b, table.k td.tr, table.k td.br { border-right: solid 2px black; } table.k td.m { background: #ccc; } table.k td.d { background: #fd5; } table.k td.o { background: #ddf; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/keylayout.dtd000066400000000000000000000034001506470510200274550ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/keyman-history.md000066400000000000000000000001561506470510200302440ustar00rootroot00000000000000{{name}} Change History ==================== {{version}} ({{date}}) ---------------- * Created by {{author}} bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/keyman-license.md000066400000000000000000000020451506470510200301640ustar00rootroot00000000000000The MIT License (MIT) {{copyright}} Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/keyman-readme.md000066400000000000000000000003231506470510200277740ustar00rootroot00000000000000{{name}} keyboard ============== Version {{version}} Description ----------- {{description}} Links ----- Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- {{targets}} bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/kkbx.dtd000066400000000000000000000156211506470510200263760ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/ksquare.css000066400000000000000000000002361506470510200271230ustar00rootroot00000000000000.ksq { font-family: "Kreative Square"; font-size: 14px; } @font-face { font-family: "Kreative Square"; src: url(KreativeSquare.ttf) format("truetype"); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/ksquare.ttf000066400000000000000000025734441506470510200271520ustar00rootroot00000000000000FFTM> iGDEFq7 eGPOS@?P4PP;h@6P?@PPP$PxxQPPP4gPPPPPPPPPPPP4PPPPPgPxxP;;ggxP@@PPxgPPxPPPPxxxxP;gg@$@$@/T p p [$gPPPPPPPPPPPPPPPx?@PPg0@pP@PPPPgPgPPPP%;PhhxPPP@@F(FP4RRP  PPPPP(PPPddaaPPPPPPPPdPP?FxxxxPxPQPxVxQVPxPP=P@@PPPPPP7PhhPPgPPPPxxPP\PPPPPPPPPPPPPPPPP44PhhPP(MP\\PP@(@(Pp@@@PPPP0?PP@@@@@@@@@@@@@4@@PP@P(PPPPPPPPPPPP@P4P\PPPA@((@((@@@@@@@((@@@@@@@h@hhvhhhhhPPPPPPPPPP$PPPPPPPPPPPPPPPPPP(P?44  PPOOPPPOOP00PxxPPPPiihhhh((((((((((((((((((((((((((((hhhh((((((((((((((((((((((((((((hhhhhhh((((((((((((((((((((((((((((((((((((((((((((((((((((((((hhhH J hhhhhhhhhhhhhhhhh00ZZZZZZZZZZZZZZZZZZZZZZ-Z-Z-hhhhhhhhhhhhxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxhhhhhhhhhhhhhhhhhhhhhh<PiiHHHhh>(00D00(@$xg( dZ?FZZPPvPPPPPPPPPPPPPP}PPPxxPQPVPxPPVPPxQPP;hgP  --ZZ---PPZP U\P4P-Zd(P@@@@xxPxxx@(((((@@PPPPP(PPPPP@@PP6<P@kh VvfPPPPP4x{<((((((((((((-----ZZZZZZPP ZPi&P(P(ZPqy FHw#((((((((&((((((((P(R(xqqxuxxxxhhhhhhhhhZzljUP(PPP@@((((((((((((((((((((((((((((((((((((((((((((((((((((((((hhhhhhPP(ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZPPPPPPPPPPPP(ZPPP4 PPP4Z-------------PUPPxPPPPxxhhhhhhhhhhhhhZhZh-LLLZdZZPPZPxg?DD/hhhhhP<P(}]CIPP\\PP7xP\P\{{xM?0/6ZbP(+FF@xVPPxxxPPhhPP';P4PPPPPP((PxPPDP6PPPP---P@PxPZZPPP=w<<PPPP(PPPP^P@PZZ,l, l@LL'39BRTY\_behjqz|"* 1 > I N Q !!!! !!! !"!'!+!.!2!9!D!K!N!!!!!!!"""!"+"."I"e""##!#(#,#{#########$)$J&&&& &&7&B&g&l&&&&''''''@'R'V''))))))+ +$+/+T+i++++++++..U#_ &27APTX[^aehjot| {& 9 B N Q p !!!! !!! !"!&!*!.!2!9!A!K!N!P!!!!!!""""'"."H"`""###$#+#{#}########$$@%&&& &&.&9&`&i&&&&''''''?'O'V''))))))+++,+S+`++++++++..^}um[CA;1.' @<;:9841=63/- {yvNJ>;650.wrpn 10.,& ނkjhgf?1.ݿ۱۰ڜژڑncE<: ;A  ( cCDFJRSW[_&'a23c79eABhPRjTTmXYn[\p^_rabteevhhwjjxoqytz||| {   "&*8 1= 9 >o B Iu N N} Q Q~ p     !!!!!!! ! !!!!! ! !"!"!&!'!*!+!.!.!2!2!9!9!A!D!K!K!N!N!P!!! !!!!&!!,!!.!!5"";""N""!S"'"+W".".\"H"I]"`"e_""e""v##w##!#$#(#+#,#{#{#}#################$$)$@$J&%&1&&2&&3& & 5&&6&.&79&9&BC&`&gM&i&lU&&Y&&i&&j&&x''y''z''{''|''}'?'@~'O'R'V'V''''))))))))))))++ ++$+,+/+S+T+`+i++++++++++++++++....U# ;^_ _ a   γκοj+p0- R/IUPpwx  CC  Pj66 AC!|$()*0<  =>?: ;  26E\),/15< |}~!!""""##$$&%%%%2%%3%%4&`&`5&c&c6&e&f79p;K   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab]sefj_yqlwk_Stcdhx=LJ[m}doPC]An~ccPQYZUV;wop ^zW[m r{ddddLx0TLLp|  \ 8 d  $ T T 0 d DhP4|\<X(d00|4h<4Tp(`8|@4 h ! !!"D""##D#|##$0$x$%$%l%&,&|&'$'h''(@(t())t)*,*+ +,,,-@--.0.d../T/00\011l12 2\233X344455p56<67 7h780889D99:T::;4;;<<8>??|@@X@A AAB(BpBC C|CCD,DtDE(E\EEF0FFG$GdGGGH(H`HHII@ItIIJ@J|JKKdKLL\LLM<MMNDNOO\OOP8PPQ@QR RtSSST`TUULUUVV|VW4WWX8XYY\YZ ZZ[$[`[\ \H\\\]@]]^^t^^_ _H_l_``X``a4aabb|bc8c|cdpdepefPffggdggh(hhihijHjjk,kpkllPlm0mmn0nxnno oxopDpppqqhqqr0rdrrs4ssst8ttu4u\uuvvdvww\wwxx<x`xxxxxyy y<yXy|yyyz z`zzz{{,{p{{{{||X||||}}d}~,~`~~~4XL8tHxHp<d|`LT $4|@|,\,h\ LL4H0tD8xxDpTL$pL,0`ddddddddddddddddd0Xx,X $HpH DT|0X0TH`,hDx<(@d<4tX0(,H|(<0hHp 0X XTĤŰdhȤ|0 \ˤ@̌,\͠`ΜHϨPЬ$tѨ`҈ t$ԴL՘$p8dؐؼ XلٰHڈHۈ,`ܔ TݜPހް@p߸8l$` hP8h8`8|0p <xP4TxLLP`$<Hp <p\|$Hpd8X @`$`l|(d lp,T$`Dd$X <T$H  , D d   P   @     @ h    ,p,4`|0T LH40DPD00$4| @ !P!"h"#`#$$$H$$%%&'@'l'''(((p(())4)d)|)))**0*`**++D+|++++,,<,\,|,,,,--<-\-|---..@.h..../$/P/t///0000\000011<1h11112$2H2x223383h3334 4P4|4455(5P5|55566@6h66677D7l7778$8T8889 9`999:(:T::;;h;;;;<<4>>0>L>h>>>>>??,?H?d?|??BHJJJJKK,KLKtKKKKL L<LhLMMXMNlNOlQQQDQ`QQQQRR4R\RxRRRSS$S@ShSSSSTT<TXT|TTTUUPUUVVW@WWXXLXXYY<Y\Y|YZZPZZZZ[[L[x[[[[\ \L\x\\]]H]p]]^^P^^__t_`$`L`t```a a(aPbbbc4cccd<de$eXeef f\ffgHghlhij jxkk\kl lhlm(mn ntnoDoopLpq qdqr\rsttttuu$uHupuuvvwLx xyHyzXz{,{d{{|<|}4}}~P~t~~| @tDpLTH|h(Tt,h,Pt Lx(T<X \<d 0Tx@hTHxH0\x 8ll@t <X8X|(D`(Tt@\,T`|0d D|< Ht0Xt 8`@d8Tp$X0d\ DDT8$@X8`,Lt$HdHl8d 8\x4Pp<`|| H|$P Hp@\ t@xLH8l(l¼0tXĬ t4(ǜ$pɌtTˬL̄\ͤpΤ ϐDР(`,ҬLӸ8 TTHج ٠ڼ|ܨ\ޜP4L,tl0X@< ,@D<<P`8ph(`8Lp$ HXP$,     T  d  t(L|Pd,<8t0h,L d !H!""#8#$($%%&P&'T'(L())t)*0*++,,`,-x-.\./4//000l01T12223@344|4545x56 6D67$7p78D8|89p9:,::;;X;X;t;;;;< <,>4>d>>>??<?\?|??@@4@T@@@A ATAABBTBBBCCHCxCCCDD4DPDhDDDE,EXEEEFFXFFGLGGHTHtHHHII0I\IIIJJXJtJJJJKK<K`K|KKKKLL$L@LlLLLLMM@MpMMMMNN0NHN`N|NNNNNOO0OHO`O|OOOOP P(PDP`P|PPPPQ$QLQtQQQRR$RDRdRRRRS$SLStSSSSTTT8TTTlTTTTTUU U8UXUxUUUUVV<VpVVWW8WlWWWXX0XPXlXXXXXYY,YLYpYYYZZDZhZZZ[[<[h[[[\ \P\\\] ]<]l]]^H^^_@___`$`L`h``a@ahaaaabbHbbbc c,cHcdc|cccd$dDddddddeee@eef4fffgh$hhi<i|iijjpjk(kkl0lplmm4m`mmnnXnnno$o|op pXpppq(qPqxqqrrPrrssDstsssttPtpttttuu4uLutuuuuv(vXvwLwxxy|z$z{({|}0}~0~X@d|@dx Lt$< D|<(P($x$lTTTҰԤ4\@߄hP,Hd ,Hh,D\t4Ld Dh(@Xp,Pt@l8\ 0Tl0Lt,Lp8T|HhDp,Tp4\<`4PPl$@h 8`4\(Pp 0T4Tx(Pp4X|8` 8`<l(D`0\| DxXHt  ( T     ( P x     D l     ( T     D l   (Tx<d<p8d(P8XDp H|<\t<p LtDp 0\<h <h$Tx@\Dh  $ D h !!"8"#4#$D$%\%&D&'0'(d)T* *+ +,l,-h-./t001(12@234H45$5P5566h667<7t7778 8P8889 9\=0@h@@@AA<AtAABDCDFGHGpGGH(HhHHI0IxIJJJJK(KtMpPRT(VYZxZZ]a`d$dtddeg|ghHhkkPkmmnDpXrdrsu w$wTwwxyzz{ {x{(|xHl,XHd`8l,x0\4 Lxh8HPL@H\TD LtP4pdHplLX,t <\,8\@h0X`4\8`0x0TDd 4(@<ĬH`Ȕ,˄p \|ѴҜӌlԌ0hդ,|׌ Ll|ڼL۔܀LDޠ`ߔ߼Lt(L,d\ hXx,Lt\(4(PDl \8lHH$x@t,|D,`  L  (|4|D<D4LLDl4ll!#$/0 001p12P23t34t45$5667,78889d9:X:;h<<<=>>L>>??0?T?|???@0@P@x@@AA0AdAABBpBC0CCD$DEELEFFFGGHIpJ0JKLMNOtPPQRSTDTUVWhXPY8Z$Z[\P\]4]^_`DaacPdd dteHe`exef,flfgghgh4hi iijdkkkl(llmdmmmnnHntnoDoop@ptppqqXqr rrss|sssst(tTtpttttu(u`u|uuv v8vpvvww@wdwwwxx4xTxxxyy$yDylyyzzz{4|8}}X}~0~pxx0d0h @t\T4dHL0|$\(l8|$Lt,(|LL|\8L0P4LDH`H$l$$d |TT<THH@<X0dp ,$|x\<,ˆ¤0PlÌð@\ĈĨ,XxŜ,TƀƤ$PlnjǬ0XȀȨ<`Ɍɰ4\ʄʬ0\˄˸ 4`̸̐0Lx͘ @dΌΰTτϸ4\ДмLрѬ$PtҘPxӤ0\Ԅ԰<lՔ$Pրְ4hל$P؄0\ٌ@lڔ@`ۀۨLxܜ(P݄ݬDdތ޴,`ߌߴ<d4` L,X|,XDh 0X@pX@PX|D\(Xp,D`X<l(Hh Dh<X|$<THt<` @d|8Pl<t<p0\(lLd  4 h    @ t   ( l    T    T   dH,Hd|,D\t $<Tp4tHd$xX( $ "@$%')8+,.p0<102P345679 :8:;?P@0AApBBC(CDEElEIK@KxKL,LM8MNNOPOP\QQRRStTTUpVHW4WXDXYZ[l\p]]^h_@`0a4bPbcdexf|ghij\kHlLmhnor r\rsst$tuuvDvwTwxyyzt{{|t}L~<~L\LTp|Tpt<h(ThT 0x$4tx8x \tLLH`DôČŐƔǰPt |˰pPͬ@Τ4ϐlиhDdӨ\ԤDռpָ`רDؔ`ٴ ڀlۨ8ܐ4|0ބ<`l,L88HH$dl\DlHhDxtH08|,l d  0   8   <   \ X H\ ,l4hxLPxTXl$4\<xT  !h!"\"#`#$x$$$%%L%&&H&t&&&' '`''((D(|(()()`))*\****++0+X+x++++,,8,\,x,,,--$-P-p---.$.D.h....//H/t//00$0P0p00001181`111122@2p22223303H3d333334444P4h444445 5,5H5d5555566,6D6`6|666677,7H7`7x777788(8L8p888889949P9l99999: :$:D:d:::;;4;P;l;;;;;<<0>AD FLLNQS8UXUV0VXVWWWZ]t`cc c@c\c|cccddLd|ddee@eteeefggTgh hPhhhi8itiijHkkl0lhlmDmn$no o@oooppp8pXpxppppqq<qdqqqr r8rdrrrs s<sXstsssstt,tLtltuu<uvvlvwTwx<xyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhXLT$,(lPl |T X`<HxL4404L|8(\d8$$<lüĤŤƼ4ʐ͔<<ՀPۀ<$@p8D (<h  | ,4|TL $  ! !!!!""8"h""""##0#H#h##%L(t*-P2`7:,<AH\MPST$TUVW@WWWXX4XtXY(YxYZ`[ [[[\0\d\\]]^^T^^__\``L`a,aabHbbccd$deLeffg gdggghh,hPhlhij8jk@kkl lDlhllmmmnXno4oop,plpqq q8qPqhqr rhrssdsttltu@uvvxvw`wx@xxy,yz zz{ {H{|H}(~\4tx ,`0P4| @t$l@,p$`$DD <(l (D$l0PPH4x,4P( h`$hL8|,\Ht\X D|L,x$p0$p|LPP\0|<|$T8|p\¼h<ĈHżƐLj0Ȑ`D$˔̈|Θ@ϠlP0ҠӘԌըth\xhۄܜ0$Hh޴PߨT\$|Xx4phhd44,@ lTTX0t`0t$|Th<84 Lh(\ 8`| 0LP<\@(D`|  @ h     0 X       4 L h       ( @ \ x      @ `    @l Hl@`\(d @@tX,H8@d#$%t&0&'()T)**\*,/2$33444h45X56|667,7|7788<8h889H9::`:;;t;<,4>>?@??@@L@@AALAAB BXBCCCDDLDDEEDEtEEFF(FTFG GhGH HhHI,IlIJ JDJJK@KKL@LLMDM|MNNlNO O8OOOP PLPQQQRRRS<SSTT<TTUU\UV4V`VVW0W|WXXHXY4YZTZZ[L[\(\\]x]^^X^^_0_|_` ``a@ab bbcHccd@dde,effpfgxghxiijjdjk<k|kllTlmhmnnlnoPopplpq0qrrhrs<sstt<ttttuu,uHuduuuv@vwxxy<yzt{ {l{{|D|}`}~P~(DtTd$hDh0p4| Lx,\Ht D P0d<tH| \8l8x<D4l DxXD8t@HXTH|8`@p@hh80X Hp(P0!!73=4>54&#">32P0P2<2uSKp PC+2F2<20PPP,6$6L?/ ,6$@%3#3#@PPPPPP3#'3#PPPPP0#373##5##5#535#53533533PPPPPPPPPPPPPPPP@PPPPPPPPPPPPPPPPP00+%2654.546753.#"#5.'7@B^RvvRsUPDjTS3B^RvvRsUPDjTSP$ ;)3ORSH6!&$ ;)3ORS H5!&P #7264&"462"264&"462"@8D  hFdFFdJ  hFdFFdl@8D  ZdFFdFh  ZdFFdFP:.6327&#"4264&"#&'#"&547&5462673/!K=W1!B//B/H,&dWdB^00^^0 d":)*bP**:6&@+&76LL67&%K@3#@PPP@ .467)`ss`)O]]kE;;E0P@ 7'>4&)`ss`)O]]E;;E0P)7'#5'7'753q(qq(qPq(qq(qP]BFAAFBBFAAFB0 33##5#53@PPPPQa%'99a9907!!pPrd$462"****44084080264&"462"FdFFdvvv2^^^ƍƍ73#1Qzf wE0%!!5>54&#"'>32,p +oTEF2+CP pKSu6LLPPPIAJ /?L6ND;0#73264&+53264&#"'>32#"&'D-2FF2((2FF2+CP pKSu<XJ803'33##5#9PPQW%Pdd032#"&'73264&+5!nRvvRAiL ?'2FF2|P^^>0/B/P0&#"632"&=4632264&"!,2F5CRvvvvRS:FdFFd}/! ^^^BB^/B//B/0!#!^3S06264&"&462"&5476264&"FdFFduu<XX>?,+**0%326=#"&462#"'$4&"2!,2F5CRvvvvRS:FdFFdc/! ^^^BB^/B//B/rT462"462"**** ****yT %'462"@99W**a995**'8888P0@7!!5!!ppPP7'788t880%3#7#4>54&#"'>32@PPPP2<2F2+CP pKSu2<2PP$6, /?L6$6,P0$%35#""&546;54&#";#"&4632PP!//!B^^BP/!cc((B^P PF21G(vvPG1P0!5'#73#5!#@.ٷrPPg״P032644#!264&+6L 4X>J))d*PL61%,F>Xp):)P64632&#"327#"PcFuT0UB^^BU0TuFcƍK>G^^G>KP03264&##32B^^Bc^^pƍP0 !!!!! dPPPP0 !!#!PdPPP%#53#"&4632&#";̌ccFuT0UB^^BPƍK>G^^P0 3!53#5!#PP@PPPഴ  3#3#53#PPPPPPP@[03##"&'7326=#@PvR@hQ:#2FPPRvL;&F2Ph 33#'#PPppxPxhP03!!PP pPP0 3373#'P88Pุ XP0 333#P8XP8X XP0264&"462"^^^ƍ2^^^ƍƍP032644+#!//!B^^BP/B/P^^PL %7654&"327$462'#"/9Q'^^^Bڍƍ>Z8b4>c9Q.:B^^^ 4ƍc]D[8aP@ 2#'##3264&#B^T=pPP!//!^B>[P/B/P0%%2654.54632.#"#"&'7@B^RvvRcPTS3B^RvvRcPTSP$ ;)9SL=!&$ ;)9SL=!&xX!###xPPpP0326=3"&5PP^^PƍB^^BccC!#336VVL> 3733#'#>Vz>8>zV8>>8F @ !#'#7'373ppppﷷ?373#5?rrP෷P0 !!!5!PX X8P8X`03#3𠠠PP4l0880`0#53#53P0PL'7' 88\L88[P`!!P0PPL798980 6326?5#"#"&546;#."Px2[EC]vRPdF<xcuSRvp0 $4&#"32'632+3."Px2[EC]vRPdF<xcuSRv%64632.#"3267#"vR@hQ:#2FF2#:Qh@RvvL;&FdF&;L0 6326?5#"#"&546;53#."Px2[EC]vRxPPdF<xcuSRvx06462!;#"7."vv >&R >L> vvvR(#-P#--#X#"3###53463Xx!/P^BP/!PPB^0 %#"&46;#"&'73265&326?5#"IWC]uSvR5[D#D2F."Px2wOiiRv5,):F2T:2d0632#54&#"#3[EC]P."PPP-cuS2F<00 3#33!535#@PPp0PPPP003#&"32653#"&5462PP n2PPSTjFd#0P< (G1@Rv@82F#i 373#'#PrrPPѷPg0 33!53#pHPPhP!#54&"#54&"#3632632P/B/P/B/PP&*I//IB^!//!!//!66^B0632#54&#"#3[EC]P."PPP-cuS2F<06264&"462"FdFFdvvvdFFdFʤvvv0 632+#34&#"32[EC]vRxPP."Px2-cuSRvxdF<x0 6326?5#"#"&546;#."Px2[EC]vRPdF<xcuSRv "#36;PPP[Ex@<ccP0#";2#!5!264&+"&4632FF22FF2P FdFP FdFX%;#"&=#53533#/!xxB^P!/P^BPxxP0%#"&=3326?53#[EC]P."PPPccuS2F<pI!#332ZZ; 3733#'#;WoL6LoW4MM4phh #'#7'37hpppȏȏ0%#"&=3326?53#"&'73265IWC]P."PPvR5[D#D2FwOiK*:2Rv5,):F20 !!!5!p8P8`00#";#"&54&+532654630(2FPPF2((RvF2((2FvR0PF2d<32327#"T-FK+)&-FK+) ((&* ((&*`0!!0006 "&462#3**PPs** @%3.#"3267#5.467@P4PQ:#2FF2#:QP4PE[[ET G2&FdF&2G TTooP0#"3#32653+5#53463x!/!/P^BPP^BP/!P/!B^PB^4L264&"7'"''7&47'762@  8x x8x8x8x x8x8(  8x8x8x x8x8x8x ?3733##5#53?rrP෷PP@`0%3#3#@PPPP%1%+53264&+"&547&546;#";2'";264&#F2P2FF2P2FPx".2FP F2."".2FP F2.V  3#'3#PPPPPPPP6462"264&"462&"27"P褤Tvvv&Fd#9  9#dT褤jvvvdF#9   9#0 #"&546;#&326?5#"!![ED\uSP."Px2pc\DC]D.<(P4L\ /'8[[8[8[[8\8\\88\\8P07!#5!PP07!!pPP264&"462"632&"#53vvvƤ褤j2#9 PPvvv褤#9 xP0!!P00P264&"462"/B//B^^^x  ZdFFdF07!!33##5#53pPPPPPPPPP3#5>54&#"'>32DB2**; 0C-2FN' 00,'- %. Q#3264&+53264&#"'>32#"&'!(****; 0C-2F$$F2-DD"0%. !&%5-!$L7$990%#"'#3326?53#[E-#PP."PPPcc2F<pP0#3'##"&463PP(2FF2 0PP@FdFr$462"****`a"'72654/7Fd#9 "Q9 (2F#9  "Q973#7{1S=)0264&"462"!!FdFFdvvvvpaB//B/^^^PP4A\ 7'7'7'7'78[[8[8[[848\\88\\8x 773#73'733##5#P"Y{1S`_"0011P"=)`0<<x$73#5>54&#"'>3273#7P"B2**; 0C-2FN'm{1S1P"W00,'- %. Q=)Q'+673264&+53264&#"'>32#"&'3'733##5#P"P(****; 0C-2F$$F2-D`_"0011P"5"0%. !&%5-!`0<<."&46233267#"&54>**=P2<2F2+CP pKSu2<2s**$6, /?L6$6,0735'73#5##7xȷ"PP398xVddO980735'73#5##7xȷ"PP9xVdd90735'73#5##'7'xȷ"PPl88\xVdd88[0;"735'73#5##&#"'>32327#"xȷ"PP-FK+)&-FK+)xVdd ((&* ((&*0 735'73#5##3#'3#xȷ"PPPPPPxVdd PPP0 735'73#5##264&"462"&xȷ"PPx/B//B^^^^xVdd""(1GG12FFP07!#3#3#5###3P)xxP)PdPPPD&"'72654/7.54632&#"327hFd#9 "NecFuT0UB^^BU0TX6 D2F#9  "RcK>G^^G2F 0 3#!!!7@p98@PPPPP980 3#!!!%7@p9@PPPPP90 3#!!!%'7'@p88\@PPPPP{88[0 3#!!!'3#'3#@pPPPP@PPPPPPPP 3#3#535#7PPPP98PPP98 3#3#535#?PPPP@9PPP9 3#3#535#7'7'PPPP88\PPP{88[ 3#3#535#73#'3#PPPPPPPPPPPPPPP0 !#5#53532'3264&+3@PPcPB^^BPPPƍ܌^^dP0; 333#&#"'>32327#"8P8d-FK+)&-FK+)p ((&* ((&*06264&"462"7FdFFdvvvC98dFFdFʤvvvO9806264&"462"7FdFFdvvv9dFFdFʤvvv906264&"462"'7'FdFFdvvv 88\dFFdFʤvvv88[0;#6264&"462"&#"'>32327#"FdFFdvvv>-FK+)&-FK+)dFFdFʤvvv ((&* ((&*0 6264&"462"3#'3#FdFFdvvvzPPPPdFFdFʤvvv PPPL ''7'7888888884L#746327#"''7&%&#"%32654PcL?I8I-cL?I8I-B&,B^&,B^c-I8I?Lc-I8I?^B,&^B,075326=3"&7PFdFPvv3982FF2Rvv98075326=3"&7PFdFPvv92FF2Rvv}9075326=3"&'7'PFdFPvvl88\2FF2RvvE88[0 75326=3"&3#'3#PFdFPvvPPPP2FF2RvvPPPgi 373#57grrP9ٷ<9P0 2+#33264&#B^^BPP!//!^^PPP/B/0$%264&+53264&+"#46;2+5))ZZZ!/P^BZ6L 4X>ZP):)P*/!@B^L61%,F>XP0 6326?5#"#"&546;#7."Px2[EC]vRP98dF<xcuSRvpO980 6326?5#"#"&546;#7."Px2[EC]vRP9dF<xcuSRvp90 6326?5#"#"&546;#'7'."Px2[EC]vRP88\dF<xcuSRvp88[0; *6326?5#"#"&546;#&#"'>32327#"."Px2[EC]vRP-FK+)&-FK+)dF<xcuSRvp ((&* ((&*0 6326?5#"#"&546;#3#'3#."Px2[EC]vRPPPPPPdF<xcuSRvp PPP0 (6326?5#"#"&546;#264&"462"&."Px2[EC]vRP/B//B^^^^dF<xcuSRvp""(1GG12FFP ,4%#"&546;632#;#"'#'326?5#"."@'4D]C#-C] &xx-#P<P". &.%c #tTSuuS( ,P4D<xF ,(D%("'72654/7.54632.#"3267Fd#9 "=PvR@hQ:#2FF2#:QH0 D2F#9  "jBRvL;&FdF&/C06462!;#"7."7vv >&R >L> $98vvvR(#-P#--#_9806462!;#"7."7vv >&R >L> 99vvvR(#-P#--#906462!;#"7."7'7'vv >&R >L> 88\vvvR(#-P#--#88[0 6462!;#"7."3#'3#vv >&R >L> PPPPvvvR(#-P#--#PPP0 33!535#7p398PP980 33!535#?p9PP90 33!535#7'7'pl88\PP{88[0 33!535#73#'3#pPPPPPPPPPA%$4&"2'6327"&463'7&#"54'FdFFd@:S-*I9=,vvvR2,_$!B//B/-4/I9<,8B^^^3U 0;'632#54&#"#37&#"'>32327#"[EC]P."PPPd-FK+)&-FK+)-cuS2F<H ((&* ((&*06264&"462"7FdFFdvvvC98dFFdFʤvvvO9806264&"462"7FdFFdvvv9dFFdFʤvvv906264&"462"'7'FdFFdvvv 88\dFFdFʤvvv88[0;#6264&"462"&#"'>32327#"FdFFdvvv>-FK+)&-FK+)dFFdFʤvvv ((&* ((&*0 6264&"462"3#'3#FdFFdvvvzPPPPdFFdFʤvvv PPP0 %3#3#!!@PPPPpPPPPPL#746327#"''7&32654'7&#"vR:4>8>"vR:4>8>"2F ؠ2FRv">8>4:Rv">8>42 F2h F20%#"&=3326?53#7[EC]P."PPP98ccuS2F<pO980%#"&=3326?53#7[EC]P."PPP9ccuS2F<p90%#"&=3326?53#'7'[EC]P."PPP88\ccuS2F<p88[0 %#"&=3326?53#3#'3#[EC]P."PPPPPPPPccuS2F<p PPP0"%#"&=3326?53#"&'732657IWC]P."PPvR5[D#D2F9wOiK*:2Rv5,):F290 632+#34&#"32[EC]vRxPP."Px2-cuSRvxdF<x0 "&%#"&=3326?53#"&'732653#'3#IWC]P."PPvR5[D#D2FPPPPPwOiK*:2Rv5,):F2PPP0 735'73#5##3#xȷ"PPPxVdd P0 6326?5#"#"&546;#3#."Px2[EC]vRPdF<xcuSRvp P03735'73#5##3"&5326xȷ"PPP^^P/B/xVdd31GG103 "6326?5#"#"&546;#3"&5326."Px2[EC]vRP(P^^P/B/dF<xcuSRvp31GG1PD47'5!#7327"&!5'# Pr)" 9#dF@.D))"  9#F}D%47'5#"&546;27"&326?5#" [EC]vR)" 9#dF."Px2DccuSRv)"  9#FpdF<x%64632.#"3267#"7vR@hQ:#2FF2#:Qh@R9vvL;&FdF&;L9%64632.#"3267#"7vR@hQ:#2FF2#:Qh@R9vvL;&FdF&;L9%64632.#"3267#"'7'vR@hQ:#2FF2#:Qh@R 88\vvL;&FdF&;L88[%64632.#"3267#"'7'vR@hQ:#2FF2#:Qh@R 88\vvL;&FdF&;L88[% 64632.#"3267#"3#vR@hQ:#2FF2#:Qh@R*PPvvL;&FdF&;L P% 64632.#"3267#"3#vR@hQ:#2FF2#:Qh@R*PPvvL;&FdF&;L P%64632.#"3267#"'7vR@hQ:#2FF2#:Qh@R88\vvL;&FdF&;L88[%64632.#"3267#"'7vR@hQ:#2FF2#:Qh@R88\vvL;&FdF&;L88[0%264&+#32'7h2FF2xxRvv 88\PFdFPvv88[ 6326?5#"#"&546;53#'P."Px2[EC]vRxPP8:dF<xcuSRvx99P0 !#5#53532'3264&+3@PPcPB^^BPPPƍ܌^^dP!%#"&46;5#53533##&326?5#" U!GYpXxPPPPPP)'Px9c !7QQ(PPPP\"<(0 3#3#!!!@p P{PPPPP0 6462!;#"7."3#vv >&R >L> vvvR(#-P#--#P03 3"&53263#!!!P^^P/B/@p31GG1PPPPP03 6462!;#"7."3"&5326vv >&R >L> P^^P/B/vvvR(#-P#--#C1GG10 3#3#!!!@PPP@p P{PPPPP0 6462!;#"7."3#vv >&R >L> IPPvvvR(#-P#--#PPD047'#!!!!!#27"& p " 9#dFDPdPP "  9#FD]%47'#"&462!;#27"&." #Rvvv >& " 9#dFI >L> DvvvR(#-P "  9#Ff#--#0'73#!!!88\x@p88[PPPPP06462!;#"7."'7vv >&R >L> 88\vvvR(#-P#--#88[&!"&4632.#";5#53'7'hRvvR@hQ:#2FF2nd88\vvL;&FdF2P88[0 &%#"&46;#"&'73265&326?5#"/7'IWC]uSvR5[D#D2F."Px2*88\wOiiRv5,):F2T:2d{88[&3 #3"&5326"&4632.#";5#53P^^P/B/PRvvR@hQ:#2FF2nd31GG1vvL;&FdF2P03 ,%#"&46;#"&'73265&326?5#"73"&5326IWC]uSvR5[D#D2F."Px2P^^P/B/wOiiRv5,):F2T:2d1GG1& 3#"&4632.#";5#53@PP(RvvR@hQ:#2FF2nd PEvvL;&FdF2P0  $%#"&46;#"&'73265&326?5#"73#IWC]uSvR5[D#D2F."Px2 PPwOiiRv5,):F2T:2dPP%#53#"&4632&#";'̌ccFuT0UB^^B99PƍK>G^^{990$7#"&46;#"&'73265&326?5#"98xIWC]uSvR5[D#D2F."Px2O98OiiRv5,):F2T:2d0 3353#5##'7'PPPPl88\p88[07632#54&#"#37'7'[EC]P."PPP88\cuSxx2F<x+88[3!533##5!##53!5PP@PPPPPPPP@PPPP@PP((P07632#54&#"##53533#[EC]P."PPPPPPPcuSxx2F<xhPPPP/;&#"'>32327#"3#3#535#T-FK+)&-FK+)PPPP ((&* ((&*3PPP0; 33!535#7&#"'>32327#"p-FK+)&-FK+)PP ((&* ((&* 3#3#3#535#PPPP P+PPP0 33!535#73#pPPPP3 3"&53263#3#535#P^^P/B/PPPP31GG1PPP03 33!535#%3"&5326pP^^P/B/PP1GG1D 3#3#27"&547'#53#PP3 " 9#dF KPPPP "  9#F2P@D0047'#535#533#27"&3#@  " 9#dFPPDPPP "  9#FP 3#3#535#73#PPPPPPPPPPP0 33!535#pPPP3#326=#53##!53#PPx2FPPvRPPPF2PPRvP@00!33#32653#"&'7#535#73#73#P#72FPvR5[&CPPPPPPPP(F2@Rv5,PPPPL%#"&'7326=#53#/7'^B;Y O,!/PP88\B^M9 &/!PP{88[%&"32653#"&5462'7'4 n2PPSTjFd#?88\ (G1@Rv@82F#f88[Ph 33#'#'PPppxP499xh+99i 373#'#'PrrPP :8ѷPg+99i 373#'#PrrPPPg0 3!!7P@p9P90 33!535#?p9PP9P0 3!!'PP 99pP+990 33!53#'p99HPPh99P0 3!!'PP j8:pP99j 33!53#%'p8:HPPhP99P0 462"'3!!**P  **pPb462"33!53#**p **HPPh40 37!!5'7P48l@p48lh48lP48l0373!535'75#48lp48l48lPPh48l0 733#098P89Ep0632#54&#"#3?[EC]P."PPP@9-cuS2F<c9P0 333#'P8XP899X X+990632#54&#"#3'[EC]P."PPP99-cuS2F<E990'733#88\8P888[p0632#54&#"#37'7[EC]P."PPP88\-cuS2F<88[53#5632#54&#"#3PP@[EC]P."PPPhxP;cuS2F<P0733#"&'73267P8XPvR5[D#D%<(XpRv5,):(!70632#"&'7326=4&#"#3[EC]vR5[D#D2F."PPP-cuSxRv5,):F2x2F<h0 6264&"462"3#FdFFdvvv&dFFdFʤvvv P0 6264&"462"3#FdFFdvvv&dFFdFʤvvv P036264&"462"3"&5326FdFFdvvvP^^P/B/dFFdFʤvvv31GG1036264&"462"3"&5326FdFFdvvvP^^P/B/dFFdFʤvvv31GG1u6264&"462"7?FdFFdvvv^99dFFdFʤvvv989u6264&"462"7?FdFFdvvv^99dFFdFʤvvv989P03#3#"&46;#"3xxccB^^BdPPƍP^^P (%."4632632#;#"'#"&264&") &.%]CI//IC] &xxI//IC .D..D ,({uCCuS( ,PCCdFFdF@72#'##3264&#9p@PP".."9+E3/CPP$ "#36;'7PPP[Ex9@<ccP9P@ 2#'##3264&#'B^T=pPP!//! 99^B>[P/B/E99g "#36;'PPP[Ex99@<ccP99@'72#'##3264&#88\p@PP".."88[E3/CPP$ "#36;'7PPP[ExX88\@<ccPH88[0#";2#!5!264&+"&463?2FF22FF29P FdFP FdFc90#";2#!5!264&+"&463?2FF22FF29P FdFP FdFc90!#";2#!5!264&+"&463/7'2FF22FF2 88\P FdFP FdF+88[0!#";2#!5!264&+"&463/7'2FF22FF2 88\P FdFP FdF+88[PD05"'72654/7.'732654.54632.#"hFd#9 "=^TS3B^RvvRcPTS3B^RvvRnR D2F#9  " E1!&$ ;)9SL=!&$ ;)1N D0,"'72654/7#5!264&+"&46;#";2+TFd#9 " G2FF22FF2_ D2F#9  " P FdFP FdF0!#";2#!5!264&+"&4637'72FF22FF288\P FdFP FdF88[0!#";2#!5!264&+"&4637'72FF22FF288\P FdFP FdF88[xDX"'72654/7#5!#Fd#9 ") D2F#9  ")sPPpDX#"'72654/7.=#53533#;#DFd#9 " ?XP/!x D2F#9  " \@PxxP!/P0 '7!###88\P88[P@7;#"&=#53533#%'/!xxB^Pj8:!/P^BPxxP99xX!#3##5#535#xȠPPPPPPX%#535#53533#3#;#"&@P/!xxB^PPPxxPPP!/P^0;#&#"'>32327#"5326=3"&T-FK+)&-FK+)PFdFPvv ((&* ((&*2FF2Rvv0;'%#"&=3326?53#&#"'>32327#"[EC]P."PPP-FK+)&-FK+)ccuS2F<p ((&* ((&*0 3#5326=3"&PPFdFPvv P2FF2Rvv0 %#"&=3326?53#3#[EC]P."PPPccuS2F<p P03 3"&53265326=3"&P^^P/B/PFdFPvv31GG12FF2Rvv03%#"&=3326?53#3"&5326[EC]P."PPP(P^^P/B/ccuS2F<p31GG10264&"462"5326=3"&/B//B^^^PFdFPvvD""YbGGbG2FF2Rvv0#%#"&=3326?53#264&"462"[EC]P."PPP/B//B^^^ccuS2F<pD""YbGGbGu7?5326=3"&99PFdFPvv9892FF2Rvvu%#"&=3326?53#7?[EC]P."PPPؔ99ccuS2F<p989PD0 47'.=326=327"& RkP^^PeN" 9#dFDUB^^BR"  9#FD0#47'.=3326?53#527"&@ AYP."PPP)')" 9#dFDtQ2F<pc,)"  9#F; 3733#'#'7';WoL6LoW4MM4%88\p88[; 3733#'#'7';WoL6LoW4MM4%88\p88[gi'7'373#5 88\rrP88[ٷ0$%#"&=3326?53#"&'73265'7'IWC]P."PPvR5[D#D2F88\wOiK*:2Rv5,):F2k88[gi  373#53#'3#grrPPPPPPٷTPPP0 !!!5!?p98P890 !!!5!?p98P890 !!!5!73#pPP8P8P0 !!!5!73#pPP8P8P0 !!!5!'7p$88\8P8H88[0 !!!5!'7p$88\8P8H88[X#"##53463Xx!/P^BP/!PB^xX#"3#+5326=#53463Xx!/^Bxx!/^BP/!PB^P/!PB^P0%%267#"&54>54&#"'>32@3STPcRvvR^B3STPcRvvR^P&!=LS9); $&!=LS9); $032+"3!!"&46;264&+2FF22FF2FdF PFdF @3#@PP 3#3#PPPP  033#3##5#535#53@PPxPPPxxPPP@%3#3#@PPPPPP0735'73#5##'7xȷ"PP$88\xVdd88[0 6326?5#"#"&546;#'7."Px2[EC]vRP88\dF<xcuSRvp88[ 3#3#535#'7PPPP88\PPPH88[0 33!535#'7p$88\PPH88[06264&"462"'7FdFFdvvv88\dFFdFʤvvv88[06264&"462"'7FdFFdvvv88\dFFdFʤvvv88[075326=3"&'7PFdFPvv$88\2FF2Rvv88[0%#"&=3326?53#'7[EC]P."PPP88\ccuS2F<p88[0"&=!.+5322670vv9 >&R >L> vvR(#-P#--#&!"&4632.#";5#53'7hRvvR@hQ:#2FF2ndb88\vvL;&FdF2P88[0 &%#"&46;#"&'73265&326?5#"'7IWC]uSvR5[D#D2F."Px288\wOiiRv5,):F2T:2dH88[i 373#'#'7PrrPP$88\Pg88[i 373#'#'7PrrPP$88\Pg88[0?3#3#3#5##37xPPxxPxx89ٷPPPPPdd/x?9P ,48%#"&546;632#;#"'#'326?5#"."7@'4D]C#-C] &xx-#P<P". &.%g9c #tTSuuS( ,P4D<xF ,(9L#'746327#"''7&32654'7&#"7vR:4>8>"vR:4>8>"2F ؠ2F@9Rv">8>4:Rv">8>42 F2h F2G9L#'746327#"''7&32654'7&#"7vR:4>8>"vR:4>8>"2F ؠ2F@9Rv">8>4:Rv">8>42 F2h F2G9P0%)%2654.54632.#"#"&'7'@B^RvvRcPTS3B^RvvRcPTS[99P$ ;)9SL=!&$ ;)9SL=!&{990#";2#!5!264&+"&463'2FF22FF2x99P FdFP FdFE99xX !###'xP99PpE99X%;#"&=#53533#'/!xxB^PP99!/P^BPxxP990 3353#5##'7PPPP$88\p88[07632#54&#"#37'7[EC]P."PPP88\cuSxx2F<x88[0 735'73#5##3#xȷ"PPPPxVdd P0 6326?5#"#"&546;#3#."Px2[EC]vRPPPdF<xcuSRvp Pgi  3#373#5rrP P+ٷ0 "3##"&=3326?53#"&'73265IWC]P."PPvR5[D#D2F POiK*:2Rv5,):F20%&"32653#"&54624 n2PPSTjFd# (G1@Rv@82F#P 3%4&#"326%326?5#"5#"546;53>32#0<P."p<P." %xQOPP %xQO4D<x?94D<x?c #Xpx #XpP 37326?5#"4&#"326>32+#5#"5463<P."<P." %xQOPP %xQO4D<x?94D<x?c #Xpx #Xp0%4>54&#"'>32#@2<2F2+CP pKSu2<2P$6, /?L6$6,0%4>54&#"'>32#@2<2F2+CP pKSu2<2PP$6, /?L6$6,P0 $4&#"32'632+3."Px2[EC]vRPdF<xcuSRv0 6463253#5#"&264&"vRC5PP5CR&FdFFdvv((p((dFFdF0 33632#"'4264&"P5CRvvRC5FdFFd((vv((dFFdF0#"&'73264&#"'>320vR@hQ:#2FF2#:Qh@RvL;&FdF&;L0+53267!54623."0vR&> v >L>vP-#(Rv#--0"&=!.+5322670vv9 >&R >L> vvR(#-P#--#,%%#"&547.54632.#";#"326N pKSu<!uSKm P @+3EE3((3EE3-C 8JE3+!-3E>0 $P$"0%73264&+53264&#"'>32#"&'C-3EE3((3EE3+@ P mKSu!E3-!+3EJ80"64632#"'3264&+53264&#"{MSu!L> >L> vvvv#--#P#--#P3#3!"&463!!";5xxRvvRh2FF2(@PPPPvvPFdF0!2#"&'#"&546"26=32654wE3-!+3E`H$P${MSu!4&@PE[[EPE[[E#--#P#--|oo||ooS >L> >L>0 %26?53#5+5@PPP[ExP<pccP0 %26?3#5+5@PPP[ExP<@ccP "#36;PPP[Ex@<ccP@ 2#'##3264&#B^S>p@PP".."E3/CPP$@ !#3373'3264&+P@p>S^".."C/3EP$xX#"+53265463Xx!/^Bxx!/^BP/!B^P/!@B^xX#"3#+53265#535463Xx!/^Bxx!/^BP/!PB^P/!PB^xX#"&54&+532;XxB^/!xxB^/!xx^B@!/P^B!/x0%4&+5323##5#53@/!xxB^P!/P^BPxxPX%;#"&5#53533#/!xxB^P(!/P^BPxxPP%#"&=#53533533##'326?5[EC]PPPPPPP."PccuS(PPPPPP(2F<(0%2654&'53#"&5475#53@#-FdF-#PPuuPP*".."*P /QC]]CQ/ P0332654&+532#"&5P".2n?9((XpROQ9?n2."PQORpXI3# #O2ZZp; !##'#373WoL6LoW4MM40632#54&#"#4632&#"IWC]P."PPvR5[D#D2FOiK*:2@Rv5,):F2gi373#5grrPٷ0%4>54&#"'>32#@2<2F2+CP pKSu2<2P$6, /?L6$6,.%#54.54632.#"P2<2uSKp PC+2F2<2,6$6L?/ ,6053#"&'732654.@P2<2uSKp PC+2F2<2@,6$6L?/ ,60 2+264&+3264&#B^((^B".."".."E3."".3E$PPP$0!#"&5467&546324&#";#"320{MSu!32327#"T-FK+)&-FK+) ((&* ((&*Li7?99989L79898TL!7T99L,'7'<88\L88[x_&#"'>32327#"-FK+)&-FK+) ((&* ((&* 3# P!!0P 3"&5326P^^P/B/2FF2p3#pPPP 3#'3#PPPPPPP264&"462"& /B//B^^^^  (1GG12FFL7?ܔ99989W,$'788\$88[p@0#5P0 @0#5##5PPP0LT7%798{9898980#"&'73264&#"'>320vR@hQ:#2FF2#:Qh@RvL;&FdF&;L%$462"4632.#"3267#"6**vR@hQ:#2FF2#:Qh@R** vL;&FdF&;L0$462"6#"&'73264&#"'>326**vR@hQ:#2FF2#:Qh@R**vL;&FdF&;LyT %'462"@99W**a995**[03##"&'7326=#@PvR@hQ:#2FPPRvL;&F2$L7$99L0 773#%3#9PPPP9PPP0735'73#5##7xȷ"PP9xVdd9r$462"****0 3#!!!%7@p9@PPPPP9073353#5##09PPPP9+p 3#3#535#?PPPP@9PPP906264&"462"7FdFFdvvv9dFFdFʤvvv9gi 373#57grrP9ٷ<90!7>54&"#535&54623#09(#-FdF-#PPuuPP9*".."*P /QC]]CQ/ P0 3#%3#7"&=3PPPPc9B^P/NPPP 9P^B!/P0!5'#73#5!#@.ٷrPPg״P032644#!264&+6L 4X>J))d*PL61%,F>Xp):)P0#!PpPC3!%'M6J@ee PP0 !!!!! dPPPP0 !!!5!PX X8P8XP0 3!53#5!#PP@PPPഴ P0 753&264&"462"^^^ƍPPj^^^ƍƍ 3#3#53#PPPPPPP@Ph 33#'#PPppxPxhC3# #M6VV LP0 3373#'P88Pุ XP0 333#P8XP8X XP0 5!3#!!Px PPdPPP0264&"462"^^^ƍ2^^^ƍƍP0!#!#PPP pP032644+#!//!B^^BP/B/P^^P0 %!!57'5!!xX P88PxX!###xPPp?373#5?rrP෷03#5.4677>4&@PE[[EPE[[E#--#P#--S YrY SS YrY R)4))4)@ !#'#7'373ppppﷷP3265463"##5"&5443@P!/^B!/^BPB^/!B^/!/!B^P/!B^^B!/P^B!/P023#5>54&"#535&54ƍPP%+^^+%PPvRY<3P7!2FF2!7P30 $P$"07632#4&#"#309x[EC]P."PPP9cuS@2F<0 %"&=37B^P/9PP^B!/90 #3#%3#7332654&+532#"&5PPPPc9P".2n?9((XpROQNPPP 9+9?n2."PQORpX0%"'#"&463263"%2654&"0I//IB^^BI//I!///B//B/PPDDvvDDPG12Fx2FF21GG0$%264&+53264&+"#46;2+5))ZZZ!/P^BZ6L 4X>ZP):)P*/!HB^L61%,F>XPC#5323#7.((7S) gVV0 5@PSlCxJ]06264&"7#""&5467&5463FdFFdx2<2vveJF2B//B/P%C.B^^B<[2F,%%#"&547.54632.#";#"326N pKSu<!uSKm P @+3EE3((3EE3-C 8JE3+!-3E>0 $P$"0654&#"&547&'7;#"32>F2RvO@ NC-2FF2Rv;K cwH%> "P^^F21$0632#4&#"#3[EC]P."PPP-cuS@2F<0 6462"'2675."vvv" @T@ @T@ ƍƍ4DD4P4DD4@ %"&=3B^P/PP^B!/i 373#'#PrrPPPgp`3'3# pC[[hx 0%#"'#3326?53#[E-#PP."PPPcc2F<pI!#3>532Z+!Z);;7=d5C\I0)654&#"&547&547&'7;#";#"32>F2Su<<=0 NC-2FF2xx2FF2Rv;K X>?,'65(%2 "P*P):)F21$06264&"462"FdFFdvvvdFFdFʤvvv0 !#####PPPPPP@@0 7#462#"&264&"PvvvRC5FdFFd(@RvvvdFFdF0654&#"&46;#"32>F2RvvR2FF2Rv;K vvPFdFF21$P06264&"3"&463!FdFFd(vvvRdFFdF5CRvvvP0%"&="#46;#B^!/P^B/PP^B/!B^P!/0332654&+532#"&5P".2n?9((XpROQ9?n2."PQORpX0!%#5.54675462'>54&"PE[M:'-#FdF[E#- ||oGBrQE$&> qRvvRGoE >&1GG1@%.#52733"&'#?[>L|p[>L|p=TPXF=TPXF07533>=3#5.P-#P#-P[EPE[&> O >&Go||oP"726=326544#"'#"&463"/B/P/B//!B^^BI//IB^^B!/2FF2PP2FF21GPvvDDvvPG 3#'3#"&=3PPPPB^P/ PPPP^B!/0 3#'3#332654&+532#"&5PPPPPP".2n?9((XpROQ PPP+9?n2."PQORpX06264&"462"7FdFFdvvv9dFFdFʤvvv907332654&+532#"&509P".2n?9((XpROQ9+9?n2."PQORpXP&726=326544#"'#"&463"09/B/P/B//!B^^BI//IB^^B!/92FF2PP2FF21GPvvDDvvPG0(%264&+53264&+"3'546;2+"&))ZZZ!//!^BZ6L 4X>ZB^P):)P*/!!/PB^L61%,F>X^03#5.4677>4&@PE[[EPE[[E#--#P#--|oo||ooS >L> >L>P$726=32654&+"'5!2#"'#"&547/B/P/B//!!/PB^^BI//IB^ 2FF2PP2FF21GGGPvvDDvRC50654&#"&46;#"32>F2RvvR2FF2Rv;K ƍP^^F21$0654&#"&46;#"32>F2RvvR2FF2Rv;K vvPFdFF21$%64632.#"3267#"vR@hQ:#2FF2#:Qh@RvvL;&FdF&;L003#&"32653#"&5462PP n2PPSTjFd#0P< (G1@Rv@82F#0"!!;#"&46;h&>  >&RvvR@-#P#-PvvP0%267!5!.+532+5h&>  >&RvvRP-#P#-PvvPP64632&#"327#"PcFuT0UB^^BU0TuFcƍK>G^^G>Kg0#"&'73264&#"'>320cFuT0UB^^BU0TuFcSƍK>G^^G>KP$462"4632&#"327#"**ۍcFuT0UB^^BU0TuFc**1ƍK>G^^G>Kg0$462"$#"&'73264&#"'>32**cFuT0UB^^BU0TuFc**ƍK>G^^G>K0735'73#5##xȷ"PPxVdd0?3#3#3#5##3xPPxxPxxٷPPPPPdd/xP ,4>32+5#"&=3.+532534&#"326%26?'4D]C#-C] &xx-#P<P".w &.%- #tTSuuS( ,P4D<xF ,(P#23#+5#535#3264&'3264&+B^ YY ^BPP".. ".."E3P3EPP$P$%64632.#"3267#"vR@hQ:#2FF2#:Qh@RvvL;&FdF&;L0%264&+#32h2FF2xxRvvPFdFPvvP0 !#5#53532'264&+3#hPPRvvR2FF2xPPPvvPFdFPPP0 3#!!!@p@PPPPP0%73264&+53264&#"'>32#"&'C-3EE3((3EE3+@ P mKSu!E3-!+3EJ8`0 #537##5!#3PPPP@PP0%#"&'7326=#53#^B;Y O,!/PPB^M9 &/!PPi 373#'#PrrPPPg0 %3!5'7537@48lP48hPh48lh480 3373#'88Pxxpxx0 !##330P8P806264&"462"FdFFdvvvdFFdFʤvvv0#"&'73264&#"'>320vR@hQ:#2FF2#:Qh@RvL;&FdF&;L(0h6264&"462"?r??rppp\""\"QQQ 02'>54&".54vL;&FdF&;LvR@hQ:#2FF2#:Qh@RL%73263'/7632'#"&54654&#"#?9)C8Q'4Xp'C8Q'4Xp1?9."JC8Q QO@)C8Q QO@q."P (726?$#"'#"&=3.+5326324&"2 &.%G]CI//IC] &xxI//IC .D..D ,({uCCuS( ,PCCdFFdF06264&"'326=3"&547&5FdFFdPFdFP33vv33  xxx/!!/2FF2/!!/0 %#4&"#4620PFdFPvv2FF2Rvv0 %"&532650vvPFdFRvvR2FF2032644+#".."B^^BP@P$PEfE0 3#5##7.546#";@P@p>S^".."pC/3EP$0 !"&5467'3353'5#"3@B^S>p@PP".."E3/CpPP$0!###PP@075326=3"&PFdFPvv2FF2Rvv0+532654&/#5!cuS2F<@[EC]P."PPP%0+532654&/#5!5353cuS2F<PPP@[EC]P."PPPPPPPP053264&+53264&+5!##!//!!//!66^BPP/B/P/B/PP&*I//IB^I!#332ZZ; 3733#'#;WoL6LoW4MM4p0 !!!5!p8P80#!P@PI3# #O2ZZp0!###PPp@032644+#".."B^^BP@P$PEfEP3265463"##5"&5443@P!/^B!/^BPB^/!B^/!/!B^P/!B^PP^B!/P^B!/07!!pP07!!pP07!!pP07!!pPP7!!P0P5!!0P`03#3#PPPP000P`P7!!!!P00PPPP@#53PxP53#5@PhxPx!53#5@PxP@3#53PPhP0 #53!#53PPxPxP0 53#5!53#5P@PhxPxP0x 353#5!53#5P@PxPxP0 3#533#53PPPPhPxP0 33###53@PPPPpP0%#5#535#53533#3PPPPPPPPPPxh6462"FdFFddFFdFxhhxxrd$462"****d$462"&462"r********F:d$462"&462"&462"************r$462"****!)-5$4632632#"'#"6264&"$462"6264&"$264&"@F2."".2FF2."".2   XFdFFd   @8  FdFFdF  dFFdF  @8T  (#+3;C76463262632#"'"'#"6264&"$462"6264&"264&"264&"H@8/!:!//!:!  /B//B  p  X  l@8dFFdF  dFFdF      4\'8[[8\8\\84\%'7'748[[848\\8F+$462"$462"462"462"7''7'7&********8888********&8888 %3#3#3#3#PPPPPPPPPPPP0"'>32#7> 54&'53@A P pKSu2<2PP -#PP  /?L6$6,h    sPPP0!!P00P0#5737'#5'7'7%37'#5'7'737'#5'7'7PO(OO(OPO(OO(OhPO(OO(OPO(OO(OPO(OO(OPO(OO(O[.F--F.[[.F--F.[[.F--F.[[.F--F.[.F--F.[[.F--F.0@!!p@4408408`0 3#3#3𠠠PPP`0 #53#535#53𠠠P0PPR.26%#4>54''67'>32632#4>54&'3#73#@P2<2(P MP pK*&')Su2<2P2<26)2<2PPPPP$6,    /? L6$6,$6,$6,lPPPR #%3#3#3#7#4>54&#"'>320PPPPPPPP2<2F2+CP pKSu2<2PPPP$6, /?L6$6,P #73#3#3#7#4>54&#"'>32PPPPP@PPPP2<2F2+CP pKSu2<2PPPP$6, /?L6$6,)7'#5'7'753q(qq(qPq(qq(qP BFAAFBBFAAFB0#%37'#5'7'737'#5'7'7@PO(OO(OPO(OO(OPO(OO(OPO(OO(O[.F--F.[[.F--F.[.F--F.[[.F--F.264&"462" *<**4&:EE:/88 *#yy#*ata632#54&#"#53 7)(80000;F2xx*$x$264&"462" *<**54&#"'>32DB2**; 0C-2FN'H00,'- %. Q#3264&+53264&#"'>32#"&'!(****; 0C-2F$$F2-D$"0%. !&%5-!%3'733##5#`_"001V`0<<%32#"&'73264&+53&B2FF2'? .3**rx08P8%!(0%&#"632"&=4632264&"* (2FFdFF21$*<**4&:EE:/88*#yy#*atax 73##5##5#00000x0x $326?5#"#"&46;# 0Hf7)(8F2x0<*$H;FdFx462#;#"7."FdF%``2v%.%2dFF20x$264&"462" *<** 733#535#```00x#54&"#54&"#536326320(0(00--(8x 8(x%632#54&#"#53 7)(80000=;F2xx*$x@x %632+#34&#"32 7)(8F2H000H=;FdFH8<*$Hx%#";2+53264&+"&463Ȑ  `**  `**x0*<*0*<*;#"&=#53533#HH(8``0``08(`0HH0P%3#!!5.54632.#"5!@@pE[vR@hQ:#2F-#PPPPoGRvL;&F2&> Pg< &,746;7767+'7&''7&%&'Pc 5F)QF^ #>#TuF 5F)QF^'X6Fc\(G ( 5>K\(G (>  3 W8P!%"67#"&4632&#"5363P:#TuFccFuT0UB^D4P[E<#3>KƍK>G^B7VccP073##5#535#535!!3PPPPPPPPPPPPPPPP0!#"3#3#32653+5#535#53463x!/!/P^BPPPP^BP/!P(P(/!B^xP(PB^2:#"32+"&=+#323533#;264&#"&463!3264&#P2FF2xB^^BPP,IPPP/!x2FF2P!//!P FdF^BB^+%xxP!/ FdF/B/P%-#"32+'#3253264&#"&463!3264&#XP2FF2ؐPB^T=x2FF2P!//!P FdF^B>[@ FdF/B/(3!733##'#'#53737>V<0>8ZpRt t ࠠPPPVVVVPi'#53>32&#"3#3#327#"&'#53&4QfvGFuT0UN/UwwU/NU0TuFGvfQP?MK>GKM?PP00&)53&5467536253#4'#5&"#5;0 ==M?PP?MP PPPPPPPPP):)L61%,F>XPPPPPPPPPd*dd *.4632&#"327#"326?5#""&46;#;) 4 )%##%) 4 )( <U.D.;)d(UP"R;&"#2#"&2# >P6462"264&"#532P褤TvvvRPP"88T褤jvvvP0@0P3264473#'#7'##!//!B^T=A@pxxp@@pxxP/B/P^B>[A@xx@@xxP46;73#5'#5#"+5326F2`hh8PPPP(F2((h2FhhhPPh2FPP!73#5'#5##5#P(hh8PPPPPPPhhhPPhP023#5>54&"#535&54ƍPP%+^^+%PPvRY<3P7!2FF2!7P3G^^P0!#!5!0PpPP0!5!0  P?!#'#53rrPF0.4&#"32"264%&'3632"&547.'#6/!K=W1!B//B/,&dWdB^00^^0 d"-:)*bP**:6&@+&76LL67&%K0 %5#5353!5PpPPPpPx %3#7#73#79P"Y{1SGP"=)x!(326=#"&462#"'64&"2%73#7* (2FFdFF21$*<**<P"Y{1S= 8P88(`(8((P"=)x!$264&"462"'73#773#7*<**32#"&/73#7(****; 0C-2F$$F2-DP"Y{1S$"0%. !&%5-![P"=)P#=A3264&+53264&#"'>32#"&'3#5>54&#"'>32(****; 0C-2F$$F2-DB2**; 0C-2FN'P"$"0%. !&%5-!J00,'- %. QP"x!%32#"&'73264&+5373#7B2FF2'? .3**r5P"Y{1Sx08P8%!(0GP"=)P473#5>54&#"'>3232#"&'73264&+53P"-B2**; 0C-2FN'B2FF2'? .3**r1P"00,'- %. Q08P8%!(0Q'>73264&+53264&#"'>32#"&'32#"&'73264&+53P"P(****; 0C-2F$$F2-DuB2FF2'? .3**r1P"5"0%. !&%5-!08P8%!(0P)3'733##5#732#"&'73264&+53`_"001_P"B2FF2'? .3**r`0<<P"i08P8%!(0x!(%&#"632"&=4632264&"%73#76* (2FFdFF21$*<**<P"Y{1Sm 8P88(`(8((P"=)V48%&#"632"&=4632264&"32#"&'73264&+536* (2FFdFF21$*<**32#"&'264&"'462"&547&6264&"P"P(****; 0C-2F$$F2-Do*<**G^^G>KP03264&##32B^^Bc^^pƍP0 3373#'P88Pุ X00 3#33!535#@PPp0PPPPP0 3#73#35+5!3!53PPPPPPР0PPPPPP0 3#'3#%3##5!3!5;5#335@PPPP@PP00PPPP0PPPPPPPPP0!#3#535#533%3#2PPPᇇZPP^PPPPI!#332ZZ70!#333#535#73#12ZPPPPPPP03##3!3!535#73#35PP2Z1PpPPPPP0P PPP0#3=3##37!3!53#%3#35#!35@PPP2xZ77PPPP@PPuKP@P P<PPPpPh0#'!535#5337'37%3#hwwfJJPPHGwfJJPPȏPPxȏPhh #'#7'37hpppȏȏh03#35!'#7'3733PPHGGHJJfwwfJJP0Pxxȏ0 3#73#35!'#7'37!3'35PPPPGGH@BJJfwwfJJnPP0PPPxxȏ0 33!53#pHPPh%64632.#"3267#"vR@hQ:#2FF2#:Qh@RvvL;&FdF&;L0 6326?5#"#"&546;53#."Px2[EC]vRxPPdF<xcuSRvxP!#54&"#54&"#3632632P/B/P/B/PP&*I//IB^!//!!//!66^B !#"&46;2'3264&+#"3cccPB^^BPPPB^^BƍƍP^^@^^P0332#'3264&+2'3264&#PccPPB^^BPB^^P!//!ƍP^^^^/B/)/%5""&463#"332+"&462#3264&#264&#@!//!B^^BPB^^BcccB^^BPB^^BP!//!/B/P^^^^ƍƍP^^^^/B/g0#"&'73264&#"'>320cFuT0UB^^BU0TuFcSƍK>G^^G>K0#"&'73264&#"'>320vR@hQ:#2FF2#:Qh@RvL;&FdF&;LP064632&#"32673#5#"PcFuT0UB^^B*`PPFZcƍK>G^^0 :L ?37#8P8"8W8P0 73264&+2'3264&+232#PB^^BPB^^P!//!P!//qccP^^^^P/B//B/ƍ !-7%264&#'2#3264&#'32+"&46"&463#"37.467"%SS%".."FFPB^^BcccFFPB^^BP".."%SS1>1.4.a~a^^Pƍƍpa~a^^P.4.1>1P37264&"462"3264&+53264&#"'>32#"&/*<**7 +oTEF2+CP pKSu6LLPPIAJ /?L6ND;.#.#";#"3267#"&47&54632D-2FF2((2FF2+CP pKSu<XJ8!!'8188P8L'#'7L8P8481σ8P'7!5!'781σ88P8wL?378P8\818 '7!'7!'7888n88888wL ?'7'78888\8n888xH##G8PP8GCX%#5'#5!XP8GCu8HPX537538HP(PH8xH33!xPH8G8P373#'7#'8l84hl8488l84Pl848P'7#'7#5373'78l84hl8488l84Pl84837!!'#'8V88V888P88L''#'75'7L88P8848V88V8P'7#'7!5!'73'78V88V888P88wL?5'737788P88\8V88V8t '#'73<88΃888888\ '7'73'7'7#88΃888888 !53#5!'8PP88p8L '3!53'7L8p848PP8P '7!#3!'78PP888wL ?#5!#788\8PP8L?'7'73!538888p8888PP!264&+532#!'8/!//!((B^^Bу88/B/P^^8P#"3!'7'7!"&463(!//!/88B^^BP/B/88^^35462+#5#'%3264&"8^^^BPP߃8P!//B/8PB^^^8xP/B//!#5#"&4623'7'7#'4&";@PPB^^^߃88P/B//!P^^^BP88!//B/ 7'7!#!8P48p@P %'7!#!'78Pσ8488 !3!'8P18\8@p8P '7!3!'81P\8Pw ?!5!788\8P18 !3!'8P18\8@p8L'3#3##5#535#535'7L8P848P(PPPP(P8wL?5#535#53533#3#78P8\8P(PPPP(P8P !!'#3L88PP8P8P '7!5!'753#588PP8P8pP 5!5! !!@(hP %'33 ## h(P %7'!! 5!5!(hhP 77##% 33hh𠸸(P%35'3#'335 ##50h(PP(@PP(PP3533##5#'8PP߃88P8P'7##5#53533'78PP߃88P8'7##5#'73533'78P88P888883533533##5##5#'8P(PPPP(P88P8P'7##5##5#53533533'78P(PPPP(P88P8%'7##5##5#'73533533'7$83SP(PS3883SP(PS38484488448P0%5!37#'3!53.ٷrP@Pg)%"&=462#54&"26=FdFFdFP  (2FF22FF2(((0'632"&463254&#"4&"2@:SRvvvvRC5F2,FdFFd}4/^BB^^^ !/B//B/P0 %5!5!5!5!!5p PdPP PP0<%5#3!'7#537#537!5!35#:F75F7e:'UQL"fPdd(4 \(4PdPP܌4L#746327#"''7&%&#"%32654PcL?I8I-cL?I8I-B&,B^&,B^c-I8I?Lc-I8I?^B,&^B,C3!%'M6J@ee PC!#!76eeP0!"&46;#"3#;cc1QZ=ƍP8,P;QP?<#3##;#"''7&546;#"3#F=;-F$'=6FFL=c4.1Q`.=<(4PeOyPz(E[cP8,P"0"!!;#"&46;h&>  >&RvvR@-#P#-PvvP0!#53267#53.+532@=ZǼQ1cPQ;P,8Pƍ?< $+'7#537#537&+5323267#73&'FL=c45F=QD/#(=6y=ZT.<(E[c\(4PPQPQ;P 0%267!5!.+532+5h&>  >&RvvRP-#P#-PvvP0!!p`0 ####5!PPP`0 3333!5PP0PPP`0 !! !!5 @00@0PPP07!!pPxh264&"462"@  hFdFFd  ZdFFdFxh6462"FdFFddFFdF4`0!!#7@880P$8`0#,3264&+53264&#"'>32#"&'%!!#71(****; 0C-2F$$F2-D?88D"0%. !&%5-!P$8`03'733##5#!!#7`_"001@88`0<<P$8PP@$/>32#"&/#"&46324&#"32$326?&#"hS/2FF2/PS/2FF2/P3 )>3 )>#FdF#FdF X  (8  (03!!P@pPh83!h88Ph8?73##67!7&&'B) 8+ SS] (~FB88HP+%".##FI3# #O2ZZpI!#332ZZ0%#54&"#54620PFdFPvv2FF2Rvv075326=3"&PFdFPvv2FF2RvvP`0#!462"&547&#""&5462326@^^/B/(!/^^/B/(!/B^^B!//!. /!pB^^B!//!. /P`0/5;%.4675462"&547&#""&546232657>4&@E[[E^^/B/(!/E[[E^^/B/(!/#--#P#--ooB^^B!//!. /!ooB^^B!//!. /!9 >L> >L>8/X'%&#"'>32327#"'&#"'>32327#"T-FK+)&-FK+)&-FK+)&-FK+)U ((&* ((&* ((&* ((&*/##327#"''7'>37&#"'>32F.FK*(-FK+)&UF.FK*(-FK+)&(N(&*E ((&*(N(&*E ((&*03#3#'7#537#53F'T/>F'T/(DPPPl(DPPP0 7!!5!!5!!pppPPPP|?3#3#3!'7#537#537#5!F5&U..LF5&U.. (\PPPPP(\PPPPP0 3!!5!!5!!5!!ppppPPPP 7!!',8[[8PP8\\8 7!!7'7'7,l8[[8PP8\\8`0 46  35%3.#>5#*ր\0 \ 3* \ \`0 46  !."!26*ր*ҞҞ3*gg`0 46  7'7&"64'2*K88oK=8pK3*KK১8pKç8`046  &#" 32654*=K]t8xK]t3*H8t]KPx8t]`0264&"6  462"P褤*FdFFd<褤S*6dFFdF`0$264&"462"&264&"6  @  hFdFFd褤*  ZdFFdF褤S*`0!264&"6  7'#5'7'753P褤*ֽq(qq(qPq(qq(qP<褤S*BFAAFBBFAAFB`0264&"6  !!5!!P褤*3pp<褤S*@PP`0264&"6  !!P褤*3p<褤S*P`0 !!35!#3#3!5#0@00P`0 !!5!!!00000P`0 !!7''7'088800888`0 6462"!%!!FdFFd00dFFdF0P0`0%!#3!PP`05!3#!PP@0@`0!5!!@PP`0!!5!@0@0PP( %#5!#53#3#xPPPPPPPPxM#746327#"''7&&#"32654'Pt]K:9;8t]K:9;8q275#7367#53&@P:V V:P:V V:I66IP6II0 V:P:V V:P:V I666I6`03#3##5##5#535#5353353#30PPPPPPPPPP04=FO626=#"&46235462+32"&=#"&46;5#"3#37264&"'4&";264&+ (hFdFPFdFF2((2FFdFPFdFF2((2PPx  ( (8 (dFF2((2FFdFPFdFF2((2FFdFPP ((  P0%!53!0pP@PPp`v0#3#5373#!5&'&47675!4&"2h-Z):  :)IICvvvO-X1Z2V II Dvvv`0 !!575'57!!'3#0NPP0PPPPPdP0!!#P0P@0#!5P0p@P`3!P@P@`!5!3p@PP@@`0462"&547&#"#@^^/B/(!/PB^^B!//!. /!P`0!"&546232653^^/B/(!/PB^^B!//!. /!0P4 7' '%3#%3#8  8h48 8PPPP 3#%33##獼PPpP !7'%! !''7'7PXX8t8[[8\\8[[8\pP8\\8[[8\\8[P|#37'%3#'#'7#3'73#3'3&tt3FHHFFHHF.EEEtt&pȄ( (44( 0 (4Pxx #'+/37;?CGKOSW[_cgko%3#73#73#'3#3#73#73#73#3#%3#73#!!%3#'3#'3#'3#%3#'3#'3#'3#%3#'3#'3#'3#'3#'3#'!%!!(((((((P(((((((<((xPP<\((<@Tdd((P((dd((P((P((xPP((P((P((P((P((P(((X0(x(x(((x(x(x(x(((((((((((((((x(((((((x(((((((((((PH( !!! !'7'77'88[[8\\8[[8\PT8\\8[[8\\8[0`0 '7'7%3#'7'%((((PP(88?E^EVE^Eռ @h? ?7#5373#?9OuBWH~x9P,P 53!53#!5#@x xP`0546 #3!#!535#7!."*ӴS*Ҟȕӕ(P@PPg`03#5.467@P#--#P#--#0 >L> >L> 3&47!!5>4&'PTT ggE[[EPE[[pRR 0ҞQooxooP`0 33##5#3333@PPP0PPP0Ppp`0  3 75!5!7'!!dh9/˴h(TTh,//PxxTT@(P 533'7'7#353P[3883,PP4884pPP`0#'+/4937'#5&''7&47'767567'7&7'%64@PoEH(HH(HEoPoEH(HH(HEom,AA,mPA,mm,nn nn 0SY*F)1n1)F*YSSY*F)1n1)F*Y'?2z2?2? ?2??Da??D`0 46  '>7#7."37*րbb``Ҟ3*@aaPgg`0 46  7264&"!*-hh褤3*褤`072644 &553P褤tӖ:8]tPӕ 8:]`0 53!3!#hȠPP`0 !#"32654'!#"#!5326546!/!/x|d!/^Bd!/^/!p*&/!*vP/!pB^P/!B^`0 7!5!! hPPh`0 !!5!%7hh0h0PP`0 !5!! 7%!'bPPh(P`0  !!5!7%!'hh0b0PP(P !!7!! @h88@`0 #463"PkmWVLP@`03#@PP00@`0 "&53mkPVPPLîڬ`0 52#4&mkPVPî&@`03#@PP00`0 2653#WVPkmP&@`0!!#@P0P@`03#@PP00@`03!!@P@p0P`0!#!P00@`03#@PP00`03!5!@Pp@00P@`0 %#463"Pꦅ@P`07#4춭f|PP|2uPu@`0 "&53ЦPPP@@`03#@PP00`0 %#44P@P@`0#467.533"P|ff|Pu22uP`0 3#5265@Pꦅ0P@`03#@PP005!!0P`0 5265463"ꦅPtPt`0 "&544Ц껅PPӕtPӕt`0!!#@0P`03!!@00PPP@!#5!#PP@P@3!53!P0P0@3!53!!#5!#P0P0PPࠠP4`03#7@P8800$8`P03#PP00`03#PP000!!00P@!!0PP5!!0PP`!!0PP@`0!!@P@`03!@P@P`003#5.4675>4&'@PE[[EPE[[E#--s#--#0oooo >L> >L> `0%55!5!!#5.46>4&'@#--#E[[EPE[[#--#W >L>(TPPToooo >L> `03!!5!5.4675>4&'@PE[[E@0@E[[E#--s#--#0ooTPPToo >L> >L> P`0 3##5#3#5@PPPee0``0 !5!!##5#3#5@PPeePP@``0 3#!!5!5#3#5@P@0@Pee0`PPPP`0+7>32332>?#"'#.#"!(I*<325!5!!32>?#"'#.#"!(I*<<-+L!(I*<32332>?#"'!!5!5.#"!(I*<2."5E;;E0D)`ss`)O]]PL "&'726E;;E0L)`ss`)O]]!#54&#"'#"#546326=332PF2d<32;) 4 )%##%) 4 )##<32#"&';) 4 )%##%) 4 )##<>x(((xR;&"#2#"&#2#x(;R;>(t $5353#'35'73#5##373#'#(x`|!!0|`!!0`0!!000`v0!!v00`0!!00`0!!>00`h0!!h00`0!!00`03#00`Z03#ZZ00h`0!!hh00@0 #'+/37;?CGKOSW[_cgkosw{3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#'3#--Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--Z----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--Z----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--Z----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--Z--F------------------------------------------------------------------------------------------------------------------------------`0 #'+/37;?CGKOSW[_cgkosw{ #'+/37;?CGKOSW[_cgkosw{3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#'3#!3#'3#'3#'3#'3#'3#'3#%3#v--Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z--v--0------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------2`0 #'+/37;?CGKOSW[_cgkosw{735335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335353353353353353353353#3#3#3#3!535#535#535#53533533533533533533533Z-----------------------------------------------------------------------------------------------------0-----------------------------------Z--------------Z--------------Z--------------Z--------------Z----------------------------vZ----------------------0!!00Zv`03#vZZ00`h5!!hh`%!!hhh0!!h0`0!!!hh00`0!)!hhh0`0!!!0`0!!!00hh0!!hh0`05!!!!hhh`0!!!hh0h00h`0!!000`0!%!!P000P0`0!"3!2654&'2#!"&5463);;)h);;)JjjJJjjJ;));;)h);PjJJjjJhJj`0 !!!%!!pP00p0P0`0 3!5%!5%!5%!5%!!P00000PPPPPPPPP0`0 3#3#3#3'!!0PPPP00000P0`0 #'+/37;?C!35#35#35#35%35#35#35#35%35#35#35#35%35#35#35#35'!!0PPPPPPPPPPPPPPPP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP0`0 !!5'##5##3!';'0``DD00D`TL00`LThD0DD```0 !!%3755!355#7#7##0`LThD0`DD`00P`L`TDD00`DDT`0 #',049=BFJOSX]bfjos!!757375'''7'7'%35''75#''37'7'7'#775'#%'#'''7'0v00 d0000 L 00*000*000 00 0000 04000*0000 00000 0d000000000 L4000 0 0  L 0*000*0000 00000>00 LP000*0 BL 00*000*000 00 d0000 0000*0000 00000 0d00000000 4000* L 0 0 0 0*000*0000 L 000|!!h||35%!!h,P|!!0||!5%!!P00,P`0!!h00`03%!!h0P0|!!||!7%!!d|d\,P`0 hh0`0! hhP0|7h|%3'6d2ddh`0 00`0% P04h| h||%7' dhd2| 0||- P6z0N`0 00`0! N4h40| |h|#7 d2,dh`0 0Рhh`0 40hh|-h|%5-dhd2|-0|%5 -0zN`0 hh0h`07 hhhh`0 '77 hhNhh`06462"264&"6  vvvƤ褤*vvvv<褤S*`07 hZZZZ|hh`0264&"6  P褤*<褤S*`0 #)17727"'&'7'&47'64'7'67&/&"'6267!H!2d|Z3J%=K iK K-3Z=%CZ3J%=+!H!2d3Z=%K K-3Z=%2d2!H!!H!2d|Z3J%=3Z=%iK KZ3J%=`0 46  7'64'&'6*m+%%uPPPP%++3*S*KPPPP?`06264&"462"264&"6  FdFFdvvvƤ褤*dFFdFʤvvv<褤S*`046  *3*`0 264&#6  htt*PS*`0 "&6  ht*P0褃*`0 %!266  Ф*t!*`0 %4&"6  P*tt*`0%!"266  t*褤!*`0 7!"6  PtP**`h0"&63hӕ*h`02hӠ`0 264&"%!!FdFFd0"dFFdF0`0 6462"2#)"&5463!P褤tӕhӕT褤ӕhӕh0 %!462%2463!Ф0ӕtӕh` %"&5!#)"&5ӕhttӕh0"#46htP0Pth0%#44PttPh`52653htPӠPt`h"&533hPtӕt0 %#4&"#46 PP*tt`  &532653PPӕtt`0Р0`0!000`0 000`0!0Рxh264&"462"@  hFdFFd  ZdFFdF`0!%!!h00P0`0!%!!P00P0`0 !!!000`0%!!P000P0`0 3!3%!!000P0`0 $462"! ,#2##2hh#2##2#P0`03 hhhP0`03 hhP0`0264&"6  P褤*<褤S*`0 !!!!#3000`0 !!%3!!5#0@P00P0`0 !!3!5#30P@00@`0 !5!%!35P00@P0P`0 46  35%!32654&*ր\0it3* gti`046  !>54&#"5#*ր=gti 3*it\\`046  .#"#>*itg=\3*gti=P `046  3267!%3.*փtig@ 3*htg=\`0! A0A0`0%! !A0!`0! !P0oA0P!%!! 0pPP!!P0035%!!p@Pp0!!pp`0! P0 `0 $).36462"3&"27#''7'#5364'3'67&'7FdFFd P..PFt9t4t9t""t9tt9t"dFFdFxt9t"hP..PFt9t7t9t""t9t`0+@ #4&"#4&""&=326=4&"#4&"#423."263262626*P P FdFP  P PX "" .""\""\""0ӕ2FF2((IXXIr !''!hUTTr #7'7#!''!h8888UTTkjkj-`06462"&264&"6  FdFFd褤*֖dFFdF褤S*`0!%!!P000P0`0 ?!! !90b09yeG0`0 !!7!'!0PߦߦB00GBߦ`0 46  %654&'67*m;Eg88gE;3*+ &i]KK]i +`0%$462"$264&"4622654&"6      |RtRRtRP*ָ  8  (:RRtRR:t*P 7!!5!!5!!P000PPPPP 3#%3#!!!!00PPPPPPPP %3#%3#5!!!!00PPPPPP 3#%3#3#%3#!!@0PPPPPPPPPP %3#%3#5!!5!!00PPPPPPP 3#%3#!!3#%3#0@PPPPPPPPPP %3#%3#5!!3#%3#0@PPPPPPPP 3#%3#3#%3#3#%3#@@PPPPPPPPPPP`0%/46  462"6462"654&">227#4&"*    PPuuuSSLFdF3*    RrttrRRrrVPP2FF2`0#+462"&462"32653".264&"6      hPFdFPvvP褤*0    P2FF2Rvv褤S*`0#264&"264&"265#"&56      hvvPFdF*P    RvvR2FF2* `0 &,16;$264&"462"3&"27#''7'#5364'3'67&'7@  hFdFFd P..PFt9t4t9t""t9tt9t"  ZdFFdFxt9t"hP..PFt9t7t9t""t9t$`0!73264&#">32#"&3264&#"$7ERvvRE7,jӕj-7tt6.Oed,,vv,\pp`0!&#"327#"&632'&#"327.467ERvvRE7,jӕj-7tt6.Oedd,vv,\p*p0)173##5#535.547&54762654264&"@;PE[;@+2|2FdFFd40A*&&*9Y +PPPP+ Y9*&&*A04$$B//B/04623##5#535.6264&"vv[EPE[PFdFFd@B^^B9Y SPPPPS YZB//B/033#"&54675#53264&"@PE[vv[EPFdFFdPPS Y9B^^B9Y SPB//B/P646327#5!#5"&264&"PvR<2qCPq!v&FdFFd&v!qPq2h!iQ=R:L: (:TpT:( :L:R=Qi7g1FF1>eR:*P54&#"'.#".54632>32hG"' >>*"H &aI=R:'F/:R:RRG3"!^^%"3 #ha}1:R8&R:1zi[P7 hoP2653$46;&546232"&5"TttT R:RtR:RRtRRtPddtR:RR:RtRR::RP2#"'3!2767#"&54>32654.'326?h!iQ=R:L: (:TpT:( :L:R=Qi!P""*k32l*"7g1FF1>eR:*P32h &aI=R:'F/:R:RRP #ha}1:R8&R:1zi[P hP&?2653'3264&+7654&"#"326?46;&546232"&5"TttTr##x&#2#&x$#  VR:RtR:RRtRRtPdd"#2#h ## h$# VvtR:RR:RtRR::R3"&5467632P4,4fF4,43j(N81(NP"&54676323654.'fF4,43PKZKG%#64,c81(N2<-D%PL%O"" (Nu!%"&5467632"&54676324,4fF4,434,4fF4,43U?(N81(N2_y(N81(Nu%% "&54676325%"&5467632@p4,4fF4,434,4fF4,43U?4&35&'&547PvR,$$,Rv[EPPPE[(((5->>Pw->>@B^ ^B9Y SPPPPPPS YuHH,%+*%->.SSL%*+%.>-`0),69E546327#5!3#5#"&'.67732654&57#5#37>7.#"vR<2qCPq!vRIo F]&&} R7 @(2F00<(!S^ R7 @(2F0Rv!qPq2546326327#5!#5#"'3##5#535.>4&'64'&47vR,$$,>5lCPjvR-#PE[u->>-x(((5->>B^ mPi%)B^ SPPPPS Y->.%+*HH,%V%.>.P`0'264&"46327#5!#53##5#535.FdFFdvR>5lCPj[EPE[B//B/PB^mPi%)9Y SPPPPS Y("6264&"46327'77#5!#5'"xFdFFdvR<2"\8\gPh\8\!!vdFFdFʤv!!\8\hPg\8\"2"2654B//B/@B^^B9Y V Y9B^^B9Y V YZB//B/@G12FF21vv[EE[vv[EE[PG12FF21`0 3##%#5#5#5353533PPP0P0PP0PP`0 %3!&462 7%7&"P;v;{9999#dF#ZP{;v; 9999#Fd#`0 5#7"&477''7''2;v;{a989r#Fd6P;v;{989#dF???9;Bx9,4 77''74888888884 77''7488888888 w6$264&"4632&5462632#"&'#"'&54767.;R;;RU7) RtR )7UH9 9$.*II*.$9 9HR;;R; =O :RR: O=5R $.G*/&&/*G.$ R v7FYiz"&547.'&547>7632&5476;2632#"&'267'#&#"76274657654&'32767#7&'7327654'./7>74&#""#7:Q0+>  9' %#5&29P#%+!*8( 0P;-E?+  d]%"" 'T&)  U %XpR:>,1%$3 B* Q:/-I ,=;Q/%$/ >!f $%  j B Be(  B\"! :`0 !%!3!5#PPP PPP`0 !!35!#P PPPPPP`0 !%!!'PXxx Pxx`0 !!7!P PxXxPXxx`0 '77'7''7ИЗИ`ЗИЗP 5!5!h`0! Z0}hh`07%!jhh`0%0hh`00 75333##PPx` 0%# &'#53> 267%!." RRRҞ*ҞPPPggPg`0   &%>4&*gg0*Ҟ*Ҟ`0"264$  &%#3#褤S*@PP褤*3pp`0  &654&#" 32*H8t]KPx8t]0*K]t8@K]t`046  264&"33!53*փ褤LPxx3*褤PPP`0 %!26 &6 5!3.'}Ҟa*\ = \g$* \\ `0#$462"462"$&"26 &6'((((褤褂@9C((((5褤,9`06264&"462"264&"6  FdFFdvvvƤ褤*dFFdFʤvvv<褤S*`06462"264&"6  vvvƤ褤*vvvv<褤S*`0 !!7!!0P 900`0 !!!7!0P9 00G 9`07'#5'7'753%!%!!q(qq(qPq(qq(qP00 BFAAFBBFAAFBP0P0`06264&"462"!%!!FdFFdvvv00dFFdFʤvvv0P0`0 35%!!!%!!pP00@Pp0P0P 3!5#!3535##35##pPPPP@pPPP`0# Nh40`0# hh40`0 h0hO0 %!7%!''7IqqƪeIqtqƪ !77'!'IqqƪhIqqƪO0 %!'!7'7Iqtqƪ(Iqtqƪ !'7'!7Iqtqƪ+Iqqƪ  5# 3'537'#ȸ蠠@hhhP !!hPP7 ##PP% 33O0!''7qƪtqƪ7!'qƪqƪO0!7'70tqƪtqƪ)7,tqƪqƪ 5# 3蠠P`0 % 35# #蠠x`07!!!P00h0`0!%!!P00P0`0!!!P000`0%!!P000P0`07 hhhh`0 hh_h`07! hhh/hh`0! hhhh`0 #'+/37;?3#3#3#3#73#73#73#73#53#53#53#53#'3#'3#'3#'3#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP`0!!000`0!%!!P000P0P@3#@P@%35'3#@PPPPq hhYq ! hfHfhh9wY0`0 7'%88N @h0`07%088h!hp88`046  *3*|<6  *~jjj| "2>4&$  &4====*,'- -''- -wjjj`02"&jjj0*`0 $4."26"&62'- -''- -wjjjt====p*`0% %Z`0 %% %\8xZ ff!!'pP@###7@P@pP5!5!5pPw@7333PPp 7'7355٠ذذw@ #7#3'3@ذذ@xH}8}}8}2X%'''!X}8}2}8}X777&}8}(}8}xH!x}8} }8}`04632!5 5!#"ӕt%T%t3*ӆjjt0 3 3.54*ӆjj0ӕt%T%t`0#"&'! !>32ӕt%T%t]ӆjj` &5467# #ӆjjӕt%T%tP 5!5!h`0! 0}hh`0%%hhj`07%!jhh`0%hh} 0`05дh`0 %hh00`0%0hh`0%hhhдP 5!#!5#5#7357#33p@PPP@pPPPPP 5!#!5#5#p@P@pPP5!#!p@p`0!!000`0 hh0hq FY`0'7!*Ӡ*`0'hiiii0iii`0 hh0`0 00`0 0Рhh`0 000%!46 0*ȕ`% &5ȕӕ`0 4ĉ3"hӕӕӠӕig 6' 7& ijjj*jjjj7j*jjjjjj`0 4ĉ3"567&'hӕӕ+@>-+@>ӕh>-+@>-+ig 6' 7& 762&47"'ijjj*jjjjI*B,*B,7j*jjjjjjI*B,*B`0#333###5#5#5353#3735#3#5#@PPPPPPPPP0PPPPPPPPPPrh'!hThr!'hUTr'7#!''!h88UTTkj-r#7!''!h88UTTkj053#5!#3#3xxxxxx.%#=4.54632.#"P2<2uSKp PC+2F2<2PPPP,6$6L?/ ,6$@h0!!h0h@0!!hh0@0!!00Ph@!!h@Ph0!!h0 P0!!!5!hhh0P0!!!0hP@!!hh@P0!!!5!hh0hP0!!hh0 P0!!5!0 P@!!0@P0!!!hh00P0!!5!hh0h0 P0!!00 `hP5!!hP`h05!!!!hhP`05!!!!hhhP`05!!!!h0P`h@!!h@ `h0!!h00`0!!!!hhh0 `0!!!0 `@!!!5!hhh@`0 !!!!5!5!hhh0`0!!!5!hhh0 `0 !!!5!5!h0 `@!!!@`0!!!!hh0`0!!!!hhh0 `0!!!0 (h@!!(h!!(h!!%!!(h(x@!!((x@!!!!(P(x!!!!P(x !!%!!!!(hPx!!(x!!!!(hPx!!!!P(x !!%!!!!(hP(x!!%!!(h(x !!!!%!!(hP(x !!!!%!!hP(x !!%!!!!%!!(hhP(@(7!!(((@!!!!((!!!!( !!%!!!!(h(@!!!!(P(@ !!!!!!(PP( !!!!!!PP( !!%!!!!!!(hPP(!!!!P( !!!!!!(hPP( !!!!!!PP( !!%!!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPPh`P%!!hhP`0%!!!!hhhPh`0%!!!!hhhP`0%!!!!hh0P`@!!!5!hh@`0!!!5!hh0 `0 !!!!5!5!hhhh0`0 !!!!5!h0h`@!!hh@ `0!!!!hh0 h`0!!hh00`0!!!00`@!!5!@ `0!!!5!hh0 `0!!5!5!hhh00`0!!5!00`P5!!0P`05!!!!0hP`05!!!!0hhP`05!!!!00P`@!!!hh0@`0!!!hh00 `0 !!!!!hhh0h0`0!!!!h00`@!!5!hh0h@ `0 !!!5!5!hh0h0 `0!!5!hh0h00`0!!5!5!0h00`@!!0@ `0!!!hh00 `0!!!hh0h00`0!!000(%!!((!!!!(h!!!!( !!%!!!!(h(!!!!(hP( !!!!!!(hPP( !!!!!!hPP( !!%!!!!!!(hhPP!!!!P( !!!!!!(hPP !!!!!!PP( !!%!!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPP((7!!%!!(h(( !!!!%!!(h( !!!!%!!h( !!%!!!!%!!(hh( !!!!%!!(hP( !!!!!!%!!(hPP( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP( !!!!%!!hP( !!!!!!%!!(hhPP( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP( !!%!!!!%!!(hhP( !!!!%!!!!%!!(hhPP( !!!!%!!!!%!!hhPP( !!%!!!!%!!!!%!!(hhhPP@h0!!h0Ph@!!h@Ph0!!h0 `hP5!!hP`h05!!!!hhP`h@!!h@ `h0!!h00h@0!!hh0@0!!00P0!!!5!hhh0P0!!!0`05!!!!hhhP`05!!!!h0P`0!!!!hhh0 `0!!!0 hP@!!hh@P0!!!5!hh0P@!!0@P0!!!hh00`@!!!5!hhh@`0 !!!!5!5!hhh0`@!!!@`0!!!!hh0hP0!!hh0 P0!!5!0 P0!!5!hh0h0 P0!!00 `0!!!5!hhh0 `0 !!!5!5!h0 `0!!!!hhh0 `0!!!0 h`P%!!hhP`0%!!!!hhhP`@!!!5!hh@`0!!!5!hh0 `P5!!0P`05!!!!0hP`@!!!hh0@`0!!!hh00 h`0%!!!!hhhP`0%!!!!hh0P`0 !!!!5!5!hhhh0`0 !!!!5!h0`05!!!!0hhP`05!!!!00P`0 !!!!!hhh0h0`0!!!!h00h`@!!hh@ `0!!!!hh0 `@!!5!@ `0!!!5!hh0 `@!!5!hh0h@ `0 !!!5!5!hh0h0 `@!!0@ `0!!!hh00 h`0!!hh00`0!!!00`0!!5!5!hhh00`0!!5!00`0!!5!hh0h00`0!!5!5!0h00`0!!!hh0h00`0!!000(h@!!((x@!!((x@!!!!(P(@(7!!(((@!!!!((@!!!!(P(@ !!!!!!(PPh!!(h!!%!!(h(x!!!!P(x !!%!!!!(hP(!!!!( !!%!!!!(h( !!!!!!PP( !!%!!!!!!(hPPx!!(x!!!!(hP(x!!%!!(h(x !!!!%!!(hP(!!!!P( !!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPPx!!!!P(x !!%!!!!(hP(x !!!!%!!hP(x !!%!!!!%!!(hhP( !!!!!!PP( !!%!!!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPP(%!!((!!!!(h(!!!!(hP( !!!!!!(hPP((7!!%!!(h(( !!!!%!!(h( !!!!%!!(hP( !!!!!!%!!(hPP!!!!( !!%!!!!(h( !!!!!!hPP( !!%!!!!!!(hhPP( !!!!%!!h( !!%!!!!%!!(hh( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP!!!!P( !!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPP( !!!!%!!hP( !!!!!!%!!(hhPP( !!%!!!!%!!(hhP( !!!!%!!!!%!!(hhPP !!!!!!PP( !!%!!!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPP( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP( !!!!%!!!!%!!hhPP( !!%!!!!%!!!!%!!(hhhPPD264&"462"264&"462"#2##2K;R;;R#2##2K;R;;RY2##2#eR;;R;s2##2#eR;;R;%73#5&264&"462"f(D#2##2K;R;;R3Ȕ#2##2#eR;;R;D%%3#5654&#"'>32264&"462"‚Ƞ#1 (8%);A!#2##2K;R;;R((I &052##2#eR;;R;D"*2%3264&+53264&#"'>32#"&'264&"462""####0 (7%*::*%8#2##2K;R;;R2   (  #2#%,2##2#eR;;R;D %3733##5#264&"462">>x(((x#2##2K;R;;Rp>(O2##2#eR;;R;F&%32#"&'73264&+53$264&"462"6);;)!3 &*##^r#2##2K;R;;R):) d(2##2#eR;;R;D$,%&"632"&=4632264&"264&"462" 2#$);;R;;)6#2##2#2##2K;R;;R #2##3273#5‚Ƞ#1 (8%);A!f(D((I &0M3Ȕ#D")%3264&+53264&#"'>32#"&'73#5"####0 (7%*::*%8f(D2   (  #2#%D3Ȕ#D %3733##5#73#5>>x(((xf(Dp>(g3Ȕ#F%32#"&'73264&+53%73#56);;)!3 &*##^lf(D):) d(3Ȕ#D#%&"632"&=4632264&"73#5 2#$);;R;;)6#2##2f(D #2##32264&"462"҂Ƞ#1 (8%);A!#2##2K;R;;R((I &02##2#eR;;R;%73#5'3#5654&#"'>32f(DނȠ#1 (8%);A!3Ȕ#((I &0D+%3#5654&#"'>32%3#5654&#"'>32‚Ƞ#1 (8%);A!Ƞ#1 (8%);A!((I &0((I &0D"8%3264&+53264&#"'>32#"&/3#5654&#"'>32"####0 (7%*::*%8Ƞ#1 (8%);A!2   (  #2#%((I &0D #%3733##5#'3#5654&#"'>32>>x(((xȠ#1 (8%);A!p>(((I &0F,%32#"&'73264&+53%3#5654&#"'>326);;)!3 &*##^Ƞ#1 (8%);A!):) d(x((I &0D2%&"632"&=4632264&"'3#5654&#"'>32 2#$);;R;;)6#2##2Ƞ#1 (8%);A! #2##32|Ȁ0xȠ#1 (8%);A!x((I &0D!7$264&"'462"&547&6264&"'3#5654&#"'>32#2##2K;R;;R;K2##2#҂Ƞ#1 (8%);A!0  <####  ((I &0D2%26=#"&462#"'64&"2%3#5654&#"'>32 2#$);;R;;)6#2##2قȠ#1 (8%);A! #2##32x32!//!xxPPނȠ#1 (8%);A!##P  (((  ((I &0?+$4632&#"327#"3#5654&#"'>32|;) 4 )%##%) 4 )Ƞ#1 (8%);A!'R;&"#2#"&((I &0D%%264&+#5323#5654&#"'>32##<32ddȠ#1 (8%);A!(((((x((I &0D %3##53%3#5654&#"'>32dd(Ƞ#1 (8%);A!((P(x((I &0D"*23264&+53264&#"'>32#"&'264&"462""####0 (7%*::*%8#2##2K;R;;R"   (  #2#%2##2#eR;;R;)%73#5'3264&+53264&#"'>32#"&'f(D"####0 (7%*::*%83Ȕ#   (  #2#%D8%3#5654&#"'>32%3264&+53264&#"'>32#"&'‚Ƞ#1 (8%);A!"####0 (7%*::*%8((I &0   (  #2#%D"E%3264&+53264&#"'>32#"&/3264&+53264&#"'>32#"&'"####0 (7%*::*%8"####0 (7%*::*%82   (  #2#%   (  #2#%D 0%3733##5#3264&+53264&#"'>32#"&'>>x(((x"####0 (7%*::*%8p>(   (  #2#%F9%32#"&'73264&+53%3264&+53264&#"'>32#"&'6);;)!3 &*##^s"####0 (7%*::*%8):) d(   (  #2#%D?%&"632"&=4632264&"%3264&+53264&#"'>32#"&' 2#$);;R;;)6#2##2"####0 (7%*::*%8 #2##32#"&'|Ȁ0x"####0 (7%*::*%8   (  #2#%D!D$264&"'462"&547&6264&"'3264&+53264&#"'>32#"&'#2##2K;R;;R;K2##2#"####0 (7%*::*%80  <####     (  #2#%D?%26=#"&462#"'64&"2%3264&+53264&#"'>32#"&' 2#$);;R;;)6#2##2"####0 (7%*::*%8 #2##32#"&'x32#"&'!//!xxPP"####0 (7%*::*%8##P  (((    (  #2#%?8$4632&#"327#"3264&+53264&#"'>32#"&'|;) 4 )%##%) 4 )"####0 (7%*::*%8'R;&"#2#"&6   (  #2#%D2%264&+#5323264&+53264&#"'>32#"&'##<32#"&'ddq"####0 (7%*::*%8(((((   (  #2#%D ,%3##53%3264&+53264&#"'>32#"&'dd(q"####0 (7%*::*%8((P(   (  #2#%D 3733##5#264&"462">>x(((x#2##2K;R;;R`>(2##2#eR;;R; %73#53733##5#f(D>>x(((x3Ȕ#>(D#%3#5654&#"'>323733##5#‚Ƞ#1 (8%);A!>>x(((x((I &0<>(D"%0%3264&+53264&#"'>32#"&'3733##5#"####0 (7%*::*%8z>>x(((x2   (  #2#%3>(D %3733##5#3733##5#>>x(((xx>>x(((xp>(V>(F$%32#"&'73264&+53%3733##5#6);;)!3 &*##^>>x(((x):) d(>(D*%&"632"&=4632264&"3733##5# 2#$);;R;;)6#2##2>>x(((x #2##(D %3#7#'3733##5#|Ȁ0xx>>x(((x>(D!$/$264&"'462"&547&6264&"'3733##5##2##2K;R;;R;K2##2#>>x(((x0  <####  >(D*%26=#"&462#"'64&"2'3733##5# 2#$);;R;;)6#2##2>>x(((x #2##(D%35'73#5##3733##5#x>x(((xH<,\\l22t>(D *%2+5264&+3264&#3733##5#!//!xxPP>>x(((x##P  (((  $>(?#$4632&#"327#"3733##5#|;) 4 )%##%) 4 )>>x(((x'R;&"#2#"&t>(D%264&+#5323733##5###<>x(((x#2#x(;R;t>(D %3#3#53%3733##5#dd>>x(((x(((((>(D %3##53%3733##5#dd(>>x(((x((P(>(D&32#"&'73264&+53264&"462"6);;)!3 &*##^R#2##2K;R;;R|):) d(2##2#eR;;R;%73#532#"&'73264&+53f(D6);;)!3 &*##^3Ȕ#):) d(D,%3#5654&#"'>3232#"&'73264&+53‚Ƞ#1 (8%);A!6);;)!3 &*##^((I &0X):) d(D"9%3264&+53264&#"'>32#"&'32#"&'73264&+53"####0 (7%*::*%86);;)!3 &*##^2   (  #2#%O):) d(D $%3733##5#32#"&'73264&+53>>x(((x6);;)!3 &*##^p>(r):) d(F-%32#"&'73264&+53%32#"&'73264&+536);;)!3 &*##^z6);;)!3 &*##^):) d():) d(D3%&"632"&=4632264&"32#"&'73264&+53 2#$);;R;;)6#2##26);;)!3 &*##^ #2##32&"632"&=4632264&"‚Ƞ#1 (8%);A! 2#$);;R;;)6#2##2((I &0T #2##32#"&'&"632"&=4632264&""####0 (7%*::*%8h 2#$);;R;;)6#2##22   (  #2#%K #2##>x(((xf 2#$);;R;;)6#2##2p>(n #2##$264&"'462"&547&6264&"&"632"&=4632264&"#2##2K;R;;R;K2##2# 2#$);;R;;)6#2##20  <####   #2##323#7#‚Ƞ#1 (8%);A!Ȁ0x((I &0D")%3264&+53264&#"'>32#"&'3#7#"####0 (7%*::*%8Ȁ0x2   (  #2#%wD %3733##5#3#7#>>x(((xȀ0xp>(F%32#"&'73264&+533#7#6);;)!3 &*##^JȀ0x):) d(D#%&"632"&=4632264&"3#7# 2#$);;R;;)6#2##2Ȁ0x #2##32$264&"'462"&547&6264&"‚Ƞ#1 (8%);A!#2##2K;R;;R;K2##2#((I &0  <####  D"*<D%3264&+53264&#"'>32#"&'&264&"'462"&547&6264&""####0 (7%*::*%8#2##2K;R;;R;K2##2#2   (  #2#%  <####  D '/%3733##5#264&"'462"&547&6264&">>x(((x#2##2K;R;;R;K2##2#p>(  <####  F08%32#"&'73264&+53$264&"'462"&547&6264&"6);;)!3 &*##^r#2##2K;R;;R;K2##2#):) d(  <####  D$6>%&"632"&=4632264&"$264&"'462"&547&6264&" 2#$);;R;;)6#2##2#2##2K;R;;R;K2##2# #2##%26=#"&462#"'64&"2$264&"'462"&547&6264&" 2#$);;R;;)6#2##2#2##2K;R;;R;K2##2# #2##%2+5264&+3264&#$264&"'462"&547&6264&"!//!xxPP#2##2K;R;;R;K2##2###P  (((    <####  ?/7$4632&#"327#"264&"'462"&547&6264&"|;) 4 )%##%) 4 )#2##2K;R;;R;K2##2#'R;&"#2#"&4  <####  D)1%264&+#532264&"'462"&547&6264&"##<32%26=#"&462#"'64&"2‚Ƞ#1 (8%);A! 2#$);;R;;)6#2##2((I &0 #2##32#"&/26=#"&462#"'64&"2"####0 (7%*::*%8 2#$);;R;;)6#2##22   (  #2#% #2##>x(((x 2#$);;R;;)6#2##2p>( #2##$264&"'462"&547&6264&"'26=#"&462#"'64&"2#2##2K;R;;R;K2##2# 2#$);;R;;)6#2##20  <####   #2##3235'73#5##‚Ƞ#1 (8%);A!x32#"&'35'73#5##"####0 (7%*::*%8x>x(((xx(.<,\\l22F%%32#"&'73264&+53%35'73#5##6);;)!3 &*##^rx322+5264&+3264&#‚Ƞ#1 (8%);A!!//!xxPP((I &0##P  (((  D"/7?%3264&+53264&#"'>32#"&'2+5264&+3264&#"####0 (7%*::*%8z!//!xxPP2   (  #2#%w##P  (((  D "*%3733##5#2+5264&+3264&#>>x(((xx!//!xxPPp>(##P  (((  F#+3%32#"&'73264&+532+5264&+3264&#6);;)!3 &*##^!//!xxPP):) d(##P  (((  D)19%&"632"&=4632264&"2+5264&+3264&# 2#$);;R;;)6#2##2!//!xxPP #2##$264&"'462"&547&6264&"2+5264&+3264&##2##2K;R;;R;K2##2#!//!xxPP0  <####  4##P  (((  D)19%26=#"&462#"'64&"22+5264&+3264&# 2#$);;R;;)6#2##2!//!xxPP #2##32$4632&#"327#"‚Ƞ#1 (8%);A!;) 4 )%##%) 4 )((I &0R;&"#2#"&D"8%3264&+53264&#"'>32#"&'&4632&#"327#""####0 (7%*::*%8;) 4 )%##%) 4 )2   (  #2#%R;&"#2#"&D #%3733##5#4632&#"327#">>x(((x;) 4 )%##%) 4 )p>( R;&"#2#"&F,%32#"&'73264&+53$4632&#"327#"6);;)!3 &*##^J;) 4 )%##%) 4 )):) d(R;&"#2#"&D2%&"632"&=4632264&"$4632&#"327#" 2#$);;R;;)6#2##2;) 4 )%##%) 4 ) #2##32'264&+#532‚Ƞ#1 (8%);A!##<32#"&/264&+#532"####0 (7%*::*%8##<>x(((x##<(#2#x(;R;F&%32#"&'73264&+53%264&+#5326);;)!3 &*##^##<323#3#53‚Ƞ#1 (8%);A!dd((I &0X(((((D".%3264&+53264&#"'>32#"&'3#3#53"####0 (7%*::*%8dd2   (  #2#%O(((((D %3733##5#3#3#53>>x(((xddp>(r(((((F"%32#"&'73264&+53%3#3#536);;)!3 &*##^rddȌ):) d((((((D(%&"632"&=4632264&"3#3#53 2#$);;R;;)6#2##2ddȈ #2##323##53‚Ƞ#1 (8%);A!dd(((I &0X((P(D",%3264&+53264&#"'>32#"&'3##53"####0 (7%*::*%8dd(2   (  #2#%O((P(D %3733##5#3##53>>x(((xdd(p>(r((P(F %32#"&'73264&+53%3##536);;)!3 &*##^rdd(Ȍ):) d(((P(D&%&"632"&=4632264&"3##53 2#$);;R;;)6#2##2dd(Ȉ #2##/AA??AXZ~0_053327654&"!U;<**UvСvU*)=;U0_05332764'&#"!N+*Сi*8+{0`0 654'&#"2%&76  4TTRyzSTTTiik(kiikVvzRTTTTT!k(kiikki`0%64'&";2&76  ??AA??=XZiik(kiik/AA??BWXA?'k(kiikki`0 327654&"&76  U;<**Uviik(kiikvU*)=;Uqk(kiikki`0 %32764'&#"&76   +*iik(kiik*8+k(kiikki`0 !hРhh0`0 hhh0`0! h`0! 00h`0 4763"'&5!ikkiРkiik0`0 24763kiikikki0`0 !#2ikkiДkiik`0 &5#!"iikД7kki0`0 !hh0h`0 hhh0hh0`0476 &5! ik(kiiikؠkiikkki`02#%&763"kiikiik0ikkiik(ki0`h0 h00!0h`0%hhh0` hhh`h02#kiik0ikki0&5! iiik1kkih`0&763"iik7k(ki0`476 ik(kikiikh05!hhh0%!hhhh`!hhh`h!hh05!hh`0!hh0`!Рh`h0!h0`0!!hh0hhhh`0!!hhhhh`0!!`0!!hРhh0`0!!hhhh0`0!!hh`0!"(Ҡ(Җ`0 4'�# hif(iihX`0 52765!kihii`0 7&!3 hii4(kih`0hh0`Рh`h0!h000!0`h0h005hh`0!hh00`5!`h0h0`Рhh`0!hh000!00h`0hh005h`h0!h00`5!0`0!0`05!h0`0!hh0`0Р`0!hР0`0Рhh0`0!hh0`0!00`0 00`0!00`05h0`0 hh0`0!0Рh`01hh00`0 !00h`0! !hhh000`0!!hhh000`0 !0Рh`0!hh00`0!00h`0!hh0`05h`050h`0!hhh0`0!0Рhhh`01!hh00`0!!00h`0!!hh00`0 !0Рhhh`0!!!hhh000`0!!0Рh`0!1hh00h`hhh`hhhh0!h0h0!hh0h05hhh0%hhhh`%!hh`h5!hh05hhh0!hh0h`%!hh`hhhh0!h0h0%hhhh`hhh`h5!h`0!hhhh0`0!hh`0!`0!hРhh0`0 hhhh`0! hh`05!h`0 !hhhhh0`0 76%3-gfik(iiki`0  .#")Ԓki0הik`0 654'&#!ikןԓki`0 7&32765 jhki1)hgik0`0 %&#"76!4gk*_iД)0`0 27654'&'kihh*Ҡikji`0 32767!ikhi0kigg`0 7&!"$Дkigh4)ikhj`05!hhh0`0!hh00`0 hР`0 hh0`0 0`05h0`0!hh000`00`000`0 hР0`05 0h0`0!hh00`04!(00`0 0*`00`0 '&Ѡ(0`0- bbbfbbbbr 7'!!'UTUw0`0 %#7'373#hhhhhhhq hhY!hp880`07%088h`0 "!46$b`r 0Ò r`0 4&$#2Ò rb`hr`0 265!b`hrLÒr`0 3"$&LÒr0b`r `0 2!4& r`0rL`0 #2$6rL0rh``0 "$&5!Вrh`r `0 46$3"r  r``0 "#46$3Гr | r`0 4.#52 rr`0 52>53#rr`0 3"$&5r0r `0 "#46$3ЫީZr ֩ޫ r`0 4$#52vޫ r"Zr`0 2$53#"ZrF"r`0 3"$&5Z"r0ީZr `0  76'& &76  ^^\\^^\SK*ddzwFldlc(l0v 5!%5!%5!vvvFllllllh 5!%5!%5!hhhFllllll 53'53'53Fllllllq$!5!5!27654&#!5!hd>22`BhnNMMPl*ll675B`lNMMP52#276544# @11`BiSRp , l657B`lZY[pZv#264&"467632#"&'&"&462```kN*+[kN*+[$, ,  ```[kN*+[kN* , , ,7#"'4432767654'&'4#"-@SK"%H"> >ddzwg+)i525l l >" >(l0+g7125f,Z` 53#!!!!!! ZvlZlvl`v 5#533!5!3!5!ZZllvZl2lb lv0 53535!35!3Zl2lb ljlZl2bl Z0 3!%3!'533Zl bl2lZFvllZl_ 5#53%53#!!5!!5!ZZDZbСYmlZ2ll llv =!5!!5!b vlllDlD =353#5!llDlllDlZv %53!!2llllllDl`=2&%44'4WNT))Vr&90l"U ]{lgr/lZ`"#463!"%5ppF5%pp`v4434' Z5%pp%5pv02653#253!%5p5%pZ0333"&5Z4&pFpv&4p5!5!0FhZ`v0333Z00`44%"#463!.#5263"Z5%p%5p;nǡo%5pZ5%pNfqqe`4434' 63"&Z5%ppZW]9%5p\V`v4'34' Z-ape`v04434' 53&Z5%ppO%5p/aZ`v0&'33V^t {00F.#527&'4S ,W5oqžG~ _GD}LMlm 52&%4pOSFO䄴eS 52&471FQ[zwFF"0v5!5!vvFhh5!5!hhFh5353Fhv$4&#!5!2#!5!25%hpph%J5 644#52Z5%pp%J5Zv%327654'&#"&462-4 -4 4 -4 -ڞ43267654'4#""53+ ;PYzwg+)i525M ;!0+g7125f,Z` !#!!!Zv>Zv>`v 5#5!3!5!ZZ>vZ´v0 53535!3Z´"ZZ0 3!33ZZFv>hZ` 5#5!3!#5!ZZZРZZ´v5!5!5!>vFD535#5!DFZv%5#!´n`4474Z5%,.gzáI;%5<<Җ<<<Z< `0 #'#%# 555#5#%5#'5<<< `0 $(+3%3%3%5%5%5%5%5%5#%5#!5t\< 0\t000000\ĸ\0C.q.Z..Z..Z..Z..Z..Z.C.q0 !!5!!5!!5!!5!!5!!5!!5!!00000000F-------- `0 #5#5#5#3#3#3#73535'3Z<<J<<h<<h<<h<<<Z<0N<:<z<J<Җ<<Җ<<<0N´<<`0 '3335#3535Ҵ>NҴ<N>N`0 '! 5#5#'5<l0xx<0<`0 #7##%3533N>NҴ´Ҵ><N`0 35%35%5!7<<<<B3!535#53533533533530#3#35#35#35735#35#3535#35#35;----------------------F----------Z-------------Z------`h0.26:>BFJNRVZ^bfjnrvz~3!535#535#535#53533533533530#3#3#3#35#35#3535#35#3535#35#3535#35#3535#35#3535#35#3535#35#35;------------------------------Z------Z------F------------Z---------------Z------Z------Z------Z------Z------`0=AEIMQUY]aeimquy}3!535#5353353353353535#5353353353353#3#30!0#3#35#35#3535#35#3535#35#3535#35#3535#35#3535#35#35;------------------------------------Z---------F------------------Z---Z-------------Z------Z------------Z------"`0AEIMQUY]aeimquy}3!535#535#535#5353353353353353353353353#3#30!0#3#35#35#3535#35#35#35#35#35#3535#35#35#35#35#35#3535#35#35#35#35#35#3535#35#3535#35#3535#35#35;--------------------------------------------------------Z------F--------------------Z---Z---------------------Z--------------Z--------------Z------Z------Z------ h` #A35#35#35735#35#3535#35#35535#5353353353353#3#3I-----------------------F------------Z--------------Z---`0 +/37;?CGKOSW[_cg35#35#353#30!535#53533533533530#35#35#3535#35#3535#35#3535#35#3535#35#35535#5353353353353#3#3I----------------------Z-----------------------F-----------------Z------Z------Z------------Z--------------Z---h`0 #'+/37;?CGKOS35#35#3535#35#3535#35#3535#35#3535#35#3535#35#3535#35#35353#3#3#3#3!535#535#535#535335335I---------Z------Z---------------------------F------------Z------Z------Z------Z------Z--------Z-------------"`0 #'+/37;?CGKOSW[_cgkosw{35#35#3535#35#35#35#35#35#3535#35#35#35#35#35#3535#35#35#35#35#35#3535#35#3535#35#3535#35#35353#3#3#3#3!535#535!535#535335335335335335335I---------------------------Z-------------------k---------------F--------------------Z--------------Z--------------Z------Z------Z--------Z---------------------` #'+/37;?CGKOS35#35#35#35#35#35#35%35#35#35#35#35#35#3535#35#35#35#35#35#35'3353353353353353353353#3#3!535#53I---------------------Z-------------------0---F----------------------------Z----------------------------Z----"`0 [_cgkosw{35#35#35#35#35#35#353#30353353353353#3#3!535#535#535#53533533533530#35#35#3535#35#3535#35#3535#35#3535#35#35#35#35#35#3535#35#35#35#35#35#35I----------------------0--------------------Z--------------------F----------------Z-------Z-------------Z------Z------Z------Z------Z--------------Z--------------#`0 #'+/37;?CGKOSW[_cgkosw{35#35#35#35#35#35#3535#35#3535#35#3535#35#3535#35#3535#35#35#35#35#35#3535#35#35#35#35#35#35353#3#3#3#3!535#5353353353353535#53533533535I-------------Z------Z------------------------0------------------F--------------------Z------Z------Z------Z--------------Z----------------Z---------------------2`0 #'+/37;?CGKOSW[_cgkosw{735335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335%35335335335335335335353353353353353353353#3#3#3#3!535#535#535#53533533533533533533533Z-----------------------------------------------------------------------------------------------------0-----------------------------------Z--------------Z--------------Z--------------Z--------------Z----------------------------vZ----------------------h0!!h0h0!!hh00!!00`h5!!h`h0!!h00`0!!!!hhh0h`0!!!0h`%!!hh`0!!!!hh0hh`0!!hh00`0!!!00h`5!!0`0!!!hh00`0!!!hh0h00h`0!!000x03#xx0x@x3#xxx@x03#xx0x@3#xx@xx03#3#xxxx@xhxx3#xxx03#xx0Px53#xxxPx053#3#xxxxxxPx53#3#xxxxxhxPx053#3#xxxxxPx@3#xx@Px03#3#xxxx@xPx3#xxPx03#xx0 xP53#xxPxx053#3#xxxxPxXxx53#3#xxxxPxxx053#3#xxxxPxXx@53#3#xxxxPxhxx0 53#3#3#xxxxxxPxhxhxx53#3#xxxxPxx053#3#xxxxPxXx53#xxx053#3#xxxxXxx53#3#xxxxxx053#3#xxxxXx@3#xx@x03#3#xxxx@Xxx3#xx x03#xx0`x3#xx(x`x03#3#xxxx(xx`x3#3#xxxx(xXx`x03#3#xxxx(x`x@3#3#xxxx(xx`x0 3#3#3#xxxxxx(xxhx`x3#3#xxxx(xX`x03#3#xxxx(x`x3#3#xxxx(xhx`x0 3#3#3#xxxxxx(xhxx`x 3#3#3#xxxxxx(xhxhx`x0 3#3#3#xxxxxx(xhx`x@3#3#xxxx(x`x0 3#3#3#xxxxxx(xx`x3#3#xxxx(xX`x03#3#xxxx(x `xP53#xxP`x053#3#xxxxPx`x53#3#xxxxPXx`x053#3#xxxxP`x@53#3#xxxxPx`x0 53#3#3#xxxxxxPxhx`x53#3#xxxxPX`x053#3#xxxxP`x53#xx`x053#3#xxxxx`x53#3#xxxxXx`x053#3#xxxx`x@3#xx@ `x03#3#xxxx@ x`x3#xx`x03#xx00@h0!!h0h@0!!hh0@0!!00Ph@!!h@Ph0!!h0 P0!!!5!hhh0P0!!!0hP@!!hh@P0!!!5!hh0hP0!!hh0 P0!!5!0 P@!!0@P0!!!hh00P0!!5!hh0h0 P0!!00 `hP5!!hP`h05!!!!hhP`05!!!!hhhP`05!!!!h0P`h@!!h@ `h0!!h00`0!!!!hhh0 `0!!!0 `@!!!5!hhh@`0 !!!!5!5!hhh0`0!!!5!hhh0 `0 !!!5!5!h0 `@!!!@`0!!!!hh0`0!!!!hhh0 `0!!!0 h`P%!!hhP`0%!!!!hhhPh`0%!!!!hhhP`0%!!!!hh0P`@!!!5!hh@`0!!!5!hh0 `0 !!!!5!5!hhhh0`0 !!!!5!h0h`@!!hh@ `0!!!!hh0 h`0!!hh00`0!!!00`@!!5!@ `0!!!5!hh0 `0!!5!5!hhh00`0!!5!00`P5!!0P`05!!!!0hP`05!!!!0hhP`05!!!!00P`@!!!hh0@`0!!!hh00 `0 !!!!!hhh0h0`0!!!!h00`@!!5!hh0h@ `0 !!!5!5!hh0h0 `0!!5!hh0h00`0!!5!5!0h00`@!!0@ `0!!!hh00 `0!!!hh0h00`0!!000|h0!!h0h|0!!hh0|0!!00h|!!h|h0!!h00!!1!5hh00!!!0h|!!hh|0!)!hhh0h0!!hh00!!5!0|!!0|0!!!hh000!!5!hh0h00!!00h5!!hȴh05!!!!hhȴ05!!!!hhhȴ05!!!!h0ȴh|!!h|h0!!h00!!!hhh0h0!!!0|!!!5!hhh|0 !!!5!5!hhhh00!!!5!hhh00 !!!5!5!h0|!!!|0!!!!hh00!!!!hhh0h0!!!0h%!!hhȴ0%!!!!hhhȴh0%!!!!hhhȴ0%!!!!hh0ȴ|!!!5!hh|0!!!5!hh00 !!!!5!5!hhhh00 !!!!5!h0h|!!hh|0!!!hhh0hh0!!hh00!!!0h|!!5!|0!!!5!hh00!!5!5!hhh0䴴0!!5!05!!0ȴ05!!!!0hȴ05!!!!0hhȴ05!!!!00ȴ|!!!hh0|0!!!hh000 !!!!hhhh0h0!!!!h00|!!5!hh0h|0 !!5!!5hhh000!!5!hh0h00!!5!5!0h0䴴|!!0|0!!!hh000!!!hh0h0h0!!00`h5!!h`h05!!!!hhд`05!!!!hhhд`05!!!!h0д`h|5!!!!hh`h05!!!!hh`0 5!!!!1!5hhhд`0 5!!!!!hд`|5!!!!hhh`0 5!!!)!hhhhд`05!!!!hhh`0 5!!!!5!h`|5!!!!h0`0 5!!!!!hhh0д`0 5!!!!5!hhh0h`05!!!!h0`h5!!h`h05!!!!hhд`05!!!!hhhд`05!!!!h0д`h|!!h|`h0!!h00`0!!!hhh0`0!!!0`|!!!!hhh|h`0 !!!!5!hhhh0h`0!!!!hhh0h`0 !!!!5!h0h`|!!!|`0!!!!hh0`0!!!!hhh0`0!!!0`%!!1!5hhȴ`0 %!!!!!5hhhhȴ`0 %!!!!!5hhhȴ`0 %!!!!!5hh0hȴ`| !!!5!!5hhh|`0 !!!5!!5hhh0`0 !!5!!!5%!5!hhhhh0`0 !!!!5!!5hh0`|!!1!5hh|`0 !!!!!5hhh0h`0!!1!5hh0䴴`0 !!!!5h0h`| !!5!!5h|`0 !!!5!!5hhh0`0 !!5!5!!5hhh0䴴`0 !!5!!5h0䴴`5!!!ȴ`0 5!!!!!hȴд`0 5!!!!!hhȴд`0 5!!!!!0ȴд`|!!!!hh|`0!!!!hh0`0 !!!!!hhhh0`0 !!!!!h0`|!!!!hhh|h`0 !!5!!!hhh0h`0!!!!hhh0h`0 !!!!5!h0h`|!!!|`0!!!!hh0`0!!!!hhh0`0!!!0h`%!!hh`0%!!!!hhhдh`0%!!!!hhhд`0%!!!!hh0д`|%!!!!hhh`0%!!!!hhh`0 %!!!!1!5hhhд`0 %!!!!!hhдh`|%!!!!hhh`0 %!!!)!hhhhhдh`0%!!!!hhh`0 %!!!!5!hh`|%!!!!hh0`0 %!!!!!hhhh0д`0 %!!!!5!hhh0h`0%!!!!hh0`5!)!hhhȴ`0 5!!!!!!hhhhȴ`0 5!!!!!!hhhhȴ`0 5!!!!!!h0hhȴ`|!)!hhh|`0!)!hhh0`0 !!!!!!hhhh0h`0 !!)!hh0`| !!!5!!!hhhh|`0 !!!5!!!5!hhhhh0h`0 !!!5!!!hhhh0`0 !!!5!5!!!hhh0`| !!)!hh|`0 !!!)!hhhh0`0 !!!!!!hhhh0h`0 !!)!hh0h`%!!hh`0%!!!!hhhдh`0%!!!!hhhд`0%!!!!hh0д`|!!!!hh|h`0!!!!hh0h`0 !!!!!5!hhhh0h`0 !!!!!h0hh`|!!hh|`0!!!hhh0h`0!!hh00`0!!!00`|!!!|h`0!!!!hh0h`0!!!5!hhh00h`0!!!00h`5!!5!`0 5!!5!!!h`0 5!!5!!!hh`0 5!!5!!!0`|!!!5!hh|`0!!!5!hh0`0 !!!!!5hhhh0h`0 !!!!5!h0`|!!5!5!hhh|䴴`0 !!5!!5!5hhh0䴴`0!!5!5!hhh00`0 !!5!5!5!h00`|!!5!|`0!!!5!hh0`0!!5!!hhh00h`0!!5!00`5!!0`05!!!!0hд`05!!!!0hhд`05!!!!00д`|5!!!!0h`05!!!!0h`0 5!!!!1!50hhд`0 5!!!!!0д`|5!!!!0hh`0 5!!!)!0hhhд`05!!!!0hh`0 5!!!!5!0`|5!!!!00`0 5!!!!!0hh0д`0 5!!!!5!0hh0h`05!!!!00`5!!!hh0ȴ`0 5!!!!!hh0hȴд`0 5!!!!!hh0hhȴд`0 5!!!!!hh00ȴд`|!!!hh0|`0!!!hh00`0 !!!!hhhh0`0!!!!h00`| !!!!!hhh0h|h`0 !!!!!5!hhh0hh0h`0 !!!!!hhh0h0h`0 !!!!!5!h0h0h`|!!!!h0|`0 !!!!!hhh00`0 !!!!!hhh0h0`0!!!!h00`%!!5!hh0h`0 %!!5!!!hh0hh`0 %!!5!!!hh0hh`0 %!!5!!!hh0h0`| !!!5!5!hh0h|`0 !!!5!5!hh0h0`0 !!!!5!5!5!hhh0hh0`0 !!!!5!5!h0h0`|!!5!hh0h|`0 !!!!5hhh00h`0!!5!hh0h00`0!!5!!0h00h`|!!5!5!0h|䴴`0 !!!5!5!hh0h0䴴`0 !!5!5!5!hh0hh00`0!!5!5!0h00`5!!0`05!!!!0hд`05!!!!0hhд`05!!!!00д`|!!!hh0|`0!!!hh00`0 !!!!hhhh0`0!!!!h00`|!!!hh0h|h`0 !!5!!hhh00h`0!!!hh0h00h`0!!!5!0h00h`|!!0|`0!!!hh00`0!!!hh0h00`0!!000t&0264&+#53235'73#5##32644+#5X##<32x P## P##hx P## P##Ƞ#1 (8%);A!(  #2#(  #2#(  #2#(  #2#p((I &0t7Z#";2+53264&+"&463#";2+53264&+"&4633264&+53264&#"'>32#"&'x P## P##hx P## P##"####0 (7%*::*%8(  #2#(  #2#(  #2#(  #2#   (  #2#%t%A264&+#5324632&#"327#"#";2+53264&+"&463x##<32(#2#(;R;P!//!P(&Ƞ#1 (8%);A!dd##dd);;U(  (#2#P((I &0t7?#";2+53264&+"&463#";2+53264&+"&463%3##5#x P## P##Xx P## P##P(P(  #2#(  #2# (  #2#(  #2#(t+7$4632&#"327#"4632&#"327#"3353#5##;) 4 )%##%) 4 );) 4 )%##%) 4 )(x((x(R;&"#2#"&+R;&"#2#"&PPPPv %37373#'#%5373#5'J+7&&7+V&&HH(<h0`0!!75#'#37350´ZZZZ00hZZZZ`0 7!!!'!!h>Z0ZZ0`0!5!!!ZZ0F0'88880 3#'7'PP8p88 %!5'770p8PPP80 %353!'8 P 88 8g0 &54632&"iiӕi9RR7ii9RRi0 '64&"'632g9RR9i79RR9iӕi` 7264'7#"i9RR9iӕ79RR9i`g 27#"&547PR9ii9--------------------------------------------------------0------------------------------0----------------------------------------------------------------------------------------------------------------------------------------------------------------`0!!!vZ0`0%!!0hh0`0%!!h0|h0`07!%!!h0h0`0!!!0|0H ''73#3H8HH8@x 8HH8`PPH~ 7''7LxL8HH8p+8HH8H ''75#53#5H8HH8hx 8HH8PpP0462"#"&'732654.56**=2<2uSKp PC+2F2<2I**<,6$6L?/ ,6$h0#?CGKOSW[_cgkosw{53535353##5353535353####53535353535353######3#1#5#5;#1#5##5#5##5;#1#5##5##5#5##5##5!3#h-----------------------------------Z-----Z-------------------Z------Z----------Z---------------------------------------------h`#?CGKOSW[_cgkosw{%53535353##5353535353####53535353535353######3#1#5#5;#1#5##5#5##5;#1#5##5##5#5##5##5!3#h-----------------------------------Z-----Z-------------------Z------Z----------Z---------------------------------------------h0#?CGKOSW[_cgkosw{53535353##5353535353####53535353535353######3#1#53#'#5#5##53#'#5##5#5##5##53#'#5##5##5---------------------------------------Z------------------------Z------Z----------Z--------------------------------------------------`h#?CGKOSW[_cgkosw{=3535353##5353535353####53535353535353######3#1#53#'#5#5##53#'#5##5#5##5##53#'#5##5##5---------------------------------------Z------------------------Z------Z----------Z--------------------------------------------------`0!!"&6hh00*`02#!hӕ0%7!"&5463!%*PppP rj8(P(8@ #!575'5!2/57@pPPp*p(8 P 8(Psr%!"&5463!'#3PppP ppx8(P(8X8pp8@?5#'5!2#!5735p0PppP0pp8p8((8p8%#5!"&5463!!PppP 00``8(P(8@%!5%#!5!5!!2 @pPPp00(8` 8%#53#!"&5463!!``PppP 00``8(P(8`@ 53#%!535#5%#!5!!5!2`` @pPPp0000(8`P`8%3!"&5463!673PppP o~X8`8(P(8a*8@ #=632%#!535#534>54&#"5!2Tw_'pPrrrTfTNjPp (8`88 %&5a8 !!!"&5463 PppP08(P(8@ #!5!5!5!2@pPPpp(808@75!5!5#5!2#!5` `PppP 0`8((8``0 5!!5!!5!!!!!!00000PPPPpPP(`0 #+37;?CGKOSW[_cgkosw{!!!53##5#53##5#53##5#53##5#53##5#53!3#1#5##5##5##5##5##5#5##5##5##5##5!3#1#5##5##5##5##5##5#5##5##5##5##5!3##533#'#5#53##5#53##5#53##5#53'#53#Zv0Z---------------------------------------------------------------------------------------Z----ZZ-------------------------------------------------------------------------------------------------5`0 #+3;CGKOSW[_cgkosw{!!!!53##5#53##5#53##5#53##5#53##5#53##5#53##5#53!3#1#5##5##5##5##5##5##5##5#5##5##5##5##5##5##5!3#1#5##5##5##5##5##5##5##5#5##5##5##5##5##5##5!3##533#'#5#53##5#53##5#53##5#53##5#53##5#53'#53#00v-----------------------------v-----------------v-------------v-----------------v-------------v------------------------------Z----0ZZ---------------------------------------------------------------------------------------------------------------------------------(`0 '/7;?CGKOSW[_cgkosw{!5!!5!#533#'#5#53##5#53##5#53##5#53##5#53#5##5##5##5##5##53#'#5##5##5##5##5#5##5##5##5##5##53#'#5##5##5##5##5#533#'#5#53##5#53##5#53##5#53'#53#v0v------------------------------------------------------------------------------------------Z----Z0Z----------------------------------------------------------------------------Z-------------------------,`0 '+/37;?CGKOSW[_cgkosw{#!##533#'#5#53##5#53##5#53#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#533#'#5#53##5#53'#53#ZZZ-----------------------;---------------;---------------;---------------;--------------------Z----0v----------------------------------------------------------------------------------------Z-----------------=`0 '+/37;?CGKOSW[_cgkosw{3!3#533#'#5#53##5#53##5#53#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#533#'#5#53##5#53'#53#ZZ-----------------------;---------------;---------------;---------------;---------------;---------------;--------------------Z----00----------------------------------------------------------------------------------------------------------------------------Z-----------------,`0 '+/37;?CGKOSW[_cgkosw{!3!3#533#'#5#53##5#53##5#53#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#5##5##5##53#'#5##5##5#533#'#5#53##5#53'#53#ZZ0Z-----------------------;---------------;---------------;---------------;--------------------Z----Fv0-----------------------------------------------------------------------------------------Z-----------------`0 #'+/37;?CGKOSW[_cgkow!!!%3#5#53533#53533#5;#5#53!53353353353%#5353353353%53353353353%#5353353353%3#5#53533#53533#553'#53Zk------------Z----------------------------------------------Z----0v--------------------------------------------------Z-----------------`0!!!!00FZZ`03!3vZ0Z00@`" #'+/37;?CGKOSW[k %#5353%3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#535#53353##5353535353####%353##'3#'3#'3#'3#!#5##5##5##5##5!3#1#5##5##5##5##5##5#5##5##5##5##5##5!3#1#5##5##5##5##5##5##5#5##5##5##5##5##5##5!3#--0---Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z----Z--Z--Z--Z--Z--Z--------------------I----Z--Z--Z--Z--h-------------------------------------------------------------v---------------------------------i----Z---------------------------------------------------------------------------M`0 #'+/37;?CGKOSW[_cgkosw{ #'+/37a3#'3#'3#'3#'3#'3#'3+53#5353%3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#3#'3#'3#'3#'3#'3#'3#%3#53535353##3533533533533533533535335335335335335335#5##5##5##5##5##5#5##5##5##5##5##5!3#1#5##5##5##5##5##5##5#5##5##5##5##5##5##5!3#13#3!535#5335335335335335335335v--Z--Z--Z--Z--Z--Z--Z---0---Z--Z--Z--Z--Z--Z--I--Z--Z--Z--Z--Z--Z----Z--Z--Z--Z--Z--Z--v--]-------------------------------------------------------------------------------------v-----0----------------0---------------Z---------------------------------Z--------------------Z--------------h------------------------------------------------------------Z--------------4`0#'+/37;?CGKOSW[_gow  !53535353##5353535353####35335335335335335335%3533533533533533533=3##5#53##5#53##5#53##5#53##5!3#1#5##5##5##5##5##5#5##5##5##5##5##5!3#1#5##5##5##5##5##5##5353#3#3!35#5353353353353353353355##5##5##5##5##5##5#------------------------------------------------------------------------------------------------------------0-------------------------------Z------Z------------------------Z------------------------------------------------------------------------------;-x73# 264&"462"1QzFdFFdvvvzf wE^^^ƍƍz77%5\*1=>z%5Ф*\3=1z7?5%5RRI.R.1=L3=1(,jKY7"'&5476767&547632'&7674'&#"2#"'3&547632'"676'&#&'&'&'#&=47632'"676"'&547>7&767"'&7&76320#"'&7654766767676'&'&'&'; 6     )+     A  .   4 z B        )   !-$ .&)  , 6 *     %   !C  =- $  S  ! # [  "     E*   7.    7A   40{ %7'77'77%77''7`````````````````𰈈777777877777f777eNOfNOfOOfN0`0 %%5757'h88Ph oooooo D '+/'75'5'75/'5'5757/735'``````````````t```(``8877o88o7n7778n7Z777n8oZNZZNZN7o88o70`0,<?Bv#5'#53#5#353#535353###5353535###75375353#77#5##53#53#353535353#####35353535353%#5'3#35353#5'###3535353###5353535####75375353%####535353#%##353#'#%%---------------------- (-- -------------d--N -----------------------rU88+-$ -- %-------$ --,%-- (p' ------------------: '+----- --,-----------$ ----- ----$ --Ah0w0 % %0p(NƝ:Ɲ:q''7'7''775'784M7GG7M4883xG7NxxN7Gx38]22>7632;2>?#"'./654&+"+"'./676=4&+"&547676=64&547654'#"'&'&547#"/&5;2326=46;2;>462"i% * #%   ! ' 8& 9+   <%. *!+7 &D]$7*." <' <'"%&> (  7   ) )0!9,x&'+0 & (/I '%. +x!9, E #R!' ."  "$0k(2(%>& 9v  `0 #############дxZ<00000000`0 3333333333333xZ<0000000`0;FV^ks{#"'#"&54767&'&547&54767&'&546326324'6>767&'767&'767&'.7"654?&#".'>>7.'27/74'32'654'3!!S##'!%%!'##'!%%!' ! d  &&  & && & &&  BH !A! H !(h@X#((((#  '!!'  #((((#  '!!' J"  && &&&&& 3 ""  "00`0;CPXemu%&547&54767&'&54632632#"'#"&54767&7>7'67&'.67&767&'27/74'32'654'74'6'"654?&#".'#!!}##'!%%!'##'!%%!' ! 2d &&  & && & &&  BH !A!  H !*(8#((((#  '!!'  #((((#  '!!' J" 2 && &&&&& 3 ""   "J00`0 ###########xZ<0000000`0 #3#3#3#3#3#3<<Zx00000 (`0$/7?OWgo707.#"'?"5470'47&7&547'432&72/6&'67>&'67.'&'67'>77&'67654&#"&#"32732654'&'67654'654!!2!=/ !H!=5  &&  & && &  &&  `2 !'!%%!'##'!%%!'##(hx2", "",0 && &&& && !2 "'  '!!'  #((((#  '!!'  #((((#% @`0&19ANVfn0&547'432&72'.'6.'>7>7.#"'?"5477.'&'67'&'67&'67>47&32732654'&'67654'654'&'67654&#"&#"!2!= / !H!=5  && & && &  &&  `2 !'!%%!'##'!%%!'##(h2",  "",0 &&&&& && 2 "'  '!!'  #((((#  '!!'  #((((#0 ##5!##PPpPPp 7;&=#7533#;!"&=#5353/!fP/!xB^P!/&*PxxP!/P^BPxx`0!%!!P000P0 `0'/7?6462"$2"&4!%!!$462"462"2"&42"&4462"#2##2@2##2#00#2##2#2##22##2#c2##2##2##22##2#x#2##20P02##2#c2##2##2##2c#2##22##2# `0#'/7?G462"2"&4&462"$2"&4!%!!$462"462"2"&42"&4,#2##22##2##2##2@2##2#00#2##2#2##22##2#c2##2#O2##2##2##2n2##2#x#2##20P02##2#c2##2##2##2c#2##2 `0#'/7?GO462"2"&4&462"$2"&4!%!!$462"462"2"&42"&4462",#2##22##2##2##2@2##2#00#2##2#2##22##2#c2##2##2##2O2##2##2##2n2##2#x#2##20P02##2#c2##2##2##2c#2##22##2#$`073264&#">32#"&$7ERvvRE7,jӕj,,vv,\pp`0&#"327#"&6327ERvvRE7,jӕjd,vv,\p*pxX0"264&"4623#''75#535.@  hFdF-#ȼ88#-  (2FF2&> /P?88?P/ >gi0%(264&"4623###5##5#7#535.3@  hFdF-#ȷȉPPPȷ#-x?~  (2FF2&> /PPPPPP/ >?(`Y0 4NZy%'57'#'7'77#'7'''77'7''777/67.'&'??7''7'7>775&'>7/.7'77''%??/>7'.7'77''.'67.'.'?75'7''7'7'67.'/>7?'7''7'7l E( \5 9, fFG$?!2XFMQ=&$ )(1 T    #* !      "  4   $" ''/     #l11'OT $ # JXZ;V7 @=80J di^ # 1 /.>()ST.1PN   3 #97 :;P /!43 67'#- BB%(@-! BC%(@];05j2'#"'.54743232654'&'&547'7&546327654&'"543#"&54654'7#"&547632;3/654'4'#"&'4&5432'&#"7654'&'4&547'7.5467,"   !"3 "!   7' ,  !, ")-   ,* ,a+ +B3 $08# " 54!!'4,G&"( 0 7F-9(!*# $2,!'5,!?+6/- %) (&0>+#2m+0J##"&5473264'3254'&#"326732754'262>=.#"654'#+&'"7654'&'#"&'&547&54632242632&'>7 B# *( "?"*   <' U $e + $+*CZ/ + i ,2bJ]= .  *  7.#    $)P:=YS)?< 1-& &1)>H %VTcyZ.9?;eH 0",3GV\p%#"&#>&'63632#"'#"&54632%&'>77#"'6632#"'#"&54632&5472632&547#"&54632632#"B"B. 4[3 ,++ %0 B( :1!&:59@G? &2!1E!!&76(61 KVV /%43sB02N5!Y MKz@;)3MR2 ), >5 &\2'C4'6V`!0 ).38IOTY^cin{7#"''7&5'76?67054'#"03267'?''7&'&/6?7#"''7&57'767'7'77''326754'#"7'6'&'67'7'#"''&57'767'677054'#"326'7'77./76?.,'H+)  $ / 8/  .9'H*N0 -,$  * [H-48$'(**A-5  0-,:$ %(:  H6 ;6 f 3"'"WW J&[q$(>  %s8,.pl G6 65[q $() :WW -""sg T,?|j!X  Hl 6Y7sf (" B'[:3 - G % B=\ `05Ok+7";3276='&'&"5654'&#"3254'&6'&#"32654&/676326?674+"%2#".'>7#"&546?&547632765654#"#"54732632"54654#""63267654&/72>764'4#"72#".'>7#"'&546?&54726326143654#"#"54732632#"54654#"62632#"'&'#"'&546?".54632"45.#"#"&4632&54;2+&=4+"&54"##"32>?6754'&>. :!2 -B   -2 2&  **' - + "2 00$  )  /M2 0  /= ""> ) 2). ;/8  3":ah2 _7$ 6*!)>4  -+6 5  s* ##7  K3$! U 8 &?/# 3  '-)" ?, 1%{'  f+ %"#%! ")#+)#&'$;  /!/C06j ) * 3 +).0& ' "(-*;3.( %E  7'6}E4  2 ;$  !&  /1 ?0 N: 5 7>,[ d`0F462"#3##!#"/&5463!/"45'4#&=7574754257##"&54?634L44L:6p\%  c  \@Q Z L44L4 FnF{'  c {  ` 2+537653232+"' ׯr Pd  \FUF Z`v0!ZŠ`0 !!575'57!!'3#0NPP0PPPPPdP???9;Bx9,`0 7''!!?qBŚx0x*,(0`0 7'!#!7!!8P0\8 0`0 5!!!!!!!!!!00000UPPZZP!!'8188P8F:d$462"&462"&462"************wL?378P8\818L'#'7L8P8481σ80!!00Z !3!'8P18\8@p8`v0!!v00`0 5!5!%#5!5! !!iZZhZZvZZZZZZZZ`0 !5!573'!! 5!5!ZZ90ZZZZZZZvZZZZ`0#37# 33ZZZZZZ"ZhZ`0%3#'53 ##vZZZZZZnZ5!!0P`03!!Zv00ZP'7!5!'781σ88P8`0 #'+/37;?CGKOSW[_cgko5335335353353353353533533535335335335353353353533533533535335335353353353353gggfgggggfgggggfgggggfgggggfgggggfgggggfgggggfgggZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ`0 #'+/37;?CGKOSW[_cgko#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5iggfggigggfgggiggfggigggfgggiggfggigggfgggiggfggigggfgggFZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZP 7!3#'#!P9Ή0PyPP@ 1!5'!5!!09 g9Pgv`03#vZZ00`0 hh0h`0!!!!00FZZP %3##%3#5#33#'3#53PP@PPPPP`06462"!5!!5FdFFd0vdFFdF0ZZ`Z03#ZZ00i;&#"'>32327#"373#'#T-FK+)&-FK+)PrrPP ((&* ((&*3Pgi;&#"'>32327#"373#'#T-FK+)&-FK+)PrrPP ((&* ((&*3PgP0 3333!PPP ppPP033#533!53#PPP PPHhPHPPh0; 3373#'&#"'>32327#"88Pxxd-FK+)&-FK+)pxx ((&* ((&*P;1!#54&"#54&"#3632632%&#"'>32327#"P/B/P/B/PP&*I//IB^-FK+)&-FK+)!//!!//!66^B ((&* ((&*P 3353#5##'"&463"PPPPPPPccB^^ഴ PPƍP^^P(4632#54.#"#34632&#"327#"$dP +PPpvR2FF2RA: )J.nvSFdFSP+"&532654.5462#4&"73353#5##2<2FdFP 2<2FdFP PPPPPPT'?/:RR:##'?/:RR:##s P.#"32+53264&#"&4634632#54.#"#3P2FF2xx2FF2$dP +PPP FdFP FdFO: )J.P3###%3353#5##PPPP@PPPPPPPpP P(7;#"&=#53533#74632#54.#"#3/!((B^PPPPP$dP +PP!/P^BPxxP: )J.P0 )33#5330 PPPphPHP %"&463"74632#54.#"#3@ccB^^$dP +PPPPƍP^^: )J.P4"&532654.5462#4&"4632#54.#"#32<2FdFP 2<2FdFP @$dP +PPT'?/:RR:##'?/:RR:##,: )J.P3###4632#54.#"#3PPPP$dP +PPPpO: )J.C6DR`2;2+".'.'#"547654&546326?6"&54765427#"'&=>324&#"267#"54;326754&'.54>7272 =D!#1  1 R   CH  " &2# , )  $* JO%7"  %J 2a R$8 MIz  2/^ 8>EAO$- "*( 9  '   " )*Ka 373#'#373#'#(\9Px9\(((\9Px9\((\\Px\(4(\\Px\(4D %3#3#53373#'#ddH(\9Px9\(((((((\\Px\(4D'%#";2+53264&+"&463%373#'#0x P## P##(\9Px9\(((  #2#(  #2#\\Px\(4t '>%3#3#535##";2+53264&+"&463'"&4632&#";5#53x((x((dx P## P##);;) 3 (%##62Z<(x((x(  #2#(  #2#(;R;&"#2#(i 0 #'+/3%3#'3#73#'3#3#'3#'3#%3#'3#'3#%3#'3#'3#PPPPPPPPPPPPPP@PPPPPP@PPPPPPPPPPPPPPPPPPPPPPPPPPP05!#3#3!535#535PPpPPPPdPPPPd}S !#5#53#'373PPP--P-P$llܔDDDP0 3#&264&"462"PPx^^^ƍ@^^^ƍƍP0 3373''P88Pุ PP*$4&"#54&"3#535.546326323#520/B/P/B//!P%+^BI//IB^+%P!dFF2PP2FFdFPvDDvR7[PxX!#"&54675#264&"xE[vv[ExFdFFdPS Y9B^^B9Y SB//B/`0'".#"'>32326=#"&46;326?5#"h8qWD#D[5/*2FIWC]uSv."Px2((:),5PF2OOiiRvT:2d`003#3#".#"'>32326PPPvR8qWD#D[5/*2F0PHhRv((:),5PF`0'%#".#"'>3232654&+"&46;#";20vR8qWD#D[5/*2F0HH02F(Rv((:),5PF25YfYP*$*^`0%26=#"&=3326?53#".#"'>32h2FIWC]P."PPvR8qWD#D[5/PF2OOiK*:2Rv((:),5Px %3#7#73#79P"Y{1SGP"=)P $%3#7#3#5>54&#"'>329P"-B2**; 0C-2FN'GP"00,'- %. QQ .%3#7#3264&+53264&#"'>32#"&'9P"P(****; 0C-2F$$F2-DGP"5"0%. !&%5-!P %3#7#3'733##5#9P"`_"001GP"`0<<V !%3#7#32#"&'73264&+539P"KB2FF2'? .3**rGP"08P8%!(0P$(&#"632"&=4632264&"3#7#* (2FFdFF21$*<**<9P" 8P88(`(8((GP"x!(326=#"&462#"'64&"2%73#7* (2FFdFF21$*<**<P"Y{1S= 8P88(`(8((P"=)P!;326=#"&462#"'64&"2%3#5>54&#"'>32* (2FFdFF21$*<**<P"-B2**; 0C-2FN'= 8P88(`(8((P"00,'- %. QP!%0326=#"&462#"'64&"2%3'733##5#* (2FFdFF21$*<**<P"`_"001= 8P88(`(8((P"`0<<V!8326=#"&462#"'64&"2%32#"&'73264&+53* (2FFdFF21$*<**<P"KB2FF2'? .3**r= 8P88(`(8((P"08P8%!(0P!(326=#"&462#"'64&"2%3#7#* (2FFdFF21$*<**<P"9= 8P88(`(8((P"P!7?C264&"'462"&547&6264&"326=#"&462#"'64&"2%*<**$264&"462"'73#73264&+53264&#"'>32#"&'*<**8>4:R&F2(8( FdvvvR:4>8>"dF (8(2F@ 2#'##3264&#B^S>p@PP".."E3/CPP$0#";2#!5!264&+"&4632FF22FF2P FdFP FdF0!###PP@075326=3"&PFdFPvv2FF2RvvI!#332ZZ; 3733#'#;WoL6LoW4MM4phh #'#7'37hpppȏȏgi373#5grrPٷ0 !!!5!p8P80 735'73#5##264&"462"&xȷ"PPx/B//B^^^^xVdd""(1GG12FFi;&#"'>32327#"373#'#T-FK+)&-FK+)PrrPP ((&* ((&*3Pg0; 333#&#"'>32327#"8P8d-FK+)&-FK+)p ((&* ((&*0?3#3#3#5##3xPPxxPxxٷPPPPPdd/x0 3#!!!%7@p9@PPPPP9P#$264&"462"264&"462"*<**nnll32644+264&+  .4&<0. *&4 "T4632&#"327#"U;*G24(88(42G*;EvU-% +8P8+ %-3264&##32`(88(;UU8P8 UvU 3#3!! <0T0 0 3##!0 <0 0#53#"&4632&#";T;UU;*G24(88(T\0UvU-% +8P8 3353#5##0000ll  3#3#535# 00000003##"&'7326=#P0F2'> 0.*00x2F-$)*x 373#'#0DxDH0xH>33!00 7373#5'"nn"0`` nn`` 7353#'"0" 264&"462"8P88PhUvUUvP88P8vUUvU32644+#(88(0`(08P8`  7654&"327&462'#"F"18P88( UvU%6";%;P"0"(88P8 vUU;7*6": 2#'##3264&#(82%aD`V008(%6a`` 0`(!2654.54632&#"#"&'7P'9KZKU;0O2B'9KZKU;0O2  )#1-% + )#1-% +!##5# x0x0326=3"&508P80UvU(88(;UU;%#373x s3PP3  37373#'#4I%"%I4l"%%"dddd %#'#7'373DnnDDnnDnnnn373#5DnnD0nn !3!57# "0" 7'#5'7'753DDDD0DDDD0(*''*(OO(*''*(O!!7P"P" ''7'7"gg"gg"gg"g"gg"gg"gg"g 3#53#3#P0000` 0000 3##5##5#000000@ 3#33#535#P00````@0000735'#73#5##RnDn00&R>nnll732644+264&+  .4&x<0. *&4 "T4632&#"327#"U;*G24(88(42G*;#vU-% +8P8+ %-73264&##32`(88(;UUx8P8 UvU 73#3!! x<0T0 0 73##!0 x<0 0#53#"&4632&#";T;UU;*G24(88(T 0UvU-% +8P8 73353#5##0000ll  %3#3#535# 0000000%3##"&'7326=#P0F2'> 0.*00x2F-$)*x 7373#'#0DxDH0xH>733!00 373#5'"nn"0``x nn`` 353#'"0"x 6264&"462"8P88PhUvUUv@P88P8vUUvU732644+#(88(0x`(08P8` _ 7654&"327&462'#"F"18P88( UvU%6";%;"0"(88P8 vUU;7*6": %2#'##3264&#(82%aD`V008(%6a`` 0`(!2654.54632&#"#"&'7P'9KZKU;0O2B'9KZKU;0O2H )#1-% + )#1-% +7!##5# x0x07326=3"&508P80UvU(88(;UU;#373x s3PP3x  737373#'#4I%"%I4l"%%"dddd #'#7'373DnnDDnnDxnnnn7373#5DnnD0nn 7!3!57# Ψ"0"%7'#5'7'753DDDD0DDDD0Y(*''*(OO(*''*(OG!P"P"w %''7'7"gg"gg"gg"g"gg"gg"gg"gx 3#53#3#P0000`H0000x462#;#"7."FdF%``2v%.%2dFF20y3%}Q|({`0 3##53#573#'3##5#535@PPP𠠠PPPPP0PPPPPPPP-`v0 !3!#5!:10M:` !73'3''!:0gZ-- O:KgZ---u kW &E%3#5# .'#53./?>76327 7;55&'&'&#"32?3 Zg[P10[h  4%0/$+$ &  l-[Z+.-  4,):$ & &  --`v0 !!73!#::00*lZZ--Z--Z---F--v*$^^$*-----`9 %-SZc.'#535737533#3#53767#!5'#'#34.'.'##"'.'#75735#5#<c><E-:m qCQ--QZ:Qx C Z-GI , (C:5, "% *DpccF8(I*-: pC:Q-ZZ@Q:ZP -(   8 =!h iD:dc`0 !%#!3!33%!#55#!5#%5#ZZ[gZ hZ->-v-nZ;g-u ->hZZZZZZ`DHLT\dl%2#"'.'&547632676654&#"#"'&'&54>7654&#"32/7'"&462&"26462"&4264&"+\57H)F<,3,+0+\@v 5\%B'  $A7 1B"Qt8HZ ZZZ Z8((8(;  8((8(;  n\+0+,3+ ? K, P LU %4%U  O'#3!#"/&4?622764'&"----V,{{{{F(\\\\YYY`#6462"6264&"3#3#'7''7'7FdFFd   h\98pdFFdF  P(P.99ɪ `) "&*.26!!!'77!!5!7#53#53#53#53#53%#53#53#53202 J>Z--Z--Z----Z--;------Okh;--------ZZ--  #'+!!!#!!%5!%#53#5353%#53#53#530-´>h;------k--Z--Z--lllh.Z,,,....Z`0%26<HYimquy}#"'&'#3676232436=4'"4'&+767654'6'32''7765"'&'327676=4'&'#533#73#7#533#73#73#73##53I;LT?NcDF  FDCF a?X:.< 3X" 695($33)9C3 CD 3?YXC 55 C(--,,C--q..--Z--C..--C..D:Z+//+-------------------------------->>------------------>------------------>---------.,,..,h,.----------------------------------------------------------------------------------------- !3573!5'#'#!'!i:힕:-_c -t)pC|:;M:- : -`00'#53000P`0 '754&"26535.=3354623533"&=#26=#  gPPFdFPPgPFdFPvvPXPSi((2FF2((iSP2FF2((RvvR(P';6463232#54&+#"%#"#546;632#"#"#546;632#"P/!. B^P/! .!l !/P^B .!//!. !/P^B .!//!.B/(^B((!/(/!((B^(/B//!((B^(/B/`003#5#'3533!PPPPp PPPPPZ`I0"(0:#'#"'#7&'&54767#5462#"3&264&"7'#5'75w@d!%&!d@w"HH]\HHmP?vvwj j )wd dwHhgH A]]A HghH4&'wvvj j  ` .4<FJN/3#'7#'#"'#7&'&54767#5462#"3&264&"7'#5'75753!530 _ -- _ w@d!%&!d@w"HH]\HHmP?vvwj j ] _  _ wd dwHhgH A]]A HghH4&'wvvj j -----353=33##5#5335#@P@d((dddx(P 7!5%!5!3p @PPPPPp0P  l0462#"''77&6264&"@vvvR:4>((>"PFdFFdhRvvv">((>4ldFFdF@'#53@Р0 %64'7'#53<<(.66.`##E[Р %64'7>4&'7'#53<<(.66.(@LL@(RbbRܠ`##E[F%%E/ħ/PРX{8 '7!!88@888PUX8 ''7%!579898S898<98}PP`0 !%!5%!!P000@pPPP0`0 7!!5!!5!!'!!!ppp0P0PPPP00`0 !3#3#3!%!!PPP0ppp0P0`0 !%!!35%!!P00p0P0Pp | #(-27%35/'3/'3/37'!!#7'#7%#?75v0 04000*00 LP000*00 L0 0d0000dL 000 0^L 00^ 0 0 04000*00 d000*00 0 0d000hP 00 0 0 00 0 0\t 77L888p 8(88pP !3!5#35#!P PPP@P @PP@ !!#3=#!500@PPPPP4l0880P(7>32.#"Px97I'@(  +,A4%x(@x7*#(?MM? S?4## x.6>463267.5367653632"&54'"'&264&"6264&"3' !"-)  )-T '3N3NH$$$$-CA>:UTT]#3#/-CC-@7[H. ## (8''8'8((8-`0!#5#53'3!5#3'5#5#35;;:GMk:s:M:-kZ`I0#@DL2#!"&546;47632.54&"2654&+#'7#547#"37&"&462+//+,..,-& +.B'+0,' gCypgh:h$ .,>,..,,.-2(Z 33 &Cyq&>h:h P@$264&"#53>32#"&@  a >&2FF2&>  PP#-FdF-P0 3"&5467264&"@P#-FdF-#  0 >&2FF2&> a  P@ 646323##"6264&"F2&> >&2   dF-#P#-  `@ 7462#5.6264&"FdF-#P#-P  2FF2&> >6  dl3533#535#3p(((x-Y(H((xx(0 !6327&547#"#"&546;3"."$7 H2E6C]vR ."FdF/$%C5>uSRv( "72FP(!#5#3#535##%!#5#3#535##@@(P((P(@(P((P(@P((((P((((`0#'5!!!#3!!##5!#5#535)!'5!5!;;--h;;O----ᇇ ` #'%!5!5!5!!53#5353#!5!!5#5!5h;;ᴴ;;ᇴhP`0#'+533533#3#3##5##5#535#535#535#3PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP`0!!!32+3264&#0P0H2FF2xx000 FdF@P @01C%53'54?654&+"#6;22#!5.=4637!26=4&#!";ZZ;*Y OZ&43JjjJ)1jJ3'g.8OO88OAZZ-7$-Z4&: -hjJJjS1Jjk,EogO88OO8`0 !!#!!#P@P0!!!!000P`0 #!5%#!5P@ @0P@`03#3#PP000`0 3!5!3!5!P0 @00P `!!!!00PP`0 3!!3!!@ P00P`03#3#PP000@`%"#46ЅPP`%"#44>ЅPu22PP|ee|`#44PꠅP`0#4춭PP|ee|Pu220=2653PP0=26533"&'Pu22PP|ee|@0%"&533ЦPꦅ@`0%"#467.53ЅP|ee|PPu22uxX 3#5!#53!xPCPPPxX 53#!#53PCP(PCPw?5#'735'7'3'7'7#78438834884388348 8348843883488438P737'#53#7#53#553#53'3#PPPjjPPjjjjPPjjPPc-?753#537#'73'#53#5'7'7#53#53'7'7#53#53'78 .Pj88jP. 88 .Pj88jP. 88jP. 88 .Pj88jP. 88 .Pj8x73#7%32#"&'73264&+53x{1S9B2FF2'? .3**r=)808P8%!(0x (73#7264&"'462"&547&6264&"x{1S3*<**323##53‚Ƞ#1 (8%);A!dd(((I &0X((P(D",%3264&+53264&#"'>32#"&'3##53"####0 (7%*::*%8dd(2   (  #2#%O((P(D %3733##5#3##53>>x(((xdd(p>(r((P(F %32#"&'73264&+53%3##536);;)!3 &*##^rdd(Ȍ):) d(((P(D&%&"632"&=4632264&"3##53 2#$);;R;;)6#2##2dd(Ȉ #2##323##5373#5:Ƞ#1 (8%);A!dd(Jf(Dd((I &0H((P(3Ȕ#t",33264&+53264&#"'>32#"&'3##5373#5"####0 (7%*::*%8Fdd(Jf(DF   (  #2#%?((P(3Ȕ#t 3733##5#3##5373#5l>>x(((xHdd(Jf(D>(b((P(3Ȕ#t '%32#"&'73264&+533##5373#5$6);;)!3 &*##^dd(Jf(D):) d(((P(3Ȕ#"`0 (3EISZhl'25=ATgk"#536;462#;#"7&"6326?5##"&46;#7;#"=#53533#73#33#535##'373462#;#"7&"254&5432&#"#"'76326?5##"&46;#7#"&=3326?53#6326?5##"&46;#7"#536;462#;#"7&"%373#'#%'!!!3#5654#"'6326462"&243#5654#"'632?33##5#73462"&243#5654#"'6323#5654#"'63264"32=#"&462#"'    1  * *(H  ( (5  2    *    PrrPPbPP(     (  |   (  ](  =    (     (   ( L     4  (    ( (  jPgPP  (     ^(         `0 7#'!"' 7'7'264'PP{;v;{99d99#dF#6P;v;{9999d#Fd#`0 736277'64&"P{;v;a989r#FdZP{;v;%989#dF0 "'#'3&"'7'#5364'3'7&'7T^F$GYP.Ft9t4t9tt9t"(Ȏt9t"hP..Pt9t""t9tP%!5%!0Px`0 !7'1'7|h䴴`0 5!!!hhhhhh0hhh `0 (3;FQYdlt%"32654&4&#"32&4&"2'4&"326&2654&#"6264&"7264&#"632654&#"264&"2654&#"264&"6  bP&&$&@&X&&bP&&$&FdFFd* &@&X&&bP&&$&@&X&&dFFdF*`0 3#3#3#3#3#PPPP PPPPPP000000`0!1!!hhh0h`0 #;G%67&'27&'&'34'6765"3#"'+547&=326&'67&#6i#ןf ,ab&i#ןgPAAPPAAPf ,ab&f ,ab&i#ןf ,ab&PPAAPPAA`i#ן`0'/7?GO#"'&'+54767&'&=32676;264&"67.>7&'.'>7i&4s4(i&;yAK(i&4s4(i&;yAK(2##2# U<"oDDo"23"".#<^4^x^4^<<^4^x^4^<PP@'52>?26?3".".#Ck9&*$( (7lCCk9&*$( (7lC ,( P ,( P@52>?3".#TJ2 5HTTJ2 5HT P P/?>2.">2.""&/526?5"&/526?P>H< >H< >H< >H< 0>H< >H< >H< >H<   P  (  P  P`73#!3#'3'5#'35!3#'@nM+p(^F$GPPP0P (M+PPȎPb01%#"'#"&463263247327&547&#"&#"32bZ7*&&*RvvR*&&*N971(((#-"> ."".2FF2-!0Aƍ?;N3Y|P((P()Le=7))^^Pb064632632#"'#"47PvR*&&*M:71)Z5*&&*Rz(((=ƍ?:O3Y4=P((P(%'3#h99aPPa990%'7#4>54&#"'>32h99P2<2F2+CP pKSu2<2a99$6, /?L6$6,%64632.#"3267#"vR@hQ:#2FF2#:Qh@RvvL;&FdF&;L0$+#"#5.5462>54.546354"0x2<2[EPE[EfE#-2<2F2xP-P%C.9Y {{ Y9@LL@K)6&62FuK<<)0 6462"7>4&'vvv*#--s#--#ƍƍY.SfSSfS0 %#"'#!#326?5[E-#PP."Pccp@x2F<x0 "&54672654&'7vL;&FdF&;LvR@hQ:#2FF2#:Qh@R0%632"&="#46;#264&"2FFdF!/P^B  FdFF2/!B^P  0#%264&+2+"#4633264&#))6L 4X>!/P^BPP):)L61%,F>X/!B^Pd*0!#"#46;23264&#@!/P^BcPB^^B/!B^ƍ^^02+#"#4633264&#B^^BP!/P^BP!//!^^/!B^P/B/@32644#'##"#463!//!B^T=p@P!/P^B/B/P^B>[/!B^(#3".%352>73#P## )&.!P#++# ) PPpK+&TqrrqT'+KpP%3#=34632&#"327#"xxxHtB^^Btxxxz^^zP%3533#535#3}}(((d-}( ((dd(P33533#535#30PPx}}(((d-lP }( ((dd(0 3##'731v7887 P8888` #533'7'7#v7887P 8888P !462"&$"&462"&462"&462Pdddd0*)8))871D11D)FddFGddD[:((:)D11D1A+0"#"'&'&'.'&'.'&'4&5&5476767&'.'&'4&/&54/&7&57454'&76&546;632632766326326323267632762>3663263262232654'&#"2654#"'"2654&32654'&#".#&#"3276'3267654'&#""7654'.'6=4&74#"276767'654'&'.'#&'&'"'&'"&##"&#"#"&#"''''#3232767'&32?54&7&5767327&'4327"'&767'767'6767#"767#4>767#67"#"'7&#"47&&767&7"&67'&4'&#"76*  )'"&++%$            #P-  .*&'.+|  $&# '  ! j&BA.               H $1 &) -B ! /           ^'   2 + .  "/ .*       %1l),  !,!" () i     ,f  1  $#  (         #I   '     +  R>0763&547"&547676=47#.54>7>767676>767627>7632+"327>32"&46=#"54767677326765567>7>7647676326326;2"&#&+"'&o  N  +  CG  7c  7@6   /&!%/ O & Mk(   -G [ 6 "H8  <     +        "       8 D  B  +  0 7!".'7462&RpR&ss() ## 4P`03#52>%3#@/632327&#&+654'+54'"1'"&=&+"547+654'#&'467&54>7>3#"&'&'#"'&5432325&#"32632#"'632#67463j$f ! # &"O :j#&    9  Ea< &*+*   $8(**]PW.    3  & $ (   p(,& . ){<=mhH?2 E=Q/'&H.  `$>IQ]fs6654&#"&#&'326;6=477327.'"&#"7.4654654;546323.;634.".'"&#"4>7>32327654&547&54653254&'"67&#"632&4&'7&#"63232#&'263256;27654&'52632#&54654'&546=.''45#" )'   4  . 1     & "    >I  6 &  &   & & a +; =)#"1 l :  *  =0DT# i      9  x 0  &=      5 $ 6 C b !=H"1 : & N p  ( $%@ s* l0 %>32#"2634654&53##"';72.'#"'&'327654&'>=67.4&+64&5.'.5474&547>7#'674&46=367&73.5274654'&%"'!# ' T" 9'% ?' :&.$87  ( MJ  #3  X  )  1.* U}9   *  "~ f O  B  )8 !  B>1 M - ' !I[ *$ !r z c  bG .$ *$ J < E  ?I XIO   7 0bx7>767&'&'632#532>7654'#"&+67#52632.'>7327"464+"#"&5>7>322#"'3%3#"&+4>7&5327'52632,/ - ! +& %;%*#CK` :) "&  4c7 7 :  EZ= %#V % ? >,  ,- !#*mE !$!: #H )"<WD2xu aBFF)   V)   F `0!%!!<Xl0X<0`0!%!!x0 x0`0 !!!%!0j,00`0 !!!'7!'0.tƜ00XƜtƜ`0 !!!%!!hxXl0xhX<0`0 !!!%!!h<0x, x0`0 3533##5#!%!!xxxxxxxXl0xxxxxhX<0`0!%!!3533##5#x0xxxxxx x0xxxxx`0264&"6  <*D?*`0264&"6  xƍ*+ƍƍ{*`06462"264&"6  jjj*~jjj0?*`0264&"6  462"xƍ*jjj+ƍƍ{*jjj`0264&"6  !!<*hD?*x`0264&"6  !!xƍ*h+ƍƍ{*x`0264&"6  3533##5#<*xxxxxxD?*xxxxx`0264&"6  3533##5#xƍ*xxxxxx+ƍƍ{*xxxxx.%#=4.54632.#"P2<2uSKp PC+2F2<2PPPP,6$6L?/ ,6$@#53#3PPPPP @L#5.54>?33#P4DDbb""8/!(PP@T @*"78 <PP6:%>54&#"'.#"4.54632>323#hM8)"' >>*")8M1GG1R:'F/:R1GG1PPP&""!^^%""&j B0:R8&R:0B (P0 33##5#533#@PPPPPPPP03#4&'#5#4673#@PE[P-#P#-P[EPPoG&> >&GotP03>53#5.533#@P#-P[EPE[P-#PP >&Go,,oG&> P? '73#F77F(PP((xP0 !#'5!'33#0xpxpPPx8xP/X$462"7&#"'>32327#"**)-FK+)&-FK+)** ((&* ((&*0 %3#573!#7@PPpxpxPP8x8xP%3#54&#"2644"&54632@PP/!#-vvvRt[EB^P!/<;#"#5#"''&#"2654B//B/**=Y00^^P %((<P7&+ !/:),**B//B/Y=@+&76LL6 c #P<x 00):/!0v#5##"'#5'.'&'&#"/&'&546?22323;27&'&#"/&'&5.'&'&546327&'&'./&'&'&5432654/.'&/&5462;2>?&5476323P *P  3     "               x %x          *     (&   > +$  $P t'53#5227>?6767>32;72676?62#535&/.'.'4&465654'&7654'4&546323276767>?617>762>7>7>7>?6?6P       2   $3P&                 PxP ,          3P +      " & (E  '*    <$462"$462"6462":T::T6**+@++@:T::T:**,>,,>,#&)/8=GSdmtz)05;RY+/I4"&56&7#&63767"'63656#"7'47443"5446726&"#054362#"'654&47652050"#22'5&346364'&70'&/&4&54/#6'"&5##;67"5&3"0'&726226&736'&&32636376&737#"&'.'.'.'&'.'.'54'654&=46=&547>765'33"'"'3&5636&7565"'3&53432532632##"'36;5672?61&57&767"7""'4'6#"2#7&32754&+"&"'&#"2?26562?34545"'&2'<6'53&327.'4654'.4652#763&5246&5"#47&5"5453&'&765&'&74"543&'27&7234'"'4676'&"#3'*#'"54726324&4'#27.7654&5&7"7"4'27"'64&'2>7&'654&=.'32654"5&=4'&6?&5456'66'"&70'72367654&547;45&6&6576'&#67"&6'6&#323&67"6'63452"63#"&2#"'434'&&1"5632&4&@./5"776&632#&7#654&/"'&7&&676>765"5432''4'>33233&'&6536&53262/6'&#"47"&32632#"&774"5""665467&&6"s  # + @     .$,        5 + \         &  A Y  4 !   " O _ G #K        A 1V      " ,              B# o        "               5       0 !   #   r     t+5#";2+53264&+"&4635326=3"&5353#'x P## P##(#2#(;R;((  #2#(  #2#dd##dd);;ȄȄt %5353#'5373#5'264&"462"(HH(<<#2##2K;R;;RȄȄHHȄ<%3#3#53$4632&#"327#"2+5264&+3264&#ddH;) 4 )%##%) 4 )!//!xxPP(((((R;&"#2#"&##P  (((  D !%3#3#53$4632&#"327#"ddH;) 4 )%##%) 4 )(((((R;&"#2#"&t",#"&'7326=#53#35'73#5##5353#'/!,'(x(xx23!2"&463P)"$F^F$") P;YhY;;YhY;P  D 5373#5'35'73#5##|HH(<32pp@F2,A P oKSuAPPP, 0>L6_!0)!!3264&+53264&#"'>32#"&'pRC-3EE3((3EE3+@ P mKSu!E3-!+3EJ80!!33##5#73p8PPP||PP<<|0!!32#"&'73264&+5!p\lRvvRAgL >&1GG1|Px(SrS=1 $0$P0 !!!264&"7&#"632"&=4632pPFdFFd~12F0HRvvvvRl:P  /!FdFF2xB^40 !!!#!p^P(3@0 %!!264&"'462"&547&264&"pdFFdFPvv44vv44PFdFFdP  2FF2,$$,2FF2,$$d  0!%326=#"&462#"'$4&"2!!12F0HRvvvvRl:FdFFdpX/!FdFF2xB^4  P@.#52733"&'#?[>L|p[>L|p=TPXF=TPXF.#%#"&547&4632.#";#"326O pLSu<?,'lL?/ *P):)"0!5!3267#"&54>7 +oTEF2+CP pKSu6LLPPIAJ /?L6ND;.#.#";#"3267#"&47&54632D-2FF2((2FF2+CP pKSu<XJ80%75###53533@9PPQ%,Pdd&%5#"&4632.#";!5nRvvRAiL ?'2FF2PP^^>0/B/P/O7476#"7676?>76767632#"+"#"#"##"'&'.'#"#  6/.%  > & ! j3 (Y&0Q > '    $ke?632'&'&'&'&'&#"#"'&'&/326?;2>76G  "!  #87      2$  % 1 .-l, 07  %h%/&   PG%24>54&'&'&#"'.#"#"54767676?3276763232#"'&'54;276{(%)# #   (,N.@+$C # /# 61/*D2  )3676O -aY ?T7 "u:K"        = 9     +Z(' #  "%& 8  /D2732".'&'&'.'&547676767676264#"27624'&p , #+* $&!%  &   %)!$!  - 58C %   >P2;26767654&'&76&#"4&#>7632#"54#"'&/.'4&54676  -(  04 :  V !  F:"'&''' 0 '6 0 ( 34 MU! #Q&BQ7"43267>7>76=.'&'&54?2##"5&7676767654&'&#"&    %&*+%LI    4&,!2  *'   ^&   /:,  ?c L%P%"&#"'&#"#"54767676767>76;2#"'&+"363#"'&,Y2  5# $    (  ,)&(&+ _6,W  !B>$&  #,2#"54'&'&"'&'&'&'.'&5476>P" $* C G 2 t2:6=    )x$# !"$ :W'0#""#"&'&'&'&'&'&5476476="7676767632#"'&#";2   *(s04      ! 2    !   '*( -   "     LM"#"'&'&'&'&'&547>7654'&=363232>?#"'&#"'&'&+"32c %&%"  *D-' I U[!-2#   -! = #:<  " *& 4 R ". !)L%#"'&'&#"'&'&5476327654'&54'&'&'&#'&'&"54323276732    "  U6U( 1# 2    ("   (*'=  JO"#"'&=676323232732;43232#"54765463276767654&'&)K AB   #'#P    h5 CD -  -&3 2>  $  @3232#"'&'&547654'&'.'&'54767676232  " "    + "&   8   ( 5  !1&    #6> & >32632#"#07>=4?54'&'&'&547>76767632< $L ,/ (E,^1U49    &4 *.% n7C49'?6;3232#"547676767654'&'&54>36326;6y+:6 E!%+  M   *Z  3%+  ] Od%"&=6#"&'&'&'#"#"547654767>5&'&'&543327632"&#"3#"32732#J !0Y m.   #%_!@%    #( -  [ 4*    !*  % ,467632#"#"'&5476762327>76  ,$0&P  2&  /FJ) ,*-")' I ,R25464'&5432327632#"#"/.547>7654&'&'&54767632;6=4  0! ".0O  .(&   "X B& 2"95-.*( . % '$   JS62#"5#"327>7>76732#"#"'5476767676327676323(   &   a*2  E*M 41$&  %   "BA &( 41QO6763#"'&'&'&'&+"767654?2;>3676767654767   " CP     6)  n).- b)!Z   # Hv<   1-6320#"#"'&/&'&5476766    &F"IF*!7; 1-olC S^23254732#"32#"'&'&'&#"'&'&574=>7>3363223264#"326 $    0$ *>) ;!3 5 83   @#. H( '56632;2#"&'.54767676=&'&/& # D    &" &10  M9632#"&'&54767676 <5$# '`F}$-^+8 "    -632#"#"#"54767>7676767632 B 76   . O  H77 -)'/`< 1    6;0#"'.'&'&'&4767 & , 7N+!51BL(  #$p5O%#"'.'&'.'.'547676763276763232763328A   -     ";A '4%  = Vz `72/54"54254'&'&5432763276767632#"'&%/&'&54'&5432732Y . B T$ !9 * )+%$M   <42/-{   %  &(    ?%0#".'&'&54'&'&5476763232?+"#"'&j  d4   +   <3F(#7#Z  vZA%"7663'.'.#"#"'&'&54;3732327676767>/    6  n;A   }N&300<5:IB  "  B;63"'&'&'&'&#"#"'#54767>323276767632=4   -KM$ -  $)/7 #/ 4#"8$( 3448  fj.5432"76763247654#&76=.54'&547363254323254'&54323273637232767632763322#"'./"'&#"/"547654w  '#,1      / BE% $0      %  ;     = /$4    4 3G     9<7"54767632#"'&'&#""57>54&'&'&14d''!  , A !  "1d)      !/Wd# 0!5!0PP&#"#3632'#3736!/PP&*=lPPl_g;/!pদ<0E74&547&546767#"'7.'4>767327&'>7654&' dJ  Kd " /P?88?P/ >  hFdF-#ȼ88#-4""264'2#"&'##5#'7'73533>h  (2FF2&> /P?88?P/ >   hFdF-#ȼ88#-x`X"4&"27"&54675#535'773#  hFdF-#ȼ88#-8  (2FF2&> /P?88?P/ >`n %33##5!5!ZZZZnZZZZZ`0 33##5#53ZZZZZZ0ZZZZ`0 33##5!5!ZZZZ0ZZZZ`0 5373#lPiP0Yw'778h8%h88{DUL%'77U888h8$!"&547&#"#52>7>32cND7]R/&$&=(!%NDc5{uIW^P[e3%#!P 52W%i=:R#12654&'56;23"&547&+"#B^WIu{{uIW^BcNDDNcR:=i%W22W%i=:RP[ee[$12654&'56323".'.#"#B^WIu{5cDN%!(=&$&/R]7DNcR:=i%W25 P!#%3e[]3%###533P PPPPPP5@P@5]3=333##%PPPPP PPPC2P2CN`L77#7'#37PHHPP8.HH8DL7'#3757#P48PPPHd8dH.8PHd8dHDL%!!' 7yW8K8P8LL873##5!##3PPдPPPPX<`0!!5!53#5!5!!PPX|PP0PP`0!.#7>54./32>7.PaE$$EaUwpD? ?DpwMM\uDDuD9?b23b?9D%6M>H  H>M6%{ڀ F]D D]F`0!!2%!264&#!hhSttP`0 '47!5!2"&64&"22#!5!&54264&"X2FFdF  BdFF2h  PFdFF"  FdFP2Z  P@ %!#"&4632264&" ='2FF2'=  P$,FdF,$P  `0 =! 77@pPȠP@@`0=3>32 #"&'6"26477W >&2FpF2&>  ȠP#-F2hh2F-#P  0%!5!30PP@`%#!5Pp@P0!!#P0P`3!PP`0#53\0܀\`05#3\<$(@7!(%!(7!3!(P(@!(x(@7!!((%!!( 7!3!!(P!x(7!!(P%!!( 7!3!!(P(!!!x( 7!!!!(P( %!!!!( 7!3!!!!(P`o#67i_  _0 5$!yMi0$!5 yMZ`o%5 _i_`*0#*Z0yM`0 "#46$3ЀdZr d递 r`0 4.#52vd递 rdZr`03#iZ0}`*0#3*iZMy`0 "$&53ВrZdFZr d`0 3#52>vZrd0rZd`03#vZi0}I!0&'*_0i^ ` %5}IFZi`%!5 }iZ!035$i_0^i5!5!0OZZZZ`I03!3Z>Z00`053#5353!533#3##5!#5%!ZZZZhZZZZZ`0#'+%#'#'#57'57'53737377'7'77'\t@tttt@tttt@tttt@tttttttt(ttttttt@tttt@tttt@tttt@tthtttttttttttt-`0 3!3!3!3IZZZZ0000 5!5!5!5!000ZZZZZZZZ `0'/7?GOW462"462"462"462"462"6462"$462"&462"$462"462"&462"&&@&&t&&@&&t&&&&N&&&&&&&&&&&&&&&&@&&&&&&&&&&t&&(&&t&& `0'/7?G462"462"462"462"462"$462"&462"462"6462"Z&&t&&@&&t&&&&N&&&&t&&&&&&&&&&&&@&&&&&&(&&t&&%!#!"&54>?3'(jJJj# -Ν1JjjJ+T83 ߝL%#!"&5!4'(! #jJJjv1! 38T+JjjJQL-0+5##5##'"&#'./>2"#ZZZ (Z(Rw&> 8Bp~oE3 %VwR(Z|ZZZZZ ;$ >/'%55%$' -n|2"&/>5#!5#)~oE3 *Ȟ8BZZ|.BC N;ZZZZs0)-264&"264&"72"''7.54>35#&&&&?{P1PVJ'r'JVP1Qy@|&&&&BZX3U44U3#[U;ZZ`0%-1#"'#535.54>;23264&"264&"35#v6H6Z]W1Qy@Z?{P1W]Z&&&&ZZV6#[U;BZX6V&&&&Z-`0-5=E%".'>54.54>?$264&"264&"6264&"*3*D"!:6E6. JXT.$*3*A\]! *mSDX&&t&&t&&//(Z %;%2K! )(9//&f[Q \Uh4&&&&&&-`0'/$'.4>?264&"264&"6264&"8OO-- $]H:A\]! *mS&&t&&t&&Lf[Q \UhLf[Q \U4&&&&&&#/7?#3#5#3#5#54>7."'>326;27264&"264&"*"&ZZZZ &V D42Z%@ &&(&&JX-ZZZZ-2,5+E &C!74@&&&&`#19A%##535!#535#4>547'7632>32."$264&"264&"ZZZZ--L@/:4(3 4D :-/--&&(&&ZZZZ6F'O3@ 4:"C&G+J('F6&&&&e2#4&'+#52>54&'"'3".54>7.'#".'&'#4>323>2367>I$6Z(5C*&;9c7  7c9;&*C5(Z6$( /:/ (1AU2Bp $9F#&8 Z UU Z 8&#F9$ pB2UA1'33'0U".'3".'"'#52>7&547&'#"367>3262632>53I 7AY+:qX8  8Xq:+Z?8 Z  &;. .;&  Z"  !? 4/#Z)B44B)Z#.6 ?!  ;S bb S;0%-%!"'!535&547'36273264&"264&"(d(2e-V-e2ʴ&&X&&ZZ^dc[[cd^&&&&`0!)1#54'"'#5367&47'36273264&"264&"д~J~]_2e-V-e2_=&&X&&FZ--Z|c[[c|h&&&&w '!'7!7ppppxxonrorxx`0 ''#77Gonrorxx٠ppppxxw 7'7'5!!ppppxxonrorxx`0 773''onrorxx0ppppxxZ`v0!#####57#535#hZZᇴ0ZZZZ`v0 5##5#5#'!#!57#ZZZhFZZZ`v0#3##5#5##57#ZZ0ZZZZZ`v0!##53##53#ZZZZZ0ZZZ`v0!#3###53#ZZZZZ0>ZZZ`v0#3##3##5vZZZZ0>Z>ZP !#'#"&463273P@HhddhH@P@@uu@@0 57&5462@@uu@@PP@HhddhH@PP 3632#"'#PP@HhddhH@P@@uu@@0 "&547'50@@uu@@P@HhddhH@P `'t4632>326;632632#"'#"'"&=&547&5467&5467547&547&547"5'#"&5474"'#"'" 5%7  %0 A)&'88', 0  &   *JNJ5! 4"7N8""          !  353!#5"&5)35ZZJj4&|ZZZjJ&4ZZ`0 5323!#54&#ZJjZZ4&ZjJZ>&4Z 3!##!53265#vZjJZ>&4Z|ZJjZhZ4&`v0 #"&5#5!335ZJjZhZ4&FZhjJZ&4ZP 535353%53?7%77@PPPq8q88q8tq8q88q8@PPPPq8q8q88q8q8q8`0 53535353%77%77@PpPp9q9q99q9q9q99q9PP@PPq9q9q99q9q9q9i`0 2#"'6hӕii0ii`  &547giiiӕi`g0 %#"&632hiӕii*i0 &546 ii*i7iӕi`0 7!5&264&"264&"6  @x    *֠PP    *&`03##"&'->32264&"00/bh-B-hb&&|RbmZZmbR&&` .5467!4&"2RbmZZmbR&&p/bh-B-hb/0&&`0>32 #"&'# 264&"0/bh-B-hb/0&&|RbmZZmbRh&&0 .54675!264&"RbmZZmbRh&&/bh-B-hb/0~&&`0 3##"&632264&"00/bӕb&&|Rb*bR&&`0 .546 !4&"2Rb*bR&&p/bӕb/0&&`0 >32#"&'# 264&"0/bӕb/0&&|RbbRh&&`0  &54675!264&"RbbRh&&/bӕb/0~&&`03!"&63!#"vZӕhZpFZ*Z`0#46 #54&"ZZ*ZFZhӕZp`0#5!2#!53264&ZZhӕZpZZ`053 &5326vZZZӕhZp`0!3!!35##53!!0P0pPPp00pp0`0!!!!35#53!!0pp0PPP`0!#!!#353#!!PPP00`0!5!!!5#3#5!!000P0pPPp0P 7577'57'7'PPPPPP((x (x(0( 3#!73!7!!7!@P((x (x(0PPPPP %5PPPPP(@(x(px(( #'3'!#'!!'!!P(@(x(px(PPPPPZ`v0 3#5!#3!!!!!!5!ZZZZhhhh00---ZZZZZ %!53#5!#####30---ZZZZZZZhZZhhhh`7! !P-0G`%!!-P0GAO6"&462&"264"&462&"264nPPnPt&&nPPnPt&&AOpOOpe&&OpOOpe&&`0/?'5373#'#5%'5373#'#5#'#57'5373#'#57'5373 G@GG@GG@GG@G@GG@GG@GG@G@GG@GG@GG@{G@GG@GG@GG@G@GG@GG@GG@GG@GG@GG@GG@G@GG@GG@GG@GG@GG@GG@GG@`0 35!35#%#΀N΀N0NN`0   ! !00`0!!%!57#'7!'30)W8g8 8g 800Pg 8W8g8 8`0 5!!!hhhhhh0hhh`0 !!!#Z"Z`0!!!0"0`0#3#3#3##5#535#535#535#53PPPPPPPPPPPPPPPdPdPdPddPdPdPdPP@3533533533##5##5##5##5PdPdPdPddPdPdPdP@PPPPPPPPPPPPPPP"*%2>?.#"#"./>32 264&"02&!  $$3GAh6-R6)  -3S-6hAG  !//p7*#2<2);;E5+2<2  "*72>32#".#" 264&"GAh6-R6)  -3S-6hAG2&!  $$3n  2<2);;E5+2<2!//7*#  $,%2>?.#"#"./7'>32 264&"02&!  $$3GAh6-R6)  -3S-6hAG  !//p7*#2<2!//<7*#2<2  $,72>32#".#" 264&"GAh6-R6)  -3S-6hAG2&!  $$3n  2<2!//<7*#2<2!//7*#  P`0*29%7'#>7'./>7532264&"7>54'0PP %)D%/ 2,Q4(  "8(fb -  .P((0''W'*S*;:3,1^B5  L"@ `0#'#3#3!535!3!535#35#5!#!5#5!5#ccccccccccczc>ZZZZZZZZkZZ`0#'5#!5##33##335!353#5#35335#IZZZZZZZZkZZccccczccccccc´`0#'35#35#5!#!5#5!#3#3!535!3!35ccccczccccccc´ZZZZZZZZZZ`0#'35!353#5#353#5#!5##33###3ZZZZZZZZZZ0ccccccccccczc>`0##3#3!535!3!535#35#5!#!5#5!ccccccccccczcZZZZZZZZ`0#5#!5##33##335!353#5#353IZZZZZZZZccccczccccccc`05!#33##3!53#5#353I>ZZ‡ZZccczccccc| %2#!"/&546;5!5!&547#v&4Z&%Y4&Z! 4LZY%&4ZZ|735!!32#!"/&463&47#ZZZ&4Y%&Z4 ȴZZ4&%YZL42`05!!hh0h0`0%!0h` 3!!75!tt02xdFZӕ֞pA*A`05232#!!4&ZFdx2>ZӕA*Ahp`0$"264"&462>3 #!&& nPPnP -Zld&&PnPPn$6Zvdl`06"264"&462#52!5 && nPPnPQ-2dl&&PnPPnZ6$>8Z`0%5!>3 #!h -ZldnZZ$6Zvdl`075!#52!5 ZQ-2dlnZZZ6$>8Z`03".54"&53 3QZpZjJZ80ZZpJjZld`0532653#3!5 Q JjZpvZ>8ZjJpZ8`0 %5!3".54 3QQZZ8ZZhZZld`0 535!3!5 Q hZ>8ZZZhZ8`03".54"3"&463 3QZG` `GllZ80ZZFF>Zld`05352#5267.3!5 Q llG` `/Z>8ZZFFZZ8`03".54"#46 3QZJjZpZ80ZZjJp>Zld`0%#44%53%3!5 ZjJpQ `Z>8nJjZZZZ8`0#54>;#"#!! PHPP`[wP.7kPPxxĜHP&P`0(.$462"&462"&462"%5#54.'&%5!#****** $P P****** P $xxPPk7 P0`0%"&'.'3;!#'#3$P 8w[`PPPPP$ww PPPp`0 35 76!3##'!@P PPPP0ww P `@ 75!!#!!0PPPPPPPP`@$2"&45!5!#5!=!  P  P PPPPP `0 #)-15!5!'53#53'#5%53#53#53'#57#53!33#'3#'3#@PP(PPxPPP0P0PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP `0 !%)-1%53!53753!53#53%3!5!%5!%53'53%3#'3#'3#@pPxPPP0@PP(hPPPPPPPPPPPPPP0PPPPPPPPPPPPPq`'%4675'5373#.#"#&54632&54632/$LRJ!LPVER`QfhN86CA8WO4.2HJ\<]/WO)e)6>$H/`_'#654&#"#33632!>32WU`RETPK#HPF(^dh?B56y0 *1!#".'332721"326;# '.'&%3#"54Wz3W;%Q,AZ1N6 p+5L60AQ0&?73!5232#"56753'EnO$S2ZA,U5(l 8 ';V1|Kl 2RM'>J( IJ$` @"324"324%!&'&54632654.54632654.54674400 \C/-C B0.Bn*@.vdd~*dXwu'S/AC-FYSY=M"0@C-Lqc4T0 /@:(`E%"3254&%"3243254&+532654&54632654&'4632!D002020.>*l B0.B C-0B\ d2~2d&2:B./N6crE 0@C-$!L;XRYF.BA/P*wu0"3263"&54654.54'!"326~.36KK1u4,h$ 2(6 _W ux!!/0$4&+5!#5323254!#53232jz/KK8WF5.>0x"xgXa 5& @ `r3!5'5733573՜8$L"o DR8"22"`r33573!535o"L"8 |"22"8RD0 3!'57!1&+^D&0 5!!35+(3^Ȏ&fDF`##33!&54>7&5463"$FF$)@QM#,N>dVL\2=98gM>&5;:@R`535#5#5254#52!5$FF$22=O,1c\:n\LV20RA979 5S|H:<2Hx0("3.'>3327&54654.'!#"3nf(yP-5 !GB( Fq'E"2  <x0&52654+52654+5!372.TtfbIfbn>&iYv54'263%c(J R +# B: TO ?% \-O0<-75B^` `!632#.#)Kb]_"J=&1@8SU Uw0 ""2654#>7#"5#'.'67!('->?2?`2&2(>; Ut$ !THuQJ\4KGA'> 2:EY03265'3!)&vO06[K|`| !&547&546$f|(*9<6BX`| 7!32Fdp:*(XB9#0 !!&5467&UC0FD0 !AL|NEʭF` ;%&547;&547"&#%3!'45.54>763"*#?O Z +!>=$=Ok>ja%5%A&7 6PdJQ]#55R=1li {/?Z1V76eA9 _Z `0'65&'65.'.#52!53&547.'#73#5462%& gA2ma'J4GtRZ 55&F|-!-w#!I;* 'G'4#"'327#!>325&'#.4675"&46;5462367&'33273'{R  4nL+/--QRq2aS-&z1e7e*0 _E,, \ >/'o"&--1 Z`0567!#!632!>=M[(ZYSa2]<. m\60L{#%55sX0`(X 35!3'#73!'73#5##3'#PP@Prg.xΔΠք< )״)ى6T<(X$17%#532!!2654'654&32+264&+2#!324#))J>X4 L  Fd)oO P):) X>F,%16LP*<dF*(4BOo0(T/3267'#"&46327.#""&4632'&#"32?PcFuT0UB^^BU0TuFccttR"$@2FF2@$"SƍK>G^^G>KXH05FdF50HX(X!264&+32+!!23264&#@ccPB^^Btx2FF2ƍ ^^x0FdF(X !5!!5!5!5!7!!!!! p(0P PP<<0(X !5!35!5!7!!#! P(0P P<0(T#0%#"&46327.#";#&;5#53'&#"46323!"̌B^^BU0TuFccxF2d$@2tR"J:td^^G>KƍPndF5XH0 (X 35!3#!5'3353#5##PP@PPx ഴ( 3#35#35%!#3!535#PPPP@PPPPPPP@P(&X*3#"&'326=3526=#5!##"'./7@PF2#:Qh@RvP!/P@Pc$9W P2F&;LvRP/!cR8,.( 35737#'373#'#PPxppx@P hx(P(X !5!'3!!Ppx P(p(X ;73#'#373#'PPP88(qqxxXุ0xx(X ;3##33#PPX8P8(qqXX0(X264&"462"&462"264&"Pƍ=^^^֤褤FdFFdSƍƍ΄^^^,褤JdFFdF(X #!353264&32+2+#3264&#PB^^!//!RvvRȠ ^^P/B/vv0P ( )63277'654&"#"&462'462'#"?654&"Pc>4b8Z>RGB^^^'Q1]pj37t*rIFdF,#Sƍa8[D]cG ^^^B:.Q]褤tWG^pirJ2FF2&> (+32+7!3533'>54&32644#'##!//!Pp=T^Rv=1W/B/ [>B^xP vR9`0k%.7M%"&'32654.546327.#"'27.'7'.#"#"&/7&547632@3STPcRvvR^B3STPcRvvR^B9)3 A A*9)8>>8Vz>8>z^"p"^p""p F(\\\\ !'7#'#37#'# 373ppp᧧᧧(35#/373#5?Pr䦦Ơ((X !!5!5%!!!5!PXX0P8PX8(qqxX264&"462"&462"264&"vvv&FdFFd̊3:33:Sƍƍ΄^^^/⧧MjCCjC 73#73#$Q1btzHET|^:qX8%>54&#">32!5'3!5767>7&#"'7>32, #YE8uSKp PC+2FPP .:At 60 U^EM 32+32#"&%#"&/73267.+5327&#"'7>32O pLSu<?,'lL?/ *P):)"$TjYJ)#    +BK,1M5*/xX 733535###5'33##5#73QPP9xrPPuddP,3ԠdduX1!5!32#"&'3264&+#"&/732>4.+!#2,2FF2'? LiARvvRn^_M},((_P/B/0>^^IqI>(1  @xX)96462"7&#"264&#"546322>4."'4632"&5FdFFd@:SRvvvvRC5F2,|(4((4(_`F'n?RB//B/-4/^BB^^^ !/  Wq8Yc>VrrVxX !35%!#!!^HPp3(f6xX'9G"&462$2654'64&"462"27&#"'462"&547&26?."dFFdF<XX>?,'lL:)):) M]]M3,09SkkS:/*  xX)9"&462326=4&"327#"64."26#"/7.5462FdFFd@:SRvvvvRC5F2,|(4((4(_`F'n?RaB//B/4/^BB^^^ !/  Vr8Yc>VrrV1%"&=4""&5*.546322=4622=(54762#""32276327654&'&'&54d0 W$M+6,%""%,6+M$W 0d+6,%I20 < 02I%,6+ S9+ "<||<" +9S hyw9+ "" +9wh|!!h|0!!1!5hh00!!!0h|!!hh|0!)!hhh00!!5!0|!!0|0!!!hh000!!5!hh0h0h5!!hȴh05!!!!hhȴ05!!!!hhhȴ05!!!!h0ȴh0!!h00!!!hhh0h0!!!0|!!!5!hhh|0 !!!5!5!hhhh00!!!5!hhh00 !!!5!5!h0|!!!|0!!!!hh00!!!!hhh0h0!!!0h%!!hhȴ0%!!!!hhhȴh0%!!!!hhhȴ0%!!!!hh0ȴ|!!!5!hh|0!!!5!hh00 !!!!5!5!hhhh00 !!!!5!h00!!!hhh0hh0!!hh00!!!0h|!!5!|0!!!5!hh00!!5!5!hhh0䴴0!!5!05!!0ȴ05!!!!0hȴ05!!!!0hhȴ05!!!!00ȴ|!!!hh0|0!!!hh000 !!!!hhhh0h0!!!!h00|!!5!hh0h|0 !!5!!5hhh000!!5!hh0h00!!5!5!0h0䴴|!!0|0!!!hh000!!!hh0h0h`h05!!!!hhд`05!!!!hhhд`05!!!!h0д`h|5!!!!hh`h05!!!!hh`0 5!!!!1!5hhhд`0 5!!!!!hд`|5!!!!hhh`0 5!!!)!hhhhд`05!!!!hhh`0 5!!!!5!h`|5!!!!h0`0 5!!!!!hhh0д`0 5!!!!5!hhh0h`05!!!!h0`h05!!!!hhд`05!!!!hhhд`05!!!!h0д`h|!!h|`0!!!hhh0`0!!!0`|!!!!hhh|h`0 !!!!5!hhhh0h`0 !!!!5!h0h`|!!!|`0!!!!hh0`0!!!!hhh0`%!!1!5hhȴ`0 %!!!!!5hhhhȴ`0 %!!!!!5hhhȴ`0 %!!!!!5hh0hȴ`| !!!5!!5hhh|`0 !!!5!!5hhh0`0 !!5!!!5%!5!hhhhh0`0 !!!!5!!5hh0`|!!1!5hh|`0 !!!!!5hhh0h`0!!1!5hh0䴴`0 !!!!5h0h`| !!5!!5h|`0 !!!5!!5hhh0`0 !!5!5!!5hhh0䴴`0 !!5!!5h0䴴`5!!!ȴ`0 5!!!!!hȴд`0 5!!!!!hhȴд`0 5!!!!!0ȴд`|!!!!hh|`0!!!!hh0`0 !!!!!hhhh0`0 !!!!!h0`|!!!!hhh|h`0 !!5!!!hhh0h`0!!!!hhh0h`0 !!!!5!h0h`|!!!|`0!!!!hh0`0!!!!hhh0`0!!!0`0%!!!!hhhдh`0%!!!!hhhд`0%!!!!hh0д`|%!!!!hhh`0%!!!!hhh`0 %!!!!1!5hhhд`0 %!!!!!hhдh`|%!!!!hhh`0 %!!!)!hhhhhдh`0%!!!!hhh`0 %!!!!5!hh`|%!!!!hh0`0 %!!!!!hhhh0д`0 %!!!!5!hhh0h`0%!!!!hh0`5!)!hhhȴ`0 5!!!!!!hhhhȴ`0 5!!!!!!hhhhȴ`0 5!!!!!!h0hhȴ`|!)!hhh|`0!)!hhh0`0 !!!!!!hhhh0h`0 !!)!hh0`| !!!5!!!hhhh|`0 !!!5!!!5!hhhhh0h`0 !!!5!!!hhhh0`0 !!!5!5!!!hhh0`| !!)!hh|`0 !!!)!hhhh0`0 !!!!!!hhhh0h`0 !!)!hh0`0%!!!!hhhдh`0%!!!!hhhд`0%!!!!hh0д`|!!!!hh|h`0 !!!!!5!hhhh0h`0 !!!!!h0hh`|!!hh|`0!!!hhh0`0!!!00`|!!!|h`0!!!!hh0h`0!!!5!hhh00h`5!!5!`0 5!!5!!!h`0 5!!5!!!hh`0 5!!5!!!0`|!!!5!hh|`0!!!5!hh0`0 !!!!!5hhhh0h`0 !!!!5!h0`|!!5!5!hhh|䴴`0 !!5!!5!5hhh0䴴`0!!5!5!hhh00`0 !!5!5!5!h00`|!!5!|`0!!!5!hh0`0!!5!!hhh00h`0!!5!00`05!!!!0hд`05!!!!0hhд`05!!!!00д`|5!!!!0h`05!!!!0h`0 5!!!!1!50hhд`0 5!!!!!0д`|5!!!!0hh`0 5!!!)!0hhhд`05!!!!0hh`0 5!!!!5!0`|5!!!!00`0 5!!!!!0hh0д`0 5!!!!5!0hh0h`05!!!!00`5!!!hh0ȴ`0 5!!!!!hh0hȴд`0 5!!!!!hh0hhȴд`0 5!!!!!hh00ȴд`|!!!hh0|`0!!!hh00`0 !!!!hhhh0`0!!!!h00`| !!!!!hhh0h|h`0 !!!!!5!hhh0hh0h`0 !!!!!hhh0h0h`0 !!!!!5!h0h0h`|!!!!h0|`0 !!!!!hhh00`0 !!!!!hhh0h0`0!!!!h00`%!!5!hh0h`0 %!!5!!!hh0hh`0 %!!5!!!hh0hh`0 %!!5!!!hh0h0`| !!!5!5!hh0h|`0 !!!5!5!hh0h0`0 !!!!5!5!5!hhh0hh0`0 !!!!5!5!h0h0`|!!5!hh0h|`0 !!!!5hhh00h`0!!5!hh0h00`0!!5!!0h00h`|!!5!5!0h|䴴`0 !!!5!5!hh0h0䴴`0 !!5!5!5!hh0hh00`0!!5!5!0h00`05!!!!0hд`05!!!!0hhд`05!!!!00д`|!!!hh0|`0 !!!!hhhh0`0!!!!h00`|!!!hh0h|h`0 !!5!!hhh00h`0!!!5!0h00h`0!!!hh00`0!!!hh0h00` &5463!2!&5"%654'&#6462"^VhV^FF/>t>/TxTTxV^^V@ttn-o o,hJJhJ`0 ###&'".Z."08?Y?8Z`%32#"'!&5476;2&462"if%%S?f .4Ru%TxTTx\O%4%I?]=F%hJJhJz`0#5#"&4?5&'&'7' &4I�H550L$4LH*0A=55`.6%2#"'#5"#&5476;26?>$462"$ AX%#,@H&TGau%"\TxTTx&    +&;LFAjA6%6<&B[hJJhJ0&7"&54?5"'&'&'35473"&='Z$6(4!- 4L4Z(3&0L6#  d ,&44&-O0`v%46;2!7#"&46326"&462%uR4. f?S%%fiTxTTx%F=]?I%4%OhJJhJ`V0!+#5'&4750#&I4& 50=A0*HL4$Luj5`/772676546;2#654&##75#"'./&546$"&462?" %uaGT&H@,#%XA $TxTTx+0B&<6%6AjAFL;&+    &hJJhJ0&%"'%&="&546?3673"'v(Z4L4 -!4(60O-&44&, d  #6L0&3`462"463!2!TxTTxjJhJj0HhJJhJJjjJ`0!###0>n0!#!#д0Zh`0!###0`0!h0`0%#535'#53#75#3#5'#ZZZZZZZ-Z-ZZ--Z*Z>66`0'/%3#5#!5#335!%"&463!2#%"3!264&#462"ZZZZh7PP77PP7&&n򴴴ZZPnPPnP&&@&&`0'/75!353#!5##%!"&463!2'!"3!264&"&462hZZZZ7PP77PP7@&&nZZ򴴴PnPPnP&&&&ldJ26747/77;2?#"=#"=#"&/#"&='#"='.=: FR RF & ( 2 F F 2 & <#D4$$4 < *"* 42T=O4 *"* <jfF2?/##"&/#"54;'#"54;'#'&546?#"4;7#"54;7>;w$M4$$4,< * "* 41T>M4 *" * <  FS RE ( ' 1 F F1 & ?s2 E%"''?'&5'&+"54?54327543275763254325432'& 8BB8 p  ( 8 8 ( o11 ?))- 0 "!)(C/A)!" 0 6>632#"&547"'"&547&5"&4632674&5462264&"9+8&44&..5J5)d)4L4..&44&8+94L4jjjr 24L48.7'88'  &44&4.84L42 &44&B99B96>%&'#"&46347&5462624&54622#"'"&546$4&"29+8&44&..5J5)d)4L4..&44&8+94L4 jjj 25J58.7'88'  %55%4.85J52 %55%B99B9U{y6"&4626"&4622"&4"&547&47&'"'#"'#"&463267&47&'#"&547&54626267&54632632#"'632'67&'*******>*>****m**>>*>*>4[5+3;_&5462"&54"&462"&4632632#"'2"&42"&47#"'"&547&5463267&54627"&463267&5462"&547&'6"&462"&462"&4622"&42"&42#"'"&547&5463262"&4r****4**w****(******K**G*********w**P*****>******m**=**=*Z** [5'/7?GO462*&4622"&4&2"&42"&42"&4&2"&4&2"&42"&4&2"&4q**********=****=****=******m**w******w****=****`0 744#52673"&63"ccccsPPttP*P`0 $"#46 #42653 &53P*PtPPPcc}cc 5!77%7%7JxJPxJx8x8@x8xPPP@B8x88x8x0!#5!#АP0`7!53!0h`0 3#!%!! 0 P0P %##5#5353'355#PPPP𠠠ph0%h0(` #!P uPDi  '% 'h8888i{8K8{8K8'L '7  7 8LL8||8LL8|8K8{8K8{`0"$&46$3"KęPP`Ħ`PKK`02$64&$#52#KPKKP`Ħ`%3#%3# PPP73#P%!5!#PP%!5!##pPPP %!#5#5!#pPPP %##5##5#5!#PPPPP`03##53@PP00PP`0 #5!#5#53@@PP0PP`0 #5!#5#535#53@@PP0PP@`0!!@P@`03!!@P@p0P`0!5!#@PP0`03!5!@Pp@00P`#5`%#!`3#P`%#3!! !!0`!### `5%#hhؐ`5#`3#`=#5!! `7573#P`7#5!#P`033##0`03#00`03#0030`%#03#0`0 3#5-h0%%!5!%hhH03x0H`7xxHH %%57'5%hhHHH`#'5h %!%hhh `# `03##5300 `0 3 #5'57h0ؐ`05#'35 @`03#'500 `0 33###530 035 003#0P033! 003 0 037#0033!53008-5%hhh8ؐؐ0573hؐ0357 003!53 0P0 3'57'5xxxx0HHHH03#'50P`73#`3#73#3#3#P03#03#3#3#03#0(h@!!(h!!(h!!%!!(h(x@!!((x@!!!!(P(x!!!!P(x !!%!!!!(hPx!!(x!!!!(hPx!!!!P(x !!%!!!!(hP(x!!%!!(h(x !!!!%!!(hP(x !!!!%!!hP(x !!%!!!!%!!(hhP(@(7!!(((@!!!!((!!!!( !!%!!!!(h(@!!!!(P(@ !!!!!!(PP( !!!!!!PP( !!%!!!!!!(hPP(!!!!P( !!!!!!(hPP( !!!!!!PP( !!%!!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPP(%!!((!!!!(h!!!!( !!%!!!!(h(!!!!(hP( !!!!!!(hPP( !!!!!!hPP( !!%!!!!!!(hhPP!!!!P( !!!!!!(hPP !!!!!!PP( !!%!!!!!!(hPP( !!%!!!!(hP( !!!!%!!!!(hPP( !!!!%!!!!hPP( !!%!!!!%!!!!(hhPP((7!!%!!(h(( !!!!%!!(h( !!!!%!!h( !!%!!!!%!!(hh( !!!!%!!(hP( !!!!!!%!!(hPP( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP( !!!!%!!hP( !!!!!!%!!(hhPP( !!!!!!%!!hPP( !!%!!!!!!%!!(hhPP( !!%!!!!%!!(hhP( !!!!%!!!!%!!(hhPP( !!!!%!!!!%!!hhPP( !!%!!!!%!!!!%!!(hhhPP|03#0|h03#0h|03#h0|03#0|3#|h|3#|h|3#h||3#|53#ȴh73#ȴh%3#hȴ%3#ȴ`53#`h73#h`%3#h`%3#h`%!!hh`7!!`5!!`h5!!h`53#`|3#|03#003#0|h0!!h0|0!!0|0!!0h|0!!hh003#003#0`|3#|`%3#g)%''''77770PPPPPP9PPPPPP9gPPPPPP9PPPPPP9 #&54623'7654&"=^^=H*/B/*P0NB^^BN0 0!//!0 `0#&)-15<@DHLS#!'#57546;27'7#37#77373'7'77'337&=7'3'37'7'735'0?xx?/!!/@4P154 p?!Pa41(2!?Pxx!//! )hH Pg@ q P`01!0РP`03!535.=!26=!gg0 vvpiPPixxRvvR( `0 #'+!!%!3535335335353353353533530PPPPPPpPPPPPpPP00P0РPPPPPPPPPPPPPPPP`0!*3463236226322#"'#5'#"&465&'"#7&5"&#xF2.z.2F2FF2!P!2FFW%W2F))F2FdFttFdFIP  PI`Q#2#"'"'#"&463267>76[[$%"B"%$[[$%  "(, 3 %"A,%BD#P`g-"&46326767g2W/.6vvvR7h6D #Qwvvv_1"(`Q5=EMU]emu}"'.'&54763267632654#"'&#"26462"6462"&462"6462"6462"$462"6462"&462"&462"$462"$462"6462"462"|,z138T87e%,5g.$z, 4$)gQbx-%7@b)R&R  8    8          |  P      |  P5S~z1!! h7DDS5@ q]BG$ xb^x $ 4^b)//  T    T      T    @    T      Z`v0CGKOSW[g75;4'3327&+327&+&'#6=465&'67#"4754';5#"3535735#35#!%!!3#3!! CEF48>" <;2D 1114444 䮨 q< & "   & A $$4(0`<0T0 0Z`v04cgk%3327&+327#"'&'232=##6=4';5#"5;47367327&+327+#6=#"5;5#"5;&!%!!2654.54632&#"#"&'7WH HC =EE   '9KZKU;0O2B'9KZKU;0O2 u  ou w[  (0 )#1-% + )#1-% +Z`v0#5:>HLP]%"5;27&+327#5##6=4';5#"&=#&'35"'>?352655#!%!!37373#'# 2&#o    ' [4I%"%I4l"%%"{ f f X +" #C< 6^$(0ddddZ`v06@DH675#"5;54'3#6=".=4'36732765353#'!%!!*%% * #&&"0"Ά  ; 2P& - 8(0Z`v0#'+/3I%3327#5##6=##6=4';54355#!%!!4632&#"327#"WE?<B<<\? ~U;*G24(88(42G*;M3 3M=77777(0vU-% +8P8+ %-Z`v0%26545"&=#327&'&'67&'7#"53&'&+3+&'32>45#"675;5#"5&'67&'75;276767&''67654&5;&'367!%!!3##! ( L   "   "< /   .  &!*  䮨0 /       ,          W DR  (0`<0 0Z`v0 )7!!75#7#55#!%!!32644+#ҴxZ 䮐(88(0ҴxZZ(0``(08P8` Z`v0cgkosw+&'30'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232=73#7'!%!! ;  ;@0 ! 3# $  4C*** 33$----!   {1S . ) * '    ' ]  1 * ) O&=)(0 Z`v0!!%!!3#5>54&#"'>32+&'3'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= B2**; 0C-2FN'a ;  ;@0 ! 3# $  4C*** 33$----!   (000,'- %. Q ) * '    ' ]  1 * ) O& Z`v0+!%!!3264&+53264&#"'>32#"&'+&'3'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= (****; 0C-2F$$F2-D ;  ;@0 ! 3# $  4C*** 33$----!   (0"0%. !&%5-! ) * '    ' ]  1 * ) O& Z`v0 z~!%!!3'733##5#+&'30'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= &`_"001 ;  ;@0 ! 3# $  4C*** 33$----!   (0>`0<< ) * '    ' ]  1 * ) O& Z`v0!%!!32#"&'73264&+53+&'3'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= B2FF2'? .3**r ;  ;@0 ! 3# $  4C*** 33$----!   (0`08P8%!(0 ) * '    ' ]  1 * ) O& Z`v0%!%!!&#"632"&=4632264&"+&'3'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= <* (2FFdFF21$*<**< ;  ;@0 ! 3# $  4C*** 33$----!   (0U 8P88(`(8((r ) * '    ' ]  1 * ) O& Z`v0rvz~!%!!3#7#+&'30'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= 9 ;  ;@0 ! 3# $  4C*** 33$----!   (0 ) * '    ' ]  1 * ) O& Z`v0!)!%!!264&"'462"&547&6264&"+&'3'"#'232>35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= *<**35##6=4';5#"6=4';5#"5;54'3354'3327&+327&+327'3535'35#35#35#.'7#67232= * (2FFdFF21$*<**{1S <....7?=)(0 Z`v0!AIOW]c!%!!3#5>54&#"'>32"'&5475&475&54762"'625'27&"425"'6"2727&" B2**; 0C-2FN'Z"N""N"144W4444G44D44(000,'- %. Q....7? Z`v0+KSYagm!%!!3264&+53264&#"'>32#"&'"'&5475&475&54762"'625'27&"425"'6"2727&" (****; 0C-2F$$F2-D"N""N"144W4444G44D44(0"0%. !&%5-!....7? Z`v0 6>DLRX!%!!3'733##5#"'&5475&475&54762"'625'27&"425"'6"2727&" &`_"001"N""N"144W4444G44D44(0>`0<<....7? Z`v0>FLTZ`!%!!32#"&'73264&+53"'&5475&475&54762"'625'27&"425"'6"2727&" B2FF2'? .3**r"N""N"144W4444G44D44(0`08P8%!(0|....7? Z`v0%EMS[ag!%!!&#"632"&=4632264&""'&5475&475&54762"'625'27&"425"'6"2727&" <* (2FFdFF21$*<**<{"N""N"144W4444G44D44(0U 8P88(`(8((....7? Z`v0.6<DJP!%!!3#7#"'&5475&475&54762"'625'27&"425"'6"2727&" 9"N""N"144W4444G44D44(0|....7? Z`v0!)IQW_ek!%!!264&"'462"&547&6264&""'&5475&475&54762"'625'27&"425"'6"2727&" *<**,,>,8&&' w{1S ;=X==Xw,>,,>L&&" =)(0Z`v0!)19A!%!!3#5>54&#"'>32"&462&"264"&462&"264 B2**; 0C-2FN')X==X=J>,,>,8&&' (000,'- %. Q=X==Xw,>,,>L&&" Z`v0+3;CK!%!!3264&+53264&#"'>32#"&'"&462&"264"&462&"264 (****; 0C-2F$$F2-DX==X=J>,,>,8&&' (0"0%. !&%5-!=X==Xw,>,,>L&&" Z`v0 &.6!%!!3'733##5#"&462&"264"&462&"264 &`_"001X==X=J>,,>,8&&' (0>`0<<=X==Xw,>,,>L&&" Z`v0&.6>!%!!32#"&'73264&+53"&462&"264"&462&"264 B2FF2'? .3**rFX==X=J>,,>,8&&' (0`08P8%!(0=X==Xw,>,,>L&&" Z`v0%-5=E!%!!&#"632"&=4632264&""&462&"264"&462&"264 <* (2FFdFF21$*<**,,>,8&&' (0U 8P88(`(8((e=X==Xw,>,,>L&&" Z`v0&.!%!!3#7#"&462&"264"&462&"264 9X==X=J>,,>,8&&' (0=X==Xw,>,,>L&&" Z`v0!)19AI!%!!264&"'462"&547&6264&""&462&"264"&462&"264 *<**,,>,8&&' (0""N .. !&%55%&0=X==Xw,>,,>L&&" Z`v0%-5=E!%!!326=#"&462#"'64&"2"&462&"264"&462&"264 * (2FFdFF21$*<**<X==X=J>,,>,8&&' (0 8P88(`(8((e=X==Xw,>,,>L&&" Z`v0!%!!32644+#33! ~(88(0`0(0``(08P8` 0Z`v0%-264&"462"!%!!2#'##3264P88PhUvUUv{ n(82%aD`V00P88P8vUUvU8(0`8(%6a`` 0`(Z`v0 $*432644+264&+!%!!735'#73#5##ؖ  .4&V RnDn00<0. *&4 "T(0R>nnllZ`v0)!%!!4632&#"327#"3353#5## NU;*G24(88(42G*; 0000(0vU-% +8P8+ %-llZ`v0)1;!%!!2654.54632&#"#"&'732644+# '9KZKU;0O2B'9KZKU;0O2B(88(0(0 )#1-% + )#1-% +p`(08P8` Z`v0)9!%!!2654.54632&#"#"&'7326=3"&5 '9KZKU;0O2B'9KZKU;0O208P80UvU(0 )#1-% + )#1-% +@(88(;UU;Z`v0'%326=3"&5!%!!35'#73#5##08P80UvU ~RnDn00(88(;UU;(0R>nnllZ`v0  %3#3#535#!%!!37373#'#P0000 +4I%"%I4l"%%"000x(0ddddZ`v0!%!!3##"&'7326=# 0F2'> 0.*0(00x2F-$)*x Z`v0/Ogw#5##5##5##5##5##353##3535353####35353535353######353535353535353########3535353535353535353##########353535353535353535353535############353535353535353535353535###########353535353535353535353535#########35353535353535353535#######3535353535353535#####353535353535###35353535#3535!I---------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------2------------------------Z----------------------Z------------------Z--------------Z----------Z------Z--Z0 /K5##5##5##353##3535353####35353535353######35353535353535!#5##5##5##353##3535353####35353535353######3535353535353535#35######353535353535!#####353535353535###35353535!###35353535#3535!#3535!v-----------------------------------------------------------h--------------------O------------O----O------------------------------------------------------------<--------------------Z------------Z----d|  !!%!!!0T(,,  !!%!!!6"&4620TԴ(,,ԣ  !!%!!!6"&462"&4620TZ(,,  #!!%!!!6"&462&"&462"&4620TԴI(,,ԣI  #+!!%!!!6"&462"&4626"&462"&4620TZ(,,  #+3!!%!!!6"&462&"&462"&4626"&462"&4620TԴI(,,ԣI  #+3;!!%!!!6"&462"&462&"&462"&4626"&462"&4620TԴI(,,  !!%!!!&"&4620TԠ(,,ԣ  !!%!!!&"&462"&4620TԠe(,,ԣ  #!!%!!!&"&462$"&462"&4620TԠ (,,ԣI  #+!!%!!!&"&462"&462&"&462"&4620TԠeI(,,ԣI  #+3!!%!!!&"&462$"&462"&4626"&462"&4620TԠ (,,ԣI  #+3;!!%!!!&"&462"&462&"&462"&4626"&462"&4620TԠeI(,,ԣI  #+3;C!!%!!!&"&462$"&462"&462&"&462"&4626"&462"&4620TԠeI(,,ԣI  !!%!!!&"&462"&4620T(,,  #!!%!!!6"&462$"&462"&4620TԴc(,,ԣI  #+!!%!!!&"&462"&462"&462"&4620Tee(,,  #+3!!%!!!6"&462$"&462"&462"&462"&4620TԴcee(,,ԣI  #+3;!!%!!!&"&462"&462"&4626"&462"&462"&4620Tee(,,  #+3;C!!%!!!6"&462$"&462"&462"&4626"&462"&462"&4620TԴcee(,,ԣI  #+3;CK!!%!!!6"&462"&462$"&462"&462"&4626"&462"&462"&4620TԴcee(,,  #!!%!!!&"&462&"&462"&4620TԠI(,,ԣI  #+!!%!!!&"&462"&462$"&462"&4620TԠec(,,ԣI  #+3!!%!!!&"&462&"&462"&462"&462"&4620TԠIee(,,ԣI  #+3;!!%!!!&"&462"&462$"&462"&462"&462"&4620TԠecee(,,ԣI  #+3;C!!%!!!&"&462&"&462"&462"&4626"&462"&462"&4620TԠIee(,,ԣI  #+3;CK!!%!!!&"&462"&462$"&462"&462"&4626"&462"&462"&4620TԠecee(,,ԣI  #+3;CKS!!%!!!&"&462$"&462"&462$"&462"&462"&4626"&462"&462"&4620TԠecee(,,ԣI  #+!!%!!!&"&462"&4626"&462"&4620T(,,  #+3!!%!!!6"&462$"&462"&4626"&462"&4620TԴc(,,ԣI  #+3;!!%!!!&"&462"&462"&4626"&462"&462"&4620Tee(,,  #+3;C!!%!!!6"&462$"&462"&462"&4626"&462"&462"&4620TԴcee(,,ԣI  #+3;CK!!%!!!&"&462"&462"&462"&462&"&462"&462"&462"&4620Teeee(,,  #+3;CKS!!%!!!6"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԴceeee(,,ԣI  #+3;CKS[!!%!!!6"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԴceeee(,,  #+3!!%!!!&"&462&"&462"&4626"&462"&4620TԠI(,,ԣI  #+3;!!%!!!&"&462"&462$"&462"&4626"&462"&4620TԠec(,,ԣI  #+3;C!!%!!!&"&462&"&462"&462"&4626"&462"&462"&4620TԠIee(,,ԣI  #+3;CK!!%!!!&"&462"&462$"&462"&462"&4626"&462"&462"&4620TԠecee(,,ԣI  #+3;CKS!!%!!!&"&462&"&462"&462"&462"&462&"&462"&462"&462"&4620TԠIeeee(,,ԣI  #+3;CKS[!!%!!!&"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeceeee(,,ԣI  #+3;CKS[c!!%!!!&"&462$"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeceeee(,,ԣI  #+3;!!%!!!&"&462"&462&"&462"&4626"&462"&4620TԠI(,,  #+3;C!!%!!!6"&462$"&462"&462&"&462"&4626"&462"&4620TԴI(,,ԣI  #+3;CK!!%!!!&"&462"&462&"&462"&462"&4626"&462"&462"&4620TԠIee(,,  #+3;CKS!!%!!!6"&462$"&462"&462&"&462"&462"&4626"&462"&462"&4620TԴIee(,,ԣI  #+3;CKS[!!%!!!&"&462"&462&"&462"&462"&462"&462&"&462"&462"&462"&4620TԠIeeee(,,  #+3;CKS[c!!%!!!6"&462$"&462"&462&"&462"&462"&462"&462&"&462"&462"&462"&4620TԴIeeee(,,ԣI  #+3;CKS[ck!!%!!!&"&462"&462"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeeceeee(,, `&0KOgw#5##5##5##353##3535353####35353535353######3535353535353535######353535353535###35353535#3535#5##5##5##353##3535353####35353535353######3535353535353535######353535353535###35353535#3535#!!------------------------------------------------------------------------------------------------|------------------------------2----------Z------Z--------------------------------F----------Z-------v0`&0 !!!!!&(,,00,,`&0 !!!!!"&462&(,,ԣ00,,`&0 !!!!!"&462"&462&(,,00,,Z`&0 #!!!!!"&4626"&462"&462&(,,ԣI00,,I`&0 #+!!!!!"&462"&462"&462"&462&(,,00,,Z`&0 #+3!!!!!"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;!!!!!"&462"&4626"&462"&462"&462"&462&(,,00,,I`&0 !!!!!6"&462&(,,ԣ00,,`&0 !!!!!6"&462"&462&(,,ԣ00,,`&0 #!!!!!6"&462"&462"&462&(,,ԣI00,,`&0 #+!!!!!6"&462"&4626"&462"&462&(,,ԣI00,,I`&0 #+3!!!!!6"&462"&462"&462"&462"&462&(,,ԣI00,, `&0 #+3;!!!!!6"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;C!!!!!6"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,I`&0 !!!!!6"&462"&462&(,,00,,`&0 #!!!!!"&462"&462"&462&(,,ԣI00,,`&0 #+!!!!!6"&462"&462&"&462"&462&(,,00,,`&0 #+3!!!!!"&462"&462"&462&"&462"&462&(,,ԣI00,, `&0 #+3;!!!!!6"&462"&462"&462"&462"&462"&462&(,,00,,C `&0 #+3;C!!!!!"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C `&0 #+3;CK!!!!!"&462"&462"&462"&462"&462"&462"&462"&462&(,,00,,C`&0 #!!!!!6"&4626"&462"&462&(,,ԣI00,,I`&0 #+!!!!!6"&462"&462"&462"&462&(,,ԣI00,,`&0 #+3!!!!!6"&4626"&462"&462&"&462"&462&(,,ԣI00,,I `&0 #+3;!!!!!6"&462"&462"&462"&462&"&462"&462&(,,ԣI00,, `&0 #+3;C!!!!!6"&4626"&462"&462"&462"&462"&462"&462&(,,ԣI00,,IC `&0 #+3;CK!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C `&0 #+3;CKS!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C`&0 #+!!!!!6"&462"&462"&462"&462&(,,00,,`&0 #+3!!!!!"&462"&462"&462"&462"&462&(,,ԣI00,, `&0 #+3;!!!!!6"&462"&462"&462"&462"&462"&462&(,,00,,C `&0 #+3;C!!!!!"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C `&0 #+3;CK!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462&(,,00,,CC `&0 #+3;CKS!!!!!"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CC `&0 #+3;CKS[!!!!!"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,00,,CC`&0 #+3!!!!!6"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;!!!!!6"&462"&462"&462"&462"&462"&462&(,,ԣI00,, `&0 #+3;C!!!!!6"&4626"&462"&462"&462"&462"&462"&462&(,,ԣI00,,IC `&0 #+3;CK!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C `&0 #+3;CKS!!!!!6"&4626"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,ICC `&0 #+3;CKS[!!!!!6"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CC`&0 #+3;CKS[c!!!!!6"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CC `&0 #+3;!!!!!6"&462"&4626"&462"&462"&462"&462&(,,00,,I `&0 #+3;C!!!!!"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CI `&0 #+3;CK!!!!!6"&462"&4626"&462"&462"&462"&462"&462"&462&(,,00,,IC `&0 #+3;CKS!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣI00,,CIC `&0 #+3;CKS[!!!!!6"&462"&4626"&462"&462"&462"&4626"&462"&462"&462"&462&(,,00,,ICC`&0 #+3;CKS[c!!!!!"&462"&462"&4626"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CICC`&0 #+3;CKS[ck!!!!!6"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,00,,CCC Z`v0/Ogw#5##5##5##5##5##353##3535353####35353535353######353535353535353########3535353535353535353##########353535353535353535353535############353535353535353535353535###########353535353535353535353535#########35353535353535353535#######3535353535353535#####353535353535###35353535#3535!I---------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------2------------------------Z----------------------Z------------------Z--------------Z----------Z------Z--Z0Z`v0"(2%#"'3#267#"&54>!%!!35'#73#5##h6**'9$$9'**6 RnDn005)*4%88%4*)5d(0R>nnllZ`v0!<!%!!3#5>54&#"'>32#"'3#267#"&54> B2**; 0C-2FN'6**'9$$9'**6(000,'- %. QZ5)*4%88%4*)5Z`v0+F!%!!3264&+53264&#"'>32#"&'#"'3#267#"&54> (****; 0C-2F$$F2-Dw6**'9$$9'**6(0"0%. !&%5-!^5)*4%88%4*)5Z`v0 1!%!!3'733##5##"'3#267#"&54> &`_"001x6**'9$$9'**6(0>`0< B2FF2'? .3**rr6**'9$$9'**6(0`08P8%!(05)*4%88%4*)5Z`v0%@!%!!&#"632"&=4632264&"#"'3#267#"&54> <* (2FFdFF21$*<**<6**'9$$9'**6(0U 8P88(`(8((5)*4%88%4*)5Z`v0)!%!!3#7##"'3#267#"&54> 9x6**'9$$9'**6(05)*4%88%4*)5Z`v0!)D!%!!264&"'462"&547&6264&"#"'3#267#"&54> *<** * (2FFdFF21$*<**<6**'9$$9'**6(0 8P88(`(8((5)*4%88%4*)5Z`v09264&"462"!%!!73#7#"'3#267#"&54>`*<**[136**'9$$9'**6P88P8vUUvU8(0c-5)*4%88%4*)5Z`v05!%!!3##"&'7326=##"'3#267#"&54> 0F2'> 0.*06**'9$$9'**6(00x2F-$)*x5)*4%88%4*)5Z`v0,!%!!353#'#"'3#267#"&54> ~"0"`6**'9$$9'**6(0p 5)*4%88%4*)5Z`v0#>!%!!7654&"327&462'#"#"'3#267#"&54> "18P88( UvU%6";%;;6**'9$$9'**6(0"0"(88P8 vUU;7*6":5)*4%88%4*)5Z`v0 .373#'#!%!!#"'3#267#"&54>0DxDH0V 6**'9$$9'**6xH>8(0`5)*4%88%4*)5Z`v0!'1.54632>32!%!!35'#73#5##h2&*$ &*** RnDn00`62@* *?6/ Z(0R>nnllZ`v0!;!%!!3#5>54&#"'>32.54632>32 B2**; 0C-2FN'2&*$ &***(000,'- %. Q62@* *?6/ Z`v0+E!%!!3264&+53264&#"'>32#"&'.54632>32 (****; 0C-2F$$F2-Dw2&*$ &***(0"0%. !&%5-!62@* *?6/ Z`v0 0!%!!3'733##5#.54632>32 &`_"001x2&*$ &***(0>`0<<62@* *?6/ Z`v08!%!!32#"&'73264&+53.54632>32 B2FF2'? .3**rr2&*$ &***(0`08P8%!(062@* *?6/ Z`v0%?!%!!&#"632"&=4632264&".54632>32 <* (2FFdFF21$*<**<2&*$ &***(0U 8P88(`(8((@62@* *?6/ Z`v0(!%!!3#7#.54632>32 9x2&*$ &***(062@* *?6/ Z`v0!)C!%!!264&"'462"&547&6264&".54632>32 *<**32 * (2FFdFF21$*<**<2&*$ &***(0 8P88(`(8((@62@* *?6/ Z`v08264&"462"!%!!73#7.54632>32`*<**[132&*$ &***P88P8vUUvU8(0c-62@* *?6/ Z`v04!%!!3##"&'7326=#.54632>32 0F2'> 0.*02&*$ &***(00x2F-$)*x62@* *?6/ Z`v0+!%!!353#'.54632>32 ~"0"`2&*$ &***(0p 62@* *?6/ Z`v0#=!%!!7654&"327&462'#".54632>32 "18P88( UvU%6";%;;2&*$ &***(0"0"(88P8 vUU;7*6":62@* *?6/ Z`v0 -373#'#!%!!%.54632>320DxDH0V 2&*$ &***xH>8(0@62@* *?6/ Z`v03##"&'7326=#%!!!5##5##5##5##5##5#3#35353###353535353#####3535353535353#####3535353535353#####3535353535353#####353535353535###35353535#3535h0F2'> 0.*0(----------------------------------------------------------------------0x2F-$)*xp0Pf""""""""""""----------------------------------------------------Z------Z--Z`v0 %'!%!!35'#73#5##hV RnDn00(0R>nnllZ`v0!%!%!!3#5>54&#"'>32' B2**; 0C-2FN'(000,'- %. QZZ`v0+/!%!!3264&+53264&#"'>32#"&'' (****; 0C-2F$$F2-Dw(0"0%. !&%5-!^Z`v0 !%!!3'733##5#' &`_"001x(0>`0<[13P88P8vUUvU8(0c-ؐZ`v0!%!!3##"&'7326=#' 0F2'> 0.*0(00x2F-$)*xZ`v0!%!!353#'' ~"0"`(0p Z`v0#'!%!!7654&"327&462'#"' "18P88( UvU%6";%;;(0"0"(88P8 vUU;7*6":Z`v0 373#'#!%!!'0DxDH0V xH>8(0`Z`v0!%!!3##"&'7326=# 0F2'> 0.*0P(00x2F-$)*xZ`v0#'-7%3#26&46;&546232"&5"!%!!35'#73#5##h;,,;**<***<**< RnDn00 1JJ<* ** *<***%(0R>nnllZ`v0!(A!%!!3#5>54&#"'>323#26&46;&546232"&5" B2**; 0C-2FN';,,;**<***<**<(000,'- %. Q1JJ<* ** *<***Z`v0+2K!%!!3264&+53264&#"'>32#"&'3#26&46;&546232"&5" (****; 0C-2F$$F2-Dw;,,;**<***<**<(0"0%. !&%5-!1JJ<* ** *<***Z`v0 6!%!!3'733##5#3#26&46;&546232"&5" &`_"001x;,,;**<***<**<(0>`0<<1JJ<* ** *<***Z`v0%>!%!!32#"&'73264&+533#26&46;&546232"&5" B2FF2'? .3**rr;,,;**<***<**<(0`08P8%!(0`1JJ<* ** *<***Z`v0%,E!%!!&#"632"&=4632264&"3#26&46;&546232"&5" <* (2FFdFF21$*<**<;,,;**<***<**<(0U 8P88(`(8((1JJ<* ** *<***Z`v0.!%!!3#7#3#26&46;&546232"&5" 9x;,,;**<***<**<(0`1JJ<* ** *<***Z`v0!)0I!%!!264&"'462"&547&6264&"3#26&46;&546232"&5" *<**264&"462"!%!!73#73#26&46;&546232"&5"`*<**[13;,,;**<***<**<P88P8vUUvU8(0c-1JJ<* ** *<***Z`v0!:!%!!3##"&'7326=#3#26&46;&546232"&5" 0F2'> 0.*0;,,;**<***<**<(00x2F-$)*x`1JJ<* ** *<***Z`v01!%!!353#'3#26&46;&546232"&5" ~"0"`;,,;**<***<**<(0p ΰ1JJ<* ** *<***Z`v0#*C!%!!7654&"327&462'#"3#26&46;&546232"&5" "18P88( UvU%6";%;;;,,;**<***<**<(0"0"(88P8 vUU;7*6":1JJ<* ** *<***Z`v0 3373#'#!%!!%3#26&46;&546232"&5"0DxDH0V ;,,;**<***<**<xH>8(01JJ<* ** *<***Z`v0 7!!%!!3##"&'7326=#4 0F2'> 0.*0xP(00x2F-$)*xZ`v0!%!!$"&462&"264 IvUUvUhP88P8(0UvUUv8P88PZ`v0!%!!#3#535#53 V0000(0000Z`v0!%!!#3#535#535# 0000`0(0000Z`v0!%!!#3!535#5!355# 0000P0`0(00000Z`v0!%!!#3!535#5!3'7# 4'[00P['D&(00000^^Z`v0!%!!#3!53'#5!7# 8MM8P=z(0000ǗZ`v0!%!!#5!#3!5;5#'7 4P00[4'0(00000^^Z`v0!%!!#3!53'#5!#3'#5# 00P['44'[e&0(00000^bZ`v0"!%!!#3!53'#5!355#'#5# $$PO'(H' &(00000^bZ`v0!%!!3!535#5!7+37'' 00-00Px*c-00`(0``0000**``**Z`v0!%!!3!537'#5!#7' WW11WW1P6666(0``00``00<<<<Z`v0!%!!'#5!#3!53775#'3 0-P00-6c-00K*(0h`0000**``**Z`v0#!%!!#3!537'#5!#3'7;5# 00P-00--00-*0(000``00``***Z`v0 #'!%!!#3!537'#5!355#'7;5# $$P!00!H00`*(000``00``***Z`v0 #&!%!!#3!537'#5!3'5#'73?# 'CP00C'L00`*&(000``00``***b^Z`v0"!%!!#3!537'#5!#3'73?# 4'[P-00-100X*&(000``00``***b^Z`v0"&!%!!#3!537'#5!7'#'7;5# P000'00`*'(000``00^^``*** Z`v0 #&*!%!!#3!537'#5!'#77335#73!5#  P,,' ,,=1'7" (000``0``^^&&% Z`v0 $'*.!%!!#3!537'#5!'#77335335!73!5#  P :1,0 4 (000``0``66 Z`v0"%(+!%!!3!537'#5!7+37'5#'7;' 00P00`*K00E00`*(0``00``00**````*****Z`v0!$'!%!!3!537'#5!7#'#3'7;' 00-P-00-x*0*00**(0``00``00**````***** Z`v0 #&+!%!!#3!537'#5!7'#73'7#7;5# P000000]***00(000``0````*******``P264&"462"2"&4>7vvvƤ褤BdFFdFu+vvv褤FdFFd +P"$"'7264&"#562264&"462"Fd#9  ###dvvvƤ褤dF#9   ###&vvv褤P )?2"&467'6755.53327'.547'654&'#4&#"褤@+#+u[E$,P!1D+'i'[E$,P!1D褤*  4 * Hn* 3! :) *66@Hn* 3! :) P6462"264&""'7264&"'62P褤TvvvFd#9  9#dT褤jvvvdF#9   9#`0!!!73#5!#!5'#0P0rPPP@.000߷״`0$!!!264&+2#!3264&#0P0))6L 4X>P000H):)L61%,F>XPd*`0!!!4632&#"327#"0P0cFuT0UB^^BU0TuFc000ƍK>G^^G>K`0!!!#323264&#0P0cB^^B000ƍ^^`0!!!!!!!!0P0H 000xdPPP`0!!!!!#!0P0HP000xdPP`0!!!#53#"&4632&#";0P0ccFuT0UB^^B000PƍK>G^^`0!!!3!53#5!#0P0P@PPP000( `0!!!3#3#53#0P0pPPPP000(PPP@`0!!!3##"&'7326=#0P0PvR@hQ:#2FP000(PRvL;&F2`0!!!5#'#330P0`xPPp00(xh`0 !!!3!!0P0P 000(pP`0!!!373#'0P088P000ุ X`0!!!33#0P08XP8000X X`0!!!462"264&"0P0ƍ=^^^000ƍƍ2^^^`0!!!2+#3264&#0P0B^^BPP!//!000(^^P/B/`0$!!!'#"&46237654&"3270PF4>cƍ>Z(9Q'^^^B00Eƍc]D[09Q.:B^^^ `0!!!32644#'##0P0H!//!B^T=pP000x/B/P^B>[`0-!!!2654.54632.#"#"&'70P0B^RvvRcPTS3B^RvvRcPTS000H$ ;)9SL=!&$ ;)9SL=!&`0!!!!###0P0P000(Pp`0!!!326=3"&50P0P^^Pƍ000(B^^Bcc`0!!!#330P06VV000L`0 !!!#'#5!3730P08>>8Dz>8>z00((P((F`0 !!%75!377!5#'0`00`00((@((`0 !!!#55!370P0P@a00G ((`0!!!!!!5!0P0X X000(8P8X`0 46  73!'35!3'#* .PP@Pr3*%״)`0$46  32+7!!2654'654&#532* J>X4 L6))3** X>F,%16Lp):)`046  3267'#"&46327.#"*[cFuT0UB^^BU0TuFc3*ƍK>G^^G>K`046  32+264&+* B^^Bcc3*^^Pƍ `046  !5!!5!5!5!*  p3*P PP`046  !5!35!5!*  P3*P P`046  #"&46327.#";#*!B^^BU0TuFcc3*,d^^G>KƍP`046  35!3#!5*[P@PP3*X ഴ`046  3#35#35*PPPP3*XPPP@P`046  3#"&'326=35*֕PF2#:Qh@RvP3*XP2F&;LvRP`03573#"&6 7#xPxTk*Op hxx*ӕ}d `0 46  !5!*[p3*X P`046  '373#'#*[PP883*xXุ`046  '33##*[PX8P83*xXX`046  462"264&"* ^^^ƍ3*&^^^ƍƍ`046  32+7!353264&* !//!PB^^3*/B/ ^^`0%327#"&6 '654&"#"&462'xc>4X\n*aU>RGB^^^'Q+ƍW>*ӕgUD]cG ^^^B:.Q`046  !3533'>54&32+*Pp=T^!//!3*X [>B^P/B/`0-46  7"&'32654.546327.#"*֕3STPcRvvR^B3STPcRvvR^3*&!=LS9); $&!=LS9); $`046  3335*[P3*XPpP`046  26=#"&=*[ƍP^^3*XccB^^B`046  7# #*ְVV3*xL `0 &547373#'##6 GG8>>88z>8>z8kB_xӕx_9Fx`0 &47373 %'7#'#6 OOOTTkO\TTkBddxdmx`0  &54735#'#6 NNPUUkBc~ӕ~cx`046  !!5!5*[XX3*XP8PX8P{462&"27"%73#5'#53Fd#9  9#dh8PPPP86dF#9   9#hhPPhP{ 73#5'#53!32+73264&#h8PPPP8&U1GG1UPxhhPPhFdFP P{ 632&"#5373#5'#532#9 PPh8PPPP8#9 xhhhPPhP-5=%27&47&#"327#"'#"&4632632&#"462"264&"::F2..)88)..2F褤Tvvv !F!  (2++FdF++2(  L褤jvvvP+7327'#"&547'462"654&#"632&'vRC39#2F:'P褤L'vRC39!2#9 Rv'9F2!93褤N3CRv':#9 P6264&"462"462"32#"'"&5"&=#"&=463vvvƤ褤L  V    vvv褤   Z >   > Z `0?3!'35!3'#%!!ȉ.PP@Pr0߉%״)x0`0 32+7!!2654'654&#532!!J>X4 L6))!0h* X>F,%16Lp):)0`03267'#"&46327.#"%!!xcFuT0UB^^BU0TuFc0+ƍK>G^^G>Kx0`032+264&+!!ȠB^^Bccx0h^^Pƍ X0`0 !5!!5!5!5!!! p0hP PP,0`0 !5!35!5!!! P0hP P,0`0%#"&46327.#";#!!B^^BU0TuFcc0d^^G>KƍP0`0 35!3#!5'!!xP@PP0 ഴx0`0 3#35#35%!!PPPP 0PPP@Px0`03#"&'326=35%!!hPF2#:Qh@RvP0P2F&;LvRPx0`0 35737#'!!xPxpp0 hxx0`0 !5!'!!xp0 Px0`0 373#'#'!!xPP88x0(Xุx0`0 33##'!!xPX8P8x0(XXx0`06462"264&"%!!^^^ƍ0^^^ƍƍx0`032+7!353264&%!!!//!PB^^0h/B/ ^^x0`0 %#"&462'$3277'654&"%!!WGB^^^'Qc>4b8Z>0xG ^^^B:.Qzƍa8[D]cx0`0 !3533'>54&32+!!Pp=T^!//!0 [>B^P/B/h0`0%)%"&'32654.546327.#"!!h3STPcRvvR^B3STPcRvvR^V0(&!=LS9); $&!=LS9); $0`0 3335%!!xP0PpPx0`026=#"&='!!xƍP^^0ccB^^Bx0`0 # #!!VV0(L X0`0 373#'#'!!>8>>8Vz>8>z0 Fx0`0 '7#'#37!!ppp0(X0`0 35#/!!?Pr0x0`0 !!5!5%!!xXX0P8PX8x0`0 3#!!!#323264&#xPPx0P0xxc(B^^B X00ƍ^^P 3#5'#53462"264&"MP((PM+褤Tvvv@{(({+褤jvvv`0 #'+/37;?IO3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#73#5!#!5'#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxrPPP@.0PPPPPPPPPPPPPPPPPPPPPPPPPPPP?״`0 #'+/37;?GT\3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#264&+2#!3264&#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP))6L 4X>P0PPPPPPPPPPPPPPPPPPPPPPPPPPPP):)L61%,F>XPd*`0 #'+/37;?U3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#4632&#"327#"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxcFuT0UB^^BU0TuFc0PPPPPPPPPPPPPPPPPPPPPPPPPPPPƍK>G^^G>K`0 #'+/37;?GO3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53##323264&#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPhcB^^B0PPPPPPPPPPPPPPPPPPPPPPPPPPPPƍ^^`0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7!!!!!PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP 0PPPPPPPPPPPPPPPPPPPPPPPPPPPP(dPPP`0 #'+/37;?I3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7!!#!PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP0PPPPPPPPPPPPPPPPPPPPPPPPPPPP(dPP`0 #'+/37;?V3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53##53#"&4632&#";PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPccFuT0UB^^B0PPPPPPPPPPPPPPPPPPPPPPPPPPPPPƍK>G^^`0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#73!53#5!#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxP@PPP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPx `0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#73#3#53#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxPPP@`0 #'+/37;?S3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#%3##"&'7326=#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPhPvR@hQ:#2FP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxPRvL;&F2`0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#733#'#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxPppxP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxxh`0 #'+/37;?E3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#73!!PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxP 0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxpP`0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#373#'PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPx88P0PPPPPPPPPPPPPPPPPPPPPPPPPPPPุ X`0 #'+/37;?I3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#33#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPx8XP80PPPPPPPPPPPPPPPPPPPPPPPPPPPPX X`0 #'+/37;?GO3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#462"264&"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxƍ=^^^0PPPPPPPPPPPPPPPPPPPPPPPPPPPPƍƍ2^^^`0 #'+/37;?IQ3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#%2+#3264&#PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPB^^BPP!//!0PPPPPPPPPPPPPPPPPPPPPPPPPPPPx^^P/B/`0 #'+/37;N\3#73#73#73#73#3#3#3#3#%3#'3#'3#53#53#53#462'#53'#"?654&"327PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxƍ>Z8 P@F4>cR9Q'^^^B0PPPPPPPPPPPPPPPPPPPPPPPPPPƍc]D[8 @PE9Q.:B^^^ `0 #'+/37;?GU3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#732644#'##PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP!//!B^T=pP0PPPPPPPPPPPPPPPPPPPPPPPPPPPP(/B/P^B>[`0 #'+/37;?e3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#2654.54632.#"#"&'7PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPhB^RvvRcPTS3B^RvvRcPTS0PPPPPPPPPPPPPPPPPPPPPPPPPPPP$ ;)9SL=!&$ ;)9SL=!&`0 #'+/37;?G3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7!###PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxPp`0 #'+/37;?O3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7326=3"&5PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxP^^Pƍ0PPPPPPPPPPPPPPPPPPPPPPPPPPPPxB^^Bcc`0 #'+/37;?F3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53##33PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP6VV0PPPPPPPPPPPPPPPPPPPPPPPPPPPPL`0 #'+/37N3#73#73#73#73#3#3#3#'3#'3#'3#'3#53#53#37333#5#'##53PPPPPPPPPPPPPPPPPPPPPPPPPPPP>Vz>8>zVMP8>>8PM0PPPPPPPPPPPPPPPPPPPPPPPPF(PHPHP`0 #'+/37;?K3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53##'#7'373PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPpppp0PPPPPPPPPPPPPPPPPPPPPPPPPPPP`0 #'+/37;?H3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7373#5PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP?rrP0PPPPPPPPPPPPPPPPPPPPPPPPPPPPx`0 #'+/37;?I3#73#73#73#73#3#3#3#3#'3#'3#'3#'3#53#53#53#7!!!5!PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPxX X0PPPPPPPPPPPPPPPPPPPPPPPPPPPPx8P8XP`03!535.=!26=!gg0 vvpiPPixxRvvR((`0 %3!53!!PP uP`0'3#546 #54&"5462"&%5462"&PP*P(/B//B/@/B//B/ȕӕtt!//!!//!!//!!// `0 #'+!!%!3535335335353353353533530PPPPPPpPPPPPpPP00P0РPPPPPPPPPPPPPPPP1%"&=4""&5*.546322=4622=(54762#""32276327654&'&'&54d0 W$M+6,%""%,6+M$W 0d+6,%I20 < 02I%,6+ S9+ "<||<" +9S hyw9+ "" +9w `7 =I'7'53753/77'72326?#"'&#"3"&54675346>54'ZDy.qZq 8T ) $='.$PDH*6* #`037!7!3!265!4&#!"%23'##!"&=#3463%#53ig0:<kl*-M **: -*QZZ0g:-qQD*)Mq**q Q*-Z`I0#@DL2#!"&546;47632.54&"2654&+#'7#547#"37&"&462+//+,..,-& +.B'+0,' gCypgh:h$ .,>,..,,.-2(Z 33 &Cyq&>h:h P`73373!'#'7PPPPP8P8PPP8/8P`73373!737PPPPP48P8PPP8/у8 P#'+/$"&462&"264'535353%53%77%77dFFdFh  PPPPP99889988t8998899PFdFFdZ  PPPPPPPP8899988998889 `0#'+/$"&462&"264'53535353%77%77dFFdFh  PPpPp9q9q99q9q9q99q9PFdFFdZ  PP@PPq9q9q99q9q9q94 %'#53'737ࠠ88h88@'#53@Р0 %64'7'#53<<(.66.`##E[Р %64'7>4&'7'#53<<(.66.(@LL@(RbbRܠ`##E[F%%E/ħ/PРl07'7'#"&4624&"2">((>4:RvvvPFdFFdh:4>((>"vvvdFFdF l0462#"''77&6264&"@vvvR:4>((>"PFdFFdhRvvv">((>4ldFFdFP`07354&"#4623!3FdFPvvPPȠ2FF2RvvRhP`0#54&"!!354620PFdFPvvhPP2FF2hRvvP352>23!2"&463P)"$F^F$") P;YhY;;YhY;P  4#352>7'76323#'#2"&463P 8z1Q/F$")48l P2)C8z^;YhY;P48l  `046  264&"37#'#5'7*փ褤LPFK3*褤([ (`0 37#'#5'76  264&"@PO(w*փ褤.FD*褤`0 33#6  264&"@Px*փ褤Pm*褤`0 3'#5'76  264&"@Pw(*փ褤DFK*褤`0 3'#5'76  264&"@PKFD*փ褤(w*褤`0 3#$6  264&"@PP*փ褤p *褤`0 3#'76  264&"@PDFK*փ褤w(*褤`0 3#'76  264&"@P(w*փ褤KFD*褤`0 3#536  264&"@Px*փ褤P*褤`0 3#'#5'76  264&"@Pw(O*փ褤DF.*褤`0 3#'#5'76  264&"@PKF*փ褤( *褤`0 3#6  264&"@PP*փ褤m*褤`046  264&"#5'753*փ褤8eP3*褤褋8f`046  264&"#5'753*փ褤}P #3*褤M"! `046  264&"'#5'75373*փ褤hP !#3*褤M!# `046  264&"'#5'75373*փ褤8-P3*褤8,`046  264&"3#5'7537*փ褤 ((P #!3*褤# U! `0264&"6  #5'75373P褤*ֽP(( !# <褤S*cU # `046  264&"'75373#5*փ褤8eP3*褤[8fߏ`046  264&"'75373#5*փ褤}#! P3*褤M" #!Ѽ`046  264&"73#5*փ褤1# P3*褤M( !`046  264&"73#5*փ褤8fP3*褤8e`046  264&"73#5*փ褤$M" P3*褤褈}#!`046  264&"#5'753*փ褤wM(P 3*褤s!#3# %.4673#,(.66.(<`E[E#] %.467.4673#,(.66.(<(RbbR(@LL`E[E#E/ħ/E%`0 736277'64&"P{;v;a989r#FdZP{;v;%989#dF`0.54632>32h0|_NiK <)  #'= KiJjj% -~?Ki**2&iK?u"`0 !%#!3!33%!#55#!5#%5#ZZ[gZ hZ->-v-nZ;g-u ->hZZZZZZ`0'!%!54&#!"!3!2653#gg:h>ZZgij:-q-`037'!%!54&#!"!3!265"&5#35463!237##3#gg:h>U*-M *<*: -*ZZgij:-qD*QMq**q V*-`0"2644&"265!!!5!L44L4-&&k0-v"4L44LZv0`n##!"&=463!254&#!"3!26%#53***H*-H--]****-Zv"/&4?622764'&"M,{{{{\\\\YYY`0 !%#!3!33%!#55#!5#%5#ZZ[gZ hZ->-v-nZ;g-u ->hZZZZZZ-%+ &6264&"62"&4264&"''67'6븸L44L4G&&4)C)C44L44LS&&4CC)`!73:0gZO:KgZ` !73'3''!:0gZ-- O:KgZ---u k` 7!5'#'#%3!737!-c ZtM:gZpp*g ZM :zgZ>-v !3!#5!:1KIM:kh-v!!7!!-I---v %7#!5!5!53!!::kgxh-Ia:g-I -v $'-%#53#53#57#5##57#53#53#57!3!#5!ZZ--Z---ZZM:1n------Z----Z------KIM:kh -v #'%#53#53#57#5##57#53#53#5%!!7!!ZZ--Z---ZZI-------Z----Z------- -v #)-%#53#57#5##57#53#53#57#!5!5!53!!ZZZ---ZZZ::kgxh-I----Z----Z------:g-I-`v0 !3!#5!:10M:-`v0!!7!!-I-00-v-`v0 !5!%7#!!53!Zgx::Zh-sgM:0 -`v0 $'-%#53#53#57#5##57#53#53#5!3!#5!ZZ--Z---ZZM:1n------Z----Z------M: -`v0 #'%#53#53#57#5##57#53#53#5%!!7!!ZZ--Z---ZZI-------Z----Z------0-v -`v0 $'-1%#53#53#57#5##57#53#53#5!5!%7#!!53!ZZ--Z---ZZgx::Zh-------Z----Z------gM:0P`P7!!P0P`0!%!!P00@p0`0 !#!3!5;5!!0РPPPp@0 P`057'5373#'# @ %'7!'%#88P88@P %'7'7#398<98}PP9898@X{8 '7!!88@888PUX8 ''7%!579898S898<98}PP@0#!2'!"&=4654&#!"3!5>hJj1)Jjj9O88OO8.g'30jJ1SjJJjk8OO88OgoE@0#2#!5.=4637!26=4&#!"JjjJ)1jJ3'g.8OO88O0jJJjS1Jjk,EogO88OO8@0%@77326=4&+"%25>=4&+"732'+5.=46;>-3'gz8OO88O;Jj4'3O8,EJj1)uR/g)1jJa,EogO8Z8OO8jJZ4oE,Z8O2(jJZ1Su'.S1ZJj:M@0$@M77326=4&+"%54&+"325>32'+55.=46;>'+23732-3'gz8OO88OvO8=(eJjA'3ŴJj1)/6OgZ)1jJS;6Og$gz=,EogO8-8OO8--8O-jJ--&AoE jJ-1S/227#4&"*    PPuuuSSLFdF3*    RrttrRRrrVPP2FF2`0#+462"&462"32653".264&"6      hPFdFPvvP褤*0    P2FF2Rvv褤S*`0#+$"&462"&4627#4&"#4624&"2 &6 @    hPFdFPvvP褤*`    P2FF2Rvv褤*`0!hh0`0!!hh00`05!!!!hhh`0!)!hhh0P`0!!!!462"0 p#2##202##2#$-6%"&5"&=&54675462"62&"&#2675"#26xFdFFdFx]CvvC]XB=r=6   6 x2FF22FF2\# RvvR #\8**`0!%!!(X0(0`0!%!!P000P0`0!%!!x0 x0`0!%!!0p0`0!%!!@0h@0`035%!! 0@0 !##'#CPPP(737654&+5323!P/!B^0Ϻ !/P^B@0PP#"&463!'7'7!";(B^^B/88!//!(P^^88/B/xX %'3533!!hxx4HPPP !!!7'7'!088P088P !#7'7P088P088P !!5!7'!P08888P !3'7'88088xw #7'7#q89qPPq98qCwX %#57#5!XPq98qCuq89qPX 53'53q89qP(Pq98qx 3'7'3!xPq98qq89qP`h0 "3"&6htt0PP*`01.54632>32'654&#"'.#"h0|_NiK <)  #'= KiJjj%%b:*F HH E*: -~?Ki**2&iK?u"L`N*:LzzL:*N`0 !!5#'#33535#0PP00P@h0!!h0h@0!!hh0@0!!00Ph@!!h@Ph0!!h0 P0!!!!hhh@P05!!PhP@!!hh@P0!!!!hhh@hP0!!hh0 P0!!5!0 P@!!0@P0!!!hh00P0!!5!hh0h0 P0!!00 `hP5!!hP`h05!!!!hhP`05!!!!hhhP`05!!!!h0P`h@!!h@ `0!!!!hhh@ `0!! `@5!!!!hhhP`0 5!!!!!!hhhhP`05!!!!hhhP `0 5!!!!5!hP `@!!`0!!!!hh0`0!5!!hh `0!! h`P%!!hhP`0%!!!!hhhPh`0%!!!!hhhP`0%!!!!hh0P`@%!!!!hhhP`0%!!!!hhhP `0 %!!!!!!hhhhhP`0 %!!%!!hhPh`@!!hh@ `0!!!!hhh@ `0!!!00`@!!5!@ `0!!!5!hh0 `0!5!!5!hh@0`0!!5!00`P5!!0P`05!!!!0hP`05!!!!0hhP`05!!!!00P`@!!!hh0@`0!!!hh00 `0 !!!!!hh0hh@`0!!!!h00`@!!5!hh0h@ `0 !!5!!!hh0hh@ `0!!5!hh0h00`0!!5!5!0h00`@!!0@ `0!!!hh00 `0!!!hh0h00`hP5!hP`P5!0P`h@!h@ `@!0@ `h0!h00`0!!hh000`0!000`0!!5hh000`0!5000`0!0h00`@!50@ h`P%hh`P%Рh`@hh `@Р h`0hh0`0!!hh00 `0!00 `0!!hh00 `0!00 `0!!hh000`@!0@`0!!%00`0!%000`0!!00`0!000`0!!00@h0!h0@0!00Ph0!h0 P0!00 `h0!h00P0!00`0!!0 `0!00 `0!!0 `0!00 `0!!00h@0!hh0@0!0hP0!hh0 P0!0 h`0!hh00P0!%00 `0!!0h00h`0 !hh00h0`0! !h00`0! 00h`h0 h00!0h`000h` hhhZ`03#ZZZ00`03#ZZ00`h03#ZZ00h`03#hZZ00`03#ZZ00`v03#ZZ00|!!0Z"|!!0|Z"!!0"Zn5!!0Zn5!!0nZ5!!0Z`03!!Zv00Z`0!#Z0Z`0#!5!ZРvZ`05!3vZZv0`0!!!!00FZZ`0 5!!!!!!!!!!00000UPPZZP|0!!00"0!!00n0!!00>0!!000!!00`03#00`0!!00`0!!>00`0!!00Z`0!!Zv00@`h0 #'+/37;?CGKOSW[_cgkosw{53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353%53353353353----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------@h`0 #'+/37;?CGKOSW[_cgkosw{53!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353=3!53353353%53353353353-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------@0 #'+/37;?CGKOSW[_cgkosw{%53!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353-]-----------------------------]-----------------------------]-----------------------------]-------------------------------------------------------------------------------------------------------------------------------------------------------------------@` #'+/37;?CGKOSW[_cgkosw{53!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353=3!53353353353353353353%53353353353353353353353-]-----------------------------]-----------------------------]-----------------------------]-------------------------------------------------------------------------------------------------------------------------------------------------------------------`0 #'+/37;?CGKOSW[_cgkosw{ #'+/37;?CGKOSW[_cgkosw{3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3+3#'3#'3#'3#'3#'3#'3#%3#I--Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v-----Z--Z--Z--Z--Z--Z--v----Z--Z--Z--Z--Z--Z--v--0------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3`0 #+3;?CGKOSW[_cgkosw{#5353!#53533#53533#53533#53533#53533#53533#5353=3!#5353353353353353353753!53353353353353353353=3!#5353353353353353353753!53353353353353353353=3!#535335335335335335375##5##5##5##5##5##5##5#!---]------------------------------------------Z-]----------------------------Z-]----------------------------Z---------------s-------------------------------------------------------------------------------------------------------------------------------------hk`0a3#3#3#3#3!33533533533533533533535##53535####535353535######535353535353%3333333#5##535###53535####5353535####5353535###53535##537333333#5#5#5#5#5#733333#5#5#5#5#73333#5#5#5#7333#5#5#733#5#73#---------0-----------------------------------------------------------------------------Z------------Z----------Z--------Z------Z----Z--0------------------------------------------------------------------------------------------------------------------------------ `0y3#3#3#3#3#3#3#3##535###5353535#####53535353535######!!33333335#535##53535###535353%333#5#5#733#5#73#35353535353535#######5353535353535######53535353535#####535353535####5353535###53535##535#----------------------------------------kh-------------------------Z----Z----------------------------------------------------------0------------------------------------------------------------------------------------------------------------------------------`033333335#535##53535###53535!!5##53535####535353535######5353535353535########53535353535353535########535353535353535#######5353535353535######53535353535#####535353535####5353535###53535##53733#5#73#--------------------------------------------------------------------------------------------------------------------------Z----Z--0------------------0-------------------------------------------------------------------------------------------------------------`0 %3#%3#3#%3#3#%3#3#%3#hhh`0 3#%3#;#%3#!3#%3#;#%3#0`|5!!!!00 `0  #533 5%35'3'5'3#5Z*nT>n>TFT**Z**Z*>n>TnFTފT*0* `0  #3#! 3'3773753*Z*>n>TnFTފT*0*v*ZT>nFTTF***`0! hh0h`0 h00h@0 #'+/37;?CGKOSW[_cgkosw{53=3'53353'53353'53353353'53353353%53353353353%53353353353%53353353353353%53353353353353%53353353353353353%53353353353353353%53353353353353353353%53353353353353353353%53353353353353353353353--Z---Z--------------------------------------------->----------->----------------------------------------------------s----------------------------------------------------------------------------------------------------------------------------------------------H`0 !%)-048;?CGKNRVZ]aeimqtx| '3#'3153#'3#'353=3#'353/353353=3!'353353/353353353=3!'353353353%'353353353353=3!'353353353353%'353353353353353=3!'353353353353353%'353353353353353353=3!'353353353353353353%'353353353353353353353------Z----------------------------------------------------->----------k-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------@-` #'+/37;?CGKOSW[_cgkosw{53!53353353353353353353%53353353353353353353=3!53353353353353353%53353353353353353=3!53353353353353%53353353353353=3!53353353353%53353353353=3!53353353'53353353=3#53353'53353=3#53=3=3-]-------------------------------------->-------------------------------k-----------------------------Z-----------------------------------------------------------------------------------------------------------------------------------------------------H`0 "&*.26:=AEIMQUX\`dhlpsw{  5!53353353353353353353%5335335335335335335335%5335335335335335335%5335335335335335335%5335335335335335%5335335335335335%5335335335335%5335335335335%5335335335%5335335335%5335335%5335335'5335'5335'5'5-]---------------------------------------------------------------------------->--------->---------------------------------------Z-Z----------------------------------------------------------------------------------------------------------------------------------------------------------------L'L88L88LL7L8h888D'78h888LD%'8888DL L8K8{L88LD L7 'L8{8K8||8L''7 8LL8|8K8{i7' 888{8KDL'!'L8888L8888DL7!7L8h808h88888' L'7 7 8L/8_8/L8|_'L  L8/L8|_L8K8{D i7' ' 8{8KѬ8_|8L/Di7 9K8{88{8K' i% /__//_ 3!!#5!5!PPZ`v0!ZŠ`0 7''!!?qBŚx0x*,(0d`0F462"#3##!#"/&5463!/"45'4#&=7574754257##"&54?634L44L:6p\%  c  \@Q Z L44L4 FnF{'  c {  ` 2+537653232+"' ׯr Pd  \FUF `0 7'!#!7!!8P0\8 0`0 5!5!%#5!5! !!iZZhZZvZZZZZZZZ`0 !5!573'!! 5!5!ZZ90ZZZZZZZvZZZZ`0#37# 33ZZZZZZ"ZhZ`0%3#'53 ##vZZZZZZnZP 7!3#'#!P9Ή0PyPP@ 1!5'!5!!09 g9PgP %3##%3#5#33#'3#53PP@PPPPP`06462"!5!!5FdFFd0vdFFdF0ZZ`0  %! !/h/h/i^h/`0!!/0_Ѡ/_`0  !!! /0//0/////9//`0?"/"&4?'&462762%32?32654/7654&#"'&#"r/WW/^/WW/^/WW/^/WW//!""!//!""!//WW/^/WW/^/WW/^/WW/B 0/!""!/0 "Z`0)1326546;2++3!!"'#363!!"#"&463ZDzmJB{GZ;)h^3Z##Z4]h);̑|T9|Y );FPZZPFF!#7.G4IF . F .  ,l&264&#!5!2#!5 4II4r . FIhIFP$!!735#535476?654'&+"36;2P0YYY3#YM X):PY,- 9&Y,"8xX0"264&"4623#''75#535.@  hFdF-#ȼ88#-  (2FF2&> /P?88?P/ >vQ0"%''75'75.54627&"264tHTTHt$$,FdF,$$  V$$VaGN ='2FF2'= NG  vQ0"%''75'75.54627&"2648_Ht$$,FdF,$$  N8$.NGa> ='2FF2'= NG  vQ0"%'''75'75.5462"264-tH_8$$,FdF,$  aN.$8NaGN ='2FF2'= >a8  gi0%(264&"4623###5##5#7#535.3@  hFdF-#ȷȉPPPȷ#-x?~  (2FF2&> /PPPPPP/ >? 75'7'ZZZMZZZBN? ''7'77%7'7''xxxxxxxxx?xx?xx?xx?axxxxxxxx9x?xx?xx?xx?3#3#PP7'ZZZZMZZZZ`0!! 00`03#00<$0|hHT'$0hHT7$$ HH<'7$$HHNB$hHB0$DNB hHB0$DNB'HHB$0$NB'DHHB$0$L7 8LL8|8K8{/DL% /8K888D  'h88{8K8DL7 '8{8K8||8LNB#7HHHDB$0$x<T 5$x$0THHhHNB '3HHhH$x$<T7'$0$ HHHD0 3 &5326PP0ӕth`0 "&63"ЕӕtPP*P` 4&"#46 P*Ӡttӕ`h0 2644#ttӕPP0!!h0`7!!hh|!!h|h|!!hh|0 &50ӕh`0"&63Еӕ*`!46 0*Ӡ`h02Ӡh0%"&5!Еhӕ`h!2hӠhh`%!46h05!hh0 #!3#'3#''57'57'57'57((((((((((h((((((h(((((((((8((((((((((((((0 '57'570(((((((((((((0 !3#'3#'3#'%'57'57(((((((((((X(((((((((((((((((((((0 !3#'3#'3#'%'57'57(((((((((((X((((((((((((((((((((((0 %3#'7'57'57'57((((((h((((((((((((((((((((0 !3#'3#'3#'7'57'57((((((((((((((h((((((((((((((((((0 #!3#'3#'3#'7'57'57'57((((((((((((((((((h((((((((((((((((((((((0 3#''57'57'57((((((h((((((((((8((((((((((0 #)!3#'3#'3#'7'57'57'57'57((((((((((((((h((((((h((((((((((((((((((((((((((0 #!3#'3#'3#'7'57'57'57((((((((((((((h((((((((((((((((((((((((((P352>23!2"&463P)"$F^F$") P;YhY;;YhY;P  `O0 $. % 4<fp+&547&67&'7#"4654432#"&+657&54754&5654'3>726367"&'"#.#"+."&4654#"#"467+32654'+7.'#"#6;'#"&#>7326767"&#"654"#'#64'&'&#54654'"#'>7&5474'632>=2#"'32654+#"&"74#"&'6323274&563225'<735632+&#32632#"&"#"'4&#"#"5354'.'#"6322327#"'3274#632#"'#647#"+.'#654+#"'#&'#"&54723254&54754'.'#"'+"'>7#"#"'67.'63267>7>7.'#"547&5432;.=#"&54723>7&5432>7>3232632.#"372;#"&53262#"'254&1432+654#2632#327326332654&526323>7&47>5&547&'#"'3267&#">5&"'6=#422>7#"';64#"322326322632326727&#"#"&#"32654'254&#"632#"&#"$;>7&'6767>3254&=63267326;3>54.'.'#"&"#"&"#"'%325432654'#3#"&'632#"&+254+632#"'      5  )    ("          ' !          $   $ 3    .        -#  &    >3    '        3   "   Z    A = 2   1 )   ,"   a 6 )  )   W1t         $   $* .*6A         #  w 8(    #      !     #    "  2,  =   L$  #  <  4+             8 q    h     t  8 $  ! 2::   $ E F       ,02D%&54632&'7>?6323##5#537'&#">54#"@:* 4   4 *:P(('J.-K  Fd*:N   N:*dPPPP((a&&b `01.54632>32'654&#"'.#"h0|_NiK <)  #'= KiJjj%%b:*F HH E*: -~?Ki**2&iK?u"L`N*:LzzL:*N`0.54632>32h0|_NiK <)  #'= KiJjj% -~?Ki**2&iK?u"0.'&#">54#"&54632>323##5#53h('J.-K  P:*2 4*:P@((a&&b ҂d*:( ,:*dFPPPP< 5<KR'&#"67&'&5463267>2>323##5##5#53735&'7>54#"'&"65('J. 2:*2 ;:;4*:PxPPx"P-K  ( ;(@((a&#d*:(** ,:*dFPPPPPPFFFW&b ( d 0.%3254&'326?#"&/#"&5475#53533#h('J.-K  P:*2 4*:PP((a&&b ҂d*:( ,:*dFPPPPP3%"'&546?#"'&476327#5!#5;327>54'&#"6R ,6:uCPpL: 4Y 96, R6vP:L W3 `0L]ehk7;67654'&#"%327#5#5"'&546?#"'&'&'&546?#"'&476327#5!3#53327>54'&#"3257PL:)4Y :#S}6R , ,69uCP* h  g*  89#S:6, , R6vP':L W3 @P(;7;327>54'&#"%"'&546?#"'&476327'77#5!#5xL: 4Y @&6R ,6:&\8\gPh\8z:L W3 ^&:6, R6&\8\hPg\8`0A3!3254&'326?#"&/#"&5475#535'7'3h('J.-K  P:*2 4*:xx\88\x((a&&b d*:( ,:*dP[88[P0&'&#">54#"&54632>32#h('J.-K  P:*2 4*:P@((a&&b ҂d*:( ,:*d}Sdr267.'&#"367.'#67&'5&5353254'+&5432+"=6767.54764&+326f1@.VM 2p    *  5[."v')A1>?A &* 2  F fC+86f D V+   89%  6 0$o#'' ]s %4IWj~&547&#"#472&547&7652546732#"&%#"&547>3#"547674767632#"'&#"'.5473632"&467>32#"&'&+" d2 6&6  *y,(  !  "  9+Q* 9  *## +8) u  '=i )  /"  ?  %  0 5*"6;/(1"  @Y!*3:CO^%#5.54675462'>54&"4632"64632"'#"'4%#&#"&'5632%2#"&546PE[M:'-#FdF[E#- ,Y*/   ||oGBrQE$&> qRvvRGoE >&1GG1D11D33B00B1 *#  M.?% 6-&C #+6>B73273#"'&#"&546654&/#6737!&'%'6%536u$U?VG .J),}+'*?W"*y? +A$\ ѠQw 5wR,!4.IY;?-IJsI><.=~i 'q3((I "(,06:@F'''7''7'77'3/#73#7#7'7'7'3737'7'h-"rb37>\8@ 9Xyo !q%,y- '}9} M"KF;Ab-8zOu V6}]7E kFF< 5W18 7/bxxeE P'2"&4$"3>23&4&"2267#"&'#褤`nS =N= S  XnS =N= S褤T[E$,,$E}  [E$,,$EP0!2+3#3##5#535#53264&+2FF2PPPPPPPPPFdFPP((PP P\f32644+#373#'#(88(00DxDH0`(08P8` xH>\D 7373#5'353#'\"nn"0``"0" nn``  $326?5#"#"&546;53#53#5@."Px2[EC]vRxPP PdF<xcuSRvxhxP 33!53#53#5pPHPPhPxP#!#54&"#54&"#3632632%53#5P/B/P/B/PP&*I//IB^0P!//!!//!66^BxxPX "#36;%53#5PPP[ExP@<ccP(xP!#";2#!5!264&+"&46353#5X2FF22FF2PP FdFP FdF(xP%;#"&=#53533#%53#5/!xxB^PpP!/P^BPxxP(xP !#3353#52ZZP(xPP`)1=.546323#3##5#"'#"3>23&4&"2267#"&'#HXtR"kSSk+ZPPnS =N= S  XnS =N= S5"RtXHP(PZ+kSS0[E$,,$E}  [E$,,$E`*2>2#5#"'#5&'#53&547#53>"3>23&4&"2267#"&'#htXHPPZ+kSSk"nS =N= S  XnS =N= StR"kSSk+ZPPHXP[E$,,$E}  [E$,,$EP0)1=33#3##"&546753632"3>23&4&"2267#"&'#PZ+kSSk"RtXHP nS =N= S  XnS =N= S0k+ZP(PHXtR"kSM[E$,,$E}  [E$,,$E0*2>363253#"&'#53&547#5367"3>23&4&"2267#"&'#PPHXtR"kSSk+ZnS =N= S  XnS =N= S0SSk"RtXHPPZ+5[E$,,$E}  [E$,,$E7  !%64''5673%3&h1Y((P(( %% \m+$$+R\))0!.54632>3233!535#h) # #<p-)6# #!ZDPP.%&"32653#"&5462.54632>324 n2PPSTjFd#) # #< (G1@Rv@82F#c-)6# #!Z!.54632>32h) # #<-)6# #!Z/%.54632>32.54632>32h) # #<) # #<-)6# #!Z-)6# #!Z0"&462&"26433!535#dFFdFh  pFdFFdZ  PP&"&462&"264&"32653#"&5462:dFFdFh   n2PPSTjFd#FdFFdZ  (G1@Rv@82F# "&462&"264dFFdFh  FdFFdZ  $"&462&"264"&462&"264dFFdFh   dFFdFh  FdFFdZ  FdFFdZ  0"&46233!535#dFFdFpFdFFdnPP"&462&"32653#"&5462:dFFdF n2PPSTjFd#FdFFd (G1@Rv@82F# "&462dFFdFFdFFd$"&462"&462dFFdFFdFFdFFdFFdFdFFdxX0*264&"'33#3#''75#535.547#53@  hPW-#ȼ88#-WPx  PP&> P88P >&PPG;# 547654'.547>32;#"&5"'#"&547464654.#"(/aDW ^1^j(/B/%#&6*8c(P-@%; UKP!//! #(  /!!=!#"&5#"&5#"&50(/B/P/B/P/B/PPPP!//!!//!!//!hp%#"/.'#+53254'&54763267&'.#"#"'#"&'#5327654&546327632$"&462  b 2Z<Ƞ 2/2;2  +x# l4+O" +      ,=;&.!PP/5 +%P  ( IW%        #+3;C!!%!!!6"&4626"&462"&462&"&462"&4626"&462"&4620TԴI(,,ԣI  #+3;CK!!%!!!6"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԴI(,,IIII  #+3;CKS!!%!!!6"&4626"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԴI(,,ԣIIIII  #+3;CK!!%!!!&"&462"&4626"&462"&462&"&462"&4626"&462"&4620TԠeI(,,ԣI  #+3;CKS!!%!!!&"&462$"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԠeI(,,ԣIIIII  #+3;CKS[!!%!!!&"&462"&4626"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԠeI(,,ԣIIIII  #+3;CKS!!%!!!6"&4626"&462"&462$"&462"&462"&4626"&462"&462"&4620TԴcee(,,ԣI  #+3;CKS[!!%!!!6"&462"&462&"&462$"&462"&462"&4626"&4626"&462"&462"&4620TԴIee(,,IIII  #+3;CKS[c!!%!!!6"&4626"&462"&462&"&462$"&462"&462"&4626"&4626"&462"&462"&4620TԴIee(,,ԣIIIII  #+3;CKS[!!%!!!&"&462"&4626"&462"&462$"&462"&462"&4626"&462"&462"&4620TԠecee(,,ԣI  #+3;CKS[c!!%!!!&"&462$"&462"&462&"&462$"&462"&462"&4626"&4626"&462"&462"&4620TԠeIee(,,ԣIIIII  #+3;CKS[ck!!%!!!&"&462"&4626"&462"&462&"&462$"&462"&462"&4626"&4626"&462"&462"&4620TԠeIee(,,ԣIIIII  #+3;CKS[c!!%!!!6"&4626"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԴceeee(,,ԣI  #+3;CKS[ck!!%!!!6"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԴIeeee(,,IIII  #+3;CKS[cks!!%!!!6"&4626"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԴIeeee(,,ԣIIIII  #+3;CKS[ck!!%!!!&"&462"&4626"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeceeee(,,ԣI  #+3;CKS[cks!!%!!!&"&462$"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԠeIeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&4626"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԠeIeeee(,,ԣIIIII  #+3;CKS[cks!!%!!!6"&462$"&462"&462"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԴeeceeee(,,ԣI  #+3;CKS[cks{!!%!!!&"&462"&462"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԠeeIeeee(,,IIII  #+3;CKS[cks{!!%!!!6"&462$"&462"&462"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԴeeIeeee(,,ԣIIIII  #+3;C!!%!!!&"&4626"&462"&462&"&462"&4626"&462"&4620TԠI(,,ԣI  #+3;CK!!%!!!&"&462"&462$"&462"&462&"&462"&4626"&462"&4620TԠeI(,,ԣI  #+3;CKS!!%!!!&"&4626"&462"&462&"&462"&462"&4626"&462"&462"&4620TԠIee(,,ԣI  #+3;CKS[!!%!!!&"&462"&462$"&462"&462&"&462"&462"&4626"&462"&462"&4620TԠeIee(,,ԣI  #+3;CKS[c!!%!!!&"&4626"&462"&462&"&462"&462"&462"&462&"&462"&462"&462"&4620TԠIeeee(,,ԣI  #+3;CKS[ck!!%!!!&"&462"&462$"&462"&462&"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeIeeee(,,ԣI  #+3;CKS[cks!!%!!!&"&4626"&462"&462"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeeceeee(,,ԣI  #+3;CKS[cks{!!%!!!&"&462"&462$"&462"&462"&462"&462$"&462"&462"&462"&462&"&462"&462"&462"&4620TԠeeeceeee(,,ԣI  #+3;CKS[cks{!!%!!!&"&4626"&462"&462"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԠeeIeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462$"&462"&462"&462"&462&"&462$"&462"&462"&462"&4626"&462$"&462"&462"&462"&4620TԠeeeIeeee(,,ԣIIIII  #+3;CK!!%!!!&"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԠI(,,IIII  #+3;CKS!!%!!!6"&462$"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԴI(,,ԣIIIII  #+3;CKS[!!%!!!&"&462"&462&"&4626"&462"&462"&4626"&4626"&462"&462"&4620TԠIee(,,IIII  #+3;CKS[c!!%!!!6"&462$"&462"&462&"&4626"&462"&462"&4626"&4626"&462"&462"&4620TԴIee(,,ԣIIIII  #+3;CKS[ck!!%!!!&"&462"&462&"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠIeeee(,,IIII  #+3;CKS[cks!!%!!!6"&462$"&462"&462&"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԴIeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462"&462"&462$"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠeeceeee(,,IIII  #+3;CKS[cks{!!%!!!6"&462$"&462"&462"&462"&462$"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԴeeceeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462"&462"&462$"&462"&462$"&462"&462"&462"&462&"&462"&462$"&462"&462"&462"&4620TԠeeceeeeee(,,IIII  #+3;CKS[cks{!!%!!!6"&462$"&462"&462"&462"&462$"&462"&462$"&462"&462"&462"&462&"&462"&462$"&462"&462"&462"&4620TԴeeceeeeee(,,ԣIIIII  #+3;CKS!!%!!!&"&4626"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԠI(,,ԣIIIII  #+3;CKS[!!%!!!&"&462"&462$"&462"&462&"&4626"&462"&4626"&4626"&462"&4620TԠeI(,,ԣIIIII  #+3;CKS[c!!%!!!&"&4626"&462"&462&"&4626"&462"&462"&4626"&4626"&462"&462"&4620TԠIee(,,ԣIIIII  #+3;CKS[ck!!%!!!&"&462"&462$"&462"&462&"&4626"&462"&462"&4626"&4626"&462"&462"&4620TԠeIee(,,ԣIIIII  #+3;CKS[cks!!%!!!&"&4626"&462"&462&"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠIeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462$"&462"&462&"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠeIeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&4626"&462"&462"&462"&462$"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠeeceeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462$"&462"&462"&462"&462$"&4626"&462"&462"&462"&462&"&4626"&462"&462"&462"&4620TԠeeeceeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&4626"&462"&462"&462"&462$"&462"&462$"&462"&462"&462"&462&"&462"&462$"&462"&462"&462"&4620TԠeeceeeeee(,,ԣIIIII  #+3;CKS[cks{!!%!!!&"&462"&462$"&462"&462"&462"&462$"&462"&462$"&462"&462"&462"&462&"&462"&462$"&462"&462"&462"&4620TԠeeeceeeeee(,,ԣIIIII `&0 #+3;C!!!!!"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;CK!!!!!"&462"&4626"&462"&462"&462"&462"&462"&462&(,,IIII00,,I `&0 #+3;CKS!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,I `&0 #+3;CK!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;CKS!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,I `&0 #+3;CKS[!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,I `&0 #+3;CKS!!!!!"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C `&0 #+3;CKS[!!!!!"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,IIII00,,ICC`&0 #+3;CKS[c!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICC `&0 #+3;CKS[!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣI00,,C`&0 #+3;CKS[c!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICC`&0 #+3;CKS[ck!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICC`&0 #+3;CKS[c!!!!!"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CC`&0 #+3;CKS[ck!!!!!"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,IIII00,,ICCCC`&0 #+3;CKS[cks!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICCCC`&0 #+3;CKS[ck!!!!!6"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CC`&0 #+3;CKS[cks!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICCCC`&0 #+3;CKS[cks!!!!!"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,IIII00,,CICCCC`&0 #+3;CKS[cks{!!!!!"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCICCCC `&0 #+3;C!!!!!6"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,I `&0 #+3;CK!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CI `&0 #+3;CKS!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣI00,,IC `&0 #+3;CKS[!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣI00,,CIC`&0 #+3;CKS[c!!!!!6"&462"&462"&4626"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,ICC`&0 #+3;CKS[ck!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CICC`&0 #+3;CKS[cks!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462&(,,ԣI00,,CCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CICCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCICCCC `&0 #+3;CK!!!!!6"&462"&4626"&462"&462"&462"&462"&462"&462&(,,IIII00,,I `&0 #+3;CKS!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CI `&0 #+3;CKS[!!!!!6"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,IIII00,,IC`&0 #+3;CKS[c!!!!!"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CIC`&0 #+3;CKS[ck!!!!!6"&462"&4626"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,IIII00,,ICC`&0 #+3;CKS[cks!!!!!"&462"&462"&4626"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CICC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,IIII00,,CCC`&0 #+3;CKS[cks{!!!!!"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,IIII00,,CCCCC`&0 #+3;CKS[cks{!!!!!"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCCCCC `&0 #+3;CKS!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,I `&0 #+3;CKS[!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CI`&0 #+3;CKS[c!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,IC`&0 #+3;CKS[ck!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CIC`&0 #+3;CKS[cks!!!!!6"&462"&462"&4626"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,ICC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&4626"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CICC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCCCC`&0 #+3;CKS[cks{!!!!!6"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&4626"&462"&462"&462"&462"&462"&462&(,,ԣIIIII00,,CCCCCC`073##54>7>5#0 Px;##K?P;##K?xP6#(&2$6#(&2$\D33!353#'\0"0"0 P`0 %4&"356'354&"#4623!3#2#PFdFPvvPP<##__2FF2RvvRh\D4632&#"327#"353#'\U;*G24(88(42G*;s"0"EvU-% +8P8+ %- `03 #h0{`U0# 3rhrhhh`0# дh00hh{`U0 3 hrhhh`0#32Ӡ`X0 $#2ӕVeeV3*=ܽ=`0"&6;ӕ*0x`00 3#.4673"ӕVeeV]=ܽ=`0!000` 0#3 r0r`0!000` 039r00`0!Р` 0 # 0r00`0!0Р` 03#9rr00_53267632327#"&#"327"732327#"#"&#"327#"&#"62#"&#"#"'2327632#"3276323278+ c!$A>L%&@Q8(5" - 1*    * *`c   2P^ "" "MY ,  +  E+ ' #*5 !&"$   @-  ' % A   1   MG95467632;.'&546?>7632326327"'&'.+"#"5?>7&'&546?676323&'&#"#"&547&'&#"#"&547>767#"'./"#"4;2327632+"327632327267632327#"&#"27"327#"#"&#"327#"&#"632#"&#"#"5463232632327.#&#"#"_)  ^    b 2 ' 1  3+?@@6#69$7?& "  3#  %"    . @.'  ,2^"(FAH!,FP3"( %7+   1 , ,Z F / #d    5V^%" O Y   Y!  9 . '    -  #  &+     $     .    2 #$ '  ! -  '$A A M_554&'&#"#"'327>?.'&#"#"&#"'327>7>;'.#&'327>?&'&#"#"'32763232654'.'327632327654'.'.+632327>3#"&#"#"&'>762_" ^P2   c`* *    '*1 - "5(8Q@&%L=B$!c +*# ' +E  + , YM" "7% '  -@   $"&! 5   1    0A?MG=&#"#"'&546?32>7&'&#"#"&#".'732767>7.#&'&46?27>7&'&#"#"'&546?3276322654'.'7327632327.'.+"57632327>76;2#"##"'&'#".'&#"#".'&#"2632#"&#'#"#323263232632#"'&#""32632;632#"&#"#"&'&546?>7632G%^V5       d# / F Z, , 1   +7% (#2PF, !HAF("^2,  '.@ .     "%  #3  " &?7$96#6@@?+3 1 ' 2 b   ^  )  !Y   Y O  "$'  - !  '  $# 2    .      $     +&  #    -     ' .  A A  \0^5#/3?COS_cgkosw{ '+7;GKOS_cgkw{35'32+"=435'32+"=435'32+"=435'32+"=435'32+"=435'32+"=43#53#53#'3#53#53#'3#53#53#'3#53#53#'3#53#53#35'32+"=435'32+"=435'32+"=43#53#53#'3#53#53#35'32+"=435'32+"=43#35'32+"=435'32+"=435'32+"=435'32+"=43#3#35'32+"=43#3#35'32+"=43#35'32+"=43#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#1/388 /388 /388@678867886788999999P888888888888R888888V888888568856885688888888V88888886788K6788K9957995799H,288 ,2888888,288G8888(088885688T888888888888888888R88888888888888888888V88888888888888888888+// 88 // 88 // 88668866886688888888888888888888888888888885588558855888888888888866886688d855885588a-- 99R,, 88N88,, 88`89[))88O8^558889989`88]89689989`88889689989`88889\/^5#/3?COS_cgkosw{ '+7;GKOS_cgkw{#372+"=43#372+"=43#372+"=43#372+"=43#372+"=43#372+"=43#53#53#53#53#53#53#53#53#53#53#53#53#53#53#5#372+"=43#372+"=43#372+"=43#53#53#53#53#53#5#372+"=43#372+"=43#5#372+"=43#372+"=43#372+"=43#372+"=43#5#5#372+"=43#5#5#372+"=43#5#372+"=43#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5#5//84//84//8668766876689999988888888888888888888558755875588888888888668668975597559,,82,,888882,,88880((88875588888888888888888888888888888888888888888888888888888888+/988 /988 /988698869886988888888888888888888888888888888g588858885888888888888888I69886988d8858885888a-999R,988N88G88O,888`88I99)888O88588888I99L99n8899'88G8888K9988I99L99n8899'88G88I88L88K9988I99L99n8899'88G88I88L88K99+6Wv7#/3?COS_cgkosw{ 35'32+"=435'32+"=435'32+"=435'32+"=435'32+"=435'32+"=43#53#53#'3#53#53#35'32+"=435'32+"=435'32+"=435'32+"=43#35'32+"=43#35'32+"=43#3#3#3#3#3#3#3#3#3#3#EKRREKRREKRRpJOSSJOSSJOSSuSSSSSS}RRRRRRAJSS AJSS eKOSS;2;+"+"#"&#"1#"&#"+"&"#""&+#"#"32327;22326;2#"'#"#"#"#";226322732;2"+"#"#"'#"##"#";2"+&+"+"72;2;226322*#"&#"+"322326;2326323267323323262322732"+"#"'#"""&""'&#"##"322;2326222;2;2###"&#"#"&+;2;2+"327;2323"#"&+"#326;327;23263233r       ' 1 '>   &  ^. &0 (   $( &   .    - 32 #  5. / )         , ;! < ! #  3$  !    "E !%  $   8 *        NC.'#"'&+"&#&+"5476;672>323276326?>;2&+"'.+"".#"#"'&+#"&#"/#"43327'#"'.'&+"&#"#"&5432;2;26323632#"&"#'26326;23226323236;2#'#"#"'#"##"'+"'"#;263232;2#'#"."#"&+#"#;2;232#'#'#":32;226;2323232>32632326;2;:+"+"#"'+#"&#"#+"'#"#"&+##3236;272;632#'#"'#6;2326;232;2#'#+"##*#'"'#";2#'#"&+"+"+"&4636726;27#&'#"=43232636?>;2367&+#"5767>7".".'#"54>?632672>2676;2376362;63&+"'&+"&+#"&+"'.'"#"'+"#"'#"+"54;67"&+#"'#"547&'.'.547>3>3>;237>2b   <%* < *      #$    !$ (     '" &    ! -!/$      2 %    & 1! &<  (+   _-   05      $ 0     *  + # (,  !. #  ' % !* ^ &       -%  .   W 0  0     2         b`1%"&46;26;27>7>54'.'.'#"#"&#"#"'"'".54;276;2>36362327>;263632654'."'"'"&#""&""'."&+#"&+*.54;32763262327632726;326323276;2326263254+"&'&#"+.*&462767>3227>76;276;263"'&+"'&+"#"&#.54;267>767626=&#"&#".'"&+#"'54654#"'&+"'&"&5476;26;2763227>76;254"5&'".#"&#"&+#"'.546;232636;32632765'.#"&"&'"&'.'#""'&#"&"+".'&#"+'"#"+&+"&+"547326;2;632323276;276326;26;26;272632326;327323254'&'&/"&+"#"&#&=672>;676;324# E"    !  $3  # ! < !; ,         ) / .5  # ' 3 -   .   & ($   ( 0& .^  &   >' 1 '        * 8   $  %!   0    PNC%&5430326;276?&'*&'"&''"#"."#"'&'#"54;276;>76326;27"&'.#+"'#"'&'".+#"'&+#"546;7632632763632?>;2632367*#"436726326?6;6;2632#"&#"+"#';632+#"#"'#"#"&#""&+"+"6;2632327632332+""+"#'37632372;222+#"'+"#32+"&+#"&+*#"&#+"#"'#"+"+";262226;22332+##'#"26;23232632#'#;232+"'&+"'&+"#"'#"546;27&"/##*#"'"'&+"'"&'#"4;26;76;2;6;267##"'#"5433236;226327"&/"&'"&'.'#"#"&#"'+"/"#"+'+#*#&+"&+"54>237326;2;63232;6;6326;2376;2727&+#"'#"=4767>3~2      $/ !--    & " '     (  $!    $#      * < *%<     .  %-      % ^ *!  % ' # .! ,/ # +   *    0 $       50 -_   +( <& !1 '        %    0  0          2 `c0 %#'73#3#3cTTTTTTÒ$$`x0 %'#37#'73'#37#37'#37#3NIIIs___Jt_5Jt_ÀHH`0@KOS%#"'3&547632"'&547'#.547632'.547'!!!!:# 2##%.,$##3 ",#"!2$#۷7Ʒ&(9H:$:= (9I@# ACP^]K AB 68%:): BC 7>$!@BH0H`0 ;EIM25#"'&54632#"'32?%732?#"'&546327327#"'327%%AN6F6#9 '5B;# =@MH =AF7 7' 7 =@E;"!54&"462*g褉g 0*Vitti`0   &>4&'*Pgggg0*,Ҟ*Ҟ`0#%#"&'&546 4&'67267'0/ba/0*Pggs''^VRbbRU_ӕi1Li71922`0   &%&"$7'27'64'*KK88KK880*K88$Kx88oKK`0A  &264&"%#"/"&=#"&54?'&5463254627632*褤 O O OO O O OO0*S褤$.[[. -- .[[. -- `0 &6 "264"&462&"264*褤ք^^^B//B/*褤^^^/B//B`0! hhP0`0 $2"&4! GB//B/hh/B//B0`0  %3 35462hh 0P4`0 %3 hhP0P||`0  ''353'hh^^^dPdZ0aPzzM`0  '3'7''373'hh5bK%^^^b5x~?0PL^xx?`0147%2#"/"&=#"&54?'&54632546276!            hh        0`0 %3'! 6d2fhhdh0`0!!!!00Р0`0!!!!2"&400B//B/0/B//B`0!!%!34620 00P0`0 !!3#0P@0000`0 !!%#!#70(00J0 `0 !!'7!0/900hB`09!!%!7"&54?'&5463254627632#"/"&=0ЍOO O O OO O O00P0Р -- .[[. -- .[[.`0 !!!!!!35#00@𠠠0H@`0   &4&'6 267!*g|xgu'D'0*j~4"pj84;33`0   &%&"!!$2?64'*LL9\.'0󶁁p[q;[[;;[Ќ;Zm[q;[Z;`0 !!+!0PP2 P`02 "' "&47 &462   #   #  $$0  #  $$  #+`012#"/"&=#"&54?'&54632546276}      }} ~~ }} ~~:k 7'$462"&462"x99****k99E****F: 3#462"&462"&462"PPP************:'/7#4>54&#"'>32462"&462"&462"P2<2F2+CP pKSu2<26******$6, /?L6$6,******F:36462"6462"6462"3632#4>54&#"'#F******]P>bSu2<2P2<2F2+C*P******44L6$6,$6,:26462"6462"6462"3#5#4>54&#"'>32F******PPF$P2<2F2+CP pKd<******q ($$6, /?4:*96462"6462"6462"'>753#7> 54&'F******]A P W=PE[2<2PP -#******  (; G/$6,h    0%#5#535462+53264&"53PFdFF2(( PPPP(2FFdFP PP@ #533#3#PPPPPPPPpP@.53#"&'732654.5>P2<2uSKp PC+2F2<2PPP,6$6L?/ ,6$y[''@9999[99q99$462"73"&5326**eP^^P/B/**2B^^B!//%3#PrT462"** **QQ'99Q99r462"**[**'Q'9999x $+3#5>54&#"'>32%73#773#74B2**; 0C-2FN'{1SP"Y{1SH00,'- %. Q=)P"=)V07;3#5>54&#"'>3232#"&'73264&+5373#74B2**; 0C-2FN'+B2FF2'? .3**r{1SP"H00,'- %. Q08P8%!(0=)P"P $+3#5>54&#"'>32%73#73#7#4B2**; 0C-2FN'{1SP"9H00,'- %. Q=)P" '.273#7?3#73#5>54&#"'>32%73#7{1S{1SwB2**; 0C-2FN'{1SP"=)+=)00,'- %. Q=)P"PP%73#7264&"462"{1S*<**32#"&/#"&46324&#"32&326?&#"h2**0 2**0  %  %  *<*  *<* 6 " x 73##5##5#00000x0H$/%>32#"&/#"&46324&#"32&326?&#"h2**0 2**0  %  % " *<*  *<* 6 " & !"&4632.#";5#533#'3#hRvvR@hQ:#2FF2ndPPPPvvL;&FdF2P PPP0  $(%#"&46;#"&'73265&326?5#"73#'3#IWC]uSvR5[D#D2F."Px2ZPPPPwOiiRv5,):F2T:2dPPP0;&#"'>32327#"3!!T-FK+)&-FK+)P@p ((&* ((&*3P0;&#"'>32327#"33!535#T-FK+)&-FK+)p ((&* ((&*3PPhh #'#7'37%3#hpppȏȏ{Phh #'#7'37%3#hpppȏȏ{P0 333#3#'3#8P8PPPPp PPP0 632#54&#"#373#'3#[EC]P."PPPPPPP-cuS2F<{PPP0'k0'kL &k+L &k+P!#333#@PPPPP333 3P(2#4&"#4&"#4&"#36326262FP P P PP.""\""F2'#'#'#37373xR''R''RxRO'R''R'O ś;;#'#'#373737dR''R''RdR;'R''R';p뛛032644+#7'7'".."B^^BPl88\@P$PEfE+88[0 632+#34&#"32'7'[EC]vRxPP."Px288\-cuSRvxdF<xk88[0032644+##53533#!//!B^^BPPPPPP@/B/P^^PP((P(P0 $4&#"32'632+##53533#."Px2[EC]vRxPPPPPPdF<xcuSRvxP((P0L32644+#'7537!//!B^^BP48lP48l@/B/P^^PX48lh48l40$ $4&#"32'632+#'7537."Px2[EC]vRxP48lP48ldF<xcuSRvx48lh48l6"#'#"'#654&"&546227'0DJ\4!!4\[FdF JvvZ8>4:R&F2(8( Fd88[`vvR:4>8>"dF (8(2F0'7'326?5#"#"&546;# 88\x."Px2[EC]vRP88[dF<xcuSRv@;!)&#"'>32327#"2#'##3264&#T-FK+)&-FK+)B^S>p@PP".." ((&* ((&*3E3/CPP$/;!&#"'>32327#""#36;T-FK+)&-FK+)PPP[Ex ((&* ((&*<ccPP#'3264H#'#'#3253264&#P!//!B^T=p`P*&PP!//!"A/B/P^B>[P/B/APX 3264&#"#'#3236;P!//!@P`P,I[E("A/B/P<Ȑ+%ccPAPX"#"#36;6;0PPPPP[EP[E(@<@<ccccPPC73#'PPP88PP88O0A !'57'5775''5'75'570????(((xx((((xx((y^??^??((xxB6((((xxB6((O:0 (2+3#7'75#535#535#5353264&+B^^BZPP 88 PPPPPPPZ!//!Z^^(P?88?P(PPPP/B/OL0!%'7462'#"&327'7654&"88vv">8>4:R&F2(8( Fdl88UvvR:4>8>"dF (8(2FP',#"'&4762+"&4632327654&";'"7&PyPOOPPO1'Hx2FF2-ELI3 tttTPP 5 PSQQSSQtAFdF<-# TtttP!#####333PPPPPppp? %3#'737@PPF77F5..PP((\PPP> %3!535#3%3'pp``00PP@( !!5%373575YOOdPڶPP!7(048<'5'5'5'5'5'5#'#'5#'5'5#535775'37(TI4(1Pờ#,5P6P..5P5P//5P5P057P5PPP77/`00 #'+/37;?CGKO3!35353335#3535335335353353353533533535335335353353PpPd(dPPd(d(((((((((((((P(hxPPP(( hPP((((((<((((((<((((((<((((((<(((( P`0/37W_gk"'&5476225&'&"5&'&"53676'53'53'5#532632632#527#"'#"'6"264&"26453bbMMbbMQ /< >!!>>!   ss <<<    Nx`l>AF#"&54'#"/&54632>?6'.5>76327'67;N*)(  P n 6 !4<+:: x@  8oy6#>=  U40. " )'#%3 $'  +7/, P  #'#3737'hhPPhxxxNNNNNN % #'#3737PPwdd:::d*t:0D4632#"'&'&2.'#".'327654'&547654&#"3#aM4/(A:-A*48s '  -,"++F:U[YW[u619!:.?/+&3=w:9  ! '(!:.$L`@:F0P)19#3##5##5#535#535335335#627"&'7&462"6462"((((Ƞ<(&!2!&  0  (((Ƞ<    #M%2654.46753&#"#5&'72+32+32+32+"/#53763X!/>L>:*(I*8!/>L>:*(I*  (<P 0dd0 d *>234 F - *>234 F -,*    B*PP3#'((((((0'570((((((0 3#''57(((X((((((8(((0%'570((((((0 3#''57(((X((((((؀(((0 '57'570(((((((((((((0 3#''57'57(((X((((((((((8((((((!3#'(((((( 3#'3#'((((((((((H(((0 '573#'0(((((((((X(((0 3#''573#'(((X(((((((((8(((X(((0 %'573#'0((((((((((((0 3#''573#'(((X(((((((((؀((((((0 '57'573#'0(((((((((((((((((((0 3#''57'573#'(((X(((((((((((((8(((((((((7'57(((((( 3#''57(((((((((؀(((0 '57'570((((((((((((0 3#''57'57(((X(((((((((8((((((0 %'57'570(((((((((((((0 3#''57'57(((X(((((((((؀(((((((0 '57'57'570((((((((((((((((((((0 3#''57'57'57(((X(((((((((((((8(((((((((( !3#'7'57(((((((((((( 3#'3#'7'57(((((((((((((H((((((0 '573#'7'570((((((((((((X((((((0 3#''573#'7'57(((X((((((((((((8(((X((((((0 %'573#'7'570((((((((((((((((((0 3#''573#'7'57(((X((((((((((((؀(((((((((0 '57'573#'7'570(((((((((((((((((((((((((0 3#''57'573#'7'57(((X((((((((((((((((8(((((((((((('57(((((( 3#''57(((((((((8(((0 '57'570(((((((((((((0 3#''57'57(((X(((((((((8(((((((0 %'57%'570(((((((((Ȁ(((0 3#''57%'57(((X(((((((((؀(((Ȁ(((0 '57'57%'570((((((((((((((((Ȁ(((0 3#''57'57%'57(((X(((((((((((((8((((((Ȁ((( !3#''57(((((((((((( 3#'3#''57(((((((((((((H((((((0 '573#''570((((((((((((X((((((0 3#''573#''57(((X((((((((((((8(((X((((((0 %'573#''570((((((((((((((((((0 3#''573#''57(((X((((((((((((؀(((((((((0 '57'573#''570(((((((((((((((((((((((((0 3#''57'573#''57(((X((((((((((((((((8(((((((((((( 7'5?'57((((((((((Ȁ((( 3#''5?'57(((((((((((((؀(((Ȁ(((0 '57'5?'570((((((((((((((((Ȁ(((0 3#''57'5?'57(((X(((((((((((((8((((((Ȁ(((0 %'57'5?'570(((((((((((((((((Ȁ(((0 3#''57'5?'57(((X(((((((((((((؀(((((((Ȁ(((0 '57'57'5?'570((((((((((((((((((((((((Ȁ(((0 3#''57'57'5?'57(((X(((((((((((((((((8((((((((((Ȁ((( !3#'7'5?'57((((((((((((((((Ȁ((( 3#'3#'7'5?'57(((((((((((((((((H((((((Ȁ(((0 '573#'7'5?'570((((((((((((((((X((((((Ȁ(((0 3#''573#'7'5?'57(((X((((((((((((((((8(((X((((((Ȁ(((0 %'573#'7'5?'570((((((((((((((((((((((Ȁ(((0 3#''573#'7'5?'57(((X((((((((((((((((؀(((((((((Ȁ(((0 '57'573#'7'5?'570(((((((((((((((((((((((((((((Ȁ(((0 #3#''57'573#'7'5?'57(((X((((((((((((((((((((8((((((((((((Ȁ(((%3#'(((((( 3#'3#'(((((((((((((0 '573#'0((((((((((((0 3#''573#'(((X(((((((((8((((((0 %'57%3#'0(((((((((8(((0 3#''57%3#'(((X(((((((((؀(((8(((0 '57'57%3#'0((((((((((((((((8(((0 3#''57'57%3#'(((X(((((((((((((8((((((8((( !3#'3#'((((((((((((( 3#'3#'3#'((((((((((((((H((((((0 '573#'3#'0(((((((((((((X((((((0 3#''573#'3#'(((X(((((((((((((8(((X((((((0 %'573#'3#'0(((((((((((((((((((0 3#''573#'3#'(((X(((((((((((((؀(((((((((0 '57'573#'3#'0((((((((((((((((((((((((((0 3#''57'573#'3#'(((X(((((((((((((((((8(((((((((((( 7'5?3#'(((8((((((8((( 3#''5?3#'((((((8((((((؀(((8(((0 '57'5?3#'0((((((8(((((((((8(((0 3#''57'5?3#'(((X((((((8((((((8((((((8(((0 %'57'5?3#'0((((((8((((((((((8(((0 3#''57'5?3#'(((X((((((8((((((؀(((((((8(((0 '57'57'5?3#'0((((((((((8(((((((((((((8(((0 3#''57'57'5?3#'(((X((((((((((8((((((8((((((((((8((( !3#'7'5?3#'((((((8(((((((((8((( 3#'3#'7'5?3#'((((((((((8((((((H((((((8(((0 '573#'7'5?3#'0(((((((((8((((((X((((((8(((0 3#''573#'7'5?3#'(((X(((((((((8((((((8(((X((((((8(((0 %'573#'7'5?3#'0(((((((((8((((((((((((8(((0 3#''573#'7'5?3#'(((X(((((((((8((((((؀(((((((((8(((0 '57'573#'7'5?3#'0(((((((((((((8(((((((((((((((8(((0 #3#''57'573#'7'5?3#'(((X(((((((((((((8((((((8((((((((((((8((( '573#'(((8((((((((( 3#''573#'((((((8((((((8((((((0 '57'573#'0((((((8(((((((((((((0 3#''57'573#'(((X((((((8((((((8((((((((((0 %'57%'573#'0((((((8((((((Ȁ((((((0 3#''57%'573#'(((X((((((8((((((؀(((Ȁ((((((0 '57'57%'573#'0((((((((((8(((((((((Ȁ((((((0 3#''57'57%'573#'(((X((((((((((8((((((8((((((Ȁ(((((( !3#''573#'((((((8(((((((((((( 3#'3#''573#'((((((((((8((((((H(((((((((0 '573#''573#'0(((((((((8((((((X(((((((((0 3#''573#''573#'(((X(((((((((8((((((8(((X(((((((((0 %'573#''573#'0(((((((((8(((((((((((((((0 3#''573#''573#'(((X(((((((((8((((((؀((((((((((((0 '57'573#''573#'0(((((((((((((8((((((((((((((((((0 #3#''57'573#''573#'(((X(((((((((((((8((((((8((((((((((((((( 7'5?'573#'(((((((8((((((Ȁ(((((( 3#''5?'573#'((((((((((8((((((؀(((Ȁ((((((0 '57'5?'573#'0((((((((((8(((((((((Ȁ((((((0 3#''57'5?'573#'(((X((((((((((8((((((8((((((Ȁ((((((0 %'57'5?'573#'0((((((((((8((((((((((Ȁ((((((0 3#''57'5?'573#'(((X((((((((((8((((((؀(((((((Ȁ((((((0 '57'57'5?'573#'0((((((((((((((8(((((((((((((Ȁ((((((0 #3#''57'57'5?'573#'(((X((((((((((((((8((((((8((((((((((Ȁ(((((( !3#'7'5?'573#'((((((((((8(((((((((Ȁ(((((( 3#'3#'7'5?'573#'((((((((((((((8((((((H((((((Ȁ((((((0 '573#'7'5?'573#'0(((((((((((((8((((((X((((((Ȁ((((((0 #3#''573#'7'5?'573#'(((X(((((((((((((8((((((8(((X((((((Ȁ((((((0 %'573#'7'5?'573#'0(((((((((((((8((((((((((((Ȁ((((((0 #3#''573#'7'5?'573#'(((X(((((((((((((8((((((؀(((((((((Ȁ((((((0 #'57'573#'7'5?'573#'0(((((((((((((((((8(((((((((((((((Ȁ((((((0 #)3#''57'573#'7'5?'573#'(((X(((((((((((((((((8((((((8((((((((((((Ȁ((((((462"  8   3#'462"(((  (((   '57462"0(((x  (((   3#''57462"(((X(((x  (((8(((   %'57462"0(((x  (((   3#''57462"(((X(((x  (((؀(((   '57'57462"0(((((((x  ((((((   3#''57'57462"(((X(((((((x  (((8((((((   !3#'462"(((  (((   3#'3#'462"(((((((  (((H(((   '573#'462"0((((((  (((X(((   3#''573#'462"(((X((((((  (((8(((X(((   %'573#'462"0((((((  ((((((   3#''573#'462"(((X((((((  (((؀((((((   '57'573#'462"0((((((((((  (((((((((   3#''57'573#'462"(((X((((((((((  (((8(((((((((   7'57462"(((  (((   3#''57462"((((((  (((؀(((   '57'57462"0((((((  ((((((   3#''57'57462"(((X((((((  (((8((((((   %'57'57462"0((((((  (((((((   3#''57'57462"(((X((((((  (((؀(((((((   '57'57'57462"0((((((((((  ((((((((((   3#''57'57'57462"(((X((((((((((  (((8((((((((((   !3#'7'57462"((((((  ((((((   3#'3#'7'57462"((((((((((  (((H((((((   '573#'7'57462"0(((((((((  (((X((((((   3#''573#'7'57462"(((X(((((((((  (((8(((X((((((   %'573#'7'57462"0(((((((((  (((((((((   3#''573#'7'57462"(((X(((((((((  (((؀(((((((((   '57'573#'7'57462"0(((((((((((((  ((((((((((((   %3#''57'573#'7'57462"(((X(((((((((((((  (((8((((((((((((   '57462"(((  (((   3#''57462"((((((  (((8(((   '57'57462"0((((((  (((((((   3#''57'57462"(((X((((((  (((8(((((((   %'57%'57462"0((((((  (((Ȁ(((   3#''57%'57462"(((X((((((  (((؀(((Ȁ(((   '57'57%'57462"0((((((((((  ((((((Ȁ(((   3#''57'57%'57462"(((X((((((((((  (((8((((((Ȁ(((   !3#''57462"((((((  ((((((   3#'3#''57462"((((((((((  (((H((((((   '573#''57462"0(((((((((  (((X((((((   3#''573#''57462"(((X(((((((((  (((8(((X((((((   %'573#''57462"0(((((((((  (((((((((   3#''573#''57462"(((X(((((((((  (((؀(((((((((   '57'573#''57462"0(((((((((((((  ((((((((((((   %3#''57'573#''57462"(((X(((((((((((((  (((8((((((((((((   7'5?'57462"(((((((  (((Ȁ(((   3#''5?'57462"((((((((((  (((؀(((Ȁ(((   '57'5?'57462"0((((((((((  ((((((Ȁ(((   3#''57'5?'57462"(((X((((((((((  (((8((((((Ȁ(((   %'57'5?'57462"0((((((((((  (((((((Ȁ(((   3#''57'5?'57462"(((X((((((((((  (((؀(((((((Ȁ(((   '57'57'5?'57462"0((((((((((((((  ((((((((((Ȁ(((   %3#''57'57'5?'57462"(((X((((((((((((((  (((8((((((((((Ȁ(((   !3#'7'5?'57462"((((((((((  ((((((Ȁ(((   3#'3#'7'5?'57462"((((((((((((((  (((H((((((Ȁ(((   '573#'7'5?'57462"0(((((((((((((  (((X((((((Ȁ(((   %3#''573#'7'5?'57462"(((X(((((((((((((  (((8(((X((((((Ȁ(((   %'573#'7'5?'57462"0(((((((((((((  (((((((((Ȁ(((   %3#''573#'7'5?'57462"(((X(((((((((((((  (((؀(((((((((Ȁ(((   %'57'573#'7'5?'57462"0(((((((((((((((((  ((((((((((((Ȁ(((   #+3#''57'573#'7'5?'57462"(((X(((((((((((((((((  (((8((((((((((((Ȁ(((   %3#'462"(((  (((   3#'3#'462"(((((((  ((((((   '573#'462"0((((((  ((((((   3#''573#'462"(((X((((((  (((8((((((   %'57%3#'462"0((((((  (((8(((   3#''57%3#'462"(((X((((((  (((؀(((8(((   '57'57%3#'462"0((((((((((  ((((((8(((   3#''57'57%3#'462"(((X((((((((((  (((8((((((8(((   !3#'3#'462"(((((((  ((((((   3#'3#'3#'462"(((((((((((  (((H((((((   '573#'3#'462"0((((((((((  (((X((((((   3#''573#'3#'462"(((X((((((((((  (((8(((X((((((   %'573#'3#'462"0((((((((((  (((((((((   3#''573#'3#'462"(((X((((((((((  (((؀(((((((((   '57'573#'3#'462"0((((((((((((((  ((((((((((((   %3#''57'573#'3#'462"(((X((((((((((((((  (((8((((((((((((   7'5?3#'462"(((8(((  (((8(((   3#''5?3#'462"((((((8(((  (((؀(((8(((   '57'5?3#'462"0((((((8(((  ((((((8(((   3#''57'5?3#'462"(((X((((((8(((  (((8((((((8(((   %'57'5?3#'462"0((((((8(((  (((((((8(((   3#''57'5?3#'462"(((X((((((8(((  (((؀(((((((8(((   '57'57'5?3#'462"0((((((((((8(((  ((((((((((8(((   %3#''57'57'5?3#'462"(((X((((((((((8(((  (((8((((((((((8(((   !3#'7'5?3#'462"((((((8(((  ((((((8(((   3#'3#'7'5?3#'462"((((((((((8(((  (((H((((((8(((   '573#'7'5?3#'462"0(((((((((8(((  (((X((((((8(((   %3#''573#'7'5?3#'462"(((X(((((((((8(((  (((8(((X((((((8(((   %'573#'7'5?3#'462"0(((((((((8(((  (((((((((8(((   %3#''573#'7'5?3#'462"(((X(((((((((8(((  (((؀(((((((((8(((   %'57'573#'7'5?3#'462"0(((((((((((((8(((  ((((((((((((8(((   #+3#''57'573#'7'5?3#'462"(((X(((((((((((((8(((  (((8((((((((((((8(((   '573#'462"(((8(((  ((((((   3#''573#'462"((((((8(((  (((8((((((   '57'573#'462"0((((((8(((  ((((((((((   3#''57'573#'462"(((X((((((8(((  (((8((((((((((   %'57%'573#'462"0((((((8(((  (((Ȁ((((((   3#''57%'573#'462"(((X((((((8(((  (((؀(((Ȁ((((((   '57'57%'573#'462"0((((((((((8(((  ((((((Ȁ((((((   %3#''57'57%'573#'462"(((X((((((((((8(((  (((8((((((Ȁ((((((   !3#''573#'462"((((((8(((  (((((((((   3#'3#''573#'462"((((((((((8(((  (((H(((((((((   '573#''573#'462"0(((((((((8(((  (((X(((((((((   %3#''573#''573#'462"(((X(((((((((8(((  (((8(((X(((((((((   %'573#''573#'462"0(((((((((8(((  ((((((((((((   %3#''573#''573#'462"(((X(((((((((8(((  (((؀((((((((((((   %'57'573#''573#'462"0(((((((((((((8(((  (((((((((((((((   #+3#''57'573#''573#'462"(((X(((((((((((((8(((  (((8(((((((((((((((   7'5?'573#'462"(((((((8(((  (((Ȁ((((((   3#''5?'573#'462"((((((((((8(((  (((؀(((Ȁ((((((   '57'5?'573#'462"0((((((((((8(((  ((((((Ȁ((((((   %3#''57'5?'573#'462"(((X((((((((((8(((  (((8((((((Ȁ((((((   %'57'5?'573#'462"0((((((((((8(((  (((((((Ȁ((((((   %3#''57'5?'573#'462"(((X((((((((((8(((  (((؀(((((((Ȁ((((((   %'57'57'5?'573#'462"0((((((((((((((8(((  ((((((((((Ȁ((((((   #+3#''57'57'5?'573#'462"(((X((((((((((((((8(((  (((8((((((((((Ȁ((((((   !3#'7'5?'573#'462"((((((((((8(((  ((((((Ȁ((((((   %3#'3#'7'5?'573#'462"((((((((((((((8(((  (((H((((((Ȁ((((((   %'573#'7'5?'573#'462"0(((((((((((((8(((  (((X((((((Ȁ((((((   #+3#''573#'7'5?'573#'462"(((X(((((((((((((8(((  (((8(((X((((((Ȁ((((((   %%'573#'7'5?'573#'462"0(((((((((((((8(((  (((((((((Ȁ((((((   #+3#''573#'7'5?'573#'462"(((X(((((((((((((8(((  (((؀(((((((((Ȁ((((((   #+'57'573#'7'5?'573#'462"0(((((((((((((((((8(((  ((((((((((((Ȁ((((((   %+1462"3#''57'573#'7'5?'573#'  h(((X(((((((((((((((((8(((8  0(((8((((((((((((Ȁ((((((`0!%!!P000P0`0!!#P0P`03!!5@P@0PPP`03!5P0P0P`0 !!7!'!0PߦߦB00GBߦ`0 !!!!!!000PPPP`0 46  7'7&"64'2*K88oK=8pK3*KK১8pKç8`0264&"6  462"P褤*FdFFd<褤S*6dFFdF`0%3#!5PP@0@P`0 !!5!!!00000P`0 46  !."!26*ր*ҞҞ3*gg0!#"&=46;2PB^^BPB^^^BPB^^BPB^0!!pp0#"&=46;2PB^^BPB^^P^BB^^BB^0!!p`0!!000P@ .467%'7#53'7)`ss`)O]]W8߃8kE;;E08P8DP@ 7'>4&3#'D)`ss`)O]]8߃8E;;E08P8`01!0Р!#";2#!5!264&+"&46353#5X2FF22FF2PP FdFP FdF(xPPP@ 7'>4&.467)`ss`)O]])`ss`)O]]E;;E0E;;E0     6l*l*02#!"&=462!!"&=463#"'%&47%2632  `  r   d  @  p  YY  p  p$p /2#!"&546;2+!#"&463"&54762#  `   r  q"o  @    n  Q 02"&=!!5462#!"&5463"&=46323  r  `    d p  YnY  p    p$p/2+"&46;!32+"&54632"'&5463      q"q  @  n   p Q 6 3#462"@PP ****3#'3#462"PPPPF****C!#'#53'33733+6`M-@V@@V@-MVJ%PP\ `0 7;?C5#35#35'35##3=#75#!5#535#535#535!3#3#3#35#5#!35#PPPPPPPPPPPPPPPPPP0PPPPPPPPPP@PPPPPPPPPPPPPРPPPPPPPPPPPPPPPPOL0!%'7462'#"&327'7654&"88vv">8>4:R&F2(8( Fdl88UvvR:4>8>"dF (8(2F`07 hohP0!%"&=3#;54&+;#"&5!2B^P/!P/!c((@B^PF2xP(RvPtG1!<632&#"327#"%#363"cFuT0UB^^BU0TuFcPP[EPƍK>G^^G>KccP< 3#5#534632&#"327#"Ї0cFuT0UB^^BU0TuFc_P1PƍK>G^^G>KP373#535'75#3#5#5348lPP48lPP48lPPh48lYP1PP%;#"&=#53533#%3##!0/!((B^PPPPPpP^!/P^B3"264&"*y} C    HdpU,RNc+@K+M;&&D ,ptP2O:+- 3H,&&-`0!)19AQ" &547&5474.#526263"264"2644&"2"264265#".5C0-[[-0C}`0\0`}&&5&&~&&&&mmH=`=RN=JA]]]]AJ=NRoo&&&&&&&&&\OO\-`0$,7>74#"'67>7.'# 264&"h@K@+cNR,UpdH C }(&&C_-+:O2Ptp,%D&&P`0)3#"'>323267#"&54>54&PP(3STPcRvvR^B3STPcRvvR^PP0&!=LS9); $&!=LS9); $%73#53##53f(Ddd(ȁ3Ȕ#((P(D%3#5654&#"'>323##53‚Ƞ#1 (8%);A!dd(((I &0X((P(D",%3264&+53264&#"'>32#"&'3##53"####0 (7%*::*%8dd(2   (  #2#%O((P(D %3733##5#3##53>>x(((xdd(p>(r((P(F %32#"&'73264&+53%3##536);;)!3 &*##^rdd(Ȍ):) d(((P(@`0!!!!@pP`0 3'!5!#5#5{~p@P{#P@P"3!!"&=463!53220RNNR0Р@2P2PNRPRNPPP%26=4&#!5!2#!50220RNNRP2P2PNRPRNP0 #3#''57'57'5?'573#'(((X((((((((((((((8((((((8((((((((((Ȁ((((((0 #3#''57'573#'7'5?3#'(((X(((((((((((((8((((((8((((((((((((8(((0 %'573#'7'5?'573#'0(((((((((((((8((((((((((((Ȁ(((((( 3#'3#'7'5?'57(((((((((((((((((H((((((Ȁ((( !3#'7'5?3#'((((((8(((((((((8(((0 '57'573#'7'5?3#'0(((((((((((((8(((((((((((((((8((( 3#'3#'7'5?'573#'((((((((((((((8((((((H((((((Ȁ((((((0 #3#''573#'7'5?'573#'(((X(((((((((((((8((((((8(((X((((((Ȁ(((((( 3#''5?'573#'((((((((((8((((((؀(((Ȁ((((((0 3#''573#'7'5?'57(((X((((((((((((((((؀(((((((((Ȁ(((0 #3#''57'573#''573#'(((X(((((((((((((8((((((8(((((((((((((((0 '57'57'5?'573#'0((((((((((((((8(((((((((((((Ȁ((((((0 %'57'5?'573#'0((((((((((8((((((((((Ȁ((((((0%'570((((((0 '57'573#'7'570((((((((((((((((((((((((( !3#'7'5?'57((((((((((((((((Ȁ(((0 3#''57'57'5?'57(((X(((((((((((((((((8((((((((((Ȁ(((0 %'57'5?3#'0((((((8((((((((((8(((0 %'573#'7'5?3#'0(((((((((8((((((((((((8(((0 3#''57'5?'573#'(((X((((((((((8((((((8((((((Ȁ((((((0 3#''57'57%'573#'(((X((((((((((8((((((8((((((Ȁ(((((( 3#''5?'57(((((((((((((؀(((Ȁ((( 7'5?3#'(((8((((((8(((0 3#''57'57(((X((((((((((8(((((( !3#'7'5?'573#'((((((((((8(((((((((Ȁ((((((0 '57'573#'7'5?'570(((((((((((((((((((((((((((((Ȁ(((0 %'573#'7'570((((((((((((((((((0 '57'573#''573#'0(((((((((((((8((((((((((((((((((0 3#''57'573#'(((X((((((8((((((8((((((((((3#'((((((%3#'((((((!3#'((((((P"&54676323654.'fF4,43PKZKG%#64,c81(N2<-D%PL%O"" (N3"&5467632P4,4fF4,43j(N81(N %4#"327>3"&5467632)#)#P4,4fF4,43J++j(N81(Nx=XS %"&5467624#"327>XMCNjMCNj)#)#(O81(O81++0 327>54#"#46762#"'@)#)#P4,4fF4,43F++Z(N81(N0#46762#"'@P4,4fF4,43P(N81(NP2#"'#4.547467fF4,43PKZKG%#64,81(N<-D%PL%O"" (N`r #463!!"^vRJJRv^r =32#54&#RvҠvR`r %"#463!vRJJRv`^r =32#4&#RvҠvRJ`^r#3^`r !!!#hrȠ ^r!!^r`r+3,\GY`r#53ݲYjr%!"&463!!"3kk);;) ֙;R;`^r #&+5325!NZZS^ _'`r##3qq/q`^r#3#5^qq0 !"&=33RvrvR^0 3+53265vR0Rv03!!r0^r=!^Ҡ0#373)b..,#Q^[[#00 ^0#^0^r!5r^0+532654&'NkZZ);0--k;)1 03#3q0^q^0#'535^qqM0qMM`0!!000`0 5!#5!5! !!ZZhZZZZZZZ`0 !573'3! 5!5!ZߏZFZZZZZvZZZ`0 #'+/37;?CGKOSW[_cgko5335335353353353353533533535335335335353353353533533533535335335353353353353gggfgggggfgggggfgggggfgggggfgggggfgggggfgggggfgggZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ`0 #'+/37;?CGKOSW[_cgko#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5%#5##5##5%#5##5##5##5iggfggigggfgggiggfggigggfgggiggfggigggfgggiggfggigggfgggFZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ `0y3#3#3#3#3#3#3#3##535###5353535#####53535353535######!!33333335#535##53535###535353%333#5#5#733#5#73#35353535353535#######5353535353535######53535353535#####535353535####5353535###53535##535#----------------------------------------kh-------------------------Z----Z----------------------------------------------------------0------------------------------------------------------------------------------------------------------------------------------`0!! 00`03#00D (3#7#264&"'462"&547&6264&"|Ȁ0x#2##2K;R;;R;K2##2#  <####  `0 33 5735'3'5!'5`TLThT0T080p8ThLT`L0`T0T`0 ! 3%37737308ThLT`L0`T0TT8T8ThL`0T0005!!!!00ȴ`0 75'%!!ZZZ0MZZZ0`0 353'35%!!PP0(PP0`0!!!5#7654&+3250C0^B!/00P0@B^P/! Ϻ`0 2#)"&5463!hӕhӕ0ӕhӕh `0 #'/7!!35335335#35335#5#335#5##35335#5#335#5#0PPPPPPPPPPPPPPPPPPPPPPPPP000PPPPPPPPPPPPPPPPPPPPPPPPZ0!!Zv0Z`!!Zv`v!!vv0!!v0`03#!!ZZ000`03#!!>000`0!!!!hh000`0!!!!h000`0!!3#>000`0!!3#vZZ000`0!!!!000ZZ`0!!!!000Z>`0!!!!000Z`0!!!!000Z`0!!!!000>Z`0!!!!000ZZP@3#@P@!!h@`0!!00h`0!!0`0!!0hh`0!!0hhhh0!00!00`0!000h`0!00`0 00`0000h`0 hh0`0!00`5!0`Рh`0!00`0!000h`05!h`05 !hh0h`0!!hhh`0 !hhhhh0`0! !000`0!1!0005!1!hhh` hhhh 52644RvvRtPPvvP "&463"3ttRvvRPPvv2tP0"&463ttP`0 5!!5264&0tP0P`0 "3!!tt0PP%!!53@@РPPPPpn|3#5#!5#5353!vZZ򴴴|ZZZZZZ3#5"#"&54>3230PP.#O6pX9(@)Q6PW!9+`03!#'7'!5350xxrxxѠ0PxxxxP`0!!!PP`0!5!!5000P0P`0!%!!0P0`+ 5!'!!>aϠPP+%EPP@7#5!53!PP PP#33#PPP0 P`0#5!#@@PP0=7'''7''7'77'7'8888888888889999888888888888999DL '  98K88K88888D L ' 7 ' 78K88K88LL8||8LL8|`0#462#4&"PP`Ħ`PKKKę`02653"&5PKKP`Ħ`0K`0#3!535!3!53#5!#!5#5!ccccccczc>ZZ‡ZZDL %'''7'7l8\\8l8䄃m8[[8m8`0;"'#4.'"'#4>767.#5262>3,YA68S<-Z'@; b ;@'Z-7&'# v6AZ+BFJNRX\`dhltx|2#"'&'&54767636753675367####6?07#534'##5#5#5#5#67#5#5&'#5#5#5#5#5#53&'#5#5#5#5#753&'#5#5#5#753&'#5#5#1#75&'#5#5#1#7535&##5#1#'35#755hggZ[ggZ[ #  (--- -----)---- ----#---!_ ---!!Z --""----""-- !Z 3Fi0Z[ggZ[gg # ---( ------------------; ----------------- !--------------#---------- -------!(-------!{- ----"O( !ON>R`#3#3#333353333!5;#35#X((((x2.">2.""&/526?5"&/526?P>H< >H< >H< >H< 0>H< >H< >H< >H<   P  (  P  P`73#!3#'3'5#'35!3#'@nM+p(^F$GPPP0P (M+PPȎPb01%#"'#"&463263247327&547&#"&#"32bZ7*&&*RvvR*&&*N971(((#-"> ."".2FF2-!0Aƍ?;N3Y|P((P()Le=7))^^Pb064632632#"'#"47PvR*&&*M:71)Z5*&&*Rz(((=ƍ?:O3Y4=P((P((#3".%352>73#P## )&.!P#++# ) PPpK+&TqrrqT'+KpP%3#=34632&#"327#"xxxHtB^^Btxxxz^^zP%3533#535#3}}(((d-}( ((dd(P33533#535#30PPx}}(((d-lP }( ((dd(0 3##'731v7887 P8888` #533'7'7#v7887P 8888P !462"&$"&462"&462"&462Pdddd0*)8))871D11D)FddFGddD[:((:)D11D1A+0"#"'&'&'.'&'.'&'4&5&5476767&'.'&'4&/&54/&7&57454'&76&546;632632766326326323267632762>3663263262232654'&#"2654#"'"2654&32654'&#".#&#"3276'3267654'&#""7654'.'6=4&74#"276767'654'&'.'#&'&'"'&'"&##"&#"#"&#"''''#3232767'&32?54&7&5767327&'4327"'&767'767'6767#"767#4>767#67"#"'7&#"47&&767&7"&67'&4'&#"76*  )'"&++%$            #P-  .*&'.+|  $&# '  ! j&BA.               H $1 &) -B ! /           ^'   2 + .  "/ .*       %1l),  !,!" () i     ,f  1  $#  (         #I   '     +  '3A2#"'%&47%6:"&5462"&5462#"&5462+"&54$  c  q  s  q  j j  j  j  i  '3?4632#"&52"&5462#"5462"&5462"&54   v  q r  r     j  j  j  j  ^`r0%B2"&=46;5462%354&"5!26'22+#"&=#"&54?63T ܜ AddB\B?byy +    . D nm AGddGAAAA/AAVyy+    / >R"04@D7#"/&54?6235432#"&=#'+"&=46;2#3%+"=4;2#311 D11 C{c cDDmח01 ""01 "@c b D0 7!".'7462&RpR&ss() ## 4R>0763&547"&547676=47#.54>7>767676>767627>7632+"327>32"&46=#"54767677326765567>7>7647676326326;2"&#&+"'&o  N  +  CG  7c  7@6   /&!%/ O & Mk(   -G [ 6 "H8  <     +        "       8 D  B  +  `0#/ &6264&"%3##5#5354635325.=#"褤4fP`03#52>%3#@/632327&#&+654'+54'"1'"&=&+"547+654'#&'467&54>7>3#"&'&'#"'&5432325&#"32632#"'632#67463j$f ! # &"O :j#&    9  Ea< &*+*   $8(**]PW.    3  & $ (   p(,& . ){<=mhH?2 E=Q/'&H.  `$>IQ]fs6654&#"&#&'326;6=477327.'"&#"7.4654654;546323.;634.".'"&#"4>7>32327654&547&54653254&'"67&#"632&4&'7&#"63232#&'263256;27654&'52632#&54654'&546=.''45#" )'   4  . 1     & "    >I  6 &  &   & & a +; =)#"1 l :  *  =0DT# i      9  x 0  &=      5 $ 6 C b !=H"1 : & N p  ( $%@ s* l0 %>32#"2634654&53##"';72.'#"'&'327654&'>=67.4&+64&5.'.5474&547>7#'674&46=367&73.5274654'&%"'!# ' T" 9'% ?' :&.$87  ( MJ  #3  X  )  1.* U}9   *  "~ f O  B  )8 !  B>1 M - ' !I[ *$ !r z c  bG .$ *$ J < E  ?I XIO   7 0bx7>767&'&'632#532>7654'#"&+67#52632.'>7327"464+"#"&5>7>322#"'3%3#"&+4>7&5327'52632,/ - ! +& %;%*#CK` :) "&  4c7 7 :  EZ= %#V % ? >,  ,- !#*mE !$!: #H )"<WD2xu aBFF)   V)   F `0!!000`0 %353%!!@PPPp0PPP@P0`0 35#35%!!PP0P0`0##5;5#5##5##3#33533535#!!PPPPPPPPPPPPPPP 0@PPPPPPPPPPPPPPP@0`0/%"&'35>54.546327.'5!!!@3STjDPUsRvvR^B3STjDh0UsRvvR^P&!5H SRO3); $&!6HS0RO3); $`0 #'7'462"&264&"462"&264&"!!8@8  hFdFFdJ  hFdFFd*0l8@8T  ZdFFdF  ZdFFdF@0`0.264632#"6"&46267#.'654&"3273&!!/!1W=K!BB//B/0"d 0^^00^BdWd&0y:)b***5K%&76LL67&+@>X<&60`035%!!@Pp0P0`0 .467'!!#!!O]]O"UVeek0050=ܽ`0 !!3!!>4&O]]O"UVee0050=ܽ`05#'7357'7'%!!Pq(qq(qPq(qq(0]BFAAFBBFAAF0`0 #33535#5%!!@Pp0PP0`0%7!!90a90`07!5!!0PP@0`0 $264&"!!**0G**0`0'%!!48080480840`06462"264&"%!!FdFFdvvv0^^^ƍƍP0`0 73#%!!$Q1Q0zHEP0`0%>54&#">32!5!!, #YE8uSKp PC+2FPP0PC?P6L?/ %11PP0`0#'732654'64&#">32+32#"&!!O pLSu<?,'lL?/ *P):)"0`0#5'33535##%!!PQPP9Y0W"uddP,P0`0!5!32#"&'3264&+'!!,2FF2'? LiARvvRn0P/B/0>^^0`0!7&#"264&#"54632462"!!@:SRvvvvRC5F2,FdFFd0}4/^BB^^^ !/B//B/0`0 !35%!!!^0Pp3P0`0#6462"2654'64&""&462%!!FdFFd<XX>?,'lL**0`0!%326=4&"327#""&462%!!@:SRvvvvRC5F2,FdFFdf0c4/^BB^^^ !/B//B/0`0264&"264&"!!****07****0`0 %7264&"%!!@9k**0a9**0`0 7'7%!!8,080`0 7!5%!5%!!p0PPPP0`0 7'%!!80t80`0%3=4>54&#">32!!@P2<2uSKp PC+2F2<20PPPP,6$6L?/ ,6$0`0$(%"&46;34&#";5#"&4632#"!!!//!PP^B((cc!/PB^^0 PP1GPvv(G12F0`073!'35!3'#%!!.PP@Pr0%״)P0`0 32+7!!2654'654&#532!!J>X4 L6))I0* X>F,%16Lp):)0`03267'#"&46327.#"'!!PcFuT0UB^^BU0TuFc0SƍK>G^^G>KP0`032+264&+!!B^^BccP0^^Pƍ 00`0 !5!!5!5!5!!! p0P PP0`0 !5!35!5!!! P0P P0`0%#"&46327.#";#!!̌B^^BU0TuFcc0d^^G>KƍP|0`0 35!3#!5'!!PP@PP0 ഴP0`0 3#35#35%!!PPPP 0PPP@PP0`03#"&'326=35%!!@PF2#:Qh@RvP0P2F&;LvRPP0`0 35737#'!!PPxpp0 hxP0`0 !5!'!!Pp0 PP0`0 ;73#'#'!!PPP88P0XุP0`0 ;3##'!!PPX8P8P0XXP0`06462"264&"'!!^^^ƍ0^^^ƍƍP0`032+7!353264&%!!!//!PB^^.0/B/ ^^P0`0 %#"&462'$3277'654&"'!!/GB^^^'Qc>4b8Z>0G ^^^B:.Qzƍa8[D]cP0`0 !3533'>54&32+!!Pp=T^!//!0 [>B^P/B/@0`0%)%"&'32654.546327.#"!!@3STPcRvvR^B3STPcRvvR^~0P&!=LS9); $&!=LS9); $0`0 3335%!!xP0PpPP0`026=#"&='!!PƍP^^0ccB^^BP0`0 !# #!!VV0L 00`0 373#'#'!!>8>>8Vz>8>z0 FP0`0 !'7#'#37!!ppp000`0 35#/!!?Pr0P0`0 !!5!5%!!PXX0P8PX8P0`0 #!3#5#3000P0`07!!l808d088d0`0 ##373#PPP0`0 77''!! \\80L[[80`0!#5!#PP00PP`07'%!!ߕ8080`0 646;#"73#"32!!F2x (%0"PRv]CE{0dFx) cvRSu00`0 $+5>325#32654&#"%!!F2x (%0"PRv]CE0dFx) vRSu0`03267'#"&46327.#"%!!vR@hQ:#2FF2#:Qh@R0vL;&FdF&;L0`0 646;#"73##"32!!F2x (%0"PPxRv]CE{0dFx) cxvRSu00`0;5#"&'!54&"#>2!!vR&> 9v >L>40vP-#(Rv#--0`0#"#3335#46;%!!XxB^P/!x0^BPP!/x0`0 $%#"'3265#"32&46;#"!!F2D#DvSu]CWF2x "V"0w'2F:),5vR@iiT:d !80`05#35>32354&#"%!!PP (%0".P]CE0-) F2Su0`0 3#!5#5!!!3@0@PPPP@0P`0%7&"3265##"54623!!349#dFjTSPP2n 0P9#F28@vR@1G(0P`0 3573'7#'!!PPrr0gP/(0`0 3#!5#%!!p0PPP(0`0!!54&#"&#"5#3546235462!!^BI//I*&PP/B/P/B/0B^66p!//!!//!00`05#35>32354&#"%!!PP (%0".P]CE0-cp) F2Su0`06462"&264&"%!!FdFFdvvv0dFFdFʤvvv0`0 5#3532654&#"+5>32%!!PPxRv]CEF2x (%0"N0-cxvRSudFx) 0`0 646;#"73#"32!!F2x (%0"PRv]CE{0dFx) vRSu00`035#"5#35>%!!xxE[PP (%00@Pccp) 0`0#";2#!!264&+"&46;%!!2FF22FF20FdF PFdF 0`0%535#5##3;5#"&!!P^Bxx!/p0PxxPB^P/0`0%3##"&=#32!!PP (%0".P]CE{0cc) F2Su00`0 !# #!!ZZ0p00`0 373#'#'!!;4MM4WoL6Lo0p0`0 #'#373'!!hpppp_0ȏh0`0"%#"'3265##"&=#32!!F2D#DvP "V".P]CWi0w'2F:),5vR@ !8:*Ki0`0 !!5!5%!!0P8P80`0"!!"+3235#"&54'6546;53RvF2((2Fvz(2FPPF2(vR2FPF2RvPF2d<7'#"&46327.'50@E[[EP4PQ:#2FF2#:QP400TooTT G2&FdF&2G T`0!!#"#33265#+535#46;0xB^PPB^P/!/!x00^BP^B!/P!/`0#!!&"'7277'64'7462"0x8x8x x8x8x8x x  00x x8x8x8x x8x8x  `0!!#33535#7#'0?Pr00PP`0 !3!!#!@P@P0@0@`05!!32+"&46654&+"&46;5#";2+326540PPF2P2FF2P2F00  x".2F PF2."".2F PF2.`0 !!353350PPP00PPPP`0#!!27'"&4627&"462"264&"0Fd#9  9#dvvvƤ褤00dF#9   9#ʤvvv<褤`0 !!7!5$46;#"73#"320F2x (%0"PSu\DE00PPD.() c@]CD\`0 !!7'?7'70$8[[8[[008\\88\\`0 !!!350@P00PP`0!!!5000PP`0!!!5#354627&#"264&"462"0^PP 9#2ۤ褤Tvvv00x 9#褤vvv`03!53!P0P00PP0`0 !!264&"462"0^^^/B//B00:dFFdF  `0!!#33535#5!50@P000PPPPPPPP`0!!>54&#"632350D6)"F2-C0 ;*`0000(&0 .% Q00`0'!!32654'654&#"632+32#"&0!0D-2F$$F2-C0 ;****(00!-5%&! .%0"`0!!7'0$8900$89`0!!3##"&=#35320PP (%0".PP#-E00c) F2`0 !!#";335#30@x2FF2(PPP00FdFP`0 !!264&"0**00**`0!!2654'7'"'3!H2F 9Q" 9#200F29Q"  9#`0 !!73#0S100s+) `0!!7!5264&"462"0pvvv&FdFFd00PP2^^^B//B/`0 !!%7'7'08[[8[[00Ԕ8\\88\\`0!!%33535#5##573#'0100"_S1D"P"00F<<0Rb+) !"P"`0 $(!!73#>54&#"63235%'0xS16)"F2-C0 ;*`00/"P"00s+) (&0 .% Q00y"P"`06:!!%33535#5##532654'654&#"632+32#"&'0100"_0D-2F$$F2-C0 ;****(*"P"00F<<0RbN!-5%&! .%0""P"`0#!!3267'#"&54>564&"20@2<2uSKp PC+2F2<2 **00,6$6L?/ ,6$Y**`037'!!35335'#7#v8=m0PP"gxx0u8=0yddٷxx`0!73!35335'#7#m=8v0PP"gxx0=8u0yddٷxx`0 !77'!!35335'#7#=8\\8=0PP"gxx0=8[[8=0yddٷxx`0 '!6323267'3!35335'#7##"'&'I$F-%*+K30PP"gxx#0>(( *&0yddٷxx| `0 !!3533535335'#7#0PPPPP"gxx00PPPPddٷxx`0 !&32654'3!473"&35335'#7#^^02<2/B/xPP"gxx02FF20 ddٷxx`0!!#5735335#535#535!0@Pxx000g״PPdP`0+!!654'7>7'#"&46327.#""'#m+ 6XT0UB^^BU0TuFceN" 900$8 F2G^^G>KcR"  9`037'!!!5!!5!535#v8=m0@p0u8=0PpPPP`0!73!!5!!5!535#m=8v0@p0=8u0PpPPP`0 !77'!!!5!!5!535#=8\\8=0@p0=8[[8=0PpPPP`0 !!35335!5!!5!535#0PPP@p00PPPPPpPPP`037'!!3#35#535v8=m0PPPP0u8=00PPPP`0!73!3#35#535m=8v0PPPP0=8u00PPPP`0 !77'!!3#35#535=8\\8=0PPPP0=8[[8=00PPPP`0 !!353353#35#5350PPPPPPP00PPPP{PPPP`0!!35#532+264&+#30PPPB^^BPPccPP00|Pd^^PƍP`0"!6323267'3!733##%#"'&'I$F-%*+K30P8P8A#0>(( *&0 `037'!!264&"462"v8=m0vvv&FdFFd0u8=0vvvdFFdF`0!73!264&"462"m=8v0vvv&FdFFd0=8u0vvvdFFdF`0 !77'!!264&"462"=8\\8=0vvv&FdFFd0=8[[8=0vvvdFFdF`0!(!6323267'3!264&"462"#"'&'I$F-%*+K30vvv&FdFFd#0>(( *&0vvvdFFdF `0 !!35335264&"462"0PPPvvv&FdFFd00PPPPvvvdFFdF`0!!'77'7088800L888`0 '!!#"'&54632732654'7'&#"0^B,&^B,-I8I?Lc-I8I?Lc00&,B^&,B^L?I8I-cL?I8I-`037'!!26=#"&=#v8=m0vvPFdFP0u8=0hRvvR2FF2`0!73!26=#"&=#m=8v0vvPFdFP0=8u0hRvvR2FF2`0 !77'!!26=#"&=#=8\\8=0vvPFdFP0=8[[8=0hRvvR2FF2`0 !!3533526=#"&=#0PPPvvPFdFP00PPPPRvvR2FF2`0!73!357#'m=8v0gPr0=8u00ٷُ`0 !!32+7#5#353264&0!//!PPB^^00/B/P P^^`0(!!%#32654'654&+"346;2+320ZZ>X4 L6ZB^P/!ZZZ))00PX>F,%16L^B@!/*P):)`0 37'!!3#"32&46;#"v8=m0PRv]CEF2x (%0"0u8=0cvRSudFx) `0 !73!3#"32&46;#"m=8v0PRv]CEF2x (%0"0=8u0cvRSudFx) `0 #!77'!!3#"32&46;#"=8\\8=0PRv]CEF2x (%0"0=8[[8=0cvRSudFx) `0*1!6323267'3!3#"32&46;#"#"'&'I$F-%*+K30PRv]CEF2x (%0"#0>(( *&0cvRSudFx)  `0 $!!353353#"32&46;#"0PPPPRv]CEF2x (%0"00PPPPXcvRSudFx) `0 #032654'3!473"&3#"32&46;#"^^02<2/B/PRv]CEF2x (%0"02FF20 icvRSudFx) `0 6!!#>246;#"&35;5#"&/354&#"5#"32670) &.%~."PAP#-xx%]C-#C]D4<00 ,(<2Fx (CD1cP((SuuSTt1`0-!!654'7>7'#"&46327.#""'#+ 0HQ:#2FF2#:Qh@RvP=" 900$8C/&FdF&;LvRBj"  9`0 37'!!#>2$;5#"&'!54&"v8=m0 >L>vR&> 9v0u8=0#--vP-#(Rv`0 !73!#>2$;5#"&'!54&"m=8v0 >L>vR&> 9v0=8u0#--vP-#(Rv`0 !77'!!#>2$;5#"&'!54&"=8\\8=0 >L>vR&> 9v0=8[[8=0#--vP-#(Rv`0  !!35335#>2$;5#"&'!54&"0PPP >L>vR&> 9v00PPPP#--vP-#(Rv`037'!!3#!5#v8=m00u8=00PPP@`0!73!3#!5#m=8v00=8u00PPP@`0 !77'!!3#!5#=8\\8=00=8[[8=00PPP@`0 !!353353#!5#0PPP00PPPP{PPP@`0 !)!!7&'632"26=4'7'&#""&46201!!,2Rvvv,=9I*-S:FdFFd001 I3^^^B8,<9I/B//B/`0'.!6323267'3!5#35>32354&#"7#"'&'I$F-%*+K30PP (%0".P]CE#0>(( *&0cp) F2Su `037'!!264&"462"v8=m0vvv&FdFFd0u8=0vvvdFFdF`0!73!264&"462"m=8v0vvv&FdFFd0=8u0vvvdFFdF`0 !77'!!264&"462"=8\\8=0vvv&FdFFd0=8[[8=0vvvdFFdF`0!(!6323267'3!264&"462"#"'&'I$F-%*+K30vvv&FdFFd#0>(( *&0vvvdFFdF `0 !!35335264&"462"0PPPvvv&FdFFd00PPPPvvvdFFdF`0 !!!5'35350PPP00PPPPPP`0 '!!&546327#"'732654'7'&#"0 F2h F2">8>4:Rv">8>4:Rv0042F ؠ2Fx:4>8>"vR:4>8>"v`037'!!3##"&=#32v8=m0PP (%0".P]CE0u8=0c) F2Su`0!73!3##"&=#32m=8v0PP (%0".P]CE0=8u0c) F2Su`0 !77'!!3##"&=#32=8\\8=0PP (%0".P]CE0=8[[8=0c) F2Su`0 !!!353353##"&=#320PPPPP (%0".P]CE00PPPPXc) F2Su`0&!73!#"'3265##"&=#32m=8v0F2D#DvP "V".P]CW0=8u0'2F:),5vR@ !8:*Ki`0!!+5>325#3532654&#"0F2x (%0"PPxRv]CE00dFx) xvRSu`0 *!!35335#"'3265##"&=#320PPPF2D#DvP "V".P]CW00PPPPl'2F:),5vR@ !8:*Ki`0#"#3+326=35#46;%!!XxB^/!xxB^/!x0^BP!/P^BP!/x0`03267'#"'&#"632%!!T%*+KF-&)+KF-0*&(( *&((0`0 333335%!!PPPPP0hPP0`0 7'!5!7%!!8108P0`0 !!'730L8P0081σ`0 !!%7'!!081σ008P`0 !!77'#'08P0081 ) !@@0`0 !')!@8$@08P`0!P0`0!!00`!!0`0!5!!00 `0%!!!500PР0!P`0 #3535#'#26=#"&=#35#5!!((;R;(#2#(Ƞ0TȄ);;)dd##d(0`0'/;!!#";2+3264&+"&46;264&"462"35335##50x##P ##P x<;R;;R#2##2(x((x00#2#  (#2#  R;;R;}2##2#PPPPP`0*258;!#'#373!#";2+3264&+"&46;3353535/70HH8dd8HH00x##P ##P x54&$3267'#"&46327.#"'!!PPPx( P8P*/s;) 4 )%##%) 4 )0  PPPP"#R;&"#2#"&0`0'/!!#";2+3264&+"&46;264&"462"0@x##P ##P x<;R;;R#2##200D#2#  (#2#  R;;R;}2##2#`0+!!3#35#535'#";2+3264&+"&46;0((x((x##P ##P x00T(x((x(#2#  (#2#  `0%!!%35#35#535#35#5'264&+7#5320ȠddȠ);;)dd<<##00((((@((;R;(x#2#`0 0!!%735#264&+7#5323267'#"&46327.#"0D();;)dd<<##s;) 4 )%##%) 4 )00$#;R;(x#2#R;&"#2#"&`0$,B!!%>54&#"63235264&+7#5323267'#"&46327.#"0:-";)%8( 1#P(();;)dd<<##s;) 4 )%##%) 4 )00<  &/((;R;(x#2#R;&"#2#"&`0&.6L!!%32654'64&#"632+32#"&264&+7#5323267'#"&46327.#"0'8%*::*%7( 0####"X);;)dd<<##s;) 4 )%##%) 4 )00Z%#2#  (  ;R;(x#2#R;&"#2#"&`0!7!!%33535#5##264&+7#5323267'#"&46327.#"0x((( >J);;)dd<<##s;) 4 )%##%) 4 )00X&(D>;R;(x#2#R;&"#2#"&`0),!'7#5#3573!35335'#7#%3535#'#5oP9\(((\00(x(\4<54&#";2+3264&+"&46;0PPPx( P8P*/ x##P ##P x00  PPPP"##2#  (#2#  `0/!!26=#"&=##";2+3264&+"&46;0;R;(#2#(x##P ##P x00);;)dd##d#2#  (#2#  `0 1!!#353264&32+#";2+3264&+"&46;0x(P!//qPPdx##P ##P x00TP#2#(  @#2#  (#2#  `0 %!!%35#5'35#35#535#'264&+7#5320ȠȠdd);;)dd<<##00(((((x;R;(x#2#`0 $$+5>3257'5#732654&#"%!!F2x (%0"l84Pl84Rv]CE0dFx) +l84@l84vRSu0`0 !!!5#!50P0Pp00`0 !!3535#'#35#50((Ƞ00|Ȅ(`0 !!7'7'7'088H8888008888 88`0!!34.546327.#"#30@P2<2F2+CP pKSu2<2PPP00@$6, /?L6$6,lP`0%!!!00@p@`05!!5!0P`0!)!@@000`03#!3000`0 !!353353350(PP00PPPPPP`0 !!353353350(PP00`0 !!3535350@PPPPP00`0 !!353535000`0 !!353353353350(dPdPdPd00PPPPPPPP`0 !!353353353350(dPdPdPd00`0 !!353535350@PPPPPPP00dddddddd`0 !!35353535000dddddddd`0 !!)!p@0p@`0 !!)5!p@0 `0 !!#!3 0p@`0 !!#!53 0 `0 5!)!!@pР@0`0 5!)!5!@pP0`0 53#!!! Р@0`0 53#!!5! P0`0 !!!!!@0@0p@`0 !!!!5!@0@0 `0 3!!#300p@`0 3!!#5300 `0 5!!!!@@0@P0`0 5!!!!@@0@0`0 53!3!0@P0`0 53!3!0@0`0 !)!!!@@@00@@`0 !)5!!5!@@@00`0 33)!#3P@0p@@`0 !##!3!!@P@0p@@`0 3#!3#300@@`0 33)5!#53P@0 `0 !##!53!5!@P@0 `0 3#!53#5300`0 5!!)!@@@@P0`0 5!!)!@@@@0`0 53!)33@P@P@0`0 5!3#!#!@P@@P@0`0 533#!3@P0`0 !5!533#5@@PP 0`0 5!3#!#5!@P@@0`0 533#!3@0`0 5!)!!@@0Р@@`0 5!)!!5!5!@@pP@P`0 5!!!)5!p@@@PP`0 5!)5!5!@@0P`0 53#!3!0Р@@`0 53#!3#5!5! P@P`0 5!!3#!53 @PP`0 53#!535!0P`0 5!!!!!@0@@P@`0 5!!5!!!!@@0@@P@`0 5!!!!!5!@@0@@PP`0 5!!!!5!@0@@`0 53!!#30@P@`0 %!5!57#3!#50 PP@`0 533!!#530@PP`0 53!!#530@`0 5!!)!!!@@@@@P@@`0 5!!)!!!@@@@@@@`0 5!!)5!!5!@@@@@P`0 5!!)5!!5!@@@@@`0 53!)!#3@@@P@@`0 5!3#!3!!@@@P@@`0 533#!3#3@P@@`0 !5!5353#3!#5@@PP P@`0 5333)5!#53P@@PP`0 5!3#!3#5#5!@P@@@P`0 5!#3#!53!5!@P@@PP`0 53!)5!#53@@@`0 5!3#!53!5!@@@`0 533#!3#3@@@`0 533#!53#53@P`0 533#!53#53@`0 !!!53!50(P00PPPP`0 !!!53!50(P00`0 !!330@PPP00`0 !!33000`0 5!!=!!!000P`0 3#!333@PP0000`0 !!)5!!5!p@@0 @P`0 !!#!333 @PP0p@@`0 !!#!!!353 @P0 P`0 5!!!)!5!@@pPP0`0 53#!33!!@PP Р@@0`0 5!#!!5!%3#P 0p@0`0 !!!!5!5!5!@0@@0 @PP`0 3!!#3!#0P0p@@`0 3!!!3%#530pP@0 PP`0 5!!!!!!@@@0@PPP0`0 53!3!#0P@P0@`0 53!3!!3!@Pp0@P@pP0`0 !)5!!5!5!5!@@@@00@PP`0 3#!333#3@PP000@@`0 3#!3!!#5353@P@@00P0`0 5!!!!)!@@@@@PPP0`0 533#!333@PP@P00`0 53!3#!3#!3@PP@P@0@P0`0 5!!=!!)5!00@@P`0 53#!333!@PP0Р@@@`0 5!!#!=!3#!53P0P@`0 5!!!%!5!!!@0@00@PP `0 53!!#3!#0P@P@@`0 53!3!!%#53!!@P@000@P@P `0 5!!!!)5!!5!5!5!@@@@@@@PPP@PP`0 533#!333#3!#@PPP@P@@@@`053!3!!#!%#533#!53@P@P0@P@P@ `0 !")463Ц0ꦅ`0 5!!4&2!ꦅ@0P`0 !!26'#@0P00@ꦅ@`0 !3!"&5!@0Ѕ@0`0! h0h`0!%!hhh8`0   7 ' /8008/88/8008/`05!5!!!h0P@0`0!3!!@P@00h0`0!!!!h00P`0!!#!P00h`05!5!5!!h0P0`0333!00h0`0!!!!h00`0!###00h`0 5!!!!!hh0@PPP`0 !##!#!@PP@0hh0`0 5!5!!!5!5!hh0PPP`0 33)33PP0hh0`0 !!!!!( x0|hP0`0!!0Z00v`0!!%0v00Z`0 !!327#!"'&'32654.0h!iQ=R:L: (:TT:( :L:R=Qi007g1FF1>eR:*P54&#".#"0h &aI=R:'F/:R:RR00P #ha}1:R8&R:1zi[`0!! 0h00`0 353'35%!!PP0(PP0`0!!!5#7654&+3250C0^B!/00P0@B^P/! Ϻ`03#!!ZZ000`03#!!>000`0!!!!hh000`0!!!!h000`0!!3#>000`0!!3#vZZ000`0!!!!000ZZ`0!!!!000Z>`0!!!!000Z`0!!!!000Z`0!!!!000>Z`0!!!!000ZZZ0!!Zv0Z`!!Zv`v!!vv0!!v005!!!!00ȴ`0 33 5735'3'5!'5`TLThT0T080p8ThLT`L0`T0T`0 ! 3%37737308ThLT`L0`T0TT8T8ThL`0T00V%C+&X    5 VJ  & :Kreative Square copyright (c) Kreative Software 2017-2024 under the Open Font License.Kreative Square copyright (c) Kreative Software 2017-2024 under the Open Font License.Kreative SquareKreative SquareMediumMediumFontForge 2.0 : Kreative Square : 29-2-2024FontForge 2.0 : Kreative Square : 29-2-2024Kreative SquareKreative SquareVersion 2024.02.29 Version 2024.02.29 KreativeSquareKreativeSquare$N  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                           ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~        !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTuni007Funi00A0uni00ADuni00B2uni00B3uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccentuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni0162uni0163TcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongsuni01A7uni01A8uni01C0uni01C1uni01C2uni01C3uni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01DDGcarongcaronuni01E8uni01E9AEacuteaeacute Oslashacute oslashacuteuni0218uni0219uni021Auni021Buni021Euni021Funi0226uni0227uni0232uni0233uni0237uni0238uni0239uni0241uni0242uni0250uni0251uni0252uni0254uni0258uni0259uni025Buni025Cuni025Euni025Funi0261uni0262uni0265uni0268uni026Auni026Funi0270uni0271uni0274uni0275uni0276uni0277uni0278uni0279uni027Auni027Cuni0280uni0281uni0283uni0284uni0285uni0287uni0288uni0289uni028Auni028Buni028Cuni028Duni028Euni028Funi0294uni0295uni0296uni0299uni029Auni029Cuni029Euni029Funi02C8uni02C9uni02CAuni02CBuni02CCuni02CDuni02CEuni02CFuni02D0uni02D1 gravecomb acutecombuni0302 tildecombuni0304uni0305uni0306uni0307uni0308uni030Auni030Buni030Cuni030Duni030Euni030Funi037Buni037Cuni037Duni037Euni037Ftonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni03D0phi1omega1uni03DAuni03DBuni03F2uni03F3uni03F5uni03F6uni03F9uni03FDuni03FEuni03FFuni1D00uni1D01uni1D02uni1D03uni1D04uni1D05uni1D06uni1D07uni1D08uni1D09uni1D0Auni1D0Buni1D0Cuni1D0Duni1D0Euni1D0Funi1D10uni1D11uni1D12uni1D13uni1D14uni1D15uni1D16uni1D17uni1D18uni1D19uni1D1Auni1D1Buni1D1Cuni1D1Duni1D1Euni1D1Funi1D20uni1D21uni1D22uni1D26uni1D27uni1D28uni1D29uni1D2Auni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200Buni200Cuni200Duni200Euni200Funi2010uni2011 figuredashuni2015uni2016 underscoredbl quotereverseduni201Funi2023onedotenleadertwodotenleaderuni2027uni2028uni2029uni202Auni202Buni202Cuni202Duni202Euni202Funi2031uni203B exclamdbluni203Duni203Euni2042uni2043uni2045uni2046uni2047uni2048uni2049uni204Euni2051uni2070uni2071uni2072uni2073uni2074uni2075uni2076uni2077uni2078uni2079uni207Auni207Buni207Cuni207Duni207Euni207Funi2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089uni208Auni208Buni208Cuni208Duni208Euni208Funi2090uni2091uni2092uni2093uni2094uni2095uni2096uni2097uni2098uni2099uni209Auni209Buni209Cuni20A0 colonmonetaryuni20A2lirapesetauni20A8uni20A9Eurouni20BEuni20BFuni2100uni2101uni2103uni2105uni2106uni2109uni2116uni2117 prescriptionuni2120uni2127uni212Auni212B estimateduni2132uni2139uni2141uni2142uni2143uni2144uni214Buni214Euni2150uni2151uni2152onethird twothirdsuni2155uni2156uni2157uni2158uni2159uni215A oneeighth threeeighths fiveeighths seveneighthsuni215Funi2160uni2161uni2162uni2163uni2164uni2165uni2166uni2167uni2168uni2169uni216Auni216Buni216Cuni216Duni216Euni216Funi2170uni2171uni2172uni2173uni2174uni2175uni2176uni2177uni2178uni2179uni217Auni217Buni217Cuni217Duni217Euni217Funi2180uni2181uni2182uni2183uni2184uni2185uni2186uni2187uni2188uni2189uni218Auni218B arrowleftarrowup arrowright arrowdown arrowboth arrowupdnuni2196uni2197uni2198uni2199uni219Auni219Buni219Euni219Funi21A0uni21A1uni21A2uni21A3uni21A4uni21A5uni21A6uni21A7 arrowupdnbseuni21A9uni21AAuni21ABuni21ACuni21B0uni21B1uni21B2uni21B3uni21B4carriagereturnuni21DEuni21DFuni21E4uni21E5uni21E6uni21E7uni21E8uni21E9uni21EAuni21F7uni21F8uni21F9uni21FAuni21FBuni21FC universaluni2201 existentialuni2204emptysetgradientelement notelementuni220Asuchthatuni220Cuni220Duni220Euni2210uni2218uni2219uni221Buni221C orthogonalangleuni2221 logicaland logicalor intersectionunionuni222Euni2249 equivalenceuni2262uni2263 circleplusuni2296circlemultiplyuni2298uni2299uni229Auni229Buni229Cuni229Duni229Euni229Funi22A0uni22A1uni22A2uni22A3uni22A4 perpendicularuni22B9uni2300uni2301houseuni2303uni2304uni2305uni2306uni2307uni2308uni2309uni230Auni230Buni230Cuni230Duni230Euni230F revlogicalnotuni2316uni2317uni2318uni2319uni231Auni231Buni231Cuni231Duni231Euni231F integraltp integralbtuni2324uni2325uni2326uni2327uni2328uni232Buni232Cuni237Buni237Duni237Euni237Funi2384uni2385uni2386uni2387uni2388uni2389uni238Auni238Buni238Duni238Euni238Funi2390uni2391uni2392uni2394uni239Buni239Cuni239Duni239Euni239Funi23A0uni23A1uni23A2uni23A3uni23A4uni23A5uni23A6uni23A7uni23A8uni23A9uni23AAuni23ABuni23ACuni23ADuni23AEuni23AFuni23B0uni23B1uni23B2uni23B3uni23B4uni23B5uni23B6uni23B7uni23B8uni23B9uni23BAuni23BBuni23BCuni23BDuni23BEuni23BFuni23C0uni23C1uni23C2uni23C3uni23C4uni23C5uni23C6uni23C7uni23C8uni23C9uni23CAuni23CBuni23CCuni23CFuni23D0uni23DAuni23DBuni23DCuni23DDuni23DEuni23DFuni23E8uni23E9uni23EAuni23EBuni23ECuni23EDuni23EEuni23EFuni23F3uni23F4uni23F5uni23F6uni23F7uni23F8uni23F9uni23FAuni23FBuni23FCuni23FDuni23FEuni2400uni2401uni2402uni2403uni2404uni2405uni2406uni2407uni2408uni2409uni240Auni240Buni240Cuni240Duni240Euni240Funi2410uni2411uni2412uni2413uni2414uni2415uni2416uni2417uni2418uni2419uni241Auni241Buni241Cuni241Duni241Euni241Funi2420uni2421uni2422uni2423uni2424uni2425uni2426uni2427uni2428uni2429uni2440uni2441uni2442uni2443uni2444uni2445uni2446uni2447uni2448uni2449uni244ASF100000uni2501SF110000uni2503uni2504uni2505uni2506uni2507uni2508uni2509uni250Auni250BSF010000uni250Duni250Euni250FSF030000uni2511uni2512uni2513SF020000uni2515uni2516uni2517SF040000uni2519uni251Auni251BSF080000uni251Duni251Euni251Funi2520uni2521uni2522uni2523SF090000uni2525uni2526uni2527uni2528uni2529uni252Auni252BSF060000uni252Duni252Euni252Funi2530uni2531uni2532uni2533SF070000uni2535uni2536uni2537uni2538uni2539uni253Auni253BSF050000uni253Duni253Euni253Funi2540uni2541uni2542uni2543uni2544uni2545uni2546uni2547uni2548uni2549uni254Auni254Buni254Cuni254Duni254Euni254FSF430000SF240000SF510000SF520000SF390000SF220000SF210000SF250000SF500000SF490000SF380000SF280000SF270000SF260000SF360000SF370000SF420000SF190000SF200000SF230000SF470000SF480000SF410000SF450000SF460000SF400000SF540000SF530000SF440000uni256Duni256Euni256Funi2570uni2571uni2572uni2573uni2574uni2575uni2576uni2577uni2578uni2579uni257Auni257Buni257Cuni257Duni257Euni257Fupblockuni2581uni2582uni2583dnblockuni2585uni2586uni2587blockuni2589uni258Auni258Blfblockuni258Duni258Euni258Frtblockltshadeshadedkshadeuni2594uni2595uni2596uni2597uni2598uni2599uni259Auni259Buni259Cuni259Duni259Euni259F filledboxH22073uni25A2uni25A3uni25A4uni25A5uni25A6uni25A7uni25A8uni25A9H18543H18551 filledrectuni25ADuni25AEuni25AFuni25B0uni25B1triagupuni25B3uni25B4uni25B5uni25B6uni25B7uni25B8uni25B9triagrtuni25BBtriagdnuni25BDuni25BEuni25BFuni25C0uni25C1uni25C2uni25C3triaglfuni25C5uni25C6uni25C7uni25C8uni25C9circleuni25CCuni25CDuni25CEH18533uni25D0uni25D1uni25D2uni25D3uni25D4uni25D5uni25D6uni25D7 invbullet invcircleuni25DAuni25DBuni25DCuni25DDuni25DEuni25DFuni25E0uni25E1uni25E2uni25E3uni25E4uni25E5 openbulletuni25E7uni25E8uni25E9uni25EAuni25EBuni25ECuni25EDuni25EEuni25EFuni25F0uni25F1uni25F2uni25F3uni25F4uni25F5uni25F6uni25F7uni25F8uni25F9uni25FAuni25FBuni25FCuni25FDuni25FEuni25FFuni2600uni2602uni2605uni2606uni2609uni2610uni2611uni2612uni262Euni262Funi2630uni2631uni2632uni2633uni2634uni2635uni2636uni2637uni2639 smileface invsmilefacesununi263Duni263Euni263Ffemaleuni2641malespadeuni2661uni2662clubuni2664heartdiamonduni2667uni2669 musicalnotemusicalnotedbluni266Cuni2680uni2681uni2682uni2683uni2684uni2685uni2686uni2687uni2688uni2689uni268Auni268Buni268Cuni268Duni268Euni268Funi26A0uni26A2uni26A3uni26A4uni26A5uni26A6uni26A7uni26A8uni26A9uni26AAuni26ABuni26ACuni26ADuni26AEuni26AFuni26F6uni270Euni2710uni2713uni2715uni2717uni273Funi2740uni274Funi2750uni2751uni2752uni2756uni27A1uni27A2uni27A3uni27A4uni27CAuni29B5uni29B6uni29B7uni29B8uni29B9uni29BAuni29BCuni29BEuni29BFuni29C4uni29C5uni29C6uni29C7uni29C8uni29C9uni29E8uni29E9uni29EBuni2B00uni2B01uni2B02uni2B03uni2B04uni2B05uni2B06uni2B07uni2B08uni2B09uni2B0Auni2B0Buni2B0Cuni2B0Duni2B12uni2B13uni2B14uni2B15uni2B16uni2B17uni2B18uni2B19uni2B1Auni2B1Buni2B1Cuni2B1Duni2B1Euni2B1Funi2B20uni2B21uni2B22uni2B23uni2B24uni2B2Cuni2B2Duni2B2Euni2B2Funi2B53uni2B54uni2B60uni2B61uni2B62uni2B63uni2B64uni2B65uni2B66uni2B67uni2B68uni2B69uni2B88uni2B89uni2B8Auni2B8Buni2B95uni2B98uni2B99uni2B9Auni2B9Buni2B9Cuni2B9Duni2B9Euni2B9Funi2BBAuni2BBBuni2BBCuni2BC0uni2BC1uni2BC2uni2BC3uni2BC4uni2BC5uni2BC6uni2BC7uni2BC8uni2BCAuni2BCBuni2BCCuni2BCDuni2BCEuni2BCFuni2BD0uni2BE8uni2BE9uni2BEAuni2BEBuni2BFFuni2E2EuniEE00uniEE01uniEE02uniEE03uniEE04uniEE05uniEE06uniEE07uniEE08uniEE09uniEE0AuniEE0BuniEE0CuniEE0DuniEE0EuniEE0FuniEE10uniEE11uniEE12uniEE13uniEE14uniEE15uniEE16uniEE17uniEE18uniEE19uniEE1AuniEE1BuniEE1CuniEE1DuniEE1EuniEE1FuniEE20uniEE21uniEE22uniEE23uniEE24uniEE25uniEE26uniEE27uniEE28uniEE29uniEE2AuniEE2BuniEE2CuniEE2DuniEE2EuniEE2FuniEE30uniEE31uniEE32uniEE33uniEE34uniEE35uniEE36uniEE37uniEE38uniEE39uniEE3AuniEE3BuniEE3CuniEE3DuniEE3EuniEE3FuniEE40uniEE41uniEE42uniEE43uniEE44uniEE45uniEE46uniEE47uniEE48uniEE49uniEE4AuniEE4BuniEE4CuniEE4DuniEE4EuniEE4FuniEE50uniEE51uniEE52uniEE53uniEE54uniEE55uniEE56uniEE57uniEE58uniEE59uniEE5AuniEE5BuniEE5CuniEE5DuniEE5EuniEE5FuniEE60uniEE61uniEE62uniEE63uniEE64uniEE65uniEE66uniEE67uniEE68uniEE69uniEE6AuniEE6BuniEE6CuniEE6DuniEE6EuniEE6FuniEE70uniEE71uniEE72uniEE73uniEE74uniEE75uniEE76uniEE77uniEE78uniEE79uniEE7AuniEE7BuniEE7CuniEE7DuniEE7EuniEE7FuniEE80uniEE81uniEE82uniEE83uniEE84uniEE85uniEE86uniEE87uniEE88uniEE89uniEE8AuniEE8BuniEE8CuniEE8DuniEE8EuniEE8FuniEE90uniEE91uniEE92uniEE93uniEE94uniEE95uniEE96uniEE97uniEE98uniEE99uniEE9AuniEE9BuniEE9CuniEE9DuniEE9EuniEE9FuniEEA0uniEEA1uniEEA2uniEEA3uniEEA4uniEEA5uniEEA6uniEEA7uniEEA8uniEEA9uniEEAAuniEEABuniEEACuniEEADuniEEAEuniEEAFuniEEB0uniEEB1uniEEB2uniEEB3uniEEB4uniEEB5uniEEB6uniEEB7uniEEB8uniEEB9uniEEBAuniEEBBuniEEBCuniEEBDuniEEBEuniEEBFuniEEC0uniEEC1uniEEC2uniEEC3uniEEC4uniEEC5uniEEC6uniEEC7uniEEC8uniEEC9uniEECAuniEECBuniEECCuniEECDuniEECEuniEECFuniEED0uniEED1uniEED2uniEED3uniEED4uniEED5uniEED6uniEED7uniEED8uniEED9uniEEDAuniEEDBuniEEDCuniEEDDuniEEDEuniEEDFuniEEE0uniEEE1uniEEE2uniEEE3uniEEE4uniEEE5uniEEE6uniEEE7uniEEE8uniEEE9uniEEEAuniEEEBuniEEECuniEEEDuniEEEEuniEEEFuniEEF0uniEEF1uniEEF2uniEEF3uniEEF4uniEEF5uniEEF6uniEEF7uniEEF8uniEEF9uniEEFAuniEEFBuniEEFCuniEEFDuniEEFEuniEEFFuniEF00uniEF01uniEF02uniEF03uniEF04uniEF05uniEF06uniEF07uniEF08uniEF09uniEF0AuniEF0BuniEF0CuniEF0DuniEF0EuniEF0FuniEF10uniEF11uniEF12uniEF13uniEF14uniEF15uniEF16uniEF17uniEF18uniEF19uniEF1AuniEF1BuniEF1CuniEF1DuniEF1EuniEF1FuniEF20uniEF21uniEF22uniEF23uniEF24uniEF25uniEF26uniEF27uniEF28uniEF29uniEF2AuniEF2BuniEF2CuniEF2DuniEF2EuniEF2FuniEF30uniEF31uniEF32uniEF33uniEF34uniEF35uniEF36uniEF37uniEF38uniEF39uniEF3AuniEF3BuniEF3CuniEF3DuniEF3EuniEF3FuniEF40uniEF41uniEF42uniEF43uniEF44uniEF45uniEF46uniEF47uniEF48uniEF49uniEF4AuniEF4BuniEF4CuniEF4DuniEF4EuniEF4FuniEF50uniEF51uniEF52uniEF53uniEF54uniEF55uniEF56uniEF57uniEF58uniEF59uniEF5AuniEF5BuniEF5CuniEF5DuniEF5EuniEF5FuniEF60uniEF61uniEF62uniEF63uniEF64uniEF65uniEF66uniEF67uniEF68uniEF69uniEF6AuniEF6BuniEF6CuniEF6DuniEF6EuniEF6FuniEF70uniEF71uniEF72uniEF73uniEF74uniEF75uniEF76uniEF77uniEF78uniEF79uniEF7AuniEF7BuniEF7CuniEF7DuniEF7EuniEF7FuniEF80uniEF81uniEF82uniEF83uniEF84uniEF85uniEF86uniEF87uniEF88uniEF89uniEF8AuniEF8BuniEF8CuniEF8DuniEF8EuniEF8FuniEF90uniEF91uniEF92uniEF93uniEF94uniEF95uniEF96uniEF97uniEF98uniEF99uniEF9AuniEF9BuniEF9CuniEF9DuniEF9EuniEF9FuniEFA0uniEFA1uniEFA2uniEFA3uniEFA4uniEFA5uniEFA6uniEFA7uniEFA8uniEFA9uniEFAAuniEFABuniEFACuniEFADuniEFAEuniEFAFuniEFB0uniEFB1uniEFB2uniEFB3uniEFB4uniEFB5uniEFB6uniEFB7uniEFB8uniEFB9uniEFBAuniEFBBuniEFBCuniEFBDuniEFBEuniEFBFuniEFC0uniEFC1uniEFC2uniEFC3uniEFC4uniEFC5uniEFC6uniEFC7uniEFC8uniEFC9uniEFCAuniEFCBuniEFCCuniEFCDuniEFCEuniEFCFuniEFD0uniEFD1uniEFD2uniEFD3uniEFD4uniEFD5uniEFD6uniEFD7uniEFD8uniEFD9uniEFDAuniEFDBuniEFDCuniEFDDuniEFDEuniEFDFuniEFE0uniEFE1uniEFE2uniEFE3uniEFE4uniEFE5uniEFE6uniEFE7uniEFE8uniEFE9uniEFEAuniEFEBuniEFECuniEFEDuniEFEEuniEFEFuniEFF0uniEFF1uniEFF2uniEFF3uniEFF4uniEFF5uniEFF6uniEFF7uniEFF8uniEFF9uniEFFAuniEFFBuniEFFCuniEFFDuniEFFEuniEFFFuniF000uniF001uniF002uniF003uniF004uniF005uniF006uniF007uniF008uniF009uniF00AuniF00BuniF00CuniF00DuniF00EuniF00FuniF010uniF011uniF012uniF013uniF014uniF015uniF016uniF017uniF018uniF019uniF01AuniF01BuniF01CuniF01DuniF01EuniF01FuniF020uniF021uniF022uniF023uniF024uniF025uniF026uniF027uniF028uniF029uniF02AuniF02BuniF02CuniF02DuniF02EuniF02FuniF030uniF031uniF032uniF033uniF034uniF035uniF036uniF037uniF038uniF039uniF03AuniF03BuniF03CuniF03DuniF03EuniF03FuniF040uniF041uniF042uniF043uniF044uniF045uniF046uniF047uniF048uniF049uniF04AuniF04BuniF04CuniF04DuniF04EuniF04FuniF050uniF051uniF052uniF053uniF054uniF055uniF056uniF057uniF058uniF059uniF05AuniF05BuniF05CuniF05DuniF05EuniF05FuniF060uniF061uniF062uniF063uniF064uniF065uniF066uniF067uniF068uniF069uniF06AuniF06BuniF06CuniF06DuniF06EuniF06FuniF070uniF071uniF072uniF073uniF074uniF075uniF076uniF077uniF078uniF079uniF07AuniF07BuniF07CuniF07DuniF07EuniF07FuniF080uniF081uniF082uniF083uniF084uniF085uniF086uniF087uniF088uniF089uniF08AuniF08BuniF08CuniF08DuniF08EuniF08FuniF090uniF091uniF092uniF093uniF094uniF095uniF096uniF097uniF098uniF099uniF09AuniF09BuniF09CuniF09DuniF09EuniF09FuniF0A0uniF0A1uniF0A2uniF0A3uniF0A4uniF0A5uniF0A6uniF0A7uniF0A8uniF0A9uniF0AAuniF0ABuniF0ACuniF0ADuniF0AEuniF0AFuniF0B0uniF0B1uniF0B2uniF0B3uniF0B4uniF0B5uniF0B6uniF0B7uniF0B8uniF0B9uniF0BAuniF0BBuniF0BCuniF0BDuniF0BEuniF0BFuniF0C0uniF0C1uniF0C2uniF0C3uniF0C4uniF0C5uniF0C6uniF0C7uniF0C8uniF0C9uniF0CAuniF0CBuniF0CCuniF0CDuniF0CEuniF0CFuniF0D0uniF0D1uniF0D2uniF0D3uniF0D4uniF0D5uniF0D6uniF0D7uniF0D8uniF0D9uniF0DAuniF0DBuniF0DCuniF0DDuniF0DEuniF0DFuniF0E0uniF0E1uniF0E2uniF0E3uniF0E4uniF0E5uniF0E6uniF0E7uniF0E8uniF0E9uniF0EAuniF0EBuniF0ECuniF0EDuniF0EEuniF0EFuniF0F0uniF0F1uniF100uniF101uniF102uniF103uniF104uniF105uniF106uniF107uniF108uniF109uniF10AuniF10BuniF10CuniF10DuniF10EuniF10FuniF110uniF111uniF112uniF113uniF114uniF115uniF116uniF117uniF118uniF119uniF11AuniF11BuniF11CuniF11DuniF11EuniF11FuniF120uniF121uniF122uniF123uniF124uniF125uniF126uniF127uniF128uniF129uniF12AuniF12BuniF12CuniF12DuniF12EuniF12FuniF130uniF131uniF132uniF133uniF134uniF135uniF136uniF137uniF138uniF139uniF13AuniF13BuniF13CuniF13DuniF13EuniF13FuniF140uniF141uniF142uniF143uniF144uniF145uniF146uniF147uniF148uniF149uniF14AuniF14BuniF14CuniF14DuniF14EuniF14FuniF150uniF151uniF152uniF153uniF154uniF155uniF200uniF201uniF202uniF203uniF204uniF205uniF206uniF207uniF208uniF209uniF20AuniF20BuniF20CuniF20DuniF20EuniF20FuniF210uniF211uniF212uniF213uniF214uniF215uniF216uniF217uniF218uniF219uniF21AuniF21BuniF21CuniF21DuniF21EuniF21FuniF220uniF221uniF222uniF223uniF224uniF225uniF226uniF227uniF228uniF229uniF22AuniF22BuniF22CuniF22DuniF22EuniF22FuniF230uniF231uniF232uniF233uniF234uniF235uniF236uniF237uniF238uniF239uniF23AuniF23BuniF23CuniF23DuniF23EuniF23FuniF240uniF241uniF242uniF243uniF244uniF245uniF246uniF247uniF248uniF249uniF24AuniF24BuniF24CuniF24DuniF24EuniF24FuniF250uniF251uniF252uniF253uniF254uniF255uniF256uniF257uniF258uniF259uniF25AuniF25BuniF25CuniF25DuniF25EuniF25FuniF260uniF261uniF262uniF263uniF264uniF265uniF266uniF267uniF268uniF269uniF26AuniF26BuniF26CuniF26DuniF26EuniF26FuniF270uniF271uniF272uniF273uniF274uniF275uniF276uniF277uniF278uniF279uniF27AuniF27BuniF27CuniF27DuniF27EuniF27FuniF280uniF281uniF282uniF283uniF284uniF285uniF286uniF287uniF288uniF289uniF28AuniF28BuniF28CuniF28DuniF28EuniF28FuniF290uniF291uniF292uniF293uniF294uniF295uniF296uniF297uniF298uniF299uniF29AuniF29BuniF29CuniF29DuniF29EuniF29FuniF2A0uniF2A1uniF2A2uniF2A3uniF2A4uniF2A5uniF2A6uniF2A7uniF2A8uniF2A9uniF2AAuniF2ABuniF2ACuniF2ADuniF2AEuniF2AFuniF2B0uniF2B1uniF2B2uniF2B3uniF2B4uniF2B5uniF2B6uniF2B7uniF2B8uniF2B9uniF2BAuniF2BBuniF2BCuniF2BDuniF2BEuniF2BFuniF2C0uniF2C1uniF2C2uniF2C3uniF2C4uniF2C5uniF2C6uniF2C7uniF2C8uniF2C9uniF2CAuniF2CBuniF2CCuniF2CDuniF2CEuniF2CFuniF2D0uniF2D1uniF2D2uniF2D3uniF2D4uniF2D5uniF2D6uniF2D7uniF2D8uniF2D9uniF2DAuniF2DBuniF2DCuniF2DDuniF2DEuniF2DFuniF2E0uniF2E1uniF2E2uniF2E3uniF2E4uniF2E5uniF2E6uniF2E7uniF2E8uniF2E9uniF2EAuniF2EBuniF2ECuniF2EDuniF2EEuniF2EFuniF2F0uniF2F1uniF2F2uniF2F3uniF2F4uniF2F5uniF2F6uniF2F7uniF2F8uniF2F9uniF2FAuniF2FBuniF2FCuniF2FDuniF2FEuniF2FFuniF300uniF301uniF302uniF303uniF304uniF305uniF306uniF307uniF308uniF309uniF30AuniF30BuniF30CuniF30DuniF30EuniF30FuniF310uniF311uniF312uniF313uniF314uniF315uniF316uniF317uniF318uniF319uniF31AuniF31BuniF31CuniF31DuniF31EuniF31FuniF320uniF321uniF322uniF323uniF324uniF325uniF326uniF327uniF328uniF329uniF32AuniF32BuniF32CuniF32DuniF32EuniF32FuniF330uniF331uniF332uniF333uniF334uniF335uniF336uniF337uniF338uniF339uniF33AuniF33BuniF33CuniF33DuniF33EuniF33FuniF340uniF341uniF342uniF343uniF344uniF345uniF346uniF347uniF348uniF349uniF34AuniF34BuniF34CuniF34DuniF34EuniF34FuniF350uniF351uniF352uniF353uniF354uniF355uniF356uniF357uniF358uniF359uniF35AuniF35BuniF35CuniF35DuniF35EuniF35FuniF360uniF361uniF362uniF363uniF364uniF365uniF366uniF367uniF368uniF369uniF36AuniF36BuniF36CuniF36DuniF36EuniF36FuniF370uniF371uniF372uniF373uniF374uniF375uniF376uniF377uniF378uniF379uniF37AuniF37BuniF37CuniF37DuniF37EuniF37FuniF380uniF381uniF382uniF383uniF384uniF385uniF386uniF387uniF388uniF389uniF38AuniF38BuniF38CuniF38DuniF38EuniF38FuniF390uniF391uniF392uniF393uniF394uniF395uniF396uniF397uniF398uniF399uniF39AuniF39BuniF39CuniF39DuniF39EuniF39FuniF3A0uniF3A1uniF3A2uniF3A3uniF3A4uniF3A5uniF3A6uniF3A7uniF3A8uniF3A9uniF3AAuniF3ABuniF3ACuniF3ADuniF3AEuniF3AFuniF3B0uniF3B1uniF3B2uniF3B3uniF3B4uniF3B5uniF3B6uniF3B7uniF3B8uniF3B9uniF3BAuniF3BBuniF3BCuniF3BDuniF3BEuniF3BFuniF3C0uniF3C1uniF3C2uniF3C3uniF3C4uniF3C5uniF3C6uniF3C7uniF3C8uniF3C9uniF3CAuniF3CBuniF3CCuniF3CDuniF3CEuniF3CFuniF3D0uniF3D1uniF3D2uniF3D3uniF3D4uniF3D5uniF3D6uniF3D7uniF3D8uniF3D9uniF3DAuniF3DBuniF3DCuniF3DDuniF3DEuniF3DFuniF3E0uniF3E1uniF3E2uniF3E3uniF3E4uniF3E5uniF3E6uniF3E7uniF3E8uniF3E9uniF3EAuniF3EBuniF3ECuniF3EDuniF3EEuniF3EFuniF3F0uniF3F1uniF3F2uniF3F3uniF3F4uniF3F5uniF3F6uniF3F7uniF3F8uniF3F9uniF3FAuniF3FBuniF3FCuniF3FDuniF3FEuniF3FFuniF400uniF401uniF402uniF403uniF404uniF405uniF406uniF407uniF408uniF409uniF40AuniF40BuniF40CuniF40DuniF40EuniF40FuniF410uniF411uniF412uniF413uniF414uniF415uniF416uniF417uniF418uniF419uniF41AuniF41BuniF41CuniF41DuniF41EuniF41FuniF420uniF421uniF422uniF423uniF55EuniF55FuniF5C0uniF5C1uniF5C2uniF5C3uniF5C4uniF5C5uniF5C6uniF5C7uniF5C8uniF5C9uniF5CAuniF5CBuniF5CCuniF5CDuniF5CEuniF5CFuniF5D0uniF5D1uniF5D2uniF5D3uniF5D4uniF5D5uniF5D6uniF5D7uniF5D8uniF5D9uniF5DAuniF5DBuniF5DCuniF5DDuniF5DEuniF5DFuniF5E0uniF5E1uniF5E2uniF5E3uniF5E4uniF5E5uniF5E6uniF5E7uniF5E8uniF5E9uniF5EAuniF5EBuniF5ECuniF5EDuniF5EEuniF5EFuniF5F0uniF5F1uniF5F2uniF5F3uniF5F4uniF5F5uniF5F6uniF5F7uniF5F8uniF5F9uniF5FAuniF5FBuniF5FCuniF5FDuniF5FEuniF5FFuniF600uniF601uniF602uniF603uniF604uniF605uniF606uniF607uniF608uniF609uniF60AuniF60BuniF60CuniF60DuniF60EuniF60FuniF610uniF611uniF612uniF613uniF614uniF615uniF616uniF617uniF618uniF619uniF61AuniF61BuniF61CuniF61DuniF61EuniF61FuniF680uniF681uniF682uniF683uniF684uniF685uniF686uniF687uniF688uniF689uniF68AuniF68BuniF68CuniF68DuniF68EuniF68FuniF690uniF691uniF692uniF693uniF694uniF695uniF696uniF697uniF698uniF699uniF69AuniF69BuniF69CuniF69DuniF69EuniF69FuniF700uniF701uniF702uniF703uniF704uniF705uniF706uniF707uniF708uniF709uniF70AuniF70BuniF70CuniF70DuniF70EuniF70FuniF710uniF711uniF712uniF713uniF714uniF715uniF716uniF717uniF718uniF719uniF71AuniF71BuniF71CuniF71DuniF71EuniF71FuniF720uniF721uniF722uniF723uniF724uniF725uniF726uniF727uniF728uniF729uniF72AuniF72BuniF72CuniF72DuniF72EuniF72FuniF730uniF731uniF732uniF733uniF734uniF735uniF736uniF737uniF738uniF739uniF73AuniF73BuniF73CuniF73DuniF73EuniF73FuniF740uniF741uniF742uniF743uniF744uniF745uniF746uniF747uniF748uniF749uniF74AuniF74BuniF74CuniF74DuniF74EuniF74FuniF750uniF751uniF752uniF753uniF754uniF755uniF756uniF757uniF758uniF759uniF75AuniF75BuniF75CuniF75DuniF75EuniF75FuniF760uniF761uniF762uniF763uniF764uniF765uniF766uniF767uniF768uniF769uniF76AuniF76BuniF76CuniF76DuniF76EuniF76FuniF770uniF771uniF772uniF773uniF774uniF775uniF776uniF777uniF778uniF779uniF77AuniF77BuniF77CuniF77DuniF77EuniF77FuniF780uniF781uniF782uniF783uniF784uniF785uniF786uniF787uniF788uniF789uniF78AuniF78BuniF78CuniF78DuniF78EuniF78FuniF790uniF791uniF792uniF793uniF794uniF795uniF796uniF797uniF798uniF799uniF79AuniF79BuniF79CuniF79DuniF79EuniF79FuniF7A0uniF7A1uniF7A2uniF7A3uniF7A4uniF7A5uniF7A6uniF7A7uniF7A8uniF7A9uniF7AAuniF7ABuniF7ACuniF7ADuniF7AEuniF7AFuniF7B0uniF7B1uniF7B2uniF7B3uniF7B4uniF7B5uniF7B6uniF7B7uniF7B8uniF7B9uniF7BAuniF7BBuniF7BCuniF7BDuniF7BEuniF7BFuniF7C0uniF7C1uniF7C2uniF7C3uniF7C4uniF7C5uniF7C6uniF7C7uniF7C8uniF7C9uniF7CAuniF7CBuniF7CCuniF7CDuniF7CEuniF7CFuniF7D0uniF7D1uniF7D2uniF7D3uniF7D4uniF7D5uniF7D6uniF7D7uniF7D8uniF7D9uniF7DAuniF7DBuniF7DCuniF7DDuniF7DEuniF7DFuniF7E0uniF7E1uniF7E2uniF7E3uniF7E4uniF7E5uniF7E6uniF7E7uniF7E8uniF7E9uniF7EAuniF7EBuniF7ECuniF7EDuniF7EEuniF7EFuniF7F0uniF7F1uniF7F2uniF7F3uniF7F4uniF7F5uniF7F6uniF7F7uniF7F8uniF7F9uniF7FAuniF7FBuniF7FCuniF7FDuniF7FEuniF7FFuniF800uniF801uniF802uniF803uniF804uniF805uniF806uniF807uniF808uniF809uniF80AuniF80BuniF80CuniF80DuniF80EuniF80FuniF810uniF811uniF812uniF813uniF814uniF815uniF816uniF817uniF818uniF819uniF81AuniF81BuniF81CuniF81DuniF81EuniF81FuniF820uniF821uniF822uniF823uniF824uniF825uniF826uniF827uniF828uniF829uniF82AuniF82BuniF82CuniF82DuniF82EuniF82FuniF830uniF831uniF832uniF833uniF834uniF835uniF836uniF837uniF838uniF839uniF83AuniF83BuniF83CuniF83DuniF83EuniF83FuniF840uniF841uniF842uniF843uniF844uniF845uniF846uniF847uniF848uniF849uniF84AuniF84BuniF84CuniF84DuniF84EuniF84FuniF850uniF851uniF852uniF853uniF854uniF855uniF856uniF857uniF858uniF859uniF85AuniF85BuniF85CuniF85DuniF85EuniF85FuniF860uniF861uniF862uniF863uniF864uniF865uniF866uniF867uniF868uniF869uniF86AuniF86BuniF86CuniF86DuniF86EuniF86FuniF870uniF871uniF872uniF873uniF874uniF875uniF876uniF877uniF878uniF879uniF87AuniF87BuniF87CuniF87DuniF87EuniF87FuniF880uniF881uniF882uniF883uniF884uniF885uniF886uniF887uniF888uniF889uniF88AuniF88BuniF88CuniF88DuniF88EuniF88FuniF890uniF891uniF892uniF893uniF894uniF895uniF896uniF897uniF898uniF899uniF89AuniF89BuniF89CuniF89DuniF89EuniF89FuniF8D0uniF8D1uniF8D2uniF8D3uniF8D4uniF8D5uniF8D6uniF8D7uniF8D8uniF8D9uniF8DAuniF8DBuniF8DCuniF8DDuniF8DEuniF8DFuniF8E0uniF8E1uniF8E2uniF8E3uniF8E4uniF8E5uniF8E6uniF8E7uniF8E8uniF8E9uniF8F0uniF8F1uniF8F2uniF8F3uniF8F4uniF8F5uniF8F6uniF8F7uniF8F8uniF8F9uniF8FAuniF8FBuniF8FCuniF8FDuniF8FEuniF8FFuniFB00uniFB01uniFB02uniFB03uniFB04uniFB05uniFB06uniFB07uniFFF0uniFFF1uniFFF2uniFFF3uniFFFCuniFFFDu1CC00u1CC01u1CC02u1CC03u1CC04u1CC05u1CC06u1CC07u1CC08u1CC09u1CC0Au1CC0Bu1CC0Cu1CC0Du1CC0Eu1CC0Fu1CC10u1CC11u1CC12u1CC13u1CC14u1CC15u1CC16u1CC17u1CC18u1CC19u1CC1Au1CC1Bu1CC1Cu1CC1Du1CC1Eu1CC1Fu1CC20u1CC21u1CC22u1CC23u1CC24u1CC25u1CC26u1CC27u1CC28u1CC29u1CC2Au1CC2Bu1CC2Cu1CC2Du1CC2Eu1CC2Fu1CC30u1CC31u1CC32u1CC33u1CC34u1CC35u1CC36u1CC37u1CC38u1CC39u1CC3Au1CC3Bu1CC3Cu1CC3Du1CC3Eu1CC3Fu1CC40u1CC41u1CC42u1CC43u1CC44u1CC45u1CC46u1CC47u1CC48u1CC49u1CC4Au1CC4Bu1CC4Cu1CC4Du1CC4Eu1CC4Fu1CC50u1CC51u1CC52u1CC53u1CC54u1CC55u1CC56u1CC57u1CC58u1CC59u1CC5Au1CC5Bu1CC5Cu1CC5Du1CC5Eu1CC5Fu1CC60u1CC61u1CC62u1CC63u1CC64u1CC65u1CC66u1CC67u1CC68u1CC69u1CC6Au1CC6Bu1CC6Cu1CC6Du1CC6Eu1CC6Fu1CC70u1CC71u1CC72u1CC73u1CC74u1CC75u1CC76u1CC77u1CC78u1CC79u1CC7Au1CC7Bu1CC7Cu1CC7Du1CC7Eu1CC7Fu1CC80u1CC81u1CC82u1CC83u1CC84u1CC85u1CC86u1CC87u1CC88u1CC89u1CC8Au1CC8Bu1CC8Cu1CC8Du1CC8Eu1CC8Fu1CC90u1CC91u1CC92u1CC93u1CC94u1CC95u1CC96u1CC97u1CC98u1CC99u1CC9Au1CC9Bu1CC9Cu1CC9Du1CC9Eu1CC9Fu1CCA0u1CCA1u1CCA2u1CCA3u1CCA4u1CCA5u1CCA6u1CCA7u1CCA8u1CCA9u1CCAAu1CCABu1CCACu1CCADu1CCAEu1CCAFu1CCB0u1CCB1u1CCB2u1CCB3u1CCB4u1CCB5u1CCB6u1CCB7u1CCB8u1CCB9u1CCBAu1CCBBu1CCBCu1CCBDu1CCBEu1CCBFu1CCC0u1CCC1u1CCC2u1CCC3u1CCC4u1CCC5u1CCC6u1CCC7u1CCC8u1CCC9u1CCCAu1CCCBu1CCCCu1CCCDu1CCCEu1CCCFu1CCD0u1CCD1u1CCD2u1CCD3u1CCD4u1CCD5u1CCD6u1CCD7u1CCD8u1CCD9u1CCDAu1CCDBu1CCDCu1CCDDu1CCDEu1CCDFu1CCE0u1CCE1u1CCE2u1CCE3u1CCE4u1CCE5u1CCE6u1CCE7u1CCE8u1CCE9u1CCEAu1CCEBu1CCECu1CCEDu1CCEEu1CCEFu1CCF0u1CCF1u1CCF2u1CCF3u1CCF4u1CCF5u1CCF6u1CCF7u1CCF8u1CCF9u1CCFAu1CCFBu1CCFCu1CD00u1CD01u1CD02u1CD03u1CD04u1CD05u1CD06u1CD07u1CD08u1CD09u1CD0Au1CD0Bu1CD0Cu1CD0Du1CD0Eu1CD0Fu1CD10u1CD11u1CD12u1CD13u1CD14u1CD15u1CD16u1CD17u1CD18u1CD19u1CD1Au1CD1Bu1CD1Cu1CD1Du1CD1Eu1CD1Fu1CD20u1CD21u1CD22u1CD23u1CD24u1CD25u1CD26u1CD27u1CD28u1CD29u1CD2Au1CD2Bu1CD2Cu1CD2Du1CD2Eu1CD2Fu1CD30u1CD31u1CD32u1CD33u1CD34u1CD35u1CD36u1CD37u1CD38u1CD39u1CD3Au1CD3Bu1CD3Cu1CD3Du1CD3Eu1CD3Fu1CD40u1CD41u1CD42u1CD43u1CD44u1CD45u1CD46u1CD47u1CD48u1CD49u1CD4Au1CD4Bu1CD4Cu1CD4Du1CD4Eu1CD4Fu1CD50u1CD51u1CD52u1CD53u1CD54u1CD55u1CD56u1CD57u1CD58u1CD59u1CD5Au1CD5Bu1CD5Cu1CD5Du1CD5Eu1CD5Fu1CD60u1CD61u1CD62u1CD63u1CD64u1CD65u1CD66u1CD67u1CD68u1CD69u1CD6Au1CD6Bu1CD6Cu1CD6Du1CD6Eu1CD6Fu1CD70u1CD71u1CD72u1CD73u1CD74u1CD75u1CD76u1CD77u1CD78u1CD79u1CD7Au1CD7Bu1CD7Cu1CD7Du1CD7Eu1CD7Fu1CD80u1CD81u1CD82u1CD83u1CD84u1CD85u1CD86u1CD87u1CD88u1CD89u1CD8Au1CD8Bu1CD8Cu1CD8Du1CD8Eu1CD8Fu1CD90u1CD91u1CD92u1CD93u1CD94u1CD95u1CD96u1CD97u1CD98u1CD99u1CD9Au1CD9Bu1CD9Cu1CD9Du1CD9Eu1CD9Fu1CDA0u1CDA1u1CDA2u1CDA3u1CDA4u1CDA5u1CDA6u1CDA7u1CDA8u1CDA9u1CDAAu1CDABu1CDACu1CDADu1CDAEu1CDAFu1CDB0u1CDB1u1CDB2u1CDB3u1CDB4u1CDB5u1CDB6u1CDB7u1CDB8u1CDB9u1CDBAu1CDBBu1CDBCu1CDBDu1CDBEu1CDBFu1CDC0u1CDC1u1CDC2u1CDC3u1CDC4u1CDC5u1CDC6u1CDC7u1CDC8u1CDC9u1CDCAu1CDCBu1CDCCu1CDCDu1CDCEu1CDCFu1CDD0u1CDD1u1CDD2u1CDD3u1CDD4u1CDD5u1CDD6u1CDD7u1CDD8u1CDD9u1CDDAu1CDDBu1CDDCu1CDDDu1CDDEu1CDDFu1CDE0u1CDE1u1CDE2u1CDE3u1CDE4u1CDE5u1CDE6u1CDE7u1CDE8u1CDE9u1CDEAu1CDEBu1CDECu1CDEDu1CDEEu1CDEFu1CDF0u1CDF1u1CDF2u1CDF3u1CDF4u1CDF5u1CDF6u1CDF7u1CDF8u1CDF9u1CDFAu1CDFBu1CDFCu1CDFDu1CDFEu1CDFFu1CE00u1CE01u1CE02u1CE03u1CE04u1CE05u1CE06u1CE07u1CE08u1CE09u1CE0Au1CE0Bu1CE0Cu1CE0Du1CE0Eu1CE0Fu1CE10u1CE11u1CE12u1CE13u1CE14u1CE15u1CE16u1CE17u1CE18u1CE19u1CE1Au1CE1Bu1CE1Cu1CE1Du1CE1Eu1CE1Fu1CE20u1CE21u1CE22u1CE23u1CE24u1CE25u1CE26u1CE27u1CE28u1CE29u1CE2Au1CE2Bu1CE2Cu1CE2Du1CE2Eu1CE2Fu1CE30u1CE31u1CE32u1CE33u1CE34u1CE35u1CE36u1CE37u1CE38u1CE39u1CE3Au1CE3Bu1CE3Cu1CE3Du1CE3Eu1CE3Fu1CE40u1CE41u1CE42u1CE43u1CE44u1CE45u1CE46u1CE47u1CE48u1CE49u1CE4Au1CE4Bu1CE4Cu1CE4Du1CE4Eu1CE4Fu1CE50u1CE51u1CE52u1CE53u1CE54u1CE55u1CE56u1CE57u1CE58u1CE59u1CE5Au1CE5Bu1CE5Cu1CE5Du1CE5Eu1CE5Fu1CE60u1CE61u1CE62u1CE63u1CE64u1CE65u1CE66u1CE67u1CE68u1CE69u1CE6Au1CE6Bu1CE6Cu1CE6Du1CE6Eu1CE6Fu1CE70u1CE71u1CE72u1CE73u1CE74u1CE75u1CE76u1CE77u1CE78u1CE79u1CE7Au1CE7Bu1CE7Cu1CE7Du1CE7Eu1CE7Fu1CE80u1CE81u1CE82u1CE83u1CE84u1CE85u1CE86u1CE87u1CE88u1CE89u1CE8Au1CE8Bu1CE8Cu1CE8Du1CE8Eu1CE8Fu1CE90u1CE91u1CE92u1CE93u1CE94u1CE95u1CE96u1CE97u1CE98u1CE99u1CE9Au1CE9Bu1CE9Cu1CE9Du1CE9Eu1CE9Fu1CEA0u1CEA1u1CEA2u1CEA3u1CEA4u1CEA5u1CEA6u1CEA7u1CEA8u1CEA9u1CEAAu1CEABu1CEACu1CEADu1CEAEu1CEAFu1CEB0u1CEB1u1CEB2u1CEB3u1CEBAu1CEBBu1CEBCu1CEBDu1CEBEu1CEBFu1F000u1F001u1F002u1F003u1F004u1F005u1F006u1F007u1F008u1F009u1F00Au1F00Bu1F00Cu1F00Du1F00Eu1F00Fu1F010u1F011u1F012u1F013u1F014u1F015u1F016u1F017u1F018u1F019u1F01Au1F01Bu1F01Cu1F01Du1F01Eu1F01Fu1F020u1F021u1F022u1F023u1F024u1F025u1F026u1F027u1F028u1F029u1F02Au1F02Bu1F030u1F031u1F032u1F033u1F034u1F035u1F036u1F037u1F038u1F039u1F03Au1F03Bu1F03Cu1F03Du1F03Eu1F03Fu1F040u1F041u1F042u1F043u1F044u1F045u1F046u1F047u1F048u1F049u1F04Au1F04Bu1F04Cu1F04Du1F04Eu1F04Fu1F050u1F051u1F052u1F053u1F054u1F055u1F056u1F057u1F058u1F059u1F05Au1F05Bu1F05Cu1F05Du1F05Eu1F05Fu1F060u1F061u1F062u1F063u1F064u1F065u1F066u1F067u1F068u1F069u1F06Au1F06Bu1F06Cu1F06Du1F06Eu1F06Fu1F070u1F071u1F072u1F073u1F074u1F075u1F076u1F077u1F078u1F079u1F07Au1F07Bu1F07Cu1F07Du1F07Eu1F07Fu1F080u1F081u1F082u1F083u1F084u1F085u1F086u1F087u1F088u1F089u1F08Au1F08Bu1F08Cu1F08Du1F08Eu1F08Fu1F090u1F091u1F092u1F093u1F0A0u1F0A1u1F0A2u1F0A3u1F0A4u1F0A5u1F0A6u1F0A7u1F0A8u1F0A9u1F0AAu1F0ABu1F0ACu1F0ADu1F0AEu1F0B1u1F0B2u1F0B3u1F0B4u1F0B5u1F0B6u1F0B7u1F0B8u1F0B9u1F0BAu1F0BBu1F0BCu1F0BDu1F0BEu1F0BFu1F0C1u1F0C2u1F0C3u1F0C4u1F0C5u1F0C6u1F0C7u1F0C8u1F0C9u1F0CAu1F0CBu1F0CCu1F0CDu1F0CEu1F0CFu1F0D1u1F0D2u1F0D3u1F0D4u1F0D5u1F0D6u1F0D7u1F0D8u1F0D9u1F0DAu1F0DBu1F0DCu1F0DDu1F0DEu1F0DFu1F0E0u1F0E1u1F0E2u1F0E3u1F0E4u1F0E5u1F0E6u1F0E7u1F0E8u1F0E9u1F0EAu1F0EBu1F0ECu1F0EDu1F0EEu1F0EFu1F0F0u1F0F1u1F0F2u1F0F3u1F0F4u1F0F5u1F10Du1F10Eu1F10Fu1F12Fu1F130u1F131u1F132u1F133u1F134u1F135u1F136u1F137u1F138u1F139u1F13Au1F13Bu1F13Cu1F13Du1F13Eu1F13Fu1F140u1F141u1F142u1F143u1F144u1F145u1F146u1F147u1F148u1F149u1F150u1F151u1F152u1F153u1F154u1F155u1F156u1F157u1F158u1F159u1F15Au1F15Bu1F15Cu1F15Du1F15Eu1F15Fu1F160u1F161u1F162u1F163u1F164u1F165u1F166u1F167u1F168u1F169u1F16Au1F16Bu1F16Cu1F16Du1F16Eu1F16Fu1F170u1F171u1F172u1F173u1F174u1F175u1F176u1F177u1F178u1F179u1F17Au1F17Bu1F17Cu1F17Du1F17Eu1F17Fu1F180u1F181u1F182u1F183u1F184u1F185u1F186u1F187u1F188u1F189u1F194u1F1ADu1F1E6u1F1E7u1F1E8u1F1E9u1F1EAu1F1EBu1F1ECu1F1EDu1F1EEu1F1EFu1F1F0u1F1F1u1F1F2u1F1F3u1F1F4u1F1F5u1F1F6u1F1F7u1F1F8u1F1F9u1F1FAu1F1FBu1F1FCu1F1FDu1F1FEu1F1FFu1F377u1F378u1F3A7u1F3E2u1F40Du1F443u1F4A3u1F4BEu1F4CBu1F4E4u1F4E5u1F505u1F506u1F507u1F508u1F509u1F50Au1F50Du1F50Eu1F512u1F513u1F514u1F515u1F550u1F551u1F552u1F553u1F554u1F555u1F556u1F557u1F558u1F559u1F55Au1F55Bu1F55Cu1F55Du1F55Eu1F55Fu1F560u1F561u1F562u1F563u1F564u1F565u1F566u1F567u1F568u1F569u1F56Au1F589u1F5A4u1F5A8u1F5AAu1F5ABu1F5ACu1F5B4u1F5B5u1F5B6u1F5B8u1F5BFu1F5C0u1F5C1u1F5C5u1F5C6u1F5C7u1F5C8u1F5C9u1F5CAu1F5CBu1F5CCu1F5CDu1F5CEu1F5CFu1F5D0u1F5D5u1F5D6u1F5D7u1F5D9u1F5E4u1F5E5u1F5E6u1F5E7u1F5E8u1F5E9u1F5EAu1F5EBu1F600u1F603u1F610u1F636u1F641u1F642u1F643u1F67Cu1F67Du1F67Eu1F67Fu1F6AAu1F6F8u1F78Eu1F78Fu1F790u1F791u1F792u1F793u1F8B0u1F8B1u1F8B2u1F8B3u1F8B4u1F8B5u1F8B6u1F8B7u1F8B8u1F8B9u1F8BAu1F8BBu1F907u1F90Du1FA9Fu1FB00u1FB01u1FB02u1FB03u1FB04u1FB05u1FB06u1FB07u1FB08u1FB09u1FB0Au1FB0Bu1FB0Cu1FB0Du1FB0Eu1FB0Fu1FB10u1FB11u1FB12u1FB13u1FB14u1FB15u1FB16u1FB17u1FB18u1FB19u1FB1Au1FB1Bu1FB1Cu1FB1Du1FB1Eu1FB1Fu1FB20u1FB21u1FB22u1FB23u1FB24u1FB25u1FB26u1FB27u1FB28u1FB29u1FB2Au1FB2Bu1FB2Cu1FB2Du1FB2Eu1FB2Fu1FB30u1FB31u1FB32u1FB33u1FB34u1FB35u1FB36u1FB37u1FB38u1FB39u1FB3Au1FB3Bu1FB3Cu1FB3Du1FB3Eu1FB3Fu1FB40u1FB41u1FB42u1FB43u1FB44u1FB45u1FB46u1FB47u1FB48u1FB49u1FB4Au1FB4Bu1FB4Cu1FB4Du1FB4Eu1FB4Fu1FB50u1FB51u1FB52u1FB53u1FB54u1FB55u1FB56u1FB57u1FB58u1FB59u1FB5Au1FB5Bu1FB5Cu1FB5Du1FB5Eu1FB5Fu1FB60u1FB61u1FB62u1FB63u1FB64u1FB65u1FB66u1FB67u1FB68u1FB69u1FB6Au1FB6Bu1FB6Cu1FB6Du1FB6Eu1FB6Fu1FB70u1FB71u1FB72u1FB73u1FB74u1FB75u1FB76u1FB77u1FB78u1FB79u1FB7Au1FB7Bu1FB7Cu1FB7Du1FB7Eu1FB7Fu1FB80u1FB81u1FB82u1FB83u1FB84u1FB85u1FB86u1FB87u1FB88u1FB89u1FB8Au1FB8Bu1FB8Cu1FB8Du1FB8Eu1FB8Fu1FB90u1FB91u1FB92u1FB93u1FB94u1FB95u1FB96u1FB97u1FB98u1FB99u1FB9Au1FB9Bu1FB9Cu1FB9Du1FB9Eu1FB9Fu1FBA0u1FBA1u1FBA2u1FBA3u1FBA4u1FBA5u1FBA6u1FBA7u1FBA8u1FBA9u1FBAAu1FBABu1FBACu1FBADu1FBAEu1FBAFu1FBB0u1FBB1u1FBB2u1FBB3u1FBB4u1FBB5u1FBB6u1FBB7u1FBB8u1FBB9u1FBBAu1FBBBu1FBBCu1FBBDu1FBBEu1FBBFu1FBC0u1FBC1u1FBC2u1FBC3u1FBC4u1FBC5u1FBC6u1FBC7u1FBC8u1FBC9u1FBCAu1FBCBu1FBCCu1FBCDu1FBCEu1FBCFu1FBD0u1FBD1u1FBD2u1FBD3u1FBD4u1FBD5u1FBD6u1FBD7u1FBD8u1FBD9u1FBDAu1FBDBu1FBDCu1FBDDu1FBDEu1FBDFu1FBE0u1FBE1u1FBE2u1FBE3u1FBE4u1FBE5u1FBE6u1FBE7u1FBE8u1FBE9u1FBEAu1FBEBu1FBECu1FBEDu1FBEEu1FBEFu1FBF0u1FBF1u1FBF2u1FBF3u1FBF4u1FBF5u1FBF6u1FBF7u1FBF8u1FBF9u1FBFAuE0001uE0020uE0021uE0022uE0023uE0024uE0025uE0026uE0027uE0028uE0029uE002AuE002BuE002CuE002DuE002EuE002FuE0030uE0031uE0032uE0033uE0034uE0035uE0036uE0037uE0038uE0039uE003AuE003BuE003CuE003DuE003EuE003FuE0040uE0041uE0042uE0043uE0044uE0045uE0046uE0047uE0048uE0049uE004AuE004BuE004CuE004DuE004EuE004FuE0050uE0051uE0052uE0053uE0054uE0055uE0056uE0057uE0058uE0059uE005AuE005BuE005CuE005DuE005EuE005FuE0060uE0061uE0062uE0063uE0064uE0065uE0066uE0067uE0068uE0069uE006AuE006BuE006CuE006DuE006EuE006FuE0070uE0071uE0072uE0073uE0074uE0075uE0076uE0077uE0078uE0079uE007AuE007BuE007CuE007DuE007EuE007FuFB009uFF000uFF001uFF002uFF003uFF004uFF005uFF006uFF007uFF008uFF009uFF00AuFF00BuFF00CuFF00DuFF00EuFF00FuFF010uFF011uFF012uFF013uFF014uFF015uFF016uFF017uFF018uFF019uFF01AuFF01BuFF01CuFF01DuFF01EuFF01FuFF020uFF021uFF022uFF023uFF024uFF025uFF026uFF027uFF028uFF029uFF02AuFF02BuFF02CuFF02DuFF02EuFF02FuFF030uFF031uFF032uFF033uFF034uFF035uFF036uFF037uFF038uFF039uFF03AuFF03BuFF03CuFF03DuFF03EuFF03FuFF040uFF041uFF042uFF043uFF044uFF045uFF046uFF047uFF048uFF049uFF04AuFF04BuFF04CuFF04DuFF04EuFF04FuFF050uFF051uFF052uFF053uFF054uFF055uFF056uFF057uFF058uFF059uFF05AuFF05BuFF05CuFF05DuFF05EuFF05FuFF060uFF061uFF062uFF063uFF064uFF065uFF066uFF067uFF068uFF069uFF06AuFF06BuFF06CuFF06DuFF06EuFF06FuFF070uFF071uFF072uFF073uFF074uFF075uFF076uFF077uFF078uFF079uFF07AuFF07BuFF07CuFF07DuFF07EuFF07FuFF080uFF081uFF082uFF083uFF084uFF085uFF086uFF087uFF088uFF089uFF08AuFF08BuFF08CuFF08DuFF08EuFF08FuFF090uFF091uFF092uFF093uFF094uFF095uFF0A0uFF0A1uFF0A2uFF0A3uFF0B0uFF0B1uFF0B2uFF0B3uFF0B4uFF0B5uFF0B6uFF0B7uFF0B8uFF0B9uFF0BAuFF0BBuFF0BCuFF0BDuFF0BEuFF0BFuFF0C0uFF0C1uFF0C2uFF0C3uFF0C4uFF0C5uFF0C6uFF0C7uFF0C8uFF0C9uFF0CAuFF0CBuFF0CCuFF0CDuFF0CEuFF0CFuFF0D0uFF0D1uFF0D2uFF0D3uFF0D4uFF0D5uFF0E0uFF0E1uFF0E2uFF0E3uFF0E4uFF0E5uFF0E6uFF0E7uFF0E8uFF0E9uFF0EAuFF0EBuFF0ECuFF0EDuFF0EEuFF0EFuFF0F0uFF0F1uFF0F2uFF0F3uFF0F4uFF0F5uFF0F6uFF0F7uFF0F8uFF0F9uFF0FAuFF0FBuFF0FCuFF0FDuFF0FEuFF0FFuFF100uFF101uFF102uFF103uFF104uFF105uFF106uFF107uFF108uFF109uFF10AuFF10BuFF10CuFF10DuFF10EuFF10FuFF110uFF111uFF112uFF113uFF114uFF115uFF116uFF117uFF118uFF119uFF11AuFF11BuFF11CuFF11DuFF11EuFF11FuFF120uFF121uFF122uFF123uFF124uFF125uFF126uFF127uFF128uFF129uFF12AuFF12BuFF12CuFF12DuFF12EuFF12FuFF130uFF131uFF132uFF133uFF134uFF135uFF136uFF137uFF138uFF139uFF13AuFF13BuFF13CuFF13DuFF13EuFF13FuFF140uFF141uFF142uFF143uFF144uFF145uFF180uFF181uFF182uFF183uFF184uFF185uFF1A0uFF1A1uFF1C0uFF1E0uFF1F0uFF700uFF701uFF702uFF703uFF704uFF705uFF706uFF707uFF708uFF709uFF70AuFF70BuFF70CuFF70DuFF70EuFF70FuFF710uFF711uFF712uFF713uFF714uFF715uFF716uFF717uFF718uFF719uFF71AuFF71BuFF71CuFF71DuFF71EuFF71FuFF720uFF721uFF722uFF723uFF724uFF725uFF726uFF727uFF728uFF729uFF72AuFF72BuFF72CuFF72DuFF72EuFF72FuFF730uFF731uFF732uFF733uFF734uFF735uFF736uFF737uFF738uFF739uFF73AuFF73BuFF73CuFF73DuFF73EuFF73FuFF740uFF741uFF742uFF743uFF744uFF745uFF746uFF747uFF748uFF749uFF74AuFF74BuFF74CuFF74DuFF74EuFF74FuFF750uFF751uFF752uFF753uFF754uFF755uFF756uFF757uFF758uFF759uFF75AuFF75BuFF75CuFF75DuFF75EuFF75FuFF760uFF761uFF762uFF763uFF764uFF765uFF766uFF767uFF768uFF769uFF76AuFF76BuFF76CuFF76DuFF76EuFF76FuFF770uFF771uFF772uFF773uFF774uFF775uFF776uFF777uFF778uFF779uFF77AuFF77BuFF77CuFF77DuFF77EuFF77FuFF780uFF781uFF782uFF783uFF784uFF785uFF786uFF787uFF788uFF789uFF78AuFF78BuFF78CuFF78DuFF78EuFF78FuFF790uFF791uFF792uFF793uFF794uFF795uFF796uFF797uFF798uFF799uFF79AuFF79BuFF79CuFF79DuFF79EuFF79FuFF7A0uFF7A1uFF7A2uFF7A3uFF7A4uFF7A5uFF7A6uFF7A7uFF7A8uFF7A9uFF7AAuFF7ABuFF7ACuFF7ADuFF7AEuFF7AFuFF7B0uFF7B1uFF7B2uFF7B3uFF7B4uFF7B5uFF7B6uFF7B7uFF7B8uFF7B9uFF7BAuFF7BBuFF7BCuFF7BDuFF7BEuFF7BFuFF7C0uFF7C1uFF7C2uFF7C3uFF7C4uFF7C5uFF7C6uFF7C7uFF7C8uFF7C9uFF7CAuFF7CBuFF7CCuFF7CDuFF7CEuFF7CFuFF7D0uFF7D1uFF7D2uFF7D3uFF7D4uFF7D5uFF7D6uFF7D7uFF7D8uFF7D9uFF7DAuFF7DBuFF7DCuFF7DDuFF7DEuFF7DFuFF7E0uFF7E1uFF7E2uFF7E3uFF7E4uFF7E5uFF7E6uFF7E7uFF7E8uFF7E9uFF7EAuFF7EBuFF7ECuFF7EDuFF7EEuFF7EFuFF7F0uFF7F1uFF7F2uFF7F3uFF7F4uFF7F5uFF7F6uFF7F7uFF7F8uFF7F9uFF7FAuFF7FBuFF7FCuFF7FDuFF7FEuFF7FFuFFC00uFFC01uFFC02uFFC03uFFC04uFFC05uFFC06uFFC07uFFC08uFFC09uFFC0AuFFC0BuFFC0CuFFC0DuFFC0EuFFC0FuFFC10uFFC11uFFC12uFFC13uFFC14uFFC16uFFC18uFFC19uFFC1AuFFC1BuFFC1CuFFC1DuFFC1EuFFC1FuFFC20uFFC21uFFC22uFFC23uFFC24uFFC25uFFC26uFFC27uFFC28uFFC29uFFC2CuFFC2DuFFC2EuFFC2FuFFC31uFFC32uFFC33uFFC34uFFC35uFFC3CuFFC3DuFFC3EuFFC3FuFFC40uFFC41uFFC42uFFC43uFFC44uFFC45uFFC46uFFC47uFFC48uFFC49uFFC4AuFFC4BuFFC4CuFFC4DuFFC4EuFFC4FuFFC50uFFC51uFFC52uFFC53uFFC54uFFC55uFFC56uFFC57uFFC58uFFC59uFFC5AuFFC5BuFFC5CuFFC5DuFFC5EuFFC5FuFFC60uFFC61uFFC62uFFC63uFFC64uFFC65uFFC66uFFC67uFFC68uFFC69uFFC6AuFFC6BuFFC6CuFFC6DuFFC6EuFFC6FuFFC70uFFC71uFFC72uFFC73uFFC74uFFC75uFFC76uFFC77uFFC78uFFC79uFFC7AuFFC7BuFFC7CuFFC7DuFFC7EuFFC7FuFFC80uFFC81uFFC82uFFC83uFFC84uFFC85uFFC86uFFC87uFFC88uFFC89uFFC8AuFFC8BuFFC8CuFFC8DuFFC8EuFFC8FuFFC90uFFC91uFFC92uFFC93uFFC94uFFC95uFFC96uFFC97uFFC98uFFC99uFFC9AuFFC9BuFFC9CuFFC9DuFFC9EuFFC9FuFFCA0uFFCA1uFFCA2uFFCA3uFFCA4uFFCA5uFFCA6uFFCA7uFFCA8uFFCA9uFFCAAuFFCABuFFCACuFFCADuFFCAEuFFCAFuFFCB0uFFCB1uFFCB2uFFCB3uFFCB4uFFCB5uFFCB6uFFCB7uFFCB8uFFCB9uFFCBAuFFCBBuFFCBCuFFCBDuFFCBEuFFCBFuFFCC0uFFCC1uFFCC2uFFCC3uFFCC4uFFCC5uFFCC6uFFCC7uFFCC8uFFCC9uFFCCAuFFCCBuFFCCCuFFCCDuFFCCEuFFCCFuFFCD0uFFCD1uFFCD2uFFCD3uFFCD4uFFCD5uFFCD6uFFCD7uFFCD8uFFCD9uFFCDAuFFCDBuFFCDCuFFCDDuFFCDEuFFCDFuFFCE0uFFCE1uFFCE2uFFCE3uFFCE4uFFCE5uFFCE6uFFCE7uFFCE8uFFCE9uFFCEAuFFCEBuFFCECuFFCEDuFFCEEuFFCEFuFFCF0uFFCF1uFFCF8uFFCF9uFFCFAuFFCFBuFFCFCuFFCFDuFFCFEuFFCFFu100020u100021u100022u100023u100024u100025u100026u100027u100028u100029u10002Au10002Bu10002Cu10002Du10002Eu10002Fu100030u100031u100032u100033u100034u100035u100036u100037u100038u100039u10003Au10003Bu10003Cu10003Du10003Eu10003Fu100040u100041u100042u100043u100044u100045u100046u100047u100048u100049u10004Au10004Bu10004Cu10004Du10004Eu10004Fu100050u100051u100052u100053u100054u100055u100056u100057u100058u100059u10005Au10005Bu10005Cu10005Du10005Eu10005Fu100060u100061u100062u100063u100064u100065u100066u100067u100068u100069u10006Au10006Bu10006Cu10006Du10006Eu10006Fu100070u100071u100072u100073u100074u100075u100076u100077u100078u100079u10007Au10007Bu10007Cu10007Du10007Eu10007Fu1000A0u1000A1u1000A2u1000A3u1000A4u1000A5u1000A6u1000A7u1000A8u1000A9u1000AAu1000ABu1000ACu1000ADu1000AEu1000AFu1000B0u1000B1u1000B2u1000B3u1000B4u1000B5u1000B6u1000B7u1000B8u1000B9u1000BAu1000BBu1000BCu1000BDu1000BEu1000BFu1000C0u1000C1u1000C2u1000C3u1000C4u1000C5u1000C6u1000C7u1000C8u1000C9u1000CAu1000CBu1000CCu1000CDu1000CEu1000CFu1000D0u1000D1u1000D2u1000D3u1000D4u1000D5u1000D6u1000D7u1000D8u1000D9u1000DAu1000DBu1000DCu1000DDu1000DEu1000DFu1000E0u1000E1u1000E2u1000E3u1000E4u1000E5u1000E6u1000E7u1000E8u1000E9u1000EAu1000EBu1000ECu1000EDu1000EEu1000EFu1000F0u1000F1u1000F2u1000F3u1000F4u1000F5u1000F6u1000F7u1000F8u1000F9u1000FAu1000FBu1000FCu1000FDu1000FEu1000FFu100192u1002DCu1003C0u102190u102191u102192u102193u102211u10221Au1023B8u1023B9u1023BAu1023BBu1023BCu1023BDu102400u102401u102402u102403u102404u102405u102406u102407u102408u102409u10240Au10240Bu10240Cu10240Du10240Eu10240Fu102410u102411u102412u102413u102414u102415u102416u102417u102418u102419u10241Au10241Bu10241Cu10241Du10241Eu10241Fu102420u102421u102422u102423u102424u102425u102426u102500u102501u102502u102503u102504u102505u102506u102507u102508u102509u10250Au10250Bu10250Cu10250Du10250Eu10250Fu102510u102511u102512u102513u102514u102515u102516u102517u102518u102519u10251Au10251Bu10251Cu10251Du10251Eu10251Fu102520u102521u102522u102523u102524u102525u102526u102527u102528u102529u10252Au10252Bu10252Cu10252Du10252Eu10252Fu102530u102531u102532u102533u102534u102535u102536u102537u102538u102539u10253Au10253Bu10253Cu10253Du10253Eu10253Fu102540u102541u102542u102543u102544u102545u102546u102547u102548u102549u10254Au10254Bu10254Cu10254Du10254Eu10254Fu102550u102551u102552u102553u102554u102555u102556u102557u102558u102559u10255Au10255Bu10255Cu10255Du10255Eu10255Fu102560u102561u102562u102563u102564u102565u102566u102567u102568u102569u10256Au10256Bu10256Cu10256Du10256Eu10256Fu102570u102571u102572u102573u102574u102575u102576u102577u102578u102579u10257Au10257Bu10257Cu10257Du10257Eu10257Fu1025ADu1025B6u1025C0u102660u102663u102665u102666u10F8B0u10F8B1u10FB70u10FB71u10FB72u10FB73u10FB74u10FB75u10FB76u10FB77u10FB78u10FB79u10FB7Au10FB7Bu10FB7Cu10FB7Du10FB7Eu10FB7Fu10FB97u10FB98u10FB99      ? @ @ AHIIJM TbDFLTcyrl&grek2latn>rlig&R^t",8BNXblvJJJVJ J J9JJ J]JUJW  J  JJVIJJ $8L`r lLLNSRNR lLRLSSS lMRORSM lMRLPNOlSKSNL @lOSNNR& $&)*./013459;DJNOPQSTU[]V  LNDFLTcyrl$grek.latn8ڇo҂Lx blbfbbbb ~c c~c$0c11*c?1cX2cq3jLN#NNNNN 0N1OPPNQjknNoNNSNNN UNVWSXN4\SNNN !"#S$%&'S()*+S,NNN N 4j SNNN4t >?@4ACNDE4`kNNNNN?N4N#N$'T()N,/N15Nrr7Dss7Jtt7Puu7Vvv7\ww7bxx7hyy7nzz7t{{7z||7}}7~~777777777777777777788 88 8*848>8H8R 8\ 8b8h8n8t88888888899 9 !!9""9 ##9*$$94%%9>&&9H''9R((9\))9f**9p++9z009119889999::9;;9<<9==9>>9fff /f$PPf$Qpf/qf7f/f f/f7f$f/f/f7<>fVo#oo9oo 9 toul /o00o1OlPPoQjmknmommmomoooolu ?o@QoRU:VWoXY:,Z[o\]:6^_o`oood:@ooolo !l"#o$%l&'o()l*+o,oooo o d ooo@:NACoDE:`koo:oooo!o"#o$?ooooo "o##o$'c()o,/o15of`kgfgg ?gfO gp fOgg015f@_ggsgt~ggfggggggggffSI OX gfgpfggggBM ggg ?f=@_g`f=gf=OR h?h@ohqh"gh,#OR h4h: hEhEg /hN1OhXQjfqfh`hhhEY- hffOghE 'fO9?hlLOhtggBhXgBh~OR gh !g"#h~$%g&'h()g*+h-/h0hfyhfOhNgB<=hEhgB !h$'h(/h0?gOR  OR fht15fABgDEgHIhELMgNPhEQRgZ[gklgz{gghNE NE NE gghhhfOhl!?g`gghf]AOh"Q_h"aoh" h hhhhfiOX  hXhX1OgQjhEqhEf]if]f]hX$%ggBhXi !hX$%hX()hX0bici+i5hi?fhi?fNE <=hXiI !gB$?gBiRiY i`15hEABhXDEhXHIhXLRhXZ[hXklihz{ihi5f=i5iiqOR N OP  ix OP ix i hfiYSE ih1OhEQjhXqhXRC iP iP 020-351-682-9;3-<>4-?A5-BD6-EN7-OX8-Yb9-ce0-fh1-ik2-ln3-oq4-rt5-uw6-x7-8-9-h`h`h`F 15hXPQklhEz{hEiiND  ND  ND f]iP ND ND ND i15 klhXz{hXgi EFT gND ND 15h` ND 15f i:BC CC$#KRKxKLLRLxO.OOOueoOOuef1P33w55w79Q;;w==w?nQ"pQRSSRS`z{ SjUUV<VJVEW&`kWXX(~~~"X2Z4?\2\ \ %]$)]>,/]15]<@]BC]EH]JK]MO]RY][k^mz^b|^^^_z_`fh()hXf= gci5() *+hXtwihi h~$%h`()h`hhhhgghhhhhi5fy()h`*+ 25hXtwhEND gggi5i5hXhX h`gc n !h`$%g()gi5ggggi5 'hX()*+h`01hX258;hX h``bdfgjihmsihtwhXxyih|~ihgY-ggj gi5gF F        gh`ggh`*+,/ih47h`?ABPU\]no-h`5nn yY gj !5$%h()h<wd 'h`(+ND ,-hX./B01h`23f45i67hX8;h`hXJh`S Y f di5()q,.IG <=|>?r~FGhXJKhXUYhX`bodfogjhXmshXtwR xyhX|~hXySj j gpfgpfMOB iEREREAREAOGOUBETOONANLH H H OGOAIL!%'+-/LMmnIGNIGNCONCONCON ARSCON{iEFTEFTiAP j%zK+"#*+1,/723=47IGN:;C?ISK@ACDFGIJKLUVWXYZ`bTEMdfTEMghijlmnopqrstuvwxy{|}~ILLESTiiiC{{OGOEYOGOEYOGOOGO7  /PP !$?  /`PP/0``aa$aN!ap$?a   b,b> !""#$$%&&'(()**+,,-../001223445667889::;<=>    bX!! ##"%%$''&))(++*--,//.110332554776998;<br>>=  b|b!! ##"%%$''&))(++*--,//.110332554776998;;:=><NTNSNNNNTNNTTttKkLLllMmCHchSHshTHthLlChShTh1 D72 D73 D74 D75 D76 D71 D92 D94 D95 D97 D98 D91 D103 D107 D109 D101 ;>50 D0ABCDEFGHIJKLMNOPQRSTUVWXYZ*/iABCDEFGHIJKLMNOPQRSTUVWXYZ*/e151819dlmrstv.,.,1 D125 D127 D1211 D120 D11 D11 D0"1""GgLlXxNnPpQqRrRRRrrrul ululululululififseifoco%mmmmululululululululululululululutloocouli233234424434342345525535352355454524545345345ii233234424434342345525535352355454524545345345iʶ6626636362366464624646346346iе6565625656356356iִ56456456iܳ456iii6626636362366464624646346346iе6565625656356356iִ56456456iܳ456iiii355352323525352354434545453454243423445245345iʶ6636656563566263623656256356iִ6464634656456456i46246346iв456iiii355352323525352354434545453454243423445245345iʶ6636656563566263623656256356iִ6464634656456456i46246346iв456iii0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFiOPjj ixjjjj( j(21021121221321421521621721821921A21B21C21D21E21F22022122222322422522622722822922A22B22C22D22E22F23023123223323423523623723823923A23B23C23D23E23Fj:23323442443434234j:23323442443434234j:23323442443434234j:23323442443434234jI233234424434342345525535352355454524545345345iʶ6626636362366464624646346346iе6565625656356356iִ56456456iܳ456iiii233234424434342345525535352355454524545345345iʶ6626636362366464624646346346iе6565625656356356iִ56456456iܳ456iiijU233234424434342345525535352355454524545345345iʶ6626636362366464624646346346iе6565625656356356iִ56456456iܳ456iii7727737372377474724747347347jb7575725757357357jh57457457jn457jtjzj7676726767367367j67467467j467jjj67567567j567jjj567jjjjjjj8828838382388484824848348348j8585825858358358j58458458j458kkk 8686826868368368k68468468k468kk%k+68568568k2568k8k>kD568kKkQkWk^kdkkkr8787827878378378kz78478478k478kkk78578578k578kkk578kkkkkkkٶ78678678k678kkk678klll lll!678l)l/l5l<lBlIlPlXl^lellltl{lllllllliRND ETllmm mWOm'm-NEWOmCmVmgiRND mwm mmmmmmnnn0!n6nERIDnTn_nnfnvngggggggghEgnnnnnnnoo oggoo7oAodono~ooooAoooooop p fggp*pLpZp|pphEghEghEghEghEghEgp pppqqqIq'HIq.EGAq5 qDEF KQW^dkr G G BG G CG CG zG DG DG DG G EG EG EG EG G FG FG FG FG  !FG )/5<BIPX^elt{0zNE WO fqHqNIX q^qeqvEN |lERONEERONEWOm'ERONEWOm'OURIVEIXyERONEWOm'OURIVEIXyyINEENyyyyu UT N fh%.Ic}hP-hxnxyxx}WY-+4;gghChJNEWOm'OURIVEggggyyhEgghEhEghEghEyihihygggggggggggggggggggg -fO&ERg"g~=h(SZgghhP-<gg`P-hhP-gg 9V{#ghUNwJ)3@wJwPMTwPwJm m_qgggggg/7/7/7/7/7/7/9/9/9/9/9/9/10/10/10/1058901234501 /12/12/12/1/1/01012345012345 :=   Bidi_Class Bidi_MirroredBlockCanonical_Combining_ClassDecomposition_MappingDecomposition_TypeGeneral_CategoryName Numeric_Type Numeric_ValueSimple_Lowercase_MappingSimple_Titlecase_MappingSimple_Uppercase_Mapping%Block Sextants (Compatible with ZVBI)'Block Sextants (Compatible with Unscii)Hex Byte PicturesModular Font ElementsModular Font Elements ExtendedBox Drawing Extended Fill PatternsShade QuadrantsSixel GraphicsBlock Sextants Block OctantsC1 Control PicturesC64-OS SymbolsCommander X16 Symbols Kreative Software Private Use-F6Apple MouseText Characters Kreative Software Private Use-F7 Kreative Software Private Use-F8Klingon!Kreative Software Private Use-FF0Domino Tiles ExtendedPowerline SymbolsRayalaka Color Symbols!Kreative Software Private Use-FF1Seven-Segment Display PatternsNumber Forms Appendix%Symbols for Legacy Computing Appendix BLOCK SEPARATED SYMBOL FILL LIGHT MEDIUM DARK SIXEL- ISOMETRIC INVERSE LATIN BLACK THREE APPLE KREATIVE GREEK VULGAR SUPERSCRIPT SUBSCRIPT VOLUME SQUARE NORTH FUNCTION HORIZONTAL KEYBOARD UPPER LOWER CHECKBOX RADIO INTERCAL MARTIN DIGIT DOZENAL TURNED KLINGON HEART-POKE WHITE JUSTIFYING DOMINO SMALL COLOR SQUARED SEVEN- HEXADECIMAL LUCILLA SEGMENTED RIGHT LEFT CENTRE ALIEN RADAR PUSH LEAP NABU SEXTANT- DRAWINGS PATTERN-SHADE QUADRANT-OCTANT-FACE- MOUSETEXT CAPITAL FRACTION LETTER WITH LINE BUTTON OPERATOR SHAPED CIRCLE SNAKE TILE RIGHT-SEGMENT BINARY QUATERNARY OCTAL ARROW LEFT-GHOST OCTET- CHARACTER PARTIAL SINGLE PRIVATE ENCLOSED FRAME DOUBLE HORIZONTAL- VERTICAL- POINTING TRIANGLE DISPLAY START SHIFT DELETE QUARTER FRAME-BOTTOM TABULATION CHECKMARKDOWN DIAGONAL INNER RIGHTDIAGONAL SEXTANT BLANK123451234612356124561345623456123456 TOP AND LEFTCENTERMIDDLE BOTTOMMIDDLE AND LEFTLEFT AND DIAGONALQUADRANT BLANK SIXEL BLANK OCTANT BLANK12347123571245713457234571234571236712467134672346712346712567135672356712356714567245671245673456713456723456712345671234812358124581345823458123458123681246813468234681234681256813568235681235681456824568124568345681345682345681234568123781247813478234781234781257813578235781235781457824578124578345781345782345781234578126781367823678123678146782467812467834678134678234678123467815678256781256783567813567823567812356784567814567824567812456783456781345678234567812345678PADDING CHARACTERHIGH OCTET PRESETBREAK PERMITTED NO BREAK INDEXNEW LINEWITH JUSTIFICATIONTABULATION SETFORWARDBACKWARDREVERSE LINE FEEDTHREEDEVICE CONTROL STRINGSET TRANSMIT STATECANCEL CHARACTERMESSAGE WAITINGSTART OF STRINGGRAPHIC CONTROL SEQUENCE STRING TERMINATOROPERATING SYSTEM COMMANDPRIVACY MESSAGEAPPLICATION PROGRAM COMMANDNO-BREAK SPACE SOFT HYPHENUNDEFINED CONTROL CHARACTERALERTCOMMANDER X16 KREATIVE ERIN WHITE CUBESTACK OF CUBESSHADED COORDINATE AXESDOGCOWFIRST LAST MALE FEMALE 5SIX-POINTED STAR SURROUNDED BY FIVE SIX-POINTED STARSTHREE BALLOONSCLOUD WITH LIGHTNINGAPPLESDIAMONDS BUTTERFLIESARROWHEAD SHAPED POINTER HOURGLASS"DOWNWARDS ARROW WITH TIP LEFTWARDS TITLE BARLEFTWARDS ARROWHORIZONTAL ELLIPSIS DOWNWARDS UPWARDS HORIZONTAL SCAN LINE-1)INVERSE BOX DRAWINGS LIGHT RIGHT VERTICAL LEFTWARDS RIGHTWARDS HORIZONTALBOTTOM AND LEFTRIGHTWARDS ARROW!BOX DRAWINGS LIGHT RIGHT VERTICAL BLACK DIAMOND!BOX DRAWINGS LIGHT TOP AND BOTTOMVOIDED GREEK CROSSRIGHT OPEN SQUARED DOTBOX DRAWINGS LEFT VERTICALL WITH SMALL LETTER LOPERATING SYSTEM KORPORATION ENTERTAINMENT SOFTWARE GAMMASOFT CHECKERBOARDPHELTAMAGNUMTAMPON ONE SEVENTHFOUR FIVE ONE NINTHSEVEN EIGHT ONE TENTHNINE SIGN ET A WITH RING E WITH ACUTEVULGAR FRACTION ZERO OVER ZEROASTERISKSOLIDUSMULTIPLICATION DIVISION GREEK SMALL LETTER PILATIN SMALL LETTER ILATIN SUBSCRIPT SMALL LETTER E ARROW POINTER CROSSHAIR DOCUMENT DIRECTORY APPLICATION REVERSED DOCUMENT HARD FLOPPY COMPUTER NETWORK ADAPTER PRINTER MODEM ETHERNET VIDEO OUTPUT FIREWIRE TELEVISIONMICROWAVE OVEN COFFEE MAKER REFRIGERATOR KITCHEN MIXER COMPACT DISC CARTRIDGE DESKTOP OPENED DIRECTORY SPEAKER MICROPHONE APPLE DESKTOP BUS BATTERY RINGING HORIZONTAL LEVEL SLIDERSEARCH MUTE DECREASE INCREASE TOP BAR VERTICAL *WHITE SQUARE CONTAINING WHITE SMALL SQUARE'RECTANGLE WITH DIAGONAL CROSSHATCH FILL-THREE LINES RUNNING UPPER RIGHT TO LOWER LEFT$TWO WHITE SQUARES OF DIFFERENT SIZESFRACTION BACKSLASHUNDO COPY PASTE /LATIN CAPITAL LETTER A WITH VERTICAL RIGHT SIDESCRIPT SMALL ADOUBLE LATIN CAPITAL LETTER TLADDER.WHITE SQUARE CONTAINING LATIN CAPITAL LETTER P'SPEECH BALLOON CONTAINING QUESTION MARKTOP LEFT VERTICAL AND EAST SOUTH WEST WEST SOUTH EAST CARDINAL CARDINAL AND FIFTEENEIGHTEENNINETEENARC VERTICAL AND HORIZONTALFONT VERSION INDICATORCONTEXTUAL MENU EJECT DIAMOND MINUS WHITE SQUARESQUARE MINUS WHITE DIAMONDTELEPHONE DIALFIVE VERTICAL LINES4ONE DOWNWARD-POINTING BLACK TRIANGLE OVER TWO OTHERSTWO INTERWOVEN EYE SHAPESNARROW-LEAF FOUR-PETAL FLORETTEFOUR INTERLEAVED FISHEYES THICKENING WITH WASP WAIST THICKENING AT CENTER ALTERNATE FLYING FLAG PULLDOWN MENUOPEN SOLID EXCLAMATION QUESTION CONVERGING LINES CHICKEN LIPSFLOATING CIRCLES RASPBERRY SCRIPT LISAACORNCHECKBOXIN ACTIVE STATEIN ACTIVE STATE BUTTON PERCONTATION WILKINS DE BRAHM LOVE CONVICTION AUTHORITY HERVE BAZIN IRONY ACCLAMATION DOUBT SNARK IRONIETEKEN SARCASM MARK SPARK-SPOTRABBITBOOKWORMBLOTCH NOT ANGRY SINCERIODHEMI-DEMI-SEMICOLON ANDORPERSAND SUPERELLIPSISMORGAN FREEMARKSUNDAYMONDAYTUESDAY WEDNESDAYTHURSDAYFRIDAYSATURDAYEIGHTH NINTH TENTH ANTE POST BEFORE CHRIST ANNO DOMINIBEFORE JANUARYFEBRUARYMARCHAPRILAUGUST SEPTEMBEROCTOBERNOVEMBERDECEMBER UNDECIMBER ALARM BELL AMPLITUDE FREQUENCY SEVENEIGHTELEVENTWELVETHIRTEENFOURTEENZERO GLOTTAL STOPRADICAL EXTENDERMODERN KRONE SIGNMUMMIFICATION GLYPHCOMMA FULL STOP APPLE LOGOHEART-SHAPED MERCURYDOUBLED EARTHHEART-SHAPED NEUTER LOVE SYMBOL PAW PRINTPHI PAW DELTA THETA SEVEN-POINTED STAR DOLLAR SIGNDEATHLY HALLOWS SYMBOLCOLONSTICK FIGURE WITH TOP HATTAIL TRUNK HEAD VERSION CONTROL BRANCH LINE NUMBER LOCK COLUMN NUMBER WHITE BUILDING BLOCK STUDS BUILDING BLOCK WHITE RIGHT-CIRCLE ONE SPOKE THREE SPOKESCROSS INNER CIRCLETRIANGLEINNER TRIANGLESQUARECOMMA INTERROBANG JE MARKELREYREVERSED INVERTED QUESTION MARK QUARTERCOLONFRIENDLY PERIOD HALF HYPHEN ONE TWELFTHELEVEN ZERO OVER ONEWHOLE OVER ZEROSUPERSCRIPT NEGATIVE POSITIVE NEGATIVE INFINITYGREEK SUBSCRIPT SMALL LETTER PISUBSCRIPT INFINITYR WITH SMALL LETTER RSMALL LETTER RRDIAGONAL EXCLAMATION MARKCOOL SSYMBOL FOR PANSEXUALITY7LATIN LETTER SMALL CAPITAL Q WITH SMALL CAPITAL V BELOWELECTRONIC SYMBOLMIKIANAN DOLLAR SIGN HISTERIA MARKLO-RESERASERINTEGRATED CIRCUIT SKYSCRAPER SHIBUYA-109 PELICAN EELDIGNITYSYMBOL FOR VOTGILWORTH STEALINGBLANKABCDEABCDFABCEFABDEFACDEFBCDEFABCDEFABCDGABCEGABDEGACDEGBCDEGABCDEGABCFGABDFGACDFGBCDFGABCDFGABEFGACEFGBCEFGABCEFGADEFGBDEFGABDEFGCDEFGACDEFGBCDEFGABCDEFGABCD ABCE ABDE ACDE BCDE ABCDE ABCF ABDF ACDF BCDF ABCDF ABEF ACEF BCEF ABCEF ADEF BDEF ABDEF CDEF ACDEF BCDEF ABCDEF ABCG ABDG ACDG BCDG ABCDG ABEG ACEG BCEG ABCEG ADEG BDEG ABDEG CDEG ACDEG BCDEG ABCDEG ABFG ACFG BCFG ABCFG ADFG BDFG ABDFG CDFG ACDFG BCDFG ABCDFG AEFG BEFG ABEFG CEFG ACEFG BCEFG ABCEFG DEFG ADEFG BDEFG ABDEFG CDEFG ACDEFG BCDEFG ABCDEFG TWELVE THIRTEEN FOURTEEN FIFTEEN RADIX POINTREPEATING DIGIT SEPARATORNULL HEADING END OF ENQUIRY LINE FEED END OF TRANSMISSION BLOCK ROUNDED BORDER-COLOURED FULL BLOCKRIGHTWARDS ARROW TO LEFT LEFTWARDS ARROW TO RIGHT BLACK RIGHT TRIANGLE CARETAPOSTROPHE S OPERATORLEFT AND RIGHT PARENTHESISZERO WIDTH ENCLOSING CIRCLEDOWN- BLOCK BLANK$WHITE RIGHT-POINTING NARROW TRIANGLECRUZEIRO NOVO CRUZADO ZLOTY FORINT FRONT-.LATIN CAPITAL LETTER REVERSED S WITH DOT BELOWCAPITAL LETTER CAPITAL LETTER PSMALL LETTER Q DEGREE SIGNOVERLINE MINUS SIGNLOW LINEHALF WHOLE NOTEL OR I"MSX INVERSE CHARACTER UNDER CURSORLEFTWARDS ARROW AND UPPER LEFT !RIGHTWARDS ARROW AND UPPER RIGHT 3LEFT HALF BLOCK AND RIGHT HALF INVERSE MEDIUM SHADE TWO THIRDS ONE THIRD RISC OS SYMBOL FOR OCTET-87LEFT TO LOWER RIGHT RIGHT TO LOWER LEFT HEAVY HORIZONTAL BLACK SMALL UP-POINTING CHEVRONUPWARDS THEN NORTH RIGHTWARDS THEN CURVING SOUTH BLACK CIRCLE+SYMBOL FOR DELETE SQUARE CHECKER BOARD FORM&EIGHTH BLOCK AND RIGHT THREE QUARTERS %QUARTER BLOCK AND RIGHT FIVE EIGHTHS #THREE EIGHTHS BLOCK AND RIGHT HALF #HALF BLOCK AND RIGHT THREE EIGHTHS )FIVE EIGHTHS BLOCK AND RIGHT ONE QUARTER *THREE QUARTERS BLOCK AND RIGHT ONE EIGHTH &EIGHTH BLOCK AND LOWER THREE QUARTERS %QUARTER BLOCK AND LOWER FIVE EIGHTHS #THREE EIGHTHS BLOCK AND LOWER HALF $HALF BLOCK AND LOWER THREE QUARTERS )FIVE EIGHTHS BLOCK AND LOWER ONE QUARTER *THREE QUARTERS BLOCK AND LOWER ONE EIGHTH THIRD 0RIGHT BLOCK DIAGONAL MIDDLE LEFT TO LOWER CENTREMIDDLE LEFT TO UPPER CENTREUPPER LEFT TO MIDDLE )LEFT BLOCK DIAGONAL MIDDLE LEFT TO UPPER *RIGHT BLOCK DIAGONAL MIDDLE LEFT TO LOWER )LEFT BLOCK DIAGONAL LOWER LEFT TO MIDDLE #LEFT BLOCK DIAGONAL MIDDLE LEFT TO $RIGHT BLOCK DIAGONAL MIDDLE LEFT TO LEFT-JUSTIFIED RIGHT RIGHT-JUSTIFIED LEFT LEFT MARGIN INDICATORWORD PROCESSING RULERSARDINEPINBALL PLUNGERHEAVY TRIANGLE WITH UNDERBAR SQUARE TILDEWHITE VERTICAL RECTANGLEVERTICAL LINE WITH TICK MARK$TWO PAIRS OF DIAGONAL LINES CROSSING%RIGHT TO MIDDLE CENTRE TO LOWER RIGHT#LEFT TO MIDDLE CENTRE TO LOWER LEFTHORIZONTAL GO-KART#SMALL UPWARDS ARROW WITH SMALL TAILSPIDER SPIDER FLYINGRADARCLOSED PIE CHART BAR GRAPH WINDOWS LOGO CONTEXT MENUATARI COMMODORE GOOGLE ASSISTANT RASPBERRY PI BACKWARD FORWARD CAPS LOCK CHANGE SIZE ACORN APPLE LISA BELL LABS DATA GENERAL BUILDING CUBE RING THORN NOTE PENTAGONAL SIMPLE FANCY INTERMEDIATE PRECEDED TRIANGULAR SEMICIRCULAR FLAMES SQUARES ICICLES HEXAGONS CORNER ABOVE STROKE TEXT FACING SELECTED GUARDED WINDOW STICK RUNNING SWISHY DISK ALARM BRICK POINTS INITIAL ITALIC CONVERGING MINUS PLUS IRONY QUASIQUOTATION MOCKWOTATION COMMON HEART PATH TRIPLE DECIMAL FORM BISECTING RECTANGULAR TRADEMARK EMPTY CHECKER EIGHTHS QUARTERS LARGE QUADRUPLE AMIGA INTRODUCER DECORATIONFIGUREARROWSHADEFOLDERTILDESEVENTHSNINTHSTENTHSCLOCKFLASHBLOCKPENCILSYMBOLAPPLESWASHLINESDOBBSCHECKBULLETPOINT SARCASTISISMERIDIEM MODULATION APOSTROPHEABOVE SEPARATORELLIPSISTWELFTHSEXPONENT DIAERESISMACRON CIRCUMFLEXSTROKE UNDERLINE PARENTHESISDOCUMENTBOARDELLIPSESTATENumericDigitDecimal11/12bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/outline.css000066400000000000000000000002621506470510200271260ustar00rootroot00000000000000.ol { border: solid 1px #999; /* Rendering hack - disables hinting??? */ display: inline-block; width: 14px; height: 14px; line-height: 14px; transform: scale(1.00001); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/prep.js000066400000000000000000000006471506470510200262500ustar00rootroot00000000000000function prep() { var ua = navigator.userAgent || navigator.appVersion; var mac = (ua.indexOf('Macintosh') >= 0) || (ua.indexOf('Mac OS') >= 0) || (ua.indexOf('MacOS') >= 0); var win = (ua.indexOf('Windows') >= 0); var os = (mac ? 'mac' : (win ? 'win' : 'linux')); var e = document.getElementsByClassName(os); for (var i = 0; i < e.length; i++) { e[i].className = e[i].className.replace('hidden', ''); } } prep(); bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/keyedit/xkb.dtd000066400000000000000000000023021506470510200262130ustar00rootroot00000000000000 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/000077500000000000000000000000001506470510200247225ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/CodePointSequence.java000066400000000000000000000063741506470510200311540ustar00rootroot00000000000000package com.kreative.mapedit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class CodePointSequence { private final int[] seq; public CodePointSequence(int... seq) { this.seq = new int[seq.length]; for (int i = 0; i < seq.length; i++) { this.seq[i] = seq[i]; } } public CodePointSequence(List seq) { int length = seq.size(); this.seq = new int[length]; for (int i = 0; i < length; i++) { this.seq[i] = seq.get(i); } } public CodePointSequence(String seq) { int length = seq.length(); int[] tempSeq = new int[length]; int di = 0, si = 0; while (di < length && si < length) { tempSeq[di] = seq.codePointAt(si); si += Character.charCount(tempSeq[di]); di++; } this.seq = new int[di]; for (si = 0; si < di; si++) { this.seq[si] = tempSeq[si]; } } public static CodePointSequence parse(String seq) { List codePoints = new ArrayList(); String[] parts = seq.split("[+]"); for (String part : parts) { if (part.startsWith("0x") || part.startsWith("0X")) { codePoints.add(Integer.parseInt(part.substring(2), 16)); } else try { codePoints.add(Integer.parseInt(part, 16)); } catch (NumberFormatException e) { MappingTag tag = MappingTag.forStringValue(part); if (tag != null) codePoints.add(tag.intValue); else throw e; } } return new CodePointSequence(codePoints); } public int[] toArray() { int[] out = new int[seq.length]; for (int i = 0; i < seq.length; i++) { out[i] = seq[i]; } return out; } public List toList() { List out = new ArrayList(); for (int ch : seq) { out.add(ch); } return out; } public String toString() { StringBuffer out = new StringBuffer(seq.length); for (int ch : seq) { if (Character.isValidCodePoint(ch)) { out.append(Character.toChars(ch)); } } return out.toString(); } public static String format(CodePointSequence seq) { StringBuffer out = new StringBuffer(seq.seq.length); for (int i = 0; i < seq.seq.length; i++) { if (i > 0) out.append("+"); if (Character.isValidCodePoint(seq.seq[i])) { String h = Integer.toHexString(seq.seq[i]).toUpperCase(); while (h.length() < 4) h = "0" + h; out.append("0x" + h); } else { MappingTag tag = MappingTag.forIntValue(seq.seq[i]); if (tag != null) out.append(tag.stringValue); else throw new IllegalArgumentException(); } } return out.toString(); } public boolean contains(int ch) { for (int sch : seq) { if (sch == ch) { return true; } } return false; } public boolean containsC0C1() { for (int ch : seq) { if ((ch >= 0 && ch < 32) || (ch >= 127 && ch < 160)) { return true; } } return false; } public boolean containsPUA() { for (int ch : seq) { if ((ch >= 0xE000 && ch < 0xF900) || (ch >= 0xF0000 && ch < 0x110000)) { return true; } } return false; } public int get(int i) { return seq[i]; } public int length() { return seq.length; } public boolean equals(Object o) { if (o instanceof CodePointSequence) { CodePointSequence that = (CodePointSequence)o; return Arrays.equals(this.seq, that.seq); } return false; } public int hashCode() { return Arrays.hashCode(seq); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/CodePointSequencePanel.java000066400000000000000000000205101506470510200321200ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import com.kreative.unicode.data.NameDatabase; import com.kreative.unicode.data.NameResolver; public class CodePointSequencePanel extends JPanel { private static final long serialVersionUID = 1L; private final String encodingPrefix; private final JLabel encodingLabel; private final List sequenceData; private final MyTableModel sequenceModel; private final JTable sequenceTable; private final JButton addButton; private final JButton removeButton; private final JButton upButton; private final JButton downButton; private final NameDatabase ndb; private final List listeners; public CodePointSequencePanel(String encodingPrefix) { this.encodingPrefix = encodingPrefix; this.encodingLabel = new JLabel(encodingPrefix + "??"); this.encodingLabel.setFont(new Font("Monospaced", Font.PLAIN, 12)); this.sequenceData = new ArrayList(); this.sequenceModel = new MyTableModel(); this.sequenceTable = new JTable(sequenceModel); setColumnWidth(sequenceTable.getColumnModel().getColumn(0), 80); setColumnWidth(sequenceTable.getColumnModel().getColumn(1), 80); setColumnWidth(sequenceTable.getColumnModel().getColumn(2), 300); squareOff(this.addButton = new JButton("+")); squareOff(this.removeButton = new JButton("\u2212")); squareOff(this.upButton = new JButton("\u2191")); squareOff(this.downButton = new JButton("\u2193")); this.ndb = NameDatabase.instance(); this.listeners = new ArrayList(); JPanel topPanel = new JPanel(new BorderLayout(8, 8)); topPanel.add(new JLabel("Encoding:"), BorderLayout.LINE_START); topPanel.add(encodingLabel, BorderLayout.CENTER); JPanel botPanel = new JPanel(new FlowLayout()); botPanel.add(addButton); botPanel.add(removeButton); botPanel.add(upButton); botPanel.add(downButton); JScrollPane sequencePane = new JScrollPane(sequenceTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(topPanel, BorderLayout.PAGE_START); mainPanel.add(botPanel, BorderLayout.PAGE_END); mainPanel.add(sequencePane, BorderLayout.CENTER); mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = sequenceTable.getSelectedRow(); index = (index < 0) ? sequenceData.size() : (index + 1); sequenceData.add(index, 0); sequenceModel.fireTableDataChanged(); sequenceTable.getSelectionModel().setSelectionInterval(index, index); fireListeners(); } }); removeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = sequenceTable.getSelectedRow(); if (index < 0) return; sequenceData.remove(index); sequenceModel.fireTableDataChanged(); sequenceTable.clearSelection(); fireListeners(); } }); upButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = sequenceTable.getSelectedRow(); if (index <= 0) return; int removed = sequenceData.remove(index); index--; sequenceData.add(index, removed); sequenceModel.fireTableDataChanged(); sequenceTable.getSelectionModel().setSelectionInterval(index, index); fireListeners(); } }); downButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = sequenceTable.getSelectedRow(); if (index < 0 || index >= (sequenceData.size() - 1)) return; int removed = sequenceData.remove(index); index++; sequenceData.add(index, removed); sequenceModel.fireTableDataChanged(); sequenceTable.getSelectionModel().setSelectionInterval(index, index); fireListeners(); } }); } public String getEncodingPrefix() { return encodingPrefix; } public CodePointSequence getCodePointSequence() { if (sequenceData.isEmpty()) return null; return new CodePointSequence(sequenceData); } public void setCodePointSequence(CodePointSequence seq, int cp, boolean notify) { if (cp >= 0) { String h = "00" + Integer.toHexString(cp); h = h.substring(h.length() - 2).toUpperCase(); encodingLabel.setText(encodingPrefix + h); } else { encodingLabel.setText(encodingPrefix + "??"); } sequenceData.clear(); if (seq != null) sequenceData.addAll(seq.toList()); sequenceModel.fireTableDataChanged(); sequenceTable.clearSelection(); if (notify) fireListeners(); } public void addListener(CodePointSequencePanelListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(CodePointSequencePanelListener listener) { if (listener != null) listeners.remove(listener); } public CodePointSequencePanelListener[] getListeners() { return listeners.toArray(new CodePointSequencePanelListener[listeners.size()]); } private void fireListeners() { for (CodePointSequencePanelListener l : listeners) l.codePointSequenceChanged(); } private class MyTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; public Class getColumnClass(int col) { return String.class; } public int getColumnCount() { return 3; } public String getColumnName(int col) { switch (col) { case 0: return "Code Point"; case 1: return "Character"; case 2: return "Character Name"; default: return null; } } public int getRowCount() { return sequenceData.size(); } public Object getValueAt(int row, int col) { if (row < 0 || row >= sequenceData.size()) return null; int e = sequenceData.get(row); switch (col) { case 0: if (Character.isValidCodePoint(e)) { String h = Integer.toHexString(e).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } else { MappingTag tag = MappingTag.forIntValue(e); if (tag != null) return tag.stringValue; else return null; } case 1: if ((e >= 32 && e < 127) || (e >= 160 && e < 0xD800) || (e >= 0xE000 && e < 0x110000)) { return String.valueOf(Character.toChars(e)); } else { return null; } case 2: if (Character.isValidCodePoint(e)) { return NameResolver.instance(e).getName(e); } else { MappingTag tag = MappingTag.forIntValue(e); if (tag != null) return tag.description; else return null; } default: return null; } } public boolean isCellEditable(int row, int col) { return true; } public void setValueAt(Object value, int row, int col) { if (row < 0 || row >= sequenceData.size()) return; String val = value.toString(); switch (col) { case 0: try { sequenceData.set(row, Integer.parseInt(val, 16)); } catch (NumberFormatException e) { MappingTag tag = MappingTag.forStringValue(val); if (tag != null) sequenceData.set(row, tag.intValue); } break; case 1: if (val.length() > 0) sequenceData.set(row, val.codePointAt(0)); break; case 2: MappingTag tag = MappingTag.forDescription(val); if (tag != null) { sequenceData.set(row, tag.intValue); break; } NameDatabase.NameEntry ne = ndb.find(val); if (ne != null) sequenceData.set(row, ne.codePoint); break; } fireTableRowsUpdated(row, row); fireListeners(); } } private static void setColumnWidth(TableColumn col, int width) { col.setMinWidth(width); col.setWidth(width); col.setMaxWidth(width); } private static void squareOff(JComponent c) { int h = c.getPreferredSize().height + 8; c.setMinimumSize(new Dimension(h, h)); c.setPreferredSize(new Dimension(h, h)); c.setMaximumSize(new Dimension(h, h)); c.putClientProperty("JButton.buttonType", "bevel"); } } CodePointSequencePanelListener.java000066400000000000000000000001741506470510200335530ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapeditpackage com.kreative.mapedit; public interface CodePointSequencePanelListener { public void codePointSequenceChanged(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/Main.java000066400000000000000000000075461506470510200264650ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Toolkit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.Charset; import javax.swing.JOptionPane; import javax.swing.UIManager; public class Main { public static void main(String[] args) { try { System.setProperty("com.apple.mrj.application.apple.menu.about.name", "MapEdit"); } catch (Exception e) {} try { System.setProperty("apple.laf.useScreenMenuBar", "true"); } catch (Exception e) {} try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) {} try { Method getModule = Class.class.getMethod("getModule"); Object javaDesktop = getModule.invoke(Toolkit.getDefaultToolkit().getClass()); Object allUnnamed = getModule.invoke(Main.class); Class module = Class.forName("java.lang.Module"); Method addOpens = module.getMethod("addOpens", String.class, module); addOpens.invoke(javaDesktop, "sun.awt.X11", allUnnamed); } catch (Exception e) {} try { Toolkit tk = Toolkit.getDefaultToolkit(); Field aacn = tk.getClass().getDeclaredField("awtAppClassName"); aacn.setAccessible(true); aacn.set(tk, "MapEdit"); } catch (Exception e) {} if (MapEditMenuBar.IS_MAC_OS) { try { Class.forName("com.kreative.mapedit.mac.MacDummyWindow").newInstance(); } catch (Exception e) { e.printStackTrace(); } } if (args.length == 0) { newMapping(); } else { for (String arg : args) { openMapping(new File(arg)); } } if (MapEditMenuBar.IS_MAC_OS) { try { Class.forName("com.kreative.mapedit.mac.MyApplicationListener").newInstance(); } catch (Exception e) { e.printStackTrace(); } } } public static MapEditFrame newMapping() { Mapping m = new Mapping(); for (int i = 32; i < 127; i++) m.root.setSequence(new CodePointSequence(i), i); for (int i = 160; i < 256; i++) m.root.setSequence(new CodePointSequence(i), i); MapEditFrame f = new MapEditFrame(null, m); f.setVisible(true); return f; } public static MapEditFrame newMapping(Charset cs) { if (cs == null) { return newMapping(); } else { Mapping m = new Mapping(); m.decode(cs); MapEditFrame f = new MapEditFrame(null, m); f.setVisible(true); return f; } } private static String lastOpenDirectory = null; public static MapEditFrame openMapping() { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Open", FileDialog.LOAD); if (lastOpenDirectory != null) fd.setDirectory(lastOpenDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; File file = new File((lastOpenDirectory = ds), fs); return openMapping(file); } public static MapEditFrame openMapping(File file) { if (file == null) { return openMapping(); } else try { Mapping m = new Mapping(); FileInputStream in = new FileInputStream(file); m.read(in); in.close(); MapEditFrame f = new MapEditFrame(file, m); f.setVisible(true); return f; } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while reading the selected file.", "Open", JOptionPane.ERROR_MESSAGE ); return null; } } private static String lastSaveDirectory = null; public static File getSaveFile(String suffix) { Frame frame = new Frame(); FileDialog fd = new FileDialog(frame, "Save", FileDialog.SAVE); if (lastSaveDirectory != null) fd.setDirectory(lastSaveDirectory); fd.setVisible(true); String ds = fd.getDirectory(), fs = fd.getFile(); fd.dispose(); frame.dispose(); if (ds == null || fs == null) return null; if (!fs.toLowerCase().endsWith(suffix.toLowerCase())) fs += suffix; return new File((lastSaveDirectory = ds), fs); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MapEditController.java000066400000000000000000000156771506470510200311740ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.Component; import java.awt.Window; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; public class MapEditController { private final MapEditFrame parent; private final MappingTablePanel mtp; private final CodePointSequencePanel csp; private final MapEditSubtableFrame[] subtableWindows; private final List listeners; private int index = -1; public MapEditController(MapEditFrame parent, MappingTablePanel mtp, CodePointSequencePanel csp) { this.parent = parent; (this.mtp = mtp).addListener(new MyMappingTableListener()); (this.csp = csp).addListener(new MyCodePointSequenceListener()); this.subtableWindows = new MapEditSubtableFrame[256]; this.listeners = new ArrayList(); } public int getSelectedIndex() { return index; } public void setSelectedIndex(int i) { mtp.getTextField(i).requestFocusInWindow(); } public CodePointSequence getSequence(int i) { if (i < 0 || i >= 256) return null; return mtp.getMappingTable().getSequence(i); } public String getSequenceString(int i) { if (i < 0 || i >= 256) return null; CodePointSequence cs = mtp.getMappingTable().getSequence(i); return (cs != null) ? cs.toString() : null; } public void setSequence(int i, CodePointSequence seq) { if (i < 0 || i >= 256 || seq == null) return; if (index == i) csp.setCodePointSequence(seq, i, false); mtp.getMappingTable().setSequence(seq, i); mtp.update(i); for (MapEditListener l : listeners) l.codePointSequenceChanged(); } public void setSequenceString(int i, String s) { if (i < 0 || i >= 256 || s == null) return; CodePointSequence seq = new CodePointSequence(s); if (index == i) csp.setCodePointSequence(seq, i, false); mtp.getMappingTable().setSequence(seq, i); mtp.update(i); for (MapEditListener l : listeners) l.codePointSequenceChanged(); } public void deleteSequence(int i) { if (i < 0 || i >= 256) return; if (index == i) csp.setCodePointSequence(null, i, false); mtp.getMappingTable().setSequence(null, i); mtp.update(i); for (MapEditListener l : listeners) l.codePointSequenceChanged(); } public MapEditSubtableFrame createSubtableFrame(int i) { if (i < 0 || i >= 256) return null; if (subtableWindows[i] == null) { MappingTable subtable = mtp.getMappingTable().getSubtable(i); if (subtable == null) { subtable = new MappingTable(); mtp.getMappingTable().setSubtable(subtable, i); mtp.update(i); for (MapEditListener l : listeners) l.mappingSubtableChanged(); } String h = "00" + Integer.toHexString(i); h = h.substring(h.length() - 2).toUpperCase(); h = csp.getEncodingPrefix() + h; subtableWindows[i] = new MapEditSubtableFrame(parent, subtable, h); subtableWindows[i].addWindowListener(new MyWindowListener(i)); subtableWindows[i].controller.addListener(new MyMapEditListener()); } return subtableWindows[i]; } public void disposeSubtableFrame(int i) { if (i < 0 || i >= 256) return; if (subtableWindows[i] == null) return; subtableWindows[i].dispose(); subtableWindows[i] = null; } public void deleteSubtable(int i) { if (i < 0 || i >= 256) return; disposeSubtableFrame(i); mtp.getMappingTable().setSubtable(null, i); mtp.update(i); for (MapEditListener l : listeners) l.mappingSubtableChanged(); } public void addListener(MapEditListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(MapEditListener listener) { if (listener != null) listeners.remove(listener); } public MapEditListener[] getListeners() { return listeners.toArray(new MapEditListener[listeners.size()]); } private class MyMappingTableListener implements MappingTablePanelListener { public void focusGained(FocusEvent e, int i) { CodePointSequence cs = mtp.getMappingTable().getSequence(i); csp.setCodePointSequence(cs, index = i, false); } public void keyPressed(KeyEvent e, int i) { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: if (i >= 1) mtp.getTextField(i - 1).requestFocusInWindow(); break; case KeyEvent.VK_RIGHT: if (i < 255) mtp.getTextField(i + 1).requestFocusInWindow(); break; case KeyEvent.VK_UP: if (i >= 16) mtp.getTextField(i - 16).requestFocusInWindow(); break; case KeyEvent.VK_DOWN: if (i < 240) mtp.getTextField(i + 16).requestFocusInWindow(); break; case KeyEvent.VK_ESCAPE: case KeyEvent.VK_CLEAR: csp.setCodePointSequence(null, index = -1, false); Component c = mtp.getTextField(i); while (c != null) { if (c instanceof Window) { c.requestFocusInWindow(); break; } else { c = c.getParent(); } } break; case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_DELETE: if (e.isMetaDown() || e.isControlDown()) { deleteSubtable(index = i); } else { csp.setCodePointSequence(null, index = i, true); } break; case KeyEvent.VK_ENTER: if (e.isMetaDown() || e.isControlDown()) { createSubtableFrame(index = i).setVisible(true); } else if (e.isShiftDown()) { if (i >= 16) mtp.getTextField(i - 16).requestFocusInWindow(); } else { if (i < 240) mtp.getTextField(i + 16).requestFocusInWindow(); } break; } } public void keyTyped(KeyEvent e, int i) { if (e.isMetaDown() || e.isControlDown()) return; char ch = e.getKeyChar(); if (ch == KeyEvent.CHAR_UNDEFINED) return; if (ch < 32 || (ch >= 127 && ch < 160)) return; if (ch >= 0xD800 && ch < 0xE000) return; CodePointSequence cs = new CodePointSequence(ch); csp.setCodePointSequence(cs, index = i, true); } public void focusLost(FocusEvent e, int i) {} public void keyReleased(KeyEvent e, int i) {} public void mouseClicked(MouseEvent e, int i) {} public void mouseEntered(MouseEvent e, int i) {} public void mouseExited(MouseEvent e, int i) {} public void mousePressed(MouseEvent e, int i) {} public void mouseReleased(MouseEvent e, int i) {} } private class MyCodePointSequenceListener implements CodePointSequencePanelListener { public void codePointSequenceChanged() { if (index < 0) return; CodePointSequence cs = csp.getCodePointSequence(); mtp.getMappingTable().setSequence(cs, index); mtp.update(index); for (MapEditListener l : listeners) l.codePointSequenceChanged(); } } private class MyWindowListener extends WindowAdapter { private final int i; public MyWindowListener(int i) { this.i = i; } public void windowClosed(WindowEvent e) { subtableWindows[i] = null; } } private class MyMapEditListener implements MapEditListener { public void codePointSequenceChanged() { for (MapEditListener l : listeners) l.mappingSubtableChanged(); } public void mappingSubtableChanged() { for (MapEditListener l : listeners) l.mappingSubtableChanged(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MapEditFrame.java000066400000000000000000000076731506470510200301000ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.event.DocumentEvent; public class MapEditFrame extends JFrame { private static final long serialVersionUID = 1L; private File file; private boolean changed; private final Mapping mapping; private final MappingNamePanel namePanel; private final MappingTablePanel tablePanel; private final CodePointSequencePanel sequencePanel; private final MapEditController controller; public MapEditFrame(File file, Mapping mapping) { this.file = file; this.changed = false; this.mapping = mapping; this.namePanel = new MappingNamePanel(mapping); this.tablePanel = new MappingTablePanel(mapping.root); this.sequencePanel = new CodePointSequencePanel(""); this.controller = new MapEditController(this, tablePanel, sequencePanel); JPanel innerPanel = new JPanel(new BorderLayout(8, 8)); innerPanel.add(tablePanel, BorderLayout.LINE_START); innerPanel.add(sequencePanel, BorderLayout.CENTER); JPanel outerPanel = new JPanel(new BorderLayout(8, 8)); outerPanel.add(namePanel, BorderLayout.PAGE_START); outerPanel.add(innerPanel, BorderLayout.CENTER); outerPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(outerPanel); setJMenuBar(new MapEditMenuBar(this, this, controller)); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); updateWindow(); namePanel.addListener(new MyNamePanelListener()); controller.addListener(new MyMapEditListener()); addWindowListener(new MyWindowListener()); } public boolean save() { if (file == null) { return saveAs(); } else try { FileOutputStream out = new FileOutputStream(file); mapping.write(out); out.close(); changed = false; updateWindow(); return true; } catch (IOException e) { JOptionPane.showMessageDialog( null, "An error occurred while saving this file.", "Save", JOptionPane.ERROR_MESSAGE ); updateWindow(); return false; } } public boolean saveAs() { File newFile = Main.getSaveFile(".TXT"); if (newFile == null) return false; file = newFile; return save(); } private void updateWindow() { if (MapEditMenuBar.IS_MAC_OS) { getRootPane().putClientProperty("Window.documentFile", file); getRootPane().putClientProperty("Window.documentModified", changed); setTitle((mapping.name != null) ? mapping.name : "Untitled"); } else if (changed) { setTitle(((mapping.name != null) ? mapping.name : "Untitled") + " \u2022"); } else { setTitle((mapping.name != null) ? mapping.name : "Untitled"); } } private class MyNamePanelListener implements MappingNamePanelListener { public void nameChanged(DocumentEvent e) { changed = true; updateWindow(); namePanel.updateDate(); } public void dateChanged(DocumentEvent e) { changed = true; updateWindow(); } public void authorChanged(DocumentEvent e) { changed = true; updateWindow(); namePanel.updateDate(); } } private class MyMapEditListener implements MapEditListener { public void codePointSequenceChanged() { changed = true; updateWindow(); namePanel.updateDate(); } public void mappingSubtableChanged() { changed = true; updateWindow(); namePanel.updateDate(); } } private class MyWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { if (changed) { String name = ((mapping.name != null) ? mapping.name : "Untitled"); switch (new SaveChangesDialog(MapEditFrame.this, name).showDialog()) { case CANCEL: return; case DONT_SAVE: break; case SAVE: if (save()) break; else return; } } dispose(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MapEditListener.java000066400000000000000000000002241506470510200306140ustar00rootroot00000000000000package com.kreative.mapedit; public interface MapEditListener { public void codePointSequenceChanged(); public void mappingSubtableChanged(); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MapEditMenuBar.java000066400000000000000000000272171506470510200303730ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import java.util.List; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import com.kreative.unicode.fontmap.FontMapController; public class MapEditMenuBar extends JMenuBar { private static final long serialVersionUID = 1L; public static final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); public static final boolean IS_MAC_OS; static { boolean isMacOS; try { isMacOS = System.getProperty("os.name").toUpperCase().contains("MAC OS"); } catch (Exception e) { isMacOS = false; } IS_MAC_OS = isMacOS; } public MapEditMenuBar(MapEditFrame f, Window w, MapEditController ctrl) { add(new FileMenu(f, w)); add(new EditMenu(ctrl)); } public static class FileMenu extends JMenu { private static final long serialVersionUID = 1L; public FileMenu(MapEditFrame f, Window w) { super("File"); add(new NewMappingMenuItem()); add(new NewMappingFromEncodingMenuItem()); add(new OpenMappingMenuItem()); add(new CloseMenuItem(w)); addSeparator(); add(new SaveMenuItem(f)); add(new SaveAsMenuItem(f)); if (!IS_MAC_OS) { addSeparator(); add(new ExitMenuItem()); } } } public static class NewMappingMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewMappingMenuItem() { super("New"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.newMapping(); } }); } } public static class NewMappingFromEncodingMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public NewMappingFromEncodingMenuItem() { super("New from Encoding..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new NewMappingFrame("New from Encoding").setVisible(true); } }); } } public static class OpenMappingMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenMappingMenuItem() { super("Open..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Main.openMapping(); } }); } } public static class CloseMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CloseMenuItem(final Window window) { super("Close Window"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); } }); } } public static class SaveMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveMenuItem(final MapEditFrame f) { super("Save"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.save(); } }); } } public static class SaveAsMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public SaveAsMenuItem(final MapEditFrame f) { super("Save As..."); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY | KeyEvent.SHIFT_MASK)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.saveAs(); } }); } } public static class ExitMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ExitMenuItem() { super("Exit"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) return; } } System.exit(0); } }); } } public static class EditMenu extends JMenu { private static final long serialVersionUID = 1L; public EditMenu(MapEditController ctrl) { super("Edit"); add(new CutMenuItem(ctrl)); add(new CopyMenuItem(ctrl)); add(new PasteMenuItem(ctrl)); add(new ClearMenuItem(ctrl)); addSeparator(); add(new OpenSubtableMenuItem(ctrl)); add(new DeleteSubtableMenuItem(ctrl)); addSeparator(); add(new LeftToRightMenuItem(ctrl)); add(new RightToLeftMenuItem(ctrl)); add(new ReverseVideoMenuItem(ctrl)); addSeparator(); add(new FontMapMenuItem()); } } public static class CutMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CutMenuItem(final MapEditController ctrl) { super("Cut"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; String content = ctrl.getSequenceString(index); if (content == null) return; Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new StringSelection(content), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); ctrl.deleteSequence(index); } }); } } public static class CopyMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public CopyMenuItem(final MapEditController ctrl) { super("Copy"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; String content = ctrl.getSequenceString(index); if (content == null) return; Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); cb.setContents(new StringSelection(content), new ClipboardOwner() { public void lostOwnership(Clipboard cb, Transferable t) {} }); } }); } } public static class PasteMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PasteMenuItem(final MapEditController ctrl) { super("Paste"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; try { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); if (cb.isDataFlavorAvailable(DataFlavor.stringFlavor)) { String content = cb.getData(DataFlavor.stringFlavor).toString(); if (content == null || content.length() == 0) ctrl.deleteSequence(index); else ctrl.setSequenceString(index, content); } } catch (Exception ex) { ex.printStackTrace(); } } }); } } public static class ClearMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ClearMenuItem(final MapEditController ctrl) { super("Clear"); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; ctrl.deleteSequence(index); } }); } } public static class OpenSubtableMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public OpenSubtableMenuItem(final MapEditController ctrl) { super("Open Subtable"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; ctrl.createSubtableFrame(index).setVisible(true); } }); } } public static class DeleteSubtableMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public DeleteSubtableMenuItem(final MapEditController ctrl) { super("Delete Subtable"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; ctrl.deleteSubtable(index); } }); } } public static class LeftToRightMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public LeftToRightMenuItem(final MapEditController ctrl) { super("Left-to-Right"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; CodePointSequence seq = ctrl.getSequence(index); if (seq == null) return; List sl = seq.toList(); sl.remove(Integer.valueOf(MappingTag.RL.intValue)); if (!sl.remove(Integer.valueOf(MappingTag.LR.intValue))) { sl.add(0, Integer.valueOf(MappingTag.LR.intValue)); } seq = new CodePointSequence(sl); ctrl.setSequence(index, seq); } }); } } public static class RightToLeftMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public RightToLeftMenuItem(final MapEditController ctrl) { super("Right-to-Left"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; CodePointSequence seq = ctrl.getSequence(index); if (seq == null) return; List sl = seq.toList(); sl.remove(Integer.valueOf(MappingTag.LR.intValue)); if (!sl.remove(Integer.valueOf(MappingTag.RL.intValue))) { sl.add(0, Integer.valueOf(MappingTag.RL.intValue)); } seq = new CodePointSequence(sl); ctrl.setSequence(index, seq); } }); } } public static class ReverseVideoMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public ReverseVideoMenuItem(final MapEditController ctrl) { super("Reverse Video"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = ctrl.getSelectedIndex(); if (index < 0) return; CodePointSequence seq = ctrl.getSequence(index); if (seq == null) return; List sl = seq.toList(); if (!sl.remove(Integer.valueOf(MappingTag.RV.intValue))) { sl.add(0, Integer.valueOf(MappingTag.RV.intValue)); } seq = new CodePointSequence(sl); ctrl.setSequence(index, seq); } }); } } public static class FontMapMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public FontMapMenuItem() { super("Font Map"); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, SHORTCUT_KEY)); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontMapController.getInstance().getFrame().setVisible(true); } }); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MapEditSubtableFrame.java000066400000000000000000000023301506470510200315430ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; public class MapEditSubtableFrame extends JFrame { private static final long serialVersionUID = 1L; public final MappingTable table; public final MappingTablePanel tablePanel; public final CodePointSequencePanel sequencePanel; public final MapEditController controller; public MapEditSubtableFrame(MapEditFrame parent, MappingTable table, String encodingPrefix) { super("Subtable " + encodingPrefix); this.table = table; this.tablePanel = new MappingTablePanel(table); this.sequencePanel = new CodePointSequencePanel(encodingPrefix + " "); this.controller = new MapEditController(parent, tablePanel, sequencePanel); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(tablePanel, BorderLayout.LINE_START); mainPanel.add(sequencePanel, BorderLayout.CENTER); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); setJMenuBar(new MapEditMenuBar(parent, this, controller)); pack(); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/Mapping.java000066400000000000000000000107261506470510200271660ustar00rootroot00000000000000package com.kreative.mapedit; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.util.Scanner; import com.kreative.unicode.data.NameResolver; public class Mapping { public String name = null; public String date = null; public String author = null; public final MappingTable root = new MappingTable(); public void read(InputStream in) { read(new Scanner(in)); } public void read(Scanner in) { while (in.hasNextLine()) { String line = in.nextLine().trim(); if (line.startsWith("#")) { line = line.substring(1).trim(); String[] parts = line.split(":", 2); if (parts.length == 2) { String key = parts[0].trim().toLowerCase(); String value = parts[1].trim(); if (key.equals("name")) name = value; if (key.equals("date")) date = value; if (key.equals("author")) author = value; } } else { String[] parts = line.split("\\s+"); if (parts.length >= 2) { try { byte[] key = parseBytes(parts[0]); CodePointSequence value = CodePointSequence.parse(parts[1]); root.setSequence(value, key); } catch (NumberFormatException nfe) { continue; } } } } } public void write(OutputStream out) { write(new PrintWriter(new OutputStreamWriter(out), true)); } public void write(PrintWriter out) { if (name != null) out.println("#\tName: " + name ); if (date != null) out.println("#\tDate: " + date ); if (author != null) out.println("#\tAuthor: " + author); out.println(); write(out, root, "0x"); } private void write(PrintWriter out, MappingTable tab, String pfx) { for (int i = 0; i < 256; i++) { String pfxi = pfx + formatByte(i); CodePointSequence cs = tab.getSequence(i); if (cs != null) { String csc = CodePointSequence.format(cs); if (cs.length() == 1) { int cp = cs.get(0); String n = NameResolver.instance(cp).getName(cp); csc += "\t# " + n; } else if (cs.length() == 2) { MappingTag tag = MappingTag.forIntValue(cs.get(0)); if (tag != null) { int cp = cs.get(1); String n = NameResolver.instance(cp).getName(cp); csc += "\t# " + n + ", " + tag.description; } } out.println(pfxi + "\t" + csc); } MappingTable st = tab.getSubtable(i); if (st != null) write(out, st, pfxi); } } public void decode(Charset cs) { name = cs.displayName(); CharsetDecoder decoder = cs.newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE); decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); decoder.replaceWith("\uFFFF"); decode(decoder, new byte[256], 0, new char[256]); } private void decode(CharsetDecoder decoder, byte[] in, int pos, char[] out) { for (int ch = 0; ch < 256; ch++) { in[pos] = (byte)ch; ByteBuffer inb = ByteBuffer.wrap(in, 0, pos + 1); CharBuffer outb = CharBuffer.wrap(out); try { decoder.reset(); decoder.decode(inb, outb, false); // Do NOT finish the decode so we can distinguish // incomplete input from invalid input. } catch (Exception e) { System.err.println("Failed to decode encoding " + name + "; it should be added to the list of broken charsets."); e.printStackTrace(); continue; } if (outb.position() > 0) { String s = new String(out, 0, outb.position()); if (s.contains("\uFFFF")) continue; CodePointSequence cps = new CodePointSequence(s); root.setSequence(cps, in, 0, pos + 1); } else if (pos + 1 < in.length) { decode(decoder, in, pos + 1, out); } else { System.err.println("Failed to decode encoding " + name + "; it should be added to the list of broken charsets."); } } } private static byte[] parseBytes(String s) { ByteArrayOutputStream os = new ByteArrayOutputStream(); String[] parts = s.split("[+]"); for (String part : parts) { part = part.toUpperCase(); if (part.startsWith("0X")) part = part.substring(2); if ((part.length() & 1) == 1) part = "0" + part; for (int i = 0, n = part.length(); i < n; i += 2) { String h = part.substring(i, i + 2); os.write(Integer.parseInt(h, 16)); } } return os.toByteArray(); } private static String formatByte(int b) { String h = "00" + Integer.toHexString(b); return h.substring(h.length() - 2).toUpperCase(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingNamePanel.java000066400000000000000000000065561506470510200307550ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import java.awt.GridLayout; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; public class MappingNamePanel extends JPanel { private static final long serialVersionUID = 1L; private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy MMMM d"); private final JTextField nameField; private final JTextField dateField; private final JTextField authorField; private final List listeners; public MappingNamePanel(final Mapping mapping) { this.nameField = new JTextField(mapping.name); this.dateField = new JTextField(mapping.date); this.authorField = new JTextField(mapping.author); this.listeners = new ArrayList(); JPanel labelPanel = new JPanel(new GridLayout(0, 1, 4, 4)); labelPanel.add(new JLabel("Name:")); labelPanel.add(new JLabel("Date:")); labelPanel.add(new JLabel("Author:")); JPanel fieldPanel = new JPanel(new GridLayout(0, 1, 4, 4)); fieldPanel.add(nameField); fieldPanel.add(dateField); fieldPanel.add(authorField); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(labelPanel, BorderLayout.LINE_START); mainPanel.add(fieldPanel, BorderLayout.CENTER); mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); nameField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { mapping.name = nameField.getText(); if (mapping.name.length() == 0) mapping.name = null; for (MappingNamePanelListener l : listeners) l.nameChanged(e); } public void insertUpdate(DocumentEvent e) { changedUpdate(e); } public void removeUpdate(DocumentEvent e) { changedUpdate(e); } }); dateField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { mapping.date = dateField.getText(); if (mapping.date.length() == 0) mapping.date = null; for (MappingNamePanelListener l : listeners) l.dateChanged(e); } public void insertUpdate(DocumentEvent e) { changedUpdate(e); } public void removeUpdate(DocumentEvent e) { changedUpdate(e); } }); authorField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { mapping.author = authorField.getText(); if (mapping.author.length() == 0) mapping.author = null; for (MappingNamePanelListener l : listeners) l.authorChanged(e); } public void insertUpdate(DocumentEvent e) { changedUpdate(e); } public void removeUpdate(DocumentEvent e) { changedUpdate(e); } }); } public void updateDate() { dateField.setText(DATE_FORMAT.format(new Date())); } public void addListener(MappingNamePanelListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(MappingNamePanelListener listener) { if (listener != null) listeners.remove(listener); } public MappingNamePanelListener[] getListeners() { return listeners.toArray(new MappingNamePanelListener[listeners.size()]); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingNamePanelListener.java000066400000000000000000000003711506470510200324500ustar00rootroot00000000000000package com.kreative.mapedit; import javax.swing.event.DocumentEvent; public interface MappingNamePanelListener { public void nameChanged(DocumentEvent e); public void dateChanged(DocumentEvent e); public void authorChanged(DocumentEvent e); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingTable.java000066400000000000000000000062121506470510200301310ustar00rootroot00000000000000package com.kreative.mapedit; public class MappingTable { private final CodePointSequence[] seqs = new CodePointSequence[256]; private final MappingTable[] submaps = new MappingTable[256]; public CodePointSequence getSequence(byte... i) { return getSequence(i, 0, i.length); } public CodePointSequence getSequence(int... i) { return getSequence(i, 0, i.length); } public MappingTable getSubtable(byte... i) { return getSubtable(i, 0, i.length); } public MappingTable getSubtable(int... i) { return getSubtable(i, 0, i.length); } public void setSequence(CodePointSequence s, byte... i) { setSequence(s, i, 0, i.length); } public void setSequence(CodePointSequence s, int... i) { setSequence(s, i, 0, i.length); } public void setSubtable(MappingTable m, byte... i) { setSubtable(m, i, 0, i.length); } public void setSubtable(MappingTable m, int... i) { setSubtable(m, i, 0, i.length); } public CodePointSequence getSequence(byte[] i, int o, int l) { if (l <= 0) return null; if (l <= 1) return seqs[i[o] & 0xFF]; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) return null; return submap.getSequence(i, o + 1, l - 1); } public CodePointSequence getSequence(int[] i, int o, int l) { if (l <= 0) return null; if (l <= 1) return seqs[i[o] & 0xFF]; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) return null; return submap.getSequence(i, o + 1, l - 1); } public MappingTable getSubtable(byte[] i, int o, int l) { if (l <= 0) return null; MappingTable submap = submaps[i[o] & 0xFF]; if (l <= 1) return submap; if (submap == null) return null; return submap.getSubtable(i, o + 1, l - 1); } public MappingTable getSubtable(int[] i, int o, int l) { if (l <= 0) return null; MappingTable submap = submaps[i[o] & 0xFF]; if (l <= 1) return submap; if (submap == null) return null; return submap.getSubtable(i, o + 1, l - 1); } public CodePointSequence setSequence(CodePointSequence s, byte[] i, int o, int l) { if (l <= 0) return s; if (l <= 1) return seqs[i[o] & 0xFF] = s; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new MappingTable(); return submap.setSequence(s, i, o + 1, l - 1); } public CodePointSequence setSequence(CodePointSequence s, int[] i, int o, int l) { if (l <= 0) return s; if (l <= 1) return seqs[i[o] & 0xFF] = s; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new MappingTable(); return submap.setSequence(s, i, o + 1, l - 1); } public MappingTable setSubtable(MappingTable m, byte[] i, int o, int l) { if (l <= 0) return m; if (l <= 1) return submaps[i[o] & 0xFF] = m; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new MappingTable(); return submap.setSubtable(m, i, o + 1, l - 1); } public MappingTable setSubtable(MappingTable m, int[] i, int o, int l) { if (l <= 0) return m; if (l <= 1) return submaps[i[o] & 0xFF] = m; MappingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new MappingTable(); return submap.setSubtable(m, i, o + 1, l - 1); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingTablePanel.java000066400000000000000000000136261506470510200311200ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import com.kreative.unicode.fontmap.FontMapController; import com.kreative.unicode.fontmap.FontMapEntry; public class MappingTablePanel extends JPanel { private static final long serialVersionUID = 1L; private static final Color BG_MB = new Color(255, 165, 0); private static final Color FG_MB = Color.black; private static final Color BG_NG = new Color(0xFFDDDDDD); private static final Color FG_NG = new Color(0xFFDDDDDD); private static final Color BG_RV = Color.black; private static final Color FG_RV = Color.white; private static final Color BG_RL = new Color(255, 255, 204); private static final Color FG_RL = Color.black; private static final Color BG_LR = new Color(204, 238, 255); private static final Color FG_LR = Color.black; private static final Color BG_CC = new Color(204, 255, 204); private static final Color FG_CC = Color.black; private static final Color BG_PU = new Color(238, 204, 255); private static final Color FG_PU = Color.black; private static final Color BG_OK = Color.white; private static final Color FG_OK = Color.black; private static final Color BLURRED = new Color(0xFFBBBBBB); private static final Color FOCUSED = new Color(0xFF6699CC); private final MappingTable mt; private final JLabel[] fields; private final Font defaultFont; private final List listeners; public MappingTablePanel(MappingTable table) { mt = table; fields = new JLabel[256]; JPanel panel = new JPanel(new GridLayout(16, 16, 4, 4)); for (int i = 0; i < 256; i++) { fields[i] = new JLabel(); fields[i].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, BLURRED)); fields[i].setFocusable(true); fields[i].setHorizontalAlignment(JLabel.CENTER); fields[i].setOpaque(true); panel.add(fields[i]); MyListener ml = new MyListener(i); fields[i].addFocusListener(ml); fields[i].addKeyListener(ml); fields[i].addMouseListener(ml); } defaultFont = fields[0].getFont(); listeners = new ArrayList(); update(); panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); panel.setPreferredSize(new Dimension(484, 484)); setLayout(new GridLayout(1, 1, 0, 0)); add(panel); } public void update() { for (int i = 0; i < 256; i++) { update(i); } } public void update(int i) { CodePointSequence cs = mt.getSequence(i); if (cs == null) { fields[i].setText(" "); fields[i].setFont(defaultFont); } else { String css = cs.toString().trim(); FontMapEntry fme = FontMapController.getInstance().entryForString(css); fields[i].setText((css.length() > 0) ? css : " "); fields[i].setFont((fme != null) ? fme.getFont() : defaultFont); } if (mt.getSubtable(i) != null) { fields[i].setBackground(BG_MB); fields[i].setForeground(FG_MB); } else if (cs == null) { fields[i].setBackground(BG_NG); fields[i].setForeground(FG_NG); } else if (cs.contains(MappingTag.RV.intValue)) { fields[i].setBackground(BG_RV); fields[i].setForeground(FG_RV); } else if (cs.contains(MappingTag.RL.intValue)) { fields[i].setBackground(BG_RL); fields[i].setForeground(FG_RL); } else if (cs.contains(MappingTag.LR.intValue)) { fields[i].setBackground(BG_LR); fields[i].setForeground(FG_LR); } else if (cs.containsC0C1()) { fields[i].setBackground(BG_CC); fields[i].setForeground(FG_CC); } else if (cs.containsPUA()) { fields[i].setBackground(BG_PU); fields[i].setForeground(FG_PU); } else { fields[i].setBackground(BG_OK); fields[i].setForeground(FG_OK); } } public MappingTable getMappingTable() { return mt; } public JLabel getTextField(int i) { return fields[i]; } public void addListener(MappingTablePanelListener listener) { if (listener != null) listeners.add(listener); } public void removeListener(MappingTablePanelListener listener) { if (listener != null) listeners.remove(listener); } public MappingTablePanelListener[] getListeners() { return listeners.toArray(new MappingTablePanelListener[listeners.size()]); } private class MyListener implements FocusListener, KeyListener, MouseListener { private final int i; public MyListener(int i) { this.i = i; } public void focusGained(FocusEvent e) { fields[i].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, FOCUSED)); for (MappingTablePanelListener l : listeners) l.focusGained(e, i); } public void focusLost(FocusEvent e) { fields[i].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, BLURRED)); for (MappingTablePanelListener l : listeners) l.focusLost(e, i); } public void keyPressed(KeyEvent e) { for (MappingTablePanelListener l : listeners) l.keyPressed(e, i); } public void keyReleased(KeyEvent e) { for (MappingTablePanelListener l : listeners) l.keyReleased(e, i); } public void keyTyped(KeyEvent e) { for (MappingTablePanelListener l : listeners) l.keyTyped(e, i); } public void mouseClicked(MouseEvent e) { for (MappingTablePanelListener l : listeners) l.mouseClicked(e, i); } public void mouseEntered(MouseEvent e) { for (MappingTablePanelListener l : listeners) l.mouseEntered(e, i); } public void mouseExited(MouseEvent e) { for (MappingTablePanelListener l : listeners) l.mouseExited(e, i); } public void mousePressed(MouseEvent e) { fields[i].requestFocusInWindow(); for (MappingTablePanelListener l : listeners) l.mousePressed(e, i); } public void mouseReleased(MouseEvent e) { for (MappingTablePanelListener l : listeners) l.mouseReleased(e, i); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingTablePanelListener.java000066400000000000000000000012021506470510200326110ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; public interface MappingTablePanelListener { public void focusGained(FocusEvent e, int i); public void focusLost(FocusEvent e, int i); public void keyPressed(KeyEvent e, int i); public void keyReleased(KeyEvent e, int i); public void keyTyped(KeyEvent e, int i); public void mouseClicked(MouseEvent e, int i); public void mouseEntered(MouseEvent e, int i); public void mouseExited(MouseEvent e, int i); public void mousePressed(MouseEvent e, int i); public void mouseReleased(MouseEvent e, int i); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/MappingTag.java000066400000000000000000000015701506470510200276170ustar00rootroot00000000000000package com.kreative.mapedit; public enum MappingTag { LR(0xE0004C52, "", "left to right"), RL(0xE000524C, "", "right to left"), RV(0xE0005256, "", "reverse video"); public final int intValue; public final String stringValue; public final String description; private MappingTag(int i, String s, String d) { this.intValue = i; this.stringValue = s; this.description = d; } public static MappingTag forIntValue(int i) { for (MappingTag tag : values()) { if (tag.intValue == i) return tag; } return null; } public static MappingTag forStringValue(String s) { for (MappingTag tag : values()) { if (tag.stringValue.equalsIgnoreCase(s)) return tag; } return null; } public static MappingTag forDescription(String d) { for (MappingTag tag : values()) { if (tag.description.equalsIgnoreCase(d)) return tag; } return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/NewMappingFrame.java000066400000000000000000000036371506470510200306160ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.nio.charset.Charset; import java.util.SortedMap; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; public class NewMappingFrame extends JFrame { private static final long serialVersionUID = 1L; private final SortedMap charsets; private final JList charsetList; private final JButton createButton; public NewMappingFrame(String title) { super(title); this.charsets = Charset.availableCharsets(); this.charsetList = new JList(charsets.keySet().toArray()); this.createButton = new JButton("Create"); charsetList.setVisibleRowCount(12); JScrollPane listPanel = new JScrollPane( charsetList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(createButton); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(listPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); pack(); setSize(500, getHeight()); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); createButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (Object o : charsetList.getSelectedValues()) { new NewMappingThread(charsets.get(o)).start(); } } }); } private static final class NewMappingThread extends Thread { private final Charset cs; public NewMappingThread(Charset cs) { this.cs = cs; } @Override public void run() { Main.newMapping(cs); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/Remap.java000066400000000000000000000153731506470510200266420ustar00rootroot00000000000000package com.kreative.mapedit; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Remap { public static void main(String[] args) { if (args.length == 0) { printHelp(); } else { boolean processingArgs = true; boolean loadedRemapping = false; Map map = new HashMap(); File outputFile = null; File outputDir = null; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (processingArgs && arg.startsWith("-")) { if (arg.equals("--")) { processingArgs = false; } else if (arg.equals("-m") && argi < args.length) { arg = args[argi++]; loadedRemapping = true; try { if (readRemapping(map, arg)) { System.out.println("Loaded " + arg); } else { System.err.println("No mappings found in " + arg); } } catch (IOException e) { System.err.println("Could not read " + arg + ": " + e.getMessage()); } } else if (arg.equals("-o") && argi < args.length) { arg = args[argi++]; outputFile = new File(arg); } else if (arg.equals("-d") && argi < args.length) { arg = args[argi++]; outputDir = new File(arg); } else if (arg.equals("--help")) { printHelp(); } else { System.err.println("Unknown option: " + arg); } } else if (!loadedRemapping) { loadedRemapping = true; try { if (readRemapping(map, arg)) { System.out.println("Loaded " + arg); } else { System.err.println("No mappings found in " + arg); } } catch (IOException e) { System.err.println("Could not read " + arg + ": " + e.getMessage()); } } else { File inFile = new File(arg); File outFile; if (outputFile != null) { outFile = outputFile; outputFile = null; } else if (outputDir != null) { String outName = inFile.getName(); outFile = new File(outputDir, outName); } else { File parent = inFile.getParentFile(); String outName = inFile.getName() + ".REMAP.TXT"; outFile = new File(parent, outName); } try { if (rewriteMapping(map, inFile, outFile)) { System.out.println("Rewrote " + arg); } else { System.out.println("No changes made to " + arg); } } catch (IOException e) { System.err.println("Could not rewrite " + arg + ": " + e.getMessage()); } } } } } private static void printHelp() { System.out.println(); System.out.println("Options:"); System.out.println(" -m Specify a remapping file. Specify column numbers using colon:"); System.out.println(" map.txt - remap from column 0 to column 1"); System.out.println(" map.txt:- - remap from column 1 to column 0"); System.out.println(" map.txt:- - remap from column 0 to column "); System.out.println(" map.txt:- - remap from column to column 0"); System.out.println(" map.txt:- - remap from column to column "); System.out.println(" -o Specify output file."); System.out.println(" -d Specify output directory."); System.out.println(" -- Process remaining arguments as file names."); System.out.println(); } private static final Pattern codePointPattern = Pattern.compile("\\b([0][Xx]|[Uu][+])?([0-9A-Fa-f]{4,8})\\b"); private static boolean rewriteMapping(Map map, File inFile, File outFile) throws IOException { boolean changed = false; Scanner scan = new Scanner(new FileInputStream(inFile), "UTF-8"); FileOutputStream outStream = new FileOutputStream(outFile); OutputStreamWriter outWriter = new OutputStreamWriter(outStream, "UTF-8"); PrintWriter out = new PrintWriter(outWriter, true); while (scan.hasNextLine()) { String line = scan.nextLine(); StringBuffer sb = new StringBuffer(); Matcher m = codePointPattern.matcher(line); while (m.find()) { if (m.start() >= 4) { Integer cp = Integer.parseInt(m.group(2), 16); if (map.containsKey(cp)) { String r = toHexString(map.get(cp)); if (m.group(1) != null) r = m.group(1) + r; m.appendReplacement(sb, r); changed = true; continue; } } m.appendReplacement(sb, m.group()); } m.appendTail(sb); sb.append("\r\n"); out.print(sb.toString()); } out.flush(); out.close(); scan.close(); return changed; } private static String toHexString(int value) { String h = Integer.toHexString(value).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } private static final Pattern remappingParam = Pattern.compile(":([0-9]*)-([0-9]*)$"); private static boolean readRemapping(Map map, String path) throws IOException { Matcher m = remappingParam.matcher(path); if (m.find()) { File file = new File(path.substring(0, m.start())); Integer from = parseInt(m.group(1)); Integer to = parseInt(m.group(2)); if (from == null && to == null) { return readRemapping(map, file, 1, 0); } else { int fromInt = (from == null) ? 0 : from.intValue(); int toInt = (to == null) ? 0 : to.intValue(); return readRemapping(map, file, fromInt, toInt); } } else { File file = new File(path); return readRemapping(map, file, 0, 1); } } private static boolean readRemapping(Map map, File file, int from, int to) throws IOException { boolean changed = false; Scanner scan = new Scanner(new FileInputStream(file), "UTF-8"); while (scan.hasNextLine()) { String line = scan.nextLine().trim(); int o = line.indexOf("#"); if (o >= 0) line = line.substring(0, o).trim(); String[] fields = line.split("\\s+"); if (fields.length > from && fields.length > to) { Integer fcp = parseInt16(fields[from]); Integer tcp = parseInt16(fields[to]); if (fcp != null && tcp != null) { map.put(fcp, tcp); changed = true; } } } scan.close(); return changed; } private static Integer parseInt(String s) { if (s == null || s.length() == 0) return null; try { return Integer.parseInt(s, 10); } catch (NumberFormatException nfe) { return null; } } private static Integer parseInt16(String s) { if (s == null || s.length() == 0) return null; if ( s.startsWith("0X") || s.startsWith("0x") || s.startsWith("U+") || s.startsWith("u+") ) { s = s.substring(2); } try { return Integer.parseInt(s, 16); } catch (NumberFormatException nfe) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/RewriteTest.java000066400000000000000000000020671506470510200300530ustar00rootroot00000000000000package com.kreative.mapedit; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Scanner; public class RewriteTest { public static void main(String[] args) throws IOException, InterruptedException { for (String arg : args) { // Read mapping File f = new File(arg); Scanner s = new Scanner(f); Mapping m = new Mapping(); m.read(s); s.close(); // Write mapping File t = File.createTempFile("com.kreative.mapedit.RewriteTest.", ".txt"); FileOutputStream o = new FileOutputStream(t); m.write(o); o.close(); // Diff System.out.println(f.getAbsolutePath()); String[] a = { "diff", "--strip-trailing-cr", f.getAbsolutePath(), t.getAbsolutePath() }; Process p = Runtime.getRuntime().exec(a); InputStream i = p.getInputStream(); byte[] b = new byte[65536]; for (int r; (r = i.read(b)) > 0; System.out.write(b, 0, r)); i.close(); p.waitFor(); t.delete(); System.out.println(); System.out.println(); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/SaveChangesDialog.java000066400000000000000000000054001506470510200310730ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; public class SaveChangesDialog extends JDialog { private static final long serialVersionUID = 1L; public static enum Action { SAVE, CANCEL, DONT_SAVE } private JLabel label; private JButton dontSaveButton; private JButton cancelButton; private JButton saveButton; private Action action; public SaveChangesDialog(Dialog parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Frame parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } public SaveChangesDialog(Window parent, String name) { super(parent, "Save Changes"); setModal(true); make(name); } private void make(String name) { label = new JLabel("Save changes to \u201C" + name + "\u201D before closing?"); dontSaveButton = new JButton("Don\u2019t Save"); cancelButton = new JButton("Cancel"); saveButton = new JButton("Save"); JPanel leftButtonPanel = new JPanel(new FlowLayout()); leftButtonPanel.add(dontSaveButton); JPanel rightButtonPanel = new JPanel(new FlowLayout()); rightButtonPanel.add(cancelButton); rightButtonPanel.add(saveButton); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.add(leftButtonPanel, BorderLayout.WEST); buttonPanel.add(rightButtonPanel, BorderLayout.EAST); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(label, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(mainPanel); SwingUtils.setDontSaveButton(getRootPane(), dontSaveButton); SwingUtils.setCancelButton(getRootPane(), cancelButton); SwingUtils.setDefaultButton(getRootPane(), saveButton); setResizable(false); pack(); setLocationRelativeTo(null); saveButton.requestFocusInWindow(); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.SAVE; dispose(); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.CANCEL; dispose(); } }); dontSaveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { action = Action.DONT_SAVE; dispose(); } }); } public Action showDialog() { action = Action.CANCEL; setVisible(true); return action; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/SwingUtils.java000066400000000000000000000024211506470510200276740ustar00rootroot00000000000000package com.kreative.mapedit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JRootPane; import javax.swing.KeyStroke; public class SwingUtils { public static void setDefaultButton(final JRootPane rp, final JButton b) { rp.setDefaultButton(b); } public static void setCancelButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); rp.getActionMap().put("cancel", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } public static void setDontSaveButton(final JRootPane rp, final JButton b) { rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "dontSave"); rp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, rp.getToolkit().getMenuShortcutKeyMask()), "dontSave"); rp.getActionMap().put("dontSave", new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent ev) { b.doClick(); } }); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/mac/000077500000000000000000000000001506470510200254625ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/mac/MacDummyWindow.java000066400000000000000000000017161506470510200312360ustar00rootroot00000000000000package com.kreative.mapedit.mac; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import com.kreative.mapedit.MapEditMenuBar; public class MacDummyWindow extends JFrame { public static final long serialVersionUID = 1L; public MacDummyWindow() { JMenu fileMenu = new JMenu("File"); fileMenu.add(new MapEditMenuBar.NewMappingMenuItem()); fileMenu.add(new MapEditMenuBar.NewMappingFromEncodingMenuItem()); fileMenu.add(new MapEditMenuBar.OpenMappingMenuItem()); JMenu editMenu = new JMenu("Edit"); editMenu.add(new MapEditMenuBar.FontMapMenuItem()); JMenuBar mb = new JMenuBar(); mb.add(fileMenu); mb.add(editMenu); setJMenuBar(mb); setUndecorated(true); setResizable(false); setMinimumSize(new Dimension(0,0)); setPreferredSize(new Dimension(0,0)); setMaximumSize(new Dimension(0,0)); setSize(new Dimension(0,0)); setLocation(-1000000, -1000000); setVisible(true); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/mapedit/mac/MyApplicationListener.java000066400000000000000000000050611506470510200326060ustar00rootroot00000000000000package com.kreative.mapedit.mac; import java.awt.Window; import java.awt.desktop.OpenFilesEvent; import java.awt.desktop.OpenFilesHandler; import java.awt.desktop.PrintFilesEvent; import java.awt.desktop.PrintFilesHandler; import java.awt.desktop.QuitEvent; import java.awt.desktop.QuitHandler; import java.awt.desktop.QuitResponse; import java.awt.event.WindowEvent; import java.io.File; import java.lang.reflect.Method; import com.kreative.mapedit.Main; public class MyApplicationListener { private static final String[][] classAndMethodNames = { { "java.awt.Desktop", "getDesktop" }, { "com.kreative.ual.eawt.NewApplicationAdapter", "getInstance" }, { "com.kreative.ual.eawt.OldApplicationAdapter", "getInstance" }, }; public MyApplicationListener() { for (String[] classAndMethodName : classAndMethodNames) { try { Class cls = Class.forName(classAndMethodName[0]); Method getInstance = cls.getMethod(classAndMethodName[1]); Object instance = getInstance.invoke(null); cls.getMethod("setOpenFileHandler", OpenFilesHandler.class).invoke(instance, open); cls.getMethod("setPrintFileHandler", PrintFilesHandler.class).invoke(instance, print); cls.getMethod("setQuitHandler", QuitHandler.class).invoke(instance, quit); System.out.println("Registered app event handlers through " + classAndMethodName[0]); return; } catch (Exception e) { System.out.println("Failed to register app event handlers through " + classAndMethodName[0] + ": " + e); } } } private final OpenFilesHandler open = new OpenFilesHandler() { @Override public void openFiles(final OpenFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openMapping((File)o); } } }.start(); } }; private final PrintFilesHandler print = new PrintFilesHandler() { @Override public void printFiles(final PrintFilesEvent e) { new Thread() { public void run() { for (Object o : e.getFiles()) { Main.openMapping((File)o); } } }.start(); } }; private final QuitHandler quit = new QuitHandler() { @Override public void handleQuitRequestWith(final QuitEvent e, final QuitResponse r) { new Thread() { public void run() { System.gc(); for (Window window : Window.getWindows()) { if (window.isVisible()) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); if (window.isVisible()) { r.cancelQuit(); return; } } } r.performQuit(); System.exit(0); } }.start(); } }; } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/000077500000000000000000000000001506470510200247255ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/000077500000000000000000000000001506470510200256365ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/Block.java000066400000000000000000000035651506470510200275440ustar00rootroot00000000000000package com.kreative.unicode.data; import java.util.AbstractList; public class Block extends AbstractList implements Comparable { public final int firstCodePoint; public final int lastCodePoint; public final String name; public Block(int first, int last, String name) { this.firstCodePoint = first; this.lastCodePoint = last; this.name = name; } public int size() { return lastCodePoint - firstCodePoint + 1; } public Integer get(int index) { return firstCodePoint + index; } public boolean contains(Object o) { if (o instanceof Integer) { int cp = (Integer)o; return cp >= firstCodePoint && cp <= lastCodePoint; } else { return false; } } public int indexOf(Object o) { if (o instanceof Integer) { int cp = (Integer)o; if (cp >= firstCodePoint && cp <= lastCodePoint) { return cp - firstCodePoint; } } return -1; } public int lastIndexOf(Object o) { if (o instanceof Integer) { int cp = (Integer)o; if (cp >= firstCodePoint && cp <= lastCodePoint) { return cp - firstCodePoint; } } return -1; } public int compareTo(Block that) { if (this.firstCodePoint != that.firstCodePoint) { return this.firstCodePoint - that.firstCodePoint; } else if (that.lastCodePoint != this.lastCodePoint) { return that.lastCodePoint - this.lastCodePoint; } else { return UnicodeUtils.naturalCompare(this.name, that.name); } } public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof Block) { Block that = (Block)o; return ( this.firstCodePoint == that.firstCodePoint && this.lastCodePoint == that.lastCodePoint && this.name.equals(that.name) ); } else { return false; } } public int hashCode() { return firstCodePoint + lastCodePoint + name.hashCode(); } public String toString() { return name; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/BlockList.java000066400000000000000000000100511506470510200303640ustar00rootroot00000000000000package com.kreative.unicode.data; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.AbstractList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Scanner; import java.util.TreeSet; import com.kreative.unicode.ttflib.PuaaEntry; import com.kreative.unicode.ttflib.PuaaTable; public class BlockList extends AbstractList { private static BlockList instance = null; public static BlockList instance() { if (instance == null) instance = new BlockList(); return instance; } private final List blocks; private BlockList() { TreeSet blocks = new TreeSet(); readTextStream(BlockList.class.getResourceAsStream("roadmap.txt"), blocks); readPuaaTable(PuaaCache.getPuaaTable("unidata.ucd"), blocks); String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); for (String fontName : fontNames) { Font font = new Font(fontName, 0, 12); PuaaTable puaa = PuaaCache.getPuaaTable(font); if (puaa != null) readPuaaTable(puaa, blocks); } readDirectory(UnicodeUtils.getTableDirectory("Blocks"), blocks); this.blocks = Arrays.asList(blocks.toArray(new Block[blocks.size()])); } private static void readDirectory(File d, Collection blocks) { for (File f : d.listFiles()) { if (f.getName().startsWith(".") || f.getName().endsWith("\r")) { continue; } else if (f.isDirectory()) { readDirectory(f, blocks); } else { String n = f.getName().toLowerCase(); if (n.endsWith(".ucd") || n.endsWith(".ttf") || n.endsWith(".otf")) { readPuaaTable(PuaaCache.getPuaaTable(f), blocks); } else if (n.endsWith(".txt")) { try { readTextStream(new FileInputStream(f), blocks); } catch (IOException e) { e.printStackTrace(); } } } } } private static void readTextStream(InputStream in, Collection blocks) { Scanner scan = new Scanner(in); while (scan.hasNextLine()) { String line = scan.nextLine().trim(); if (line.length() > 0 && line.charAt(0) != '#') { String[] f1 = line.split(";"); if (f1.length == 2) { String blockName = f1[1].trim(); String[] f2 = f1[0].split("[.]+"); if (f2.length == 2) { try { int first = Integer.parseInt(f2[0], 16); int last = Integer.parseInt(f2[1], 16); blocks.add(new Block(first, last, blockName)); } catch (NumberFormatException e) { continue; } } } } } scan.close(); } private static void readPuaaTable(PuaaTable puaaTable, Collection blocks) { if (puaaTable != null) { List puaaEntries = puaaTable.getPropertyEntries("Block"); if (puaaEntries != null && puaaEntries.size() > 0) { for (PuaaEntry puaaEntry : puaaEntries) { int fcp = puaaEntry.getFirstCodePoint(); int lcp = puaaEntry.getLastCodePoint(); String name = puaaEntry.getPropertyString(fcp); blocks.add(new Block(fcp, lcp, name)); } } } } public boolean contains(Object o) { return blocks.contains(o); } public boolean containsAll(Collection c) { return blocks.containsAll(c); } public Block get(int index) { return blocks.get(index); } public int indexOf(Object o) { return blocks.indexOf(o); } public boolean isEmpty() { return blocks.isEmpty(); } public Iterator iterator() { return blocks.iterator(); } public int lastIndexOf(Object o) { return blocks.lastIndexOf(o); } public ListIterator listIterator() { return blocks.listIterator(); } public ListIterator listIterator(int index) { return blocks.listIterator(index); } public int size() { return blocks.size(); } public List subList(int fromIndex, int toIndex) { return blocks.subList(fromIndex, toIndex); } public Object[] toArray() { return blocks.toArray(); } public T[] toArray(T[] a) { return blocks.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/Encoding.java000066400000000000000000000125421506470510200302330ustar00rootroot00000000000000package com.kreative.unicode.data; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Scanner; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Encoding extends EncodingTable implements Comparable { private String name; private Set aliases; public Encoding(String name, InputStream in) { this.name = name; this.aliases = Collections.emptySet(); read(new Scanner(in)); } public Encoding(String name, Scanner in) { this.name = name; this.aliases = Collections.emptySet(); read(in); } public Encoding(Charset cs) { this.name = cs.displayName(); this.aliases = cs.aliases(); decode(cs); } public String getName() { return name; } public Set getAliases() { return aliases; } public int compareTo(Encoding that) { return UnicodeUtils.naturalCompare(this.name, that.name); } public boolean isMultiByte() { for (int i = 0; i < 256; i++) { if (submaps[i] != null) { return true; } } return false; } public GlyphList toGlyphList() { boolean foundOne = false; int[] codePoints = new int[256]; for (int i = 0; i < 256; i++) { if (seqs[i] != null && seqs[i].codePointCount(0, seqs[i].length()) == 1) { foundOne = true; codePoints[i] = seqs[i].codePointAt(0); } else { codePoints[i] = -1; } } return foundOne ? new GlyphList(codePoints, name, aliases) : null; } private static final Pattern FUZZY_NAME = Pattern.compile( "(map\\s+from\\s+)?(.+?)(\\s+character\\s+set)?(\\s+to\\s+unicode)?(\\s+table)?", Pattern.CASE_INSENSITIVE ); private void read(Scanner in) { while (in.hasNextLine()) { String line = in.nextLine().trim(); if (line.length() > 0) { String[] parts = line.split("#", 2); line = parts[0].trim(); if (line.length() > 0) { parts = line.split("\\s+"); if (parts.length > 1) { try { byte[] key = parseBytes(parts[0]); String value = parseChars(parts[1]); setSequence(value, key); } catch (NumberFormatException nfe) { continue; } } } else if (parts.length > 1) { line = parts[1].trim(); if (line.startsWith("Name:")) { String name = line.substring(5).trim(); if (name.length() > 0) { Matcher m = FUZZY_NAME.matcher(name); String n2 = m.matches() ? m.group(2).trim() : name; this.name = (n2.length() > 0) ? n2 : name; } } else if (line.startsWith("Aliases:")) { String aliases = line.substring(8).trim(); if (aliases.length() > 0) { List al = Arrays.asList(aliases.split("\\s*[,;]\\s*")); this.aliases = Collections.unmodifiableSet(new HashSet(al)); } } else if (line.startsWith("Include:")) { String includes = line.substring(8).trim(); if (includes.length() > 0) { List il = Arrays.asList(includes.split("\\s*[,;]\\s*")); for (EncodingInclude inc : EncodingInclude.values()) { if (il.contains(inc.name())) inc.includeIn(this); } } } } } } } private void decode(Charset cs) { CharsetDecoder decoder = cs.newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE); decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); decoder.replaceWith("\uFFFF"); decode(decoder, new byte[256], 0, new char[256]); } private void decode(CharsetDecoder decoder, byte[] in, int pos, char[] out) { for (int ch = 0; ch < 256; ch++) { in[pos] = (byte)ch; ByteBuffer inb = ByteBuffer.wrap(in, 0, pos + 1); CharBuffer outb = CharBuffer.wrap(out); try { decoder.reset(); decoder.decode(inb, outb, false); // Do NOT finish the decode so we can distinguish // incomplete input from invalid input. } catch (Exception e) { System.err.println("Failed to decode encoding " + name + "; it should be added to the list of broken charsets."); e.printStackTrace(); continue; } if (outb.position() > 0) { String s = new String(out, 0, outb.position()); if (s.contains("\uFFFF")) continue; setSequence(s, in, 0, pos + 1); } else if (pos + 1 < in.length) { decode(decoder, in, pos + 1, out); } else { System.err.println("Failed to decode encoding " + name + "; it should be added to the list of broken charsets."); } } } private static byte[] parseBytes(String s) { ByteArrayOutputStream os = new ByteArrayOutputStream(); String[] parts = s.split("[+,]"); for (String part : parts) { part = part.toUpperCase(); if (part.startsWith("0X")) part = part.substring(2); if ((part.length() & 1) == 1) part = "0" + part; for (int i = 0, n = part.length(); i < n; i += 2) { String h = part.substring(i, i + 2); os.write(Integer.parseInt(h, 16)); } } return os.toByteArray(); } private static String parseChars(String s) { StringBuffer sb = new StringBuffer(); String[] parts = s.split("[+,]"); for (String part : parts) { part = part.toUpperCase(); if (part.startsWith("0X")) part = part.substring(2); sb.append(Character.toChars(Integer.parseInt(part, 16))); } return sb.toString(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/EncodingInclude.java000066400000000000000000000015441506470510200315370ustar00rootroot00000000000000package com.kreative.unicode.data; public enum EncodingInclude { C0 { @Override public void includeIn(Encoding e) { for (char i = 0x00; i < 0x20; i++) { e.setSequence(Character.toString(i), i); } } }, ASCII { @Override public void includeIn(Encoding e) { for (char i = 0x20; i < 0x7F; i++) { e.setSequence(Character.toString(i), i); } } }, DEL { @Override public void includeIn(Encoding e) { e.setSequence(Character.toString((char)0x7F), 0x7F); } }, C1 { @Override public void includeIn(Encoding e) { for (char i = 0x80; i < 0xA0; i++) { e.setSequence(Character.toString(i), i); } } }, Latin1 { @Override public void includeIn(Encoding e) { for (char i = 0xA0; i < 0x100; i++) { e.setSequence(Character.toString(i), i); } } }; public abstract void includeIn(Encoding e); } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/EncodingList.java000066400000000000000000000142541506470510200310710ustar00rootroot00000000000000package com.kreative.unicode.data; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.kreative.unicode.mappings.BOM; public class EncodingList { private static EncodingList instance = null; public static EncodingList instance() { if (instance == null) instance = new EncodingList(); return instance; } private final List encodings; private final Map encodingMap; private final List glyphLists; private final Map glyphListMap; private EncodingList() { List encodings = new ArrayList(); Map encodingMap = new HashMap(); List glyphLists = new ArrayList(); Map glyphListMap = new HashMap(); for (Charset cs : Charset.availableCharsets().values()) { // Charsets known to not play well with the table generator. // Some take a long time to decode and some just break entirely. String name = cs.displayName().toUpperCase(); if (name.equals("CESU-8")) continue; // no astral chars if (name.equals("GB18030")) continue; // slow if (name.startsWith("ISO-2022-")) continue; // broken if (name.startsWith("UTF-")) continue; // 16 slow, 32 broken if (name.equals("X-COMPOUND_TEXT")) continue; // so broken it just flat out crashes if (name.startsWith("X-EUC")) continue; // slow if (name.startsWith("X-IBM93")) continue; // broken if (name.equals("X-IBM964")) continue; // slow if (name.equals("X-IBM1364")) continue; // broken if (name.startsWith("X-ISO-2022-")) continue; // broken if (name.equals("X-JISAUTODETECT")) continue; // broken if (name.startsWith("X-UTF-")) continue; // broken if (name.startsWith("X-WINDOWS-5022")) continue; // broken if (name.startsWith("X-WINDOWS-ISO2022")) continue; // broken add(new Encoding(cs), encodings, encodingMap, glyphLists, glyphListMap, false); } for (String filename : BOM.getResourceNames()) { String name = UnicodeUtils.stripExtension(filename); InputStream res = BOM.getResource(filename); if (res == null) continue; Encoding enc = new Encoding(name, res); add(enc, encodings, encodingMap, glyphLists, glyphListMap, true); } readDirectory( UnicodeUtils.getTableDirectory("Mappings"), encodings, encodingMap, glyphLists, glyphListMap, false ); Collections.sort(encodings); Collections.sort(glyphLists); this.encodings = Collections.unmodifiableList(encodings); this.encodingMap = Collections.unmodifiableMap(encodingMap); this.glyphLists = Collections.unmodifiableList(glyphLists); this.glyphListMap = Collections.unmodifiableMap(glyphListMap); } private static void add( Encoding enc, List encodings, Map encodingMap, List glyphLists, Map glyphListMap, boolean ignoreDupes ) { // Ignore null. if (enc == null) return; // If ignoreDupes and the encoding is already in the list, ignore it. String normalizedName = enc.getName().replaceAll("[^A-Za-z0-9]", "").toLowerCase(); if (ignoreDupes && encodingMap.containsKey(normalizedName)) return; // Create list of normalized names. Set names = new HashSet(); names.add(normalizedName); for (String alias : enc.getAliases()) { names.add(alias.replaceAll("[^A-Za-z0-9]", "").toLowerCase()); } // Add encoding. encodings.add(enc); for (String n : names) encodingMap.put(n, enc); // Don't create glyph lists for multibyte encodings. if (enc.isMultiByte()) return; // Create glyph list from encoding. GlyphList gl = enc.toGlyphList(); // Add glyph list. glyphLists.add(gl); for (String n : names) glyphListMap.put(n, gl); } private static void readDirectory( File d, List encodings, Map encodingMap, List glyphLists, Map glyphListMap, boolean ignoreDupes ) { for (File f : d.listFiles()) { if (f.getName().startsWith(".") || f.getName().endsWith("\r")) { continue; } else if (f.isDirectory()) { readDirectory(f, encodings, encodingMap, glyphLists, glyphListMap, ignoreDupes); } else try { String encName = UnicodeUtils.stripExtension(f.getName()); Encoding enc = new Encoding(encName, new FileInputStream(f)); add(enc, encodings, encodingMap, glyphLists, glyphListMap, ignoreDupes); } catch (IOException ioe) { ioe.printStackTrace(); } } } public List encodings() { return encodings; } public List glyphLists() { return glyphLists; } public boolean containsEncoding(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return encodingMap.containsKey(nn); } public boolean containsGlyphList(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn); } public Encoding getEncoding(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return encodingMap.get(nn); } public GlyphList getGlyphList(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.get(nn); } public int indexOfEncoding(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return encodingMap.containsKey(nn) ? encodings.indexOf(encodingMap.get(nn)) : -1; } public int indexOfGlyphList(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn) ? glyphLists.indexOf(glyphListMap.get(nn)) : -1; } public int lastIndexOfEncoding(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return encodingMap.containsKey(nn) ? encodings.lastIndexOf(encodingMap.get(nn)) : -1; } public int lastIndexOfGlyphList(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn) ? glyphLists.lastIndexOf(glyphListMap.get(nn)) : -1; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/EncodingTable.java000066400000000000000000000060501506470510200312000ustar00rootroot00000000000000package com.kreative.unicode.data; public class EncodingTable { protected final String[] seqs = new String[256]; protected final EncodingTable[] submaps = new EncodingTable[256]; public String getSequence(byte... i) { return getSequence(i, 0, i.length); } public String getSequence(int... i) { return getSequence(i, 0, i.length); } public EncodingTable getSubtable(byte... i) { return getSubtable(i, 0, i.length); } public EncodingTable getSubtable(int... i) { return getSubtable(i, 0, i.length); } public void setSequence(String s, byte... i) { setSequence(s, i, 0, i.length); } public void setSequence(String s, int... i) { setSequence(s, i, 0, i.length); } public void setSubtable(EncodingTable m, byte... i) { setSubtable(m, i, 0, i.length); } public void setSubtable(EncodingTable m, int... i) { setSubtable(m, i, 0, i.length); } public String getSequence(byte[] i, int o, int l) { if (l <= 0) return null; if (l <= 1) return seqs[i[o] & 0xFF]; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) return null; return submap.getSequence(i, o + 1, l - 1); } public String getSequence(int[] i, int o, int l) { if (l <= 0) return null; if (l <= 1) return seqs[i[o] & 0xFF]; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) return null; return submap.getSequence(i, o + 1, l - 1); } public EncodingTable getSubtable(byte[] i, int o, int l) { if (l <= 0) return null; EncodingTable submap = submaps[i[o] & 0xFF]; if (l <= 1) return submap; if (submap == null) return null; return submap.getSubtable(i, o + 1, l - 1); } public EncodingTable getSubtable(int[] i, int o, int l) { if (l <= 0) return null; EncodingTable submap = submaps[i[o] & 0xFF]; if (l <= 1) return submap; if (submap == null) return null; return submap.getSubtable(i, o + 1, l - 1); } public String setSequence(String s, byte[] i, int o, int l) { if (l <= 0) return s; if (l <= 1) return seqs[i[o] & 0xFF] = s; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new EncodingTable(); return submap.setSequence(s, i, o + 1, l - 1); } public String setSequence(String s, int[] i, int o, int l) { if (l <= 0) return s; if (l <= 1) return seqs[i[o] & 0xFF] = s; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new EncodingTable(); return submap.setSequence(s, i, o + 1, l - 1); } public EncodingTable setSubtable(EncodingTable m, byte[] i, int o, int l) { if (l <= 0) return m; if (l <= 1) return submaps[i[o] & 0xFF] = m; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new EncodingTable(); return submap.setSubtable(m, i, o + 1, l - 1); } public EncodingTable setSubtable(EncodingTable m, int[] i, int o, int l) { if (l <= 0) return m; if (l <= 1) return submaps[i[o] & 0xFF] = m; EncodingTable submap = submaps[i[o] & 0xFF]; if (submap == null) submap = submaps[i[o] & 0xFF] = new EncodingTable(); return submap.setSubtable(m, i, o + 1, l - 1); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/GlyphList.java000066400000000000000000000026721506470510200304270ustar00rootroot00000000000000package com.kreative.unicode.data; import java.util.AbstractList; import java.util.Arrays; import java.util.Collections; import java.util.Set; public class GlyphList extends AbstractList implements Comparable { private final int[] codePoints; private final String name; private final Set aliases; public GlyphList(int[] codePoints, String name) { this.codePoints = codePoints; this.name = name; this.aliases = Collections.emptySet(); } public GlyphList(int[] codePoints, String name, Set aliases) { this.codePoints = codePoints; this.name = name; this.aliases = aliases; } public int size() { return codePoints.length; } public Integer get(int index) { return codePoints[index]; } public String getName() { return name; } public Set getAliases() { return aliases; } public int compareTo(GlyphList that) { return UnicodeUtils.naturalCompare(this.name, that.name); } public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o instanceof GlyphList) { GlyphList that = (GlyphList)o; return ( Arrays.equals(this.codePoints, that.codePoints) && this.name.equals(that.name) && this.aliases.equals(that.aliases) ); } else { return false; } } public int hashCode() { return Arrays.hashCode(codePoints) + name.hashCode() + aliases.hashCode(); } public String toString() { return name; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/GlyphLists.java000066400000000000000000000126671506470510200306170ustar00rootroot00000000000000package com.kreative.unicode.data; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.AbstractList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Scanner; import java.util.SortedSet; import java.util.TreeSet; public class GlyphLists extends AbstractList { private static GlyphLists instance = null; public static GlyphLists instance() { if (instance == null) instance = new GlyphLists(); return instance; } private final List glyphLists; private final Map glyphListMap; private GlyphLists() { TreeSet glyphLists = new TreeSet(); Map glyphListMap = new HashMap(); add(readBinaryStream(GlyphLists.class.getResourceAsStream("wgl4.pchgl")), glyphLists, glyphListMap); add(readBinaryStream(GlyphLists.class.getResourceAsStream("kgl1.pchgl")), glyphLists, glyphListMap); readDirectory(UnicodeUtils.getTableDirectory("GlyphLists"), glyphLists, glyphListMap); this.glyphLists = Arrays.asList(glyphLists.toArray(new GlyphList[glyphLists.size()])); this.glyphListMap = Collections.unmodifiableMap(glyphListMap); } private static void add(GlyphList gl, Collection glyphLists, Map glyphListMap) { if (gl != null) { String nn = gl.getName().replaceAll("[^A-Za-z0-9]", "").toLowerCase(); glyphLists.add(gl); glyphListMap.put(nn, gl); } } private static void readDirectory(File d, Collection glyphLists, Map glyphListMap) { for (File f : d.listFiles()) { if (f.getName().startsWith(".") || f.getName().endsWith("\r")) { continue; } else if (f.isDirectory()) { readDirectory(f, glyphLists, glyphListMap); } else try { String n = f.getName().toLowerCase(); if (n.endsWith(".pchgl")) { FileInputStream in = new FileInputStream(f); add(readBinaryStream(in), glyphLists, glyphListMap); in.close(); } else if (n.endsWith(".txt")) { FileInputStream in = new FileInputStream(f); String name = UnicodeUtils.stripExtension(f.getName()); add(readTextStream(in, name), glyphLists, glyphListMap); in.close(); } } catch (IOException ioe) { ioe.printStackTrace(); } } } private static GlyphList readTextStream(InputStream in, String glName) { SortedSet codePoints = new TreeSet(); Scanner scan = new Scanner(in); while (scan.hasNextLine()) { String line = scan.nextLine().trim(); if (line.length() > 0 && line.charAt(0) != '#') { String[] f = line.split("\\s+"); String cps = f[0].trim().toLowerCase(); if (cps.startsWith("0x")) { try { int cp = Integer.parseInt(cps.substring(2), 16); codePoints.add(cp); } catch (NumberFormatException e) { continue; } } } } scan.close(); if (codePoints.isEmpty()) return null; int[] cpa = new int[codePoints.size()]; int i = 0; for (int cp : codePoints) cpa[i++] = cp; return new GlyphList(cpa, glName); } private static GlyphList readBinaryStream(InputStream in) { if (in == null) { return null; } else try { DataInputStream din = new DataInputStream(in); String name = din.readUTF(); int[] codePoints = new int[din.readUnsignedShort()]; for (int i = 0; i < codePoints.length; i++) { int cp = din.readUnsignedShort(); if (cp < 0x20) { cp <<= 16; cp |= din.readUnsignedShort(); } codePoints[i] = cp; } return new GlyphList(codePoints, name); } catch (Exception e) { e.printStackTrace(); return null; } } public boolean contains(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn); } public boolean contains(Object o) { return glyphLists.contains(o); } public boolean containsAll(Collection c) { return glyphLists.containsAll(c); } public GlyphList get(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.get(nn); } public GlyphList get(int index) { return glyphLists.get(index); } public int indexOf(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn) ? glyphLists.indexOf(glyphListMap.get(nn)) : -1; } public int indexOf(Object o) { return glyphLists.indexOf(o); } public boolean isEmpty() { return glyphLists.isEmpty(); } public Iterator iterator() { return glyphLists.iterator(); } public int lastIndexOf(String name) { String nn = name.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); return glyphListMap.containsKey(nn) ? glyphLists.lastIndexOf(glyphListMap.get(nn)) : -1; } public int lastIndexOf(Object o) { return glyphLists.lastIndexOf(o); } public ListIterator listIterator() { return glyphLists.listIterator(); } public ListIterator listIterator(int index) { return glyphLists.listIterator(index); } public int size() { return glyphLists.size(); } public List subList(int fromIndex, int toIndex) { return glyphLists.subList(fromIndex, toIndex); } public Object[] toArray() { return glyphLists.toArray(); } public T[] toArray(T[] a) { return glyphLists.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/NameDatabase.java000066400000000000000000000251171506470510200310140ustar00rootroot00000000000000package com.kreative.unicode.data; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.kreative.unicode.ttflib.PuaaEntry; import com.kreative.unicode.ttflib.PuaaTable; public class NameDatabase { private static NameDatabase instance = null; public static NameDatabase instance() { if (instance == null) instance = new NameDatabase(); return instance; } private static class NameKey { private final int codePoint; private final String category; private final String name; private NameKey(int codePoint, String category, String name) { this.codePoint = codePoint; this.category = category; this.name = name; } @Override public boolean equals(Object o) { if (o instanceof NameKey) { NameKey that = (NameKey)o; return ( this.codePoint == that.codePoint && this.category.equals(that.category) && this.name.equals(that.name) ); } return false; } @Override public int hashCode() { return this.codePoint ^ this.category.hashCode() ^ this.name.hashCode(); } } private static class NameValue { private final Set aliases; private final Set fonts; private NameValue() { this.aliases = new HashSet(); this.fonts = new HashSet(); } } public static class NameEntry implements Comparable { public final int codePoint; public final String category; public final String name; public final Set aliases; public final Set fonts; public final double searchDistance; private NameEntry(NameKey key, NameValue value, double searchDistance) { this.codePoint = key.codePoint; this.category = key.category; this.name = key.name; this.aliases = Collections.unmodifiableSet(value.aliases); this.fonts = Collections.unmodifiableSet(value.fonts); this.searchDistance = searchDistance; } public boolean isPUA() { return (codePoint >= 0xE000 && codePoint < 0xF900) || codePoint >= 0xF0000; } public String shortestFontName() { String shortest = null; for (String font : fonts) { if (shortest == null || font.length() < shortest.length()) { shortest = font; } } return shortest; } @Override public int compareTo(NameEntry that) { if (this.isPUA() && !that.isPUA()) return +1; if (!this.isPUA() && that.isPUA()) return -1; if (this.searchDistance < that.searchDistance) return -1; if (this.searchDistance > that.searchDistance) return +1; if (this.codePoint < that.codePoint) return -1; if (this.codePoint > that.codePoint) return +1; return 0; } } private final NameResolver resolver; private final Map names; private final LoaderThread thread; private NameDatabase() { this.resolver = NameResolver.instance(); this.names = new HashMap(); this.thread = new LoaderThread(); this.thread.start(); } private synchronized NameValue getOrAdd(int codePoint, String category, String name) { NameKey key = new NameKey(codePoint, category, name); NameValue value = names.get(key); if (value == null) { value = new NameValue(); names.put(key, value); } return value; } private synchronized void loadPuaaTable(PuaaTable puaa, String font) { Map puaaNameMap = puaa.getPropertyMap("Name"); if (puaaNameMap == null || puaaNameMap.isEmpty()) return; Map puaaCategoryMap = puaa.getPropertyMap("General_Category"); if (puaaCategoryMap == null) puaaCategoryMap = new HashMap(); Map puaaUni1NameMap = puaa.getPropertyMap("Unicode_1_Name"); if (puaaUni1NameMap == null) puaaUni1NameMap = new HashMap(); List puaaNameAliases = puaa.getPropertyEntries("Name_Alias"); if (puaaNameAliases == null) puaaNameAliases = new ArrayList(); for (int codePoint : puaaNameMap.keySet()) { String name = puaaNameMap.get(codePoint); if (name.startsWith("<") && name.endsWith(">")) { if (name.equals("")) { name = puaaUni1NameMap.get(codePoint); if (name == null) { name = Integer.toHexString(codePoint).toUpperCase(); if (name.length() < 4) name = ("0000" + name).substring(name.length()); name = "CONTROL-" + name; } } else { continue; } } String category = puaaCategoryMap.get(codePoint); if (category == null) category = "Cn"; NameValue value = getOrAdd(codePoint, category, name); if (font != null) value.fonts.add(font); value.aliases.add(name); String uni1Name = puaaUni1NameMap.get(codePoint); if (uni1Name != null) value.aliases.add(uni1Name); for (PuaaEntry e : puaaNameAliases) { if (e.contains(codePoint)) { Object o = e.getPropertyValue(codePoint); if (o instanceof PuaaEntry.NameAlias) { PuaaEntry.NameAlias a = (PuaaEntry.NameAlias)o; value.aliases.add(a.alias); } } } } } private synchronized void loadPropertyMap(Map propertyMap) { if (propertyMap == null || propertyMap.isEmpty()) return; for (Map.Entry e : propertyMap.entrySet()) { String c = resolver.getCategory(e.getKey()); String n = resolver.getName(e.getKey()); NameValue v = getOrAdd(e.getKey(), c, n); if (v.aliases.isEmpty()) v.aliases.add(n); v.aliases.add(e.getValue()); } } private void loadDirectory(File d) { for (File f : d.listFiles()) { if (f.getName().startsWith(".") || f.getName().endsWith("\r")) { continue; } else if (f.isDirectory()) { loadDirectory(f); } else { String n = f.getName().toLowerCase(); if (n.endsWith(".ucd") || n.endsWith(".ttf") || n.endsWith(".otf")) { PuaaTable puaa = PuaaCache.getPuaaTable(f); if (puaa != null) { String name = UnicodeUtils.stripExtension(f.getName()); loadPuaaTable(puaa, name); } } } } } private class LoaderThread extends Thread { @Override public void run() { loadPuaaTable(PuaaCache.getPuaaTable("unidata.ucd"), null); PuaaTable extras = PuaaCache.getPuaaTable("extras.ucd"); loadPropertyMap(extras.getPropertyMap("HTML_Entity")); loadPropertyMap(extras.getPropertyMap("PostScript_Name")); String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); for (String fontName : fontNames) { Font font = new Font(fontName, 0, 12); PuaaTable puaa = PuaaCache.getPuaaTable(font); if (puaa != null) loadPuaaTable(puaa, fontName); } loadDirectory(UnicodeUtils.getTableDirectory("UnicodeData")); } } private static final Pattern CP_PATTERN = Pattern.compile("^\\s*([Uu][Nn][Ii]|[Uu][+]|[Uu]|[0][Xx]|[$])?([0-9A-Fa-f]{1,6})([Hh])?\\s*$"); public synchronized NameEntry find(String name) { String[] query = querySplit(name); if (query != null) { int codePoint = -1; if (query.length == 1) { Matcher m = CP_PATTERN.matcher(query[0]); if (m.matches()) { codePoint = Integer.parseInt(m.group(2), 16); if (codePoint < 0x110000) { String c = resolver.getCategory(codePoint); String n = resolver.getName(codePoint); NameValue v = getOrAdd(codePoint, c, n); if (v.aliases.isEmpty()) v.aliases.add(n); } } } List results = new ArrayList(); for (Map.Entry e : names.entrySet()) { if (e.getKey().codePoint == codePoint) { results.add(new NameEntry(e.getKey(), e.getValue(), 0)); continue; } if (queryMatch(query, e.getKey(), e.getValue())) { double distance = searchDistance(name, e.getKey().name); for (String alias : e.getValue().aliases) { double d = searchDistance(name, alias); if (d < distance) distance = d; } results.add(new NameEntry(e.getKey(), e.getValue(), distance)); } } if (!results.isEmpty()) { Collections.sort(results); return results.get(0); } } if (name.length() > 0) { int codePoint = name.codePointAt(0); String c = resolver.getCategory(codePoint); String n = resolver.getName(codePoint); NameValue v = getOrAdd(codePoint, c, n); if (v.aliases.isEmpty()) v.aliases.add(n); return new NameEntry(new NameKey(codePoint, c, n), v, 0); } return null; } private static String[] querySplit(String query) { if (query == null) return null; query = query.trim().toUpperCase(); if (query.length() == 0) return null; String[] tokens = query.split("\\s+"); for (int i = 0; i < tokens.length; i++) { if (tokens[i].length() < 4) { tokens[i] = " " + tokens[i] + " "; } } return tokens; } private static boolean queryMatch(String[] query, String name) { name = " " + name.toUpperCase() + " "; for (String token : query) { if (!name.contains(token)) { return false; } } return true; } private static boolean queryMatch(String[] query, NameKey key, NameValue value) { if (queryMatch(query, key.name)) { return true; } for (String alias : value.aliases) { if (queryMatch(query, alias)) { return true; } } return false; } private static int phraseDistance(String s1, String s2) { if (s1.equalsIgnoreCase(s2)) return 0; int l1 = s1.length() + 1; int l2 = s2.length() + 1; int[][] d = new int[l1][l2]; for (int i = 0; i < l1; i++) d[i][0] = i; for (int j = 0; j < l2; j++) d[0][j] = j; for (int j = 1; j < l2; j++) { for (int i = 1; i < l1; i++) { int ci = d[i - 1][j] + 1; int cd = d[i][j - 1] + 1; int cs = d[i - 1][j - 1]; int c1 = s1.charAt(i - 1); int c2 = s2.charAt(j - 1); if (c1 != c2) cs++; if (ci <= cd) { if (ci <= cs) d[i][j] = ci; else d[i][j] = cs; } else { if (cd <= cs) d[i][j] = cd; else d[i][j] = cs; } } } return d[l1 - 1][l2 - 1]; } private static int wordDistance(String s1, String s2) { if (s1.equalsIgnoreCase(s2)) return 0; String[] w1 = s1.split("[^A-Za-z0-9]+"); String[] w2 = s2.split("[^A-Za-z0-9]+"); int d = 0; for (int i1 = 0; i1 < w1.length; i1++) { int d1 = s2.length(); for (int i2 = 0; i2 < w2.length; i2++) { int d2 = phraseDistance(w1[i1], w2[i2]); if (d2 < d1) d1 = d2; if (d2 == 0) break; } d += d1; } return d; } private static double searchDistance(String s1, String s2) { if (s1.equalsIgnoreCase(s2)) return 0; double pd = phraseDistance(s1, s2); pd -= 0.8 * Math.abs(s1.length() - s2.length()); double wd = wordDistance(s1, s2); return Math.min(pd, wd) * 0.8 + Math.max(pd, wd) * 0.2; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/NameResolver.java000066400000000000000000000150361506470510200311100ustar00rootroot00000000000000package com.kreative.unicode.data; import java.awt.Font; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import com.kreative.unicode.fontmap.FontMapController; import com.kreative.unicode.fontmap.FontMapEntry; import com.kreative.unicode.ttflib.PuaaTable; public class NameResolver { private static NameResolver baseInstance = null; private static Map fontInstances = null; public static NameResolver instance() { if (baseInstance == null) baseInstance = new NameResolver(); return baseInstance; } public static NameResolver instance(Font font) { if (font == null) return instance(); if (fontInstances == null) fontInstances = new HashMap(); if (fontInstances.containsKey(font)) return fontInstances.get(font); NameResolver instance = new NameResolver(instance(), font); fontInstances.put(font, instance); return instance; } public static NameResolver instance(String codePoints) { FontMapEntry e = FontMapController.getInstance().entryForString(codePoints); return (e == null) ? instance() : instance(e.getFont()); } public static NameResolver instance(int codePoint) { FontMapEntry e = FontMapController.getInstance().entryForCodePoint(codePoint); return (e == null) ? instance() : instance(e.getFont()); } private final Map baseCategoryMap; private final Map baseCombClassMap; private final SortedMap baseNameMap; private final Map baseUni1NameMap; private final Map categoryMap; private final Map combClassMap; private final Map nameMap; private final Map uni1NameMap; private NameResolver() { PuaaTable base = PuaaCache.getPuaaTable("unidata.ucd"); this.baseCategoryMap = base.getPropertyMap("General_Category"); this.baseCombClassMap = base.getPropertyMap("Canonical_Combining_Class"); this.baseNameMap = base.getPropertySortedMap("Name"); this.baseUni1NameMap = base.getPropertyMap("Unicode_1_Name"); this.categoryMap = this.baseCategoryMap; this.combClassMap = this.baseCombClassMap; this.nameMap = this.baseNameMap; this.uni1NameMap = this.baseUni1NameMap; } private NameResolver(NameResolver base, Font font) { this.baseCategoryMap = base.baseCategoryMap; this.baseCombClassMap = base.baseCombClassMap; this.baseNameMap = base.baseNameMap; this.baseUni1NameMap = base.baseUni1NameMap; PuaaTable puaa = PuaaCache.getPuaaTable(font); if (puaa == null) { this.categoryMap = this.baseCategoryMap; this.combClassMap = this.baseCombClassMap; this.nameMap = this.baseNameMap; this.uni1NameMap = this.baseUni1NameMap; } else { this.categoryMap = new HashMap(); this.combClassMap = new HashMap(); this.nameMap = new HashMap(); this.uni1NameMap = new HashMap(); if (baseCategoryMap != null) categoryMap.putAll(baseCategoryMap); if (baseCombClassMap != null) combClassMap.putAll(baseCombClassMap); if (baseNameMap != null) nameMap.putAll(baseNameMap); if (baseUni1NameMap != null) uni1NameMap.putAll(baseUni1NameMap); Map puaaCategoryMap = puaa.getPropertyMap("General_Category"); Map puaaCombClassMap = puaa.getPropertyMap("Canonical_Combining_Class"); Map puaaNameMap = puaa.getPropertyMap("Name"); Map puaaUni1NameMap = puaa.getPropertyMap("Unicode_1_Name"); if (puaaCategoryMap != null) categoryMap.putAll(puaaCategoryMap); if (puaaCombClassMap != null) combClassMap.putAll(puaaCombClassMap); if (puaaNameMap != null) nameMap.putAll(puaaNameMap); if (puaaUni1NameMap != null) uni1NameMap.putAll(puaaUni1NameMap); } } public String getCategory(int cp) { if (categoryMap == null) return null; String category = categoryMap.get(cp); if (category != null) return category; try { int prevcp = baseNameMap.headMap(cp).lastKey(); int nextcp = baseNameMap.tailMap(cp).firstKey(); String prevName = baseNameMap.get(prevcp); String nextName = baseNameMap.get(nextcp); if (isRangePair(prevName, nextName)) { String prevcat = baseCategoryMap.get(prevcp); String nextcat = baseCategoryMap.get(nextcp); if (prevcat.equals(nextcat)) return prevcat; } return "Cn"; } catch (Exception e) { return "Cn"; } } public String getCombiningClass(int cp) { if (combClassMap == null) return null; String combClass = combClassMap.get(cp); if (combClass != null) return combClass; try { int prevcp = baseNameMap.headMap(cp).lastKey(); int nextcp = baseNameMap.tailMap(cp).firstKey(); String prevName = baseNameMap.get(prevcp); String nextName = baseNameMap.get(nextcp); if (isRangePair(prevName, nextName)) { String prevccc = baseCombClassMap.get(prevcp); String nextccc = baseCombClassMap.get(nextcp); if (prevccc.equals(nextccc)) return prevccc; } return "0"; } catch (Exception e) { return "0"; } } public String getName(int cp) { if (nameMap == null) return null; String name = nameMap.get(cp); if (name != null) { if (!(name.startsWith("<") && name.endsWith(">"))) return name; if (name.equals("")) { name = uni1NameMap.get(cp); if (name != null) return name; return "CONTROL-" + toHexString(cp); } } else { try { int prevcp = baseNameMap.headMap(cp).lastKey(); int nextcp = baseNameMap.tailMap(cp).firstKey(); String prevName = baseNameMap.get(prevcp); String nextName = baseNameMap.get(nextcp); if (isRangePair(prevName, nextName)) { name = prevName; } else { return "UNDEFINED-" + toHexString(cp); } } catch (Exception e) { return "UNDEFINED-" + toHexString(cp); } } if (name.contains("CJK Ideograph")) return "CJK UNIFIED IDEOGRAPH-" + toHexString(cp); if (name.contains("Tangut Ideograph")) return "TANGUT IDEOGRAPH-" + toHexString(cp); if (name.contains("High Surrogate")) return "HIGH SURROGATE-" + toHexString(cp); if (name.contains("Private Use")) return "PRIVATE USE-" + toHexString(cp); return name.replaceAll("^<|, (Fir|La)st>$", "").toUpperCase() + "-" + toHexString(cp); } private static boolean isRangePair(String a, String b) { return ( a.startsWith("<") && a.endsWith(", First>") && b.startsWith("<") && b.endsWith(", Last>") && a.substring(0, a.length() - 6).equals(b.substring(0, b.length() - 5)) ); } private static String toHexString(int cp) { String h = Integer.toHexString(cp).toUpperCase(); if (h.length() < 4) h = ("0000" + h).substring(h.length()); return h; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/PuaaCache.java000066400000000000000000000034151506470510200303160ustar00rootroot00000000000000package com.kreative.unicode.data; import java.awt.Font; import java.awt.font.OpenType; import java.io.File; import java.util.HashMap; import java.util.Map; import com.kreative.unicode.ttflib.FindOpenType; import com.kreative.unicode.ttflib.PuaaTable; import com.kreative.unicode.ttflib.TtfFile; public class PuaaCache { private static final Map resCache = new HashMap(); private static final Map fileCache = new HashMap(); private static final Map fontCache = new HashMap(); public static synchronized PuaaTable getPuaaTable(String res) { if (resCache.containsKey(res)) return resCache.get(res); try { TtfFile ttf = new TtfFile(PuaaCache.class.getResourceAsStream(res)); PuaaTable puaa = ttf.getTableAs(PuaaTable.class, "PUAA"); resCache.put(res, puaa); return puaa; } catch (Exception e) {} resCache.put(res, null); return null; } public static synchronized PuaaTable getPuaaTable(File file) { if (fileCache.containsKey(file)) return fileCache.get(file); try { TtfFile ttf = new TtfFile(file); PuaaTable puaa = ttf.getTableAs(PuaaTable.class, "PUAA"); fileCache.put(file, puaa); return puaa; } catch (Exception e) {} fileCache.put(file, null); return null; } public static synchronized PuaaTable getPuaaTable(Font font) { if (fontCache.containsKey(font)) return fontCache.get(font); try { OpenType ot = FindOpenType.forFont(font); if (ot != null) { byte[] data = ot.getFontTable("PUAA"); if (data != null && data.length > 0) { PuaaTable puaa = new PuaaTable(data); fontCache.put(font, puaa); return puaa; } } } catch (Exception e) {} fontCache.put(font, null); return null; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/UnicodeUtils.java000066400000000000000000000047121506470510200311140ustar00rootroot00000000000000package com.kreative.unicode.data; import java.io.File; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.List; public class UnicodeUtils { public static File getTableDirectory(String subdirName) { File root; if (System.getProperty("os.name").toUpperCase().contains("MAC OS")) { File u = new File(System.getProperty("user.home")); File l = new File(u, "Library"); if (!l.exists()) l.mkdir(); File p = new File(l, "Preferences"); if (!p.exists()) p.mkdir(); root = new File(p, "com.kreative.unicode"); } else if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) { File u = new File(System.getProperty("user.home")); File a = new File(u, "Application Data"); if (!a.exists()) a.mkdir(); File k = new File(a, "Kreative"); if (!k.exists()) k.mkdir(); root = new File(k, "Unicode"); } else { File u = new File(System.getProperty("user.home")); root = new File(u, ".com.kreative.unicode"); } if (!root.exists()) root.mkdir(); File subdir = new File(root, subdirName); if (!subdir.exists()) subdir.mkdir(); return subdir; } public static String stripExtension(String fileName) { int o = fileName.lastIndexOf('.'); return (o > 0) ? fileName.substring(0, o) : fileName; } public static int naturalCompare(String a, String b) { List na = naturalTokenize(a.trim()); List nb = naturalTokenize(b.trim()); for (int i = 0; i < na.size() && i < nb.size(); i++) { try { double va = Double.parseDouble(na.get(i)); double vb = Double.parseDouble(nb.get(i)); int cmp = Double.compare(va, vb); if (cmp != 0) return cmp; } catch (NumberFormatException e) { int cmp = na.get(i).compareToIgnoreCase(nb.get(i)); if (cmp != 0) return cmp; } } return na.size() - nb.size(); } private static List naturalTokenize(String s) { List tokens = new ArrayList(); StringBuffer token = new StringBuffer(); int tokenType = 0; CharacterIterator iter = new StringCharacterIterator(s); for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter.next()) { int tt = Character.isDigit(ch) ? 1 : Character.isLetter(ch) ? 2 : 3; if (tt != tokenType) { if (token.length() > 0) { tokens.add(token.toString()); token = new StringBuffer(); } tokenType = tt; } token.append(ch); } if (token.length() > 0) tokens.add(token.toString()); return tokens; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/extras.ucd000066400000000000000000000672341506470510200276550ustar00rootroot00000000000000PUAAPUAAn--  !, ./:@ [`({}BP""$+X.MzP~445775 5M$B O Q\^_H  R  d       " % & 0 5 9 : > >: A A: C D O O: W W: _ c : !!:!!; ! !"!!L!"!";!$!$;!'!)v!,!-!/!1!3!8!E!H!S!^!!!!,!!Z!!t!!!!!!?!!!!?!"("" N" " \""f""""@""8":"W"Y"Zz"\"\B"_"b"d"""8""v""""""""n""""########&##0#"##B#-#.L#6#6H#=#=H#?#?H#|#|H##V##`##n##Ic##In$#$#Iy$$ȦoS;%%I%%I% % I%%I%%I%%I%%I%$%$I%,%,I%4%4I%<%<I%P%l%%J%%J%%J%%%%J%%%%%%K$%%%%&%%0%%>%%H%%K%%K%%R&&h&&L&@&@L&B&BL&`&`L&c&cL$&e&fr&j&jLC&m&o|''Lc''Lo' ' Lw'6'6L'X'XL'r's''''''''M1''M8))) )))M)) )#)*0)3)3NM)5)9R)<)=h)E)EN)H)Kr)N)v)x)y*){)4))J))T))Q))))))R))))))R)))) )).))S{))S))S**<**S**S* * J**T*"*'v*)***-*1*3*<*?*@*B*M*P*PU~*S*X *Z*] 0*_*_U*f*fU*j*jU*m*u B*w* h** **!**!J**!**!**YX**!**!**Y"ԜԜZԞԟ"2ԢԢZԥԦ"<ԩԬ"FԮԹ"XԻԻZԽ""" " "#9#2;>#@D#FF\JP#Rk#x ~$T%&&!&,$5'8:(=D(&GU(HXa(d(e)"),)6)@)Z)d)~e  e##e)f-)))**Z****  *  * "+  $ &+ 0 0h 2 3+( 9 :+2 < <h D Dh h +< i +F!!i !!i!!i!!i(!"!"i5!&!&i?!.!.iE!5!5iO!S!T+P![!^+Z!!+l!!i!!i!!+""j/""+"" +" " j|""j""+""j""j"" +"'"++"4"4k "<"<k"E"Ek"H"Hk&"`"a+"d"e+"","",""k""k""k""k##k##k# #!,#)#*,$%%l%%l% % l!%%l*%%l3%%l<%%lE%$%$lN%,%,lW%4%4l`%<%<li%P%l,.%%mw%%m%%m%%m%%,%%,%%,%%m%%m%%m%%m%%,%%n %%,%%n'&:&<,&@&@nI&B&Bale&`&`nP&c&club&e&f,&j&k,- -& -0-7->-D-M-V-\-c-j-q-z-----lt;-gt;-----------t.. ... .)./.8.?.E.L.S.[.a.g.m.upm;.{................// ///#/,/5/>/F/M/V/_/g/n/t/}///////////////00 000$0,050>0G0O0V0_0h0p0w0}00000000000000011 111%1-161?1G1O1V1]1f1o1x1111 11111111111122 222%2.272@2H 2P2X2`2g2p2x2222222222222223333 3)323;3C3I3O3W/3_3h3q3y3333333333333334444!4*434<4E4M4U4^4g4o4w44444444444444555!5)5/565=5E5Y5a5h5p5x555555Mu;Nu;Xi;5Pi;5555555555566666%6-6469E9M9T9\9c9j9q9z 999999999999999:: :::#:,:5:?:H:O:V:_:i:q:y:::::::ݦaf;it;ic;:: ;;;#;3;A;K;T;_;j;s ;y;;wp;;;;;;rx;;;;;;<<<<<&<-<5<<> > >2>8>>>E>L>T>e">w>>>>>>>>>?? ???!?)?1?B?J?R?Z?b?j?q?x??????????? ????@@@@"@,@9@A@I@S@Y@c@j@s@ymp;@@@@@@@@@@@@@@AA AAAA$A*A1A8APAZAbAmAxAAAAAAAAAAAAAAABB BBB#B-B8B?BGBQBXBaBiBpBBBBBBBB˦ne;BB(BBBBCCll;gg;CCC$C*C1C8C?CFCOCWlg;C_CiCpCwC~CCCCCCCCCCCCCDDDD)D2D:DEDPD]DjDrDzDDDDDD DDDDDDDDD DEEEEE!E*E3E<EE ENEVE^EoEEEEEEEEEEEEEEEFF FFF$F-F6F?FGFOFWF`FiFoFuFFFLl;FFFFFFFFFFGG GGG-G>GPGcGlGtG|GGGGGGGGGGGGGG HHHH H)H2H;HDHMHTH_HjHsH|HHHHHHHHHI III%I7IJIVIIIIIIJJ JJJ%J-J5J=JEJMJUJ]JeJmJuJ}JJJJJJJJJJJJKKK,K4K<KCKKK[KcKkKzKKKKKKKKKKL/L;LJLQL[LLLLLLLLLLLLMM MMM!M)MCMLMUM^MdMlMtM|MMMMMMMMMMMMN NNN$N-N6N=NDNUN_NfNmNwNNNNNN)NNNOOO'O8OKO`OtOOOOOOOP P!P3PGPNPUP\PcPmPwPPPPPPPPPPPPPPQQQQ#Q,Q5Q>QGQO QWQ_QgQqQ{QQQQQQQQQQQQQRRRR%R0R;RFRQR\RfRpRzRRRRRRRRRRRRRRSSSS+S>SGSRS\SeSpSSSSSSSSSSTTTT(T2T=TGTPTZTdTmTwTTTT TTTTTTTTTTUU UUU#U,U4U=UFUQU\UeUnUvUOr;UUUUUUUU UUUVV VVV V)$V1V9VCVKVSV]VgVmVsV|VVVVVVVVVVVVWWWWW&W,W2W;WDWRW_Whel;eg;WqWxWWWW WWWWWWWWWWWWXX XXXX'X4XAXIPr;Sc;XWX`XiXsX}XXXXXXXXX XXXXYYYY"Y+Y5Y?YGYQYhYqYxY YYYYYYYYYYYYYYZZZZ$Z+Z2Z9Z@ ZGZNZUZ\ZcZjZqZxZZZZZZZZZZZ ZZZZZZZ[[ [[[ [&[,[2[8[>[D[J[P[V[\[b[h[n[t[z[[[[[[[[[[[[[[[[[[[[[[\\ \\\\"\(\.\4\:\A\H\O\V\]\d\k\r\y\\\\\\\\\\\\\\\\\\]] ]]]!](]/]6]=]D]K]R]Y]`]g]n_]u]{]]]]]]]]]lus]]]]eronewo]ouriveix]]ine^^ ess^^^#t^,^8^B^O^[^f^lar^v^ ^ent^^en^^^^^^^^^__ _u__&_5h_=_J_Y_d_l_z______E_________th` ````*`1`;`D`K`R`Y`e`o`v`|``````e`````````tha aaaa*a1a;aBaIaPaWacamatazaaaaaaaaaaaaaaabb bbb b(b/b6bAbLbTb\bcbjbvbbbbbbbarbarbbbbbbbbbcJjccc&c3c:cAcHdotdotcOcVc]cdckcrcyngngccccccEecc ccccccdd ddd!d(barbard/d6d=dEdMdTd[dadgdudddddddddddddde eeee$e+e2e=eHePeXedepe{eeingeeeeeeeeff ff#f:fGfRfdetafj fpetatafxotaf~fuuifihofaufhihisiffffffffetagg getatagotagg$uig+ihog3g:aug@hihisigHgNg[gkgxggghi1gggggggggggggh hh!h0h>hKhYhfhmhwh~hhhhhhhiraonguroiUi^ihiriiiiiiiiiijjj"j9jEjQjZj`jijqjjjjjjjjjjkk2k;kGkQk^kkkzkkkkkllrl{llllllllllllllmm mmm&m/m8mAmJmSm\memnmmmmmmmmmmnnnn2n?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~7              ! " $ % & ' 0 1 9 : < = D !!! !"!&!'""""""""""+"H"`"d"e#%bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/roadmap.txt000066400000000000000000000010151506470510200300170ustar00rootroot00000000000000000000..00FFFF; Unicode (BMP) 010000..01FFFF; Unicode (SMP) 020000..02FFFF; Unicode (SIP) 030000..03FFFF; Unicode (TIP) 040000..04FFFF; Unicode (Plane 4) 050000..05FFFF; Unicode (Plane 5) 060000..06FFFF; Unicode (Plane 6) 070000..07FFFF; Unicode (Plane 7) 080000..08FFFF; Unicode (Plane 8) 090000..09FFFF; Unicode (Plane 9) 0A0000..0AFFFF; Unicode (Plane 10) 0B0000..0BFFFF; Unicode (Plane 11) 0C0000..0CFFFF; Unicode (Plane 12) 0D0000..0DFFFF; Unicode (Plane 13) 0E0000..0EFFFF; Unicode (SSP) 000000..10FFFF; Unicode (Full) bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/data/unidata.ucd000066400000000000000000025143041506470510200277710ustar00rootroot00000000000000PUAAPUAAcE 2x|2;2a2oh22~22n22333/ 3H"3a;N vN v!"N#%T&*N+-v./S09N::S;@NAZ[`Naz{~NNNvTNNNNTNvNvNNNNNNNNoSMpstuNvwz}~vNvNSM/1VYNNTSMwSMSMwNNL  T  wNSMJLK_SM`iNjjTklNmoLppSMqLSMw(SMLSMNSMLN LLSM/L0JSMMLSMLSMNSMSM#SM$$%'SM(()-SM0>@XY[SM^^`jLpLNSMLSMN SM  9 : <w2 = @ A HSM I L M MSM N P Q WSM X a b cSM d  SM        SM  SM   w@    SM  T  T  SM  SM        ( * 0 2 3 5 6 8 9 < @ A BSM G HSM K MSM Q QSM Y \ ^ ^ f o p qSM r t u vwJ SM        SM  SM SM   SM   SM  T  SM  SM        ( * 0 2 3 5 9 <  ? @wT A DSM G H K L M MSM U VSM W W \ ] _ a b cSM f w w^           SM    SM    N wh SM    SM      ( * 9 < =wr > @SM A D F HSM J MSM U VSM X Z \ ] ` a b cSM f o w w x ~N   SM      SM    SM    SM   SM      : ; GIlq~SMSMSMSMSMSM,-0SM1127SM889:SM;<=>SM?WXYSMZ]^`SMapqtSMuSMSMSMSMHJMPVXXZ]`Z]_SM`|NNSNSM123SM46@QRSSM`lnprsSMSMSMSMSMwN N  SMw xSMw "SM#&'(SM)+0122SM389;SM@@NDENFmptNSMSMUVWwX^SM`bwcdelSMmrs|SMSMSMSMSM345w6:SM;<w=ABBSMCLNjksSMtSMSMSMSMwSMwSM+,3SM4567SM;IMSMSMSMSMSMSMSM EHMPWYY[[]]_}wNNNNN S N  w  'N ( /x 0 4T 5 CN D DS E ^N _ _S ` dN f ix* j oN p qx< t yN z {S | ~N   N S N  T SM!!N!!!!N!!!! N! !!!xF!!N!!!!#N!$!)xP!*!-!.!.T!/!9!:!;N!>@ACDFOPLN=L>ONPLNLNLNSMN /SM0ONPRxTUxV^N__T`aNbcSdfNhhNijTkkNptLvLNNT N xSNS N!:;@NAZ[eNfTNTNN  &(:<=?MP]x37?@NNNSMSMN#-JPuvzSM'0coz|6@U`g 578<<?UW   N 9 ? Y     SM  SM SM      5 8 :SM ? ?SM @ H P X `   SM  5 9 ?N @ U X r x    H    #L $ 'SM 0 9N @ IN J e i mSM n nN o  `~NSMLNSM'0ELFPSMQYLpSMx78FSMGMReNfoppSMqrstSMuuSMSMSMSMSM&'+SM,,-4SM6GPrssSMtvSMSMSMSM./1SM2345x67SM8=>>SM?@AASMSMSMSM (*02359;y&?@SMADPY`lNy0SMy>yH !"%SM&&'+SM0F./7SM889:SM;;   578;yV?BCCSMDFPYSMSMSMSM  SM 238SM9:;>SM?FGGSMPPQVSMWXY[SM\SMSM `ay`bdSMegyj /06SM8=SM>EPlpSMSMSMSM  016SM::SM<=SM?ESMFGyxPY`eghjSMySMSM56:SM>?@ByCYZZSMNTN#$$n$p$t$%C//04?4@4@SM4A4F4G4USM4`CDFFaaaa)SMa*a,a-a/SMa0a9hj8j@j^j`jijnjjjjjjjSMjjkk/k0k6SMk7kEkPkYk[kakckwk}km@myn@nnnnnooJoOoOSMoPoooSMooooooyoopp"22PRUUdgpjp|SMNNNNγNκNN-SM0FSMP&)fgiSMjrszN{тSMуфхыSMьѩѪѭSMѮNANBDSMEENVN`xTVԜԞԟԢԢԥԦԩԬԮԹԻԻԽ  9;>@DFFJPR֥֨NNNN455N6NOONPnooNp׈׉׉N׊רששNתNN6SM7:;lSMmtuuSMvڃڄڄSMڅڋڛڟSMڡگSM%*SMSM!SM#$SM&*SM0mSM,06SM7=@INOSMSMTSMSMSMSMSMSMSMCDJSMKKPY^_qL=LLL!"L$$L''L)2L47L99L;;LBBLGGLIILKKLMOLQRLTTLWWLYYL[[L]]L__LabLddLgjLlrLtwLy|L~~LLLLLLN+N0NNNNN N N.//N0ijoNpN;@HPQ`eNNNNNNN NGNPYN`NNNNNWN`mNp|NNNNNNNNNNNߦ?@ έέΰΰ]]JJPP##4y4yN NSM'()*;<<==>>?Z[[\\]]^z{{||}}~wz/1VY JM-0>@[^^`jp                      ( * 0 2 3 5 6 8 9 < < > B G H K M Q Q Y \ ^ ^ f v                      ( * 0 2 3 5 9 < D G H K M U W \ ] _ c f w                     ( * 9 < D F H J M U V X Z \ ] ` c f o w                  D F H J O T c f             :?[9:=>GIlqHJMPVXXZ]`Z]|6@S`lnprs x +0;@@Dmpt^`|LN7;IM EHMPWYY[[]]_} 8 9 : ; D E F G d f q t | } ~      !!?!@!@!A!!""""""" """"""""""""""""""#"#"$"$"%"%"&"&"'"*"+"3"4"8"9"9":":";"L"M"Q"R"U"V"^"_"`"a"a"b"b"c"c"d"k"l"l"m"""""""""""""""""""""""""""""""""""""#### # ## #!#"#(#)#*#+$)$@$J$`'g'h'u'v''''''''''''''''''''''''''''))))))))))))))))))))))))))))))))))))))))))))))))))))))))* * *****!*"*#*$*$*%*%*&*&*'*(*)*)*****+*.*/*3*4*5*6*;*<*>*?*V*W*X*Y*c*d*e*f*i*j*m*n*n*o*p*q*r*s*t*u*x*y**************************************+s+v++++,,-%-'-'-----0-g-o-p-------------------...... . . . . . ....... .).*.T.U.\.].]....///000000000?0A00011/11111122 4MNЦ+@,09@wΨS_|ϩީ6@MPY\۪  &(.0kpףףװۀmp68<>>@ACDF RTXY^_cdeffhkptv  :;;<<==>Z[[\\]]^^_`aabcd  &(:<=?MP]37#-JPz'0coz|6@U`g 578<<?UW   9 ? Y          5 8 : ? H P X `    5 9 U X r x    H   ' 0 9 @ e i  `~'0YpMRu46GPvA (*02359;DGHKMPPWW]cflpt[]aDPY`l+0F;   578;FPYGP `g 68EPlp  6::<=?GPY`eghj:>Z#$$n$p$t$%C//04U4`CDFFaa9hj8j@j^j`jijnjjjjjjjkkEkPkYk[kakckwk}km@myn@nnnnnooJoOooooooopp"22PRUUdgpjp|γκ-0FP&)EV`xTVԜԞԟԢԢԥԦԩԬԮԹԻԻԽ  9;>@DFFJPR֥֨NOOP׈׉׉׊ڋڛڟڡگ%*!#$&*0m,0=@INOKPY^_q=!"$$'')24799;;BBGGIIKKMOQRTTWWYY[[]]__abddgjlrtwy|~~+0;@HPQ`e GPY`W`mp|ߦ?@ έέΰΰ]]JJPP##4y4y Z3p3|3O3P33o3p34/404#4,43O4:P4A4SKo?4Z@_4d`o4lp4~4 4 4 4 4 4 4 4 4 4 4haiao4455 55"565?5e5k5q ?5y@_5`5555O5P5555 566-666@O6FP6M6V6j6|666667 o7% p 79 7U 7f!!O7!P!7!!7""7##7$$?7$@$_7$`$8%%8*%%86%%8E&&8V''8l''8u''8((8))8))8**8++9 ,,_9A,`,9L,,9]--/9d-0-9x--9--9..9..9//9//900?: 0@0:'00:011/:9101:B11:\11:c11:u11:22:33:4M:MM:N; ;";/Фisu?ai@;;;O;U ;k/;|0?;@;;;/;0_;`;;;_ham`< ?> @>/>E>U>c>j>q/>0O>P>>>O>P>>>/>0o>p>>?? ??@_?-`?>?H?R ?Y ??d @ _?k ?s ? _? ` ? ? ? ?? @ _? ` ? @ O@ @# ?@1 @ @A`@G@\@c/@u0o@p@@@@@@O@P@@@O@@AA AewaA!A)_odi`A1AFALOhomOA_Ae_AqA}OAPAAA_A`ABoBpB_B"`B0B>BJ_awiBRBb #Bs$$B}$%OB//B04/B404_B4`CBDFCaa?C4hj?CAj@jorojpjCRjjCYkkCcm@mCpn@nCznnCooiaoooCpCCCCCDD!/D10oDApDVD\DeοDDDDDOE E+E=_EL`EbExگEE/E0EOEotoEFFFF!F5_FCpFIOF]Fs/F0FFFFGOG*PG4GHGbGuGGoGpGGH?H;@H^ ίHΰH_HHOIP#I5#4IXagsI{II !"#&'()3489<=DEEFFGIJLMNOOPRSVWWXXYZ[[\\]^__`abbcopwz/1VY     JKKLLMMNNOOPP QQ!RR"STUVW[\\]^__`opp#q $/001123445679::;<==>>?ABBCCDDEEFFGGHHIJM#$$%'(()-0>@XY[^^`jp ; < < = L M M  N P Q Q R R S T U                          ( * 0 2 3 5 6 8 9 < < > B G H K L M M  Q Q Y \ ^ ^ f v                        ( * 0 2 3 5 9 < < = D G H K L M M  U W \ ] _ c f w                      ( * 9 < < = D F H J L M M  U UT V V[ X Z \ ] ` c f o w                    : ; <  = D F H J L M M  N O T c f             789g:: ?GHKkL[v z45566778899:GIlqqrrssttuyz}~ 677889: ;HJMPVXXZ]`Z]_`| 344 56@S`lnprs  x +0899::;;@@Dmpt^`` atu|3445CDD ELNjkkllmst  677;IM EHMPWYY[[]]_} d f q t                  !!!$)$@$J$`+s+v,,,,,,-%-'-'-----0-g-o-p-- --------------------..]....///0)0*0*0+0+0,0,0-0-0.0/000?0A0000011/11111122 4MNЦ+@noopst}~ +,, 09@wĨ ŨΨ*+-.RSS _| ϩީ6@MPY\ª۪   &(.0kp ףףװۀmp68<>>@ACDF &'-./0RTfhkptv  &(:<=?MP]37#-JPuvz'0coz|6@U`g 578<<?UW   9 ? Y                 5 8 8 9 9 : : ? ?  @ H P X `      5 9 U X r x    H   # $ ' 0 9 @ e i m n  `~'0EFGHJKKLLMPQYpEFF GMRopp qu  234 6GPrsstv 455 667A  (*02359;<=DGHKLMM PPWW]cflpt ABB CEFFG[]]^^_a  >?? @DPY`l *++ 0F899 ::;;   578;<=> ?BCCDFPY 344 5FGG P  `g 68>?? @EPlp  6::<=?ABBCCDE FGPY`eghj :>@AB CZ#$$n$p$t$%C//04U4`CDFFaa.a/a/ a0a9hj8j@j^j`jijnjjjjjjjjjkk/k0k6k7kEkPkYk[kakckwk}km@myn@nnnnnooJoOooooooooopp"22PRUUdgpjp|γκ-0FP&)defgijlmmnrsz{туфхщъыьѩѪѭѮABDEEV`xTVԜԞԟԢԢԥԦԩԬԮԹԻԻԽ  9;>@DFFJPR֥֨ڋڛڟڡگ%*!#$&*0m,067=@INOCDIJJKKPY^_q=!"$$'')24799;;BBGGIIKKMOQRTTWWYY[[]]__abddgjlrtwy|~~+0;@HPQ`e GPY`W`mp|ߦ?@ έέΰΰ]]JJPP##4y4y 6yyyyyyyyyyyzzzz,z6z@zJzTz^zhzrz|zzzzzzzzzzzzz{{{{&{0{:{D{N{X{b{l{v{{{{{{{{{{{{{|| || |*|4|>|H|R|\|f|p|z||  |  |  |  |  |||||||}}}}$}.}8}B}L}V}`  }j!!}t""}~##}$$}%%}((}))}**}++},,}--}..}//}00}22~33~ 44~55~66~(77~299~<::~F;;~P<<~Z==~d>>~n??~x@@~CC~DD~EE~FF~GG~HH~II~LL~MM~NN~OO~PP~QQTTUUVV"WW,XX6YY@ZZJ[[T\\^]]h^^r__|``aabbccddeehhiijjkkllmmnnooppqqrr&ss0tt:uuDvvNwwXxxbyylzzv{{||}}~~&0:DNXblv  *4>HR\fpz$.8BL  V  `  j  t  ~ &&(''2((<))F**P++Z,,d--n..x//00112233&,28>@@DAAJCCPDDVtt`zzf~~pv&0:DNX^djt~    99PPQQSSWW&\\0]]:^^DvvNwwXblv  *4>HR\fpz""##$$%%&&uuvvwwxx$. ) )8 1 1B 4 4L X XV Y Y` Z Zj [ [t \ \~ ] ] ^ ^ _ _      3 3 6 6 Y Y Z Z [ [ ^ ^  H H K K L L( \ \2 ] ]< F P Z d H Hn x     J J K K L L    33  CCMM(RR2WW<\\FiiPssZuudvvnwwxxxyy&&     ;;(==2@@<AAFCCP,,Z--`..f00l11r22x33~445566778899::<<==>>??@@AABBCCDDEEFFGGHHIIJJKKLLMMOOPP QQ&RR,SS2TT8UU>VVDWWJXXPYYVZZ\[[b\\h]]n^^t__z``aabbccddeeffgghhiijjxx "(.4:@FLRX^djpv|           (2<FPZdnx  !!""##$$%%&&"'',((6))@**J++T,,^--h..r//|00112233445566778899::;;<<==>>??@@&AA0BB:CCDDDNEEXFFbGGlHHvIIJJKKLLMMNNOOPPQQRRSSTTUUVVWW XXYY ZZ*[[4\\>]]H^^R__\``faapbbzccddeeffgghhiijjkkllmmnnooppqqrrss$tt.uu8vvBwwLxxVyy`zzj{{t||~}}~~ (2<FPZdnx",6@JT^hr|&0:DNXblv  *4>HR\fpz$.8BLV`jt~           (2<FP  Z!!d""n##x$$%%&&''(())**++,,--..//0011223344"55,66677@88J99T::^;;h<<r==|>>??@@AABBCCDDEEHHIIJJKKLLMMPPQQRR&SS0TT:UUDVVNWWXYYb[[l]]v__``aabbccddeeffgghhiijjkkllmm nnoo pp*qq4rr:ssDttJuuTvvZwwdxxjyytzzz{{||}}&0:DNXblv  *4>HR\fpz&0:DNX^hnx$.4>HR\fpz          $ $ $. % %4 & &> / /L 3 3R 4 4\ 6 6j 7 7t < < > > G G H H I I W W _ _ p p q q t t u u v v w w x x y y z z { { | | } } ~ ~     & , 2 8 > D J P V \ b h n t z             !!!!!!!!!!!! !!! !  ! ! *! ! 0!!6!!<!!B!!H!!N!!T!!Z!!d!!j!!p! ! v!!!!!"!"!$!$!&!&!(!(!*!*!+!+!,!,!-!-!/!/!0!0!1!1!3!3!4!4!5!5!6!6!7!7!8!8!9!9!;!;!!>!?!?!@!@$!E!E*!F!F0!G!G6!H!H<!I!IB!P!PH!Q!QV!R!Rd!S!Sv!T!T!U!U!V!V!W!W!X!X!Y!Y!Z!Z![![!\!\!]!]!^!^!_!_!`!`(!a!a.!b!b8!c!cF!d!dP!e!eV!f!f`!g!gn!h!h!i!i!j!j!k!k!l!l!m!m!n!n!o!o!p!p!q!q!r!r!s!s!t!t!u!u!v!v!w!w!x!x!y!y"!z!z(!{!{2!|!|@!}!}F!~!~L!!R!!X!!f!!p!!z!!!!!!""" " " " "$"$"&"&",","-"-"/"/"0"0"A"A"D"D"G"G"I"I""`"`,"b"b6"m"m@"n"nJ"o"oT"p"p^"q"qh"t"tr"u"u|"x"x"y"y""""""""""""""""""""""""""""""&""0"":""D#)#)N#*#*T$`$`Z$a$a`$b$bf$c$cl$d$dr$e$ex$f$f~$g$g$h$h$i$i$j$j$k$k$l$l$m$m$n$n$o$o$p$p$q$q$r$r$s$s$t$t$u$u $v$v$w$w($x$x6$y$yD$z$zR${${`$|$|n$}$}|$~$~$$$$$$$$$$$$$$ $$$$0$$B$$L$$V$$`$$j$$t$$~$$$$$$$$$$$$$$$$$$$$$$ $$$$($$6$$D$$R$$`$$n$$|$$$$$$$$$$$$$$$$$$$$$$$$$$$2$$@$$N$$\$$j$$x$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$&$$,$$2$$8$$>$$D$$J$$P$$V$$\$$b$$h$$n$$t$$z$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$* * *t*t*u*u*v*v **,|,|",},}(-o-o...4..://@//F//L//R//X//^//d//j//p/ / v/ / |/ / / / / / ///////////////////////////////////// / /!/!/"/" /#/#/$/$/%/%/&/&$/'/'*/(/(0/)/)6/*/*</+/+B/,/,H/-/-N/./.T////Z/0/0`/1/1f/2/2l/3/3r/4/4x/5/5~/6/6/7/7/8/8/9/9/:/:/;/;//>/?/?/@/@/A/A/B/B/C/C/D/D/E/E/F/F/G/G/H/H/I/I/J/J/K/K/L/L/M/M/N/N/O/O/P/P /Q/Q&/R/R,/S/S2/T/T8/U/U>/V/VD/W/WJ/X/XP/Y/YV/Z/Z\/[/[b/\/\h/]/]n/^/^t/_/_z/`/`/a/a/b/b/c/c/d/d/e/e/f/f/g/g/h/h/i/i/j/j/k/k/l/l/m/m/n/n/o/o/p/p/q/q/r/r/s/s/t/t/u/u/v/v/w/w /x/x/y/y/z/z/{/{"/|/|(/}/}./~/~4//://@//F//L//R//X//^//d//j//p//v//|//////////////////////////////////////////////// ////////$//*//0//6//<//B//H//N//T//Z//`//f//l//r//x//~////////////////////////////////////////////////////// //&//,//2//8//>00D0606J0808P0909V0:0:\0L0Lb0N0Nl0P0Pv0R0R0T0T0V0V0X0X0Z0Z0\0\0^0^0`0`0b0b0e0e0g0g0i0i0p0p0q0q0s0s 0t0t0v0v 0w0w*0y0y40z0z>0|0|H0}0}R00\00f00p00z0000000000000000000000000000000000$00.00800B00L00V00`00j00t00~000000000000001111121213131414151516161717181819191:1:1;1; 1<1<1=1=1>1>1?1?"1@1@(1A1A.1B1B41C1C:1D1D@1E1EF1F1FL1G1GR1H1HX1I1I^1J1Jd1K1Kj1L1Lp1M1Mv1N1N|1O1O1P1P1Q1Q1R1R1S1S1T1T1U1U1V1V1W1W1X1X1Y1Y1Z1Z1[1[1\1\1]1]1^1^1_1_1`1`1a1a1b1b1c1c1d1d1e1e1f1f 1g1g1h1h1i1i1j1j$1k1k*1l1l01m1m61n1n<1o1oB1p1pH1q1qN1r1rT1s1sZ1t1t`1u1uf1v1vl1w1wr1x1xx1y1y~1z1z1{1{1|1|1}1}1~1~11111111111111111111111111111111111111111111 11&11,11211811>11D11J11P22V22d22r2222222222222 2 2 2 2 2 2 2 2 2  2222,22>22P22b22t22222222222222222222(22F2 2 `2!2!n2"2"|2#2#2$2$2%2%2&2&2'2'2(2(2)2)2*2*2+2+2,2,2-2-2.2.$2/2/22020@2121N2222\2323j2424x252526262727282829292:2:2;2;2<2<2=2=2>2>2?2?2@2@ 2A2A.2B2B<2C2CJ2D2DX2E2E^2F2Fd2G2Gj2P2Pp2Q2Q~2R2R2S2S2T2T2U2U2V2V2W2W2X2X2Y2Y2Z2Z2[2[2\2\2]2]2^2^2_2_ 2`2`2a2a2b2b 2c2c&2d2d,2e2e22f2f82g2g>2h2hD2i2iJ2j2jP2k2kV2l2l\2m2mb2n2nh2o2or2p2p|2q2q2r2r2s2s2t2t2u2u2v2v2w2w2x2x2y2y2z2z2{2{2|2|2}2} 2~2~22&22,22222822>22D22J22P22V22\22b22h22n22t22z222222222222222222222222222222222222222222222222 22222222"22(22.22422:22@22F22L22V22`22j22t22~2222222222222222222222222222 222222(22222<22J22X22f22p22~22222222222222222222222222222222222222222222222222 22&22,22222822>22D22J22P22V22\22b22h22n22t22z2222222222222222223333333333333333,33B3 3 T3 3 b3 3 p3 3 ~3 3 33¢33°33¾33333333333333433J33X33n33Ä33Ö33ä33ò333 3 3!3!3"3"3#3#3$3$3%3%$3&3&.3'3'83(3(B3)3)L3*3*Z3+3+h3,3,~3-3-Č3.3.Ğ3/3/Ĵ3030313132323333343435353636"373783838B3939P3:3:^3;3;l3<3<z3=3=ň3>3>Ś3?3?Ũ3@3@Ų3A3A3B3B3C3C3D3D3E3E3F3F 3G3G3H3H.3I3I@3J3JJ3K3K`3L3Lj3M3M|3N3NƎ3O3OƜ3P3Pƪ3Q3QƸ3R3R3S3S3T3T3U3U3V3V3W3W3X3X"3Y3Y,3Z3Z63[3[@3\3\J3]3]T3^3^^3_3_h3`3`r3a3a|3b3bdž3c3cǔ3d3dǢ3e3eǰ3f3fǾ3g3g3h3h3i3i3j3j3k3k3l3l3m3m 3n3n.3o3o<3p3pJ3q3qX3r3rf3s3sp3t3tz3u3uȈ3v3vȒ3w3wȜ3x3xȦ3y3yȴ3z3z3{3{3|3|3}3}3~3~3333333333$33.33833B33L33V33d33v33ɀ33Ɋ33ɔ33ɞ33ɨ33ɲ33ɼ333333333333333333&33033:33D33N33X33f33t33~33ʌ33ʚ33ʨ33ʲ3333333333333333"33833R33\33f33p33z33˄33ˎ33˘33ˢ33ˬ33˶33333333333333333333"33,33633H33V33`33j33t33~33̈33̒33̜33̦33̰33̺3333333333333333"33,33633@33J33X33f33p33z33̈́33͎33͘33͢33ͬ33Ͷ3333333333333333"33033>33L33Z33h33v33΄33Β33Π33ή33μ33333333pp &,2\\8]]>^^D__JiiPV\bhntzπ φ ό ϒ Ϙ ϞϤϪϰ϶ϼ  !!""##"$$(%%.&&4'':((@))F**L++R,,X--^..d//j00p11v22|33Ђ44Ј55Ў66Д77К88Р99Ц::Ь;;в<<и==о>>??@@AABBCCDDEEFFGGHHIIJJ KKLLMMNN$OO*PP0QQ6RR<SSBTTHUUNVVTWWZXX`YYfZZl[[r\\x]]~^^ф__ъ``ѐaaіbbќccѢddѨeeѮffѴggѺhhiijjkkllmmnnooppqqrrssttuuvvwwxx yy&zz,{{2||8}}>~~DJPV\bhntzҀ҆ҌҒҘҞҤҪҰҶҼ "(.4:@FLRX^djpv|ӂӈӎӔӚӠӦӬӲӸӾ $*06<BHNTZ`flrx~ԄԊԐԖԜԢԨԮԴԺ &,28>DJPV\bhntzՀ Ն Ռ Ւ ՘ ՞դժհնռ ""%%&&**++ ,,--..//"00(11.22433:44@55F66L77R88X99^::d;;j<<p==v>>|??ւ@@ֈAA֎BB֔CC֚DD֠EE֦FF֬GGֲHHָII־JJKKLLMMNNOOPPQQRRSSTTUUVV WWXXYYZZ$[[*\\0]^6__<``BaaHbbNccTddZee`fffgglhhriixjj~kkׄll׊mmאppזqqלrrעssרtt׮uu״vv׺wwxxyyzz{{||}}~~ &,28>DJPV\bhntz؀؆،ؘؒ؞ؤتذضؼ "(.4:@FLRX^djpv|قؤَٚ٠٦٬ٲٸپ &0>LV`jt~ڈڒڜ ڦ!!ڬ""ڲ##ڸ$$ھ%%&&''(())**++,,--.. //0011(22233<44F55P66Z88d99n::x;;ۂ<<ی>>ۖ@@۠AA۪CC۴DD۾FFGGHHIIJJKKLLMMNNOO"PQ,RU2VY8Z]>^aDbeJfiPjmVnq\rubvyhz}n~tz܀܆܌ܒܘܞܤܪܼܰܶ &0:DNXblr|݆ݐݚݤݮݸ     &0:DNXblvހފޔޞި ޲!!޼""##$$%%&&''(()) **++ ,,*--4..>//H00R11\22f33p44z55߄66ߎ77ߘ88ߢ99߬::߶;;<<==>>??@@AABBCCDDEE$FF.GG8HHBIILJJVKK`LLjMMtNN~OOPPQQRRSSTTUUVVWWXXYYZZ[[\\ ]]^^__,``:aaHbbVccdddree|ffgghhiijjkkllmmnnooppqqrrssttuuvv&ww0xx:yyDzzN{{X||b}}l~~v  *4>HR\fpz$.8BLV`jt~ (2<FPZdnx",6@JT^hr| (2<FPZdnx     ",6@JT^hr| !!""##$$%%&&''((&))0**:++D,,N--X..b//l00v112233445566778899::;;<=PPQRSSTT"UU0VV>WWLXYZZZh[[v\\]]^^_`aabcdeffghiijklmnn,op:qrHssVttduurvwxxyyzz{{|}~~ (6DR`n|$2@N\jx .<JXft*8FTbp~&p0011223455667788 99::;;<<"==(>>.??4@@:AA@BBFCCLDDRGGXHH^ILdMOjPPpQQvRR|TTUUVVWWXXYYZZ[[\\]]^^__``aabbccddeeffhhiijjkkpp qqrr tt*vv4ww>xxHyyRzz\{{f||p}}z~~ "(.4:@FLRX^djpz      "(.4:@FL R!!X""^##d$$j%%p&&v''|(())**++,,--..//00112233445566778899::;;<<==>>?? @@AABBCC$DD*EE0FF6GG<HHBIIHJJNKKTLLZMM`NNfOOlPPrQQxRR~SSTTUUVVWWXXYYZZ[[\\]]^^__``aabbccddeeffgghhiijjkkllmm nn&oo,pp2qq8rr>ssDttJuuPvvVww\xxbyyhzzn{{t||z}}~~ "(.4:@FLRX^djpv| $*06<BHNTZ`flrx~ "(.4:@FLRX^djpv| $*06<BLV..`//jKKtLL~88a!a! a"a"a#a#a$a$(a%a%2a&a&<a'a'Fa(a(PmhmhZmimidmjmjnx~ &,28>DJ^^P__Z``daanbbxccddѻѻѼѼѽѽѾѾѿѿ      &,28>DJPV\bhntz !!""##$$%%&&''(())**++,,--..//0011223344 55667788"99(::.;;4<<:==@>>F??L@@RAAXBB^CCdDDjEEpFFvGG|HHIIJJKKLLMMNNOOPPQQRRSSTTVVWWXXYYZZ[[\\]]^^__`` aabbccdd$ee*ff0gg6hh<iiBjjHkkNllTmmZnn`oofpplqqrrrxss~ttuuvvwwxxyyzz{{||}}~~ԀԀԁԁԂԂԃԃԄԄԅԅԆԆԇԇԈԈԉԉԊԊԋԋԌԌԍԍԎԎ ԏԏ&ԐԐ,ԑԑ2ԒԒ8ԓԓ>ԔԔDԕԕJԖԖPԗԗVԘԘ\ԙԙbԚԚhԛԛnԜԜtԞԞzԟԟԢԢԥԥԦԦԩԩԪԪԫԫԬԬԮԮԯԯ԰԰ԱԱԲԲԳԳԴԴԵԵԶԶԷԷԸԸԹԹԻԻԽԽԾԾԿԿ "(.4:@FLRX^djpv| $*06<BHNTZ`flrx~    & ,!!2""8##>$$D%%J&&P''V((\))b**h++n,,t--z..//00112233445566778899;;<<==>>@@AABBCCDDFFJJKK LLMMNNOO"PP(RR.SS4TT:UU@VVFWWLXXRYYXZZ^[[d\\j]]p^^v__|``aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvww xxyyzz{{$||*}}0~~6<ՀՀBՁՁHՂՂNՃՃTՄՄZՅՅ`ՆՆfՇՇlՈՈrՉՉxՊՊ~ՋՋՌՌՍՍՎՎՏՏՐՐՑՑՒՒՓՓՔՔՕՕՖՖ՗՗՘՘ՙՙ՚՚՛՛՜՜՝՝՞՞՟՟ՠՠաաբբգգդդեե զզ&էէ,ըը2թթ8ժժ>իիDլլJխխPծծVկկ\հհbձձhղղnճճtմմzյյննշշոոչչպպջջռռսսվվտտ "(.4:@FLRX^djpv| $*06<BHNTZ`flr x ~     !! "" ## $$ %% && &'' ,(( 2)) 8** >++ D,, J-- P.. V// \00 b11 h22 n33 t44 z55 66 77 88 99 :: ;; << == >> ?? @@ AA BB CC DD EE FF GG HH II JJ KK LL MM NN OO PP "QQ (RR .SS 4TT :UU @VV FWW LXX RYY XZZ ^[[ d\\ j]] p^^ v__ |`` aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz {{ $|| *}} 0~~ 6 <րր Bցց Hււ Nփփ Tքք Zօօ `ֆֆ fևև lֈֈ r։։ x֊֊ ~֋֋ ֌֌ ֍֍ ֎֎ ֏֏ ֐֐ ֑֑ ֒֒ ֓֓ ֔֔ ֕֕ ֖֖ ֗֗ ֘֘ ֙֙ ֚֚ ֛֛ ֜֜ ֝֝ ֞֞ ֟֟ ֠֠ ֡֡ ֢֢ ֣֣ ֤֤ ֥֥ ֨֨ &֩֩ ,֪֪ 2֫֫ 8֬֬ >֭֭ D֮֮ J֯֯ Pְְ Vֱֱ \ֲֲ bֳֳ hִִ nֵֵ tֶֶ zַַ ָָ ֹֹ ֺֺ ֻֻ ּּ ֽֽ ־־ ֿֿ                    " ( . 4 : @ F L R X ^ d j p v |                      $*06<BHNTZ`f l r x ~  !!""##$$%%&&'' ((&)),**2++8,,>--D..J//P00V11\22b33h44n55t66z778899::;;<<==>>??@@AABBCCDDEEFFGGHHIIJJKKLLMMNN OOPPQQRR"SS(TT.UU4VV:WW@XXFYYLZZR[[X\\^]]d^^j__p``vaa|bbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyy zz{{||}}$~~*0׀׀6ׁׁ<ׂׂB׃׃HׄׄNׅׅT׆׆Zׇׇ`׈׈f׉׉l׊׊r׋׋x׌׌~׍׍׎׎׏׏אאבבגגדדההווזזחחטטייךךככללםםממןןננססעעףףפפץץצצקק רר&שש,תת2׫׫8׬׬>׭׭D׮׮JׯׯPװװVױױ\ײײb׳׳h״״n׵׵t׶׶z׷׷׸׸׹׹׺׺׻׻׼׼׽׽׾׾׿׿ "(.4:@FLRX^djpv| $00*11022633<44B55H66N77T88Z99`::f;;l<<r==x>>~??@@AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYY ZZ&[[,\\2]]8^^>__D``JaaPbbVcc\ddbeehffnggthhziijjkkllmm      "(.4:@FLR!!X""^$$d''j))p**v++|,,--..//0011224455667799;;BBGGIIKKMMNNOOQQRRTTWW YY[[]]__$aa*bb0dd6gg<hhBiiHjjNllTmmZnn`oofpplqqrrrxtt~uuvvwwyyzz{{||~~ &,28>DJPV\bhntz (2< F PZhv, :!!H""V##d$$r%%&&''(())**++,,--..0011223344 55667788$99*::0;;6<<<==B>>H??N@@TAAZBB`CCfDDlEErFFxGG~HHIIJJKKLLMMNNOOjjkkll $*06<BHNTZ`fl r!!x""~##$$%%&&''(())**++,,--..//00112233445566778899::;;@@AA(BB6CCDDDREE`FFnGG|HHPPQQ    " ( .4:@FLRX^djpv| !!""##$$%%&&''(())**++,,--..//001344 55667788$99*::0;;6<<<==B>>H??N@@TAAZBB`CCfDDlEFrGGxHH~IIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^ __ `` aa bb cc dd &ee ,ff 2gg 8hh >ii Djk Jll Pmm Vnn \oo bpp hqq nrr tss ztt uu vv ww xx yy zz {{ || }} ~~            !! !!!!"!(!.!4!:!@!F!L!R!X!^!d!j!p!v!|!!!!!!!!!!!!!!!!!!!!!""" """"$"*"0"6"<"B"H"N"T"Z"`"f"l"r"x"~"""""""""""""""""""""###### #&#,#2#8#>#D#J#P#V#\#b#h#n#t#z################### # # # $ $ $$$$"$($.$4$:$@$F$L$R$X$^$d$j$p$v $|!!$""$##$$$$%%$&&$''$(($))$**$++$,-$..$//$00$11$22$33$44$55$66$77%88%99% ::%;;%<<%==%$>>%*??%0@@%6AA%<BB%BCC%HDD%NEE%TFG%ZHH%`II%fJJ%lKK%rLL%xMM%~NN%OO%PP%QQ%RR%SS%TT%UU%VV%WW%XX%YY%ZZ%[[%\\%]^%__%``%aa%bb%cc%dd&ee&ff&gg&hh&ii& jj&&kk&,ll&2mm&8nn&>oo&Dpp&Jqq&Prr&Vss&\tt&buu&hvv&nww&txx&zyy&zz&{{&||&}}&~~&&&&&&&&&&&&&&&&&'' ''''"'('.'4':'@'F'L'R'X'^'d'j'p'v'|'''''''''''''''''''''((( (((($(*(0(6(<(B(H(N(T(Z(`(f(l(r(x(~((((((((((((((((((((()))))) )&),)2)8)>)D)J)P)V)\)b)h)n)t)z))))))))))))))) ) ) ) ) )))** ****"*(*.*4*:*@*F*L*RIIIIIIIII23I?@IIIIIIIIIIzzIIIIIIIIuxI33III  IwwIyyII,.I0:I<MIOaIbjJxxIIIIII  I  I  I  I  I $ &I / /I 3 4I 6 7I < <I > >I G II W WI _ _I p qI t I J J I!!I!!*X!!I! ! I! !J!!*b!!J! !"*l!$!$J!(!(J!,!-J!/!1J!3!4J!5!8I!9!9J!;!;I!JFJPJ3,J>-3JF4;JP<=,PQ,RWJFXY,Z[J>\]JF^_J>`aJFbe,fgJ>hhJFijJ>km,noJ>pq-rsJFtvJ>wwJFx|J>}}JF~J>JFJ>- JFJ>JFJFJ>JFJ>JFJ>JFJ>-J>JFJ>J3J0DJGHJIOIPRJYTfJYhkJYpr-"ttJ3v-0J3-Z`JaJaJaJaJaJaJJaIIIJTJVԜJԞԟJԢԢJԥԦJԩԬJԮԹJԻԻJԽJJ J JJ9J;>J@DJFFJJPJR֥J֨JJ0PIQjJkmIJJ!"J$$J''J)2J47J99J;;JBBJGGJIIJKKJMOJQRJTTJWWJYYJ[[J]]J__JabJddJgjJlrJtwJy|J~~JJJJJJ I*I+.J0OJ*jlIJ*J*;J*@HIPQJJc s!#o$$c%'o(-/H./o09d:;o<>m?@oAZu[`/bazl{~/|c/c/o/o/ooumulml6/78l9G0HIlJw1xyuz}1~lu1ululululululu1u1l1ulu2ul2lo2l2l2u2239l:;u<u?@lAB3CFuGN3Ololmkmkmk3konpw4zzm{}l~4"k4,uuuluululul46l4ul/u0_l`4ne58u6l/6D1VuYYmZ_o`l7ocn7non7ooofm  o  c  oon7o ?o@@mAJoK_n`idjmonooppnqo7n7nmnonodooo o8/o0JnMonodonmoomnconm#n$$m%'n((m)-n0>o@XoY[n^^o`jopokofnomnf n  c  9o : =8 > @c A Hn I Lc M Mn N Oc P Po Q Wn X ao b cn d eo f od p q8& r o n c o o o o o o 80 c n c c 8: c o o n d o c o 8D  n  c  o  o  (o * 0o 2 3o 5 6o 8 9o < @c A Bn G Hn K Mn Q Qn Y \o ^ ^o f od p qn r to u v8Z n c o o o o o o 8d c n n c c n o o n d 8n o n  n  c  o  o  (o * 0o 2 3o 5 9o < @8x A Dn G Hc K Lc M Mn U Vn W Wc \ ]o _ ao b cn f od p q8 r wo 8 o o o o o o o o o c n c c c n o c d o o 8 n  c  n  o  o  (o * 9o < =8 > @n A Dc F Hn J Mn U Vn X Zo \ ]o ` ao b cn f od w wo x ~o  8 c o o o o o o 8 c n c c n c o o n d o c n  c  o  o  :o ; @c A Dn F Hc J Lc M O8 T Vo W Wc X ^o _ ao b cn f od p xo y yo z o n c o o o o o n c n n c d c o0o11n23o4:n??c@EoFFmGNnOOoPYdZ[ooooooononoomndoooo8ono )d*3o4=8>?c@GoIloq~ncnononnonooooo*o+,c-0n11c27n88c9:n;n??o@IdJOoPUoVWcXYnZ]o^`naaobdcefogmcnpoqtnuoncnc9dcnouuul9&lHoJMoPVoXXoZ]o`ooooooooooZo]_n`hoi|ooouldlomn90ooso9:ooloonc1o23n44c56o@QoRSn`lonporsnoncncncnomo9Ddood o  n9Rd BoCCmDxoono9\oo "n#&c'(n)+c01c22n38c9;n@@oDEoFOdPmoptooodoooncno ToUW9fX^n`b9tcdcelnmrcs|nnddomonennnc3o4596:n;<9=AcBBnCDcELoNOoPYdZ`oajoksnt|o}oncocncncnodo9nc9nco#o$+c,3n45c67n;?o@IdMOoPYdZwox}m~ol9uuononcnononocno+l,jmkwlxxmylmn9l< lulu 'l(/u07l8?u@ElHMuPWlYYu[[u]]u__u`glhoup}lltltltllu=kllutklluklukllutk s f  d  o  =  i  = 'o ( )= * .f / /s 0 8o 9 := ; >o ? @c A Co D F= G Qo R T= U ^o _ _s ` df f of p q= t yo z |m } = o m > m c n e n e n!!o!!u!!o!!u!! o! ! l! ! u!!l!!u!!> !!o!!m!!u!!#o!$!)>!*!-u!.!/>4!0!3u!4!4l!5!8o!9!9l!:!;o!!?u!@!Dm!E!Eu!F!Il!J!K>>!L!Mo!N!O>H!P!_o!`!l!!>R!!l!!o!!o!!m!!o!!m!!o!!m!!o!!m!!o!!m!!o!!m!!o!!m!!o!!>\!!o!"m##o## >j# #o# #!m#"#(o#)#*>|#+#{o#|#|m#}#o##m##o##m#$)o$@$Jo$`$o$$o$$o%%o%%m%%o%%m%%o%%m&&no&o&om&p'go'h'u>'v'o''o''m''>''m''>''m((o))m))>))m))?N))m))?`)*m++/o+0+Dm+E+Fo+G+Lm+M+so+v+o,,/u,0,_l,`,a?j,b,du,e,fl,g,l?t,m,pu,q,r?,s,tl,u,uu,v,{l,|,}m,~,u,,?,,l,,o,,A",,n,,A4,,o,,o,,o--%l-'-'l----l-0-go-o-pA>--n--o--o--o--o--o--o--o--o--o--n..o..AH..o. . AZ..o..d..o..Ap..o. .)A.*..o././m.0.9o.:.;d.<.?o.@.BA.C.Oo.P.Qo.R.To.U.]A..o..o//o//o00s00o00A00o00B00e0 0 o0!0)l0*0-n0.0/c0000d0105m0607o080:l0;0=BD0>0?o0A0o00n00k00m00BR00o00o00m00o11/o111o11o11o11o11o11o11o11o22o2 2)o2*2Go2H2Oo2P2Po2Q2_o2`2o22o22o22o23o44oMMoMMoNNoomooФomo o m oo )d*+o@oB\pressot}n~Cmnolnokm !k".C/1l2pCqxly|D}~uDkElE*uluE|ħuȧE˧uͧEmF mlonon o n "o#$c%&n''c(+o,,n05o67o89F@sotwococĨnΨoШdnooF"on d %o&-n./o0FoGQnRSc__o`|onconcncncoϩmЩdީooF,odo(o).n/0c12n34c56n@BoCCnDKoLMF6PYd\_o`ooppmqvowyoz}F@~oFRnononF\۪oݪmުoocncoomFjo oo &o(.o0Zl[[k\_m`hliimjkkplocncncFtdoףףoװoosۀssFomopollF(o))m*6o8>o@AoCDoFoko=o>?F@OoPoooooconoF /n00o12d34c5DFEFoGHFILoMOcPRoTWoX^F_aobcGdfmhiG"jkoptovofoco G,odom o!:u;@GFAZl[cG`deofooppmqomooooocGcomofo o &o(:o<=o?MoP]ooo3o7?o@tluxoyoooooonoonoo #o-@oAAlBIoJJlPuovznoooool'u(OlPodul'o0coooopzu|uuullllo6o@Uo`gommmoo 5o78o<>n?@oAAnoooooooncndnc oo(o*0o23o59o;?c@@nADcGHcKMcPPoWWc]aobccflnptnooooocnccccGoon4o57c8?n@AcBDnEFGGJoKOoPYdZ[o]^H_aoocnH cncnoHdocncncnoon/o02c3:n;H?@nACoDDoPYd`looH(cnH6ddoHH !c"%n&&c'+n09d:;o<>o??o@Fo+o,.c/7n88c9:n;;ouldoo  o oo/o05c78c;n?FoGGnPPoQVnWXcY[n\oncnoooo o`aHbdnegHoodo .o//c06n8=n>@HAEoPYdZlopqoroncncncno o 0o16n::n<=n?EnFGHPYd`eoghojocncHdomodonconHo3o45c6:n>?c@BHCOoPYdZZnooocoo #o$$nl$p$to$%Co//o//o04/o404?f4@4@n4A4Fo4G4Un4`CoDFFoaaoaa)na*a,ca-a/na0a9dhj8oj@j^oj`jidjnjoojpjojjdjjojjnjjokk/ok0k6nk7k;oku@DuFFuJPuRkllՅuՆ՟lՠչuպlul!u";lK@[K `jJpJJ K K! K! K! K! K! K! K! K! K! K! K! K!  K*  K*  K*  (K* * 0K* 2 3K* 5 6K* 8 9K* > BK* G HK* K MK* Y \K* f vK* K4 K4 K4 K4 K4 K4 K4 K4 K4 K4 K4 K4 K4  K>  K>  K>  (K> * 0K> 2 3K> 5 9K> < DK> G HK> K MK> U WK> \ ]K> _ cK> f wK> KE KE KE KE KE KE KE KE KE KE KE KE KE KL  KL  (KL * 9KL < DKL F HKL J MKL U VKL X ZKL \ ]KL ` cKL f oKL w KL KT KT KT KT KT KT KT KT KT KT KT KT KT K]  K]  DK] F HK] J OK] T cK] f K] Kh Kh Kh Kh Kh Kh Kh Kh Kh:Kq?[KqAO AO AO AO AO AO AO AO GKwIlKwqKwKwKwKwKwKKKKKHKJMKPVKZ]K`KKKKKKKKKZK]|KKKKKKKK 4K56K@SK`lKnpKrsKKKKK xKKKL +L0;LDOLPmAI ptAI EW EW EW EW KLL ^AI `|AI AI AI AI JJLLNLL#L.L.7L5;IL5MOL5PL JKKL#L=%J{&*J,aJbeJ{fjJkwJ{yJ{JJJ{JJ EJHMJPWJ_}JJJJJJJJ LD  LJ  LR  LJ 0 1ER  5 7LZ 9 :LR L MLd b dLk p qJ t J Lv J{ J! ! L!!L!!L!!L!/!1L!3!4L!)?M)J)KL)L)MP )f)gL)h)iL)j)kL)l)mL)t)uL)) )) ))LJ))O))O))O))O%))ME))N))ME))N))MN))O,))O6))O>))OE))OM))Ld))OS))IG **-**WO **OZ**Od**OZ**! *"*(Oj*)*,Op*-*.Oj*0*1Ow*4*5Ow*A*BO*C*DO*E*FO*L*MO*N*OLJ*Q*RL*S*TLJ*U*VWO *W*XO*Y*`L*b*cL*d*e *h*iO*j*kO**O**L**O**LJ**O**LJ**M=**O**O**O**O**LJ**O**O**O**L++L++L++ L+ + L++L++L++M=++O+ +!N+$+%Ld+)+*Ld+4+>L+C+DL+J+KL+N+OO+U+YN+f+gL+h+iL+v+wL+x+yL++P++P++P++N++Ld++L++L++Ld++P%++P-++ME++Ld++Ld++P:++PA++PG++PM,,_PV,`,|J{,~,J{,,J,,J--%K-0-gPb-o-pPb--K--K--K--K--K--K--K--K--K--J..MW..N..O.".#OP .$.%M.3.4N.6.7Pl.E.FPt.G.HOW .P.QN0.S.TP~.Y.ZOP .[.\M..JK ..JK //P/0P00P0!0)P0*0-P0.0/K0105O080:P0>0?P0A0P00J00P00P00P00P11/P111K11P11P11JK 11P22M2 2CM2D2OME2Q2~ME22ME22P22M=22ME23WM=3X3pP3q3M=33PMMPI I ФP+AI @nJorJt}J~JJJP!J"oJ{qJ{JJ{JJ{JJ{,P09L@wPPΨPJK/Q0SQ`|KQϩQީQK6Q@MQPYQ\_Q`KAI ۪AI Q K KK &K(.K0ZJ{[_J`dJ{fhJ{ikJpKQ Q װKKmJK pJK J{J6J8<J@AJCDJFOJP=J>?Q(@JJJQ0Q; /J0DQ;GHQ;PRLTfLhkLptJvJ`QIaQTQTQTQTQTQIQTQ_ Ql &Ql(:Ql<=Ql?MQlP]QlQlQt3Qt7?Qt@JLQ|QQJ#LD -/LD 0JQPuLD vzJQLD LD OQPQQQQQ'Q0cQpzQ|QQQQQQQQ6Ql@UQl`gQlJJJQ 5Q78Q@UQW_Q`RRRRRR R! 9R- @ YR5 R> R> R> RH  RH RH  RH  5RH 8 :RH ? HRH P XRH ` LD  RT RT 5R` < ?N @ URi X rRi x Ri Rx Rx Rx HLD  LD  LD  LD  'R 0 9R @ eR i R R`~RRRRJJJ'LD 0YRpLD RRMRRuRRRR4R6GRPvRRKhRARRRRRRRS  S S (S *0S 23S 59S <DS GHS KMS ]cS flJptJSSSSSSS[S]aSSSS'S'DS0PYS0`lKS6S6KS=+S=0FS=;SCSJSR SRSR5SR78SR;FSRPYSRSYSYSYGSfPSqKAU  K`gRSzSzS 6S8ESPlSpSSSS S 6S<=S?GSPYS`eSghSjSSSSSSSS:S>ZSKE #S$$nS$p$tS$%CS//S04US4`CSDFFSaa9Shj8Pj@j^RO j`jiRO jnjoRO jpjSjjSjjSjjSkkESkPkYSk[kaSkckwSk}kSm@myTn@nT nnTnnTooJT!oOoT!ooT!ooLD ooT'ooT3ooT<TETMTEPPPTU "PPRPdgPpTajThp|ThThThThTrT} OX !/T07M8?M@ATDETFGTJKTLUTZ\OP ]_MijNkoLd|M=̀̃T̆̇N̉̌M=̜̝O̦̩M̪̱M̲̳M̴̵M̶̷M̸̹M̺̻M̼̽M̾̿MMMMMMMMMMMMTTMOP T OX OX PNQΏTΐΗMΘΟMΠΡMW΢ΣLΤΥMΦΧMΨΩLΪΫMWάέMήίMT-T0FTPTT&T)TAJBDJUUNdVU`qU rvPwxU*TNVԜNԞԟNԥԦNԩԬNԮԹNԽNN N NN9N;>N@DNJPNR֥N֨NNڋU1ڛڟU1ڡگU1J{%*J{JJ!J#$J&*J0PJQjJkmJ,U>0=U>@IU>NOU>UHUNAG L AI AI AI KKKKUVUVKU]PYU]^_U]qUd=UkJJ!"J)2J47JMOJQRJabJgjJlrJtwJy|JJJJJJJ+Ut0U}UUUU Jt N ME)M+.ME0OMNPiMjlNmoMEpMMMNUMN;MN@HUPQME`eU U#&N'*U=>AR XYUN@UUUUFINMNUabUlmWO rsAN tuUyzUUVVONVL V $V&47N89LABN0CDV-PgV6hjMWMLZV=LdV=LdVGVQVXO%V^O%VdNlVlN(VwV VVV01V67V:;VABVDFVLOVTWL\_NdgNhiVjkVstNvxV|}MeVP-VsVLdLdNLdNLdMeNNNTULVWL`VNNOMLLNNMEL V)*VwstVyzVUVVV NLdV#N$)Ld*/V38N9>Ld?DVNPNQSLdTUNVWLd`mWW VW;TW:?@LCFW:OaLciLksLwLWMLLWMWMLWMLWMLWMWMWMLJBEJUWMW\bLJcoJ{{}LW:W:W:W:LWUW:/W:0_LJL1VW:`LW^WfWfWmWMWsW}WUd  UdWL ?WMAJWMTUWZ\W`iUdnWMLLO%WMJWMWW  W/WM02W35W67W89W:;W=>WCDWO EFNlGHOMWMJtWMJMWMWm#W%'W),W05W}7>W}@XWM`jWMpWMWWMLWMLNNLM^WNWLJ W  9WM : ;W < =W > LW N OW Q RW U WW X aWM b cW f oJt r WM W WM WM WM WM WM W W W W WM WM W Jt WM W X  W  WM  WM  (WM * 0WM 2 3WM 5 6WM 8 9WM > BW G HW K LW Y \WM f oJt W WM WM WM WM WM WM W W W W WM W Jt W  W  WM  WM  (WM * 0WM 2 3WM 5 9WM < =W > DW G HW K LW \ ]WM _ aWM b cW f oJt r wWC W WM WM WM WM WM WM WM WM W W W Jt M W  WM  WM  (WM * 9WM < =W > DW F HW J LW X ZWM ` aWM b cW f oJt x ~WC  W WM WM WM WM WM W W W W WM WM W Jt W W  WM  WM  :WM ; =W > DW F HW J LW T VWM X ^WC _ aWM b cW f oJt p rM s xWC z WM W WM WM WM WM W W X  W:X@OXPYJtZ[XWMWMWMWMWXWWJtO WMWmX'X1W 3Jt4=Wm>?W@GWMIlWMq}W~WWWWmWX?X?U XJMWWmWm*WM+5W6:W;>XX@IJtJKWLOMPUWMVYWZ]WM^`XXcdWefWMghWimWnpWMqtWuWMWWXcWWMW:WMWM_Xi`XsX~HXJMXPVXZ]X`XXXXXXXXXZX]_JiqJtr|MXXWMLXWMWMWMWMWW 1WM23W@QWMRSW`lWMnpWMrsWWMXWWWJtM X  XJt xWMWMXWM (W)+X?08L9;WFOJtPmE ptE AI AI AI AI MWMW ^X`|XXXXXJ{LJJ{XLJW3WM5CWELWMNOPtPYJt]_Xa|TWWMXXWWXXWMJtWMWXXM#WM$%X?&,W-5XX67W;?W}@IJtMOWMPXLXXW}WWWWWWWMWM L WMLLWML *WM,aWMbjLvkwLyLWMWJ{XLLW:LW: 'L(/W:07L8?W:@ELHMW:PWL`gLhoW:p}LLW:LW:LW:LLW:LLW:XLLW:YLW:Y LLW: Y Lv Y Y!!Y(!0!1W:!?[D@t[MuvNE [YWMWM[_#[f-/[f0JWMPu[nvzLD WM[v[v'W:(OLPWMJtW:L'WM0c[pzW:|W:W:W:LLLLWM6 @U `g WMWMWMX 5X78X@U[W_[`vWMyMWMMMWMWMM WM  M 9WM @ YWM [ [ [ [  W  W W  WM  WM  5WM 8 :W @ CJt D GM P XW} ` L L WM WM [ M W} 5WM @ U[ X _[ ` r[ x [ [ [ H[ [ [ [ '[ 0 9[ @ IJt J NW P eW: k lJ p L`hJtizM{~WCWMJWMWMWMWsL'R0DWMFPJQTMUYW}p[WMMWMW7WM8EWIMW}ReMfoJtqrWMstWWWMWW[[W&WM'0W6?JtEFWPrWMWWMWWJt[\WM+WM,3W47W?@WMWMWMWMWMWMWWJtW WMWM(WM*0WM23WM59WM<=W>DWGHWKLW^aWMbcWflS ptS \ \ \ \ \ \ \ 4WM5AWBHWPYJt`aWWMWWJtWMWWW\\[WMW/WM0<W=@WPYJtef\+ghPtik\4WMWWWJtAO \;WMXX *W09Jt:;M<>W@FWM+WM,6W7:W\D\J \J\J5\J78\J;F\JPY\JWMWMWWWGM=Q[W\WMW\QZWWm\Z\`XIN \Z W`gWWMJtWM .WM/6W8;W<@WDEAP PYJtZkMrWMX?X?WW\j \j 6\j<=\j?G\jPY\j`e\jgh\jj\j\j\j\j\q\qWMWWWM3WM4:W>@WEOW}PYJtWCW\wW #W$$n\$p$tW}$%CW//\04U\4`C\DFF\aa9\hj8WMj@j^WMj`jiJtjpjWMjjJtjjAH jjAH kkE\kPkY\k[ka\kckw\k}k\m@myAI n@n_W:n`nLnnJtnnMnnJtnn\nn\ooJWMoQoSWoToWooWooWMooT3oo\ooLooW\L\WMWMWMWM "WMPRWMdgWMp\jWMp|\\\\\ Y|!/T12\78W!=>\FG\JK]LM] NO]PQ]RS]#TU] Z_Zmij]+knN|Vd̆̇M̉̋NJ{Jt]1ZmZm]9 Y|Y|P]@QΏTΑΒ\ΔΛW!ΝΞ\Ρ΢NlΣΤZmΥΦNlΧΨZmΩΪNlΫάZmέήNl]F-J0AJBF]NP]WT&M)M]^A]eBEJY0Y0VOR `qOD rvU*wxWm3]s4T[fVg[fhԛ]sԞԟLԥԦLԩԬLԮԹLԽLL]s]y ]y ]y]y7]y89L;>L@DLJPLRkLl՟]sՠoVp֣]֤֥[f֨]s[fU]sVV]s]sLV]]] ] ]]UB ]]]!J]KT]Uـ]فه]و١]٢٤]٥٩]٪٬]٭ٰ]ٱٳ]ٴ]]]]]]]]\Z V ] ]^^ YE ^  ^!)^*,^$-/^,14^358IR 9:^9;R^ATUIP VX^AY`^Hbg^Phi]mn^Wrt^av}^hڀ^nځچ^xڛڟ\ڡگ^L L LWML%*LPVPV!PV#$PV&*PV0PWMQjLvkmWM,^0=^@I^NO^WMWMWJt^^O O O XXXX^^!W:"CLPYJt^_^q^=^NN!"N)2N47NMONQRNabNgjNlrNtwNy|NNNNNNN+^0^VXVXVXVXLD)J{+,[f0IJ{PiMEpMNMN^PJK ;JK @H^PQZ`eM ^$&UN '*YH=>F JrsYHYHYH^L YH $MPgVijVLNUNLdNLdYH^V^]+^V VVYH9 OW Q RW U WW ` a_ b cW _ W W W _ W A  _ > BW G HW K MW _ W W W _ W _ > DW G HW K MW ` a_ b cW r sNE  u vNE  W W W NE  _ > DW F HW J MW ` a_ b cW x ~Jt _ W W W _ W _ > DW F HW J MW T V_ X YNE  [ \NE  ` a_ b cW q tNE  v wNE  z _ _ W W Jt WHO  HO HO HO (*O 29`@D`HKAI ` HO `WWWAI ``!W`'*3Zm:;UG <=NG q}WWRU WWMWMU WOR `'+5W;>WRU_VYWZ]ON ^`WcdWmef`-ghWim`-np\;qtWuXcWXcJt`6WXcWM`>*`E-;`LAF`RHK`RRS`Y[]`>_``bvw-xyA-z|O-}~EO--O--U-U--`i-`>`p`w`>``p`p``E`L`R```w``WmWM `*Z67`ST`` `t{````H-````l`w~``W24WRSWrsWW`WEK   Q0C\a]raswXLI aXLI aZ```a (W)+WM08WMPmWMptWMUE UE UE UE a%AP-a%AP-W TWMUWXXY^XXasWt|Wa+XWLOjLa1a7LU   A  A A  A 01A 4CWNOXa|MWWZWa=$%WM&5WPYJtZwWM~W}WMW:W:a=aDaPaPaYL WM LWMLWM #L&*L,BW:CjLkwWMyzWM|}WMWMLLLWMWMLZ1WMWMWM EWMHMWMPWWM`}WMWMWMWMWMND WMWMND WMND WMWM L!!W:!!?W:!A!B^!E!I[f!P!SNE !p!Y0!!ac!!aj!!YH!!YH!!LJ!!O!!LJ""L""R ""YH""YH""YH#6#zM##ap##ax##a1##N##a$$a$$ND $$a$$a$'$)a$$L$$W:$$L$$M$$Jt% %a%%a%%P %%P %/%0a%7%8P %P%QLJ%R%Sa%U%Va%X%YP %[%\P %^%_O%a%bO%d%ea%g%hP %j%kO%m%wN%x%{N%|%}N%~%N%%L%%MW%%M%%M%%N%%L%%O,%%YH&&YH&s&zOR &&YH&&a&&a&&Z&&a'v'ME''V''ME''ZX''Y''MW''a''YH((a))_))YH))_)$))O)4)5L)6)7L)M)NL)f)mYH)t)uZ1))a))a))YH))YH))ND ))O,**ME**O**M=**YH**!a*"*,YH*-*.N *0*1YH*4*5N *B*Ca*D*EL*U*VL*^*`YH*b*cYH*h*iAR *j*kYH**O **Mk**O**a**YH**AR **O++YH+4+7_+8+:YH+;+=_+C+Da+J+KZ1+g+hZN+w+xZN++_++_++L++L++a++P ++M,,_WM,b,fWM,m,pWM,s,tWM,v,{WM,~,WM,,a,,b--%WM-P-Qb--WM..b..OT .P.QYH..b&..b...L..b5..b;..bB..bI..AW ..bP..ET ..]..bX..Y..-..b_..N..-..be..-..AT ..-..bl//X0105bx00L00P00L1516`>1:1@`p1f1h`>1i1m`p1n1p`1r1w`E1z1~`L11`11O-11U-11WM11L22X2Q2Yb2[2_b2|2}X22b22b22M3X3pM3{3~b33b33b33MMMHE MMHE MMHE MMHE Wb*+bt{WMJWMWmT3 bbOT N !W/1LqxWM}~WMWMWMħWM˧WMW:LWMWM WM "WM#'W(+b05WC@fWMghX?ipWMvwWm_WJtWMb Jt %WM&*W+-W./WGRW`c`dn`poq`rt`Evw`RGA A A WXcAI bAI )6W@BZDKZLMW`o`6qv`6wyb|}AI ~bWMWWW۪MWMW0ZWM\_L`dWMfhWMpWMWJtװױ-ײ״O-׵׶-׷׸U-׹׼U-׽-`i`>``p`p```E`E`Lb`Lb`bbmbpbWsWs!(c *-c.0_xPQ_xRUcVYEH Z]c^ac"bec*fic1jmEH nqc7ruc>vycDz}cJ~cQcZcbUL ciEH co_~AF cuc{_cEH EH OT WO NlNWO LcccG  E U E c cEH c_EH  EH  EH c_AH c_ !AD "%AD &'AH )*IN +,c-2EH 36AF 7>AF ?DAM EJ_KP_QTEH UZEH ^c['diEH joEH puEH v{c|}EH ~AF AF AM __EH EH EH _AH c_AD AD IN cEH AF AF AM __EH EH EH EH c_cAF _EH ['AH IN c_cAH _cAD AD  cAH IN c_cAH _ c!"AD #$AD %)c-0c46_79c<=_xAEcPWEH XY_Z[AH \c_dfAD gmcnpAD qtAH uxIN y{c|}EH ~AF AM _cEH _EH EH _AM EH cOR "#O./c0DOR GHOR _xAW _xEH _xEH EH c_AH cAL cEH c_cAD AD AH AH IN cEH AF AF AM __EH AW _xEH AM !:W:AZLfoWMqWMWMWMWMWMWM X &X(:X<=X?MXP]McNZcNZccc\@Wc_acded fgcikd qrd uvZmWJtMWM #Y0-/WMPuWMvz[nWWMOWMWMWM0cWMpzWM|WMWMWMWMWMWMWM6W@UW`gWJLL@UWMX_M WM M WM WC Z M M WC  W  W F GNE  ` d Wm @ UWM X _M ` rWM x M WM N M HWM W: L M WM  !W " #Wm $ 'W 0 9Jt J MW P eWM p WM{}NE dOW WM%MJKd&LMd-UVWO pWMJW} _57LD 8EWdeNE qrLD stWWWMJt'0WEFW_Wd3JtM,3WW  _>DWGHWKMW^_L=`a_bcWflJtptWMWMWMWWWWL= _5AW_W_WWd3WmWO-W _0<Wdfd9jkd9WJtWO +W,6WW:LJtMWM WMWM/WM05W78W;=WPYJt_WW W 2WM49W:>\QADWmQZW^XXWmd3d@AU J`-`gW_/6W8;WDEdJWMWMWWM WM 0WM16W<=W@DWPYJt`eWMghWMjWMWWWWJtWMWJtW  _4:W>AWNE NlNE NlNE     B   B2   K  ! (L  . 1N  9 =SH  J LI  N PU  W mAG  { }U  dR  2  N  dX A2  d^!!I !!I4 ! !dd!!dj!!U2 !!!UD !*!+A !.!6I !9!=dp!C!Ddv!G!JGI !O!RM !X!A !!AL !!d|!!I !!d!!d!!AM !"U2 ""d""UM "!""A "3"8d":"=d"A"Cd"I"KE "P"QIM "S"_d"d"lUN "n"yd""I ""d""AG ""d""HE ""d""d""d""A ""AB ""AG ##IR # # ##D ##!M #$#%d#)#*R #,#3R2 #8#NRU #R#USH #^#_A #w#xdX#y#zA2 #~#A ##U2 ##d$$nW$p$tW$$B $$d$$IM $$UG $$2 $$dX$$A2 $$A $%AK-%%U2 % %!d%"%,d%-%0AG %2%5HE %6%7d%:%;UM %<%=R2 %>%@RU //W4245d494;d4G4UJaaWMaa)Wa*a,XXa0a9Jthj8djjOjjWMjjJkkWkk/XXk0k6Wmk7kEWkPkYJtk[kaMkckwWk}kdm@mBWmCmbWMmcmjWmkmmWmpmyJtn@nWMnnW:nnLo o I o0o1I oRoSeoToWooe ooeooeooeLe"e"e"- - ---"A-#*I-+1U-27E-8;O-?MWFG]9PQeTTUe^knN|ed̉̋ejW:ere{ LJNPeQΏ_)ΐΑLΒΓMWΕΖ\ΙΚ\ΜΝLΞΟMWΡ΢eΥΦeΩΪeέήe-Wm02X3=Wm?@WmBFJ^becjeqtev|e~πeχϏeϒϦeϨϫeϬϮeϰϴeϵϾeM eIX- "$ %&e*+LJ,-e./e01e23f67f89fFGM=HQO,RSf%TUZNZ[f+eiJjlf4mrJ{тJуфf>хыJєѕfJљњfQћѥfWѪѭJѮѯfaѱѲfhѹѺfsѽѾfѿfffffAYBETf`hfiqfrvWmW:3L4MW:NTLVgLhԛ[fԞԟW:ԥԦW:ԩԬW:ԮԵW:ԶԹLԽLLLW: W: W:W:7L89Y(;>Y(@DY(JPY(RkY(l՟]yՠo^p։W:֊֥L֨W:LW:LU[fV^JtY(^Jt fff CfDHeLReSTUP WYe[eegifnsUP xzf{|f~؄f؋،f؎ؓfؚؗf؞؟Yئاfخذfشظfؽؿd-YffYfd-ffUP fYf!'f*TfUd_2eهfوٶfٷfffffff_P] f g ]g !#f$&f-/^$;=O?@gBCgDLNNOg"QR^,WXg([\IP _`\cfN mnIP rsfw}g2ڛڟg:ڡگg:WM WMWM%*WMWMWM!WM#$WM&*WM0PJQjLkmJ,\0=\@I\NO\WMWJtWMWJtWMWMWMWMWWMgDgDXJtJCWMqMMWCM-M/;\<=WC_!"^)2^47^MOgLQRgLabgTgjgTlrgTtwgTy|gTg_g_LLLZ'1aggcXgs)W:+,J{0IW:PiJ{pJ{Mgz;gz@Hg`eOR %&ggYHND  $OR ijYHgggYH YHYHg9<VhkM=rsNvyNz{VLsOR ggJYUVVdeLfgLlmLnoLtuLvwL|}L~LLLggLOY?OgN(+YH/LNSgh@VY_^`ON cdhHefWO gh`-ipWO rtQXce hNe b"$`LhW``E%&LJh]hehehew~hehkOO Ahs  hzhLI hhehpte WMWWMWJtW "_r#%OW '(_r)+OW 23_r45OW 8:_r;=OW FI_rU^W`sWuve wyhJtJtWMWWM h:;A <=A ?AhksJtwhx|hhhWMWMW:W: L W:V=W:V= #W:&*W:bjWMrs W:   WMLWMNhhh /TA 0?h@EhHMhPWWU`ohpqhrshtuTA vwhxyhz{WU|}hhTA hhhTA TA hTA hhWUHO WUhhhh WM!=!>h!A!BW:!F!IL!!NE !!IP !!Y!!aj!!N #8#<h#=#>N#A#Dh#G#Hh#L#Mh#S#Th#o#ph##O##O$$F $$h$$WM% % N%%N%%N%%N%%N%%N%%N%%N%S%TLJ%V%WLJ%Y%ZLJ%\%]LJ%_%`LJ%b%cLJ%e%fLJ%h%iLJ%k%lLJ%m%pRC %q%s_2%%ND %%ND %%h%%i%%YH%%M%%M%%M&s&yi'v'~Jt''^''V''O))O))i))O)$)&YH)'))ND )4)7i)f)mY))N))O))YH**Z'*V*WR*b*cLJ*h*iYH**R **O **Mk**N++IP +4+6O+9+:i+;+>O+g+h_+w+x_++O++ND ,$,%L,T,UL,o,pL..i#..bl..bl..bl..bl//i*//i*1t1u`L22OR 3X3pOR 33OR YA W OW  _rOW _r !ND 02W: LLLZ#'W(+d301NE 34NE ghWM_bJtbLMZ|}b~i4AI W79 =>i=ADLKLLNO TUHI VY ]^ W`EEN *0YHPQiJiQYHiYi_h__AH ilE U iuYHcEH 'YH)ZYH^YHYHYHYH YH)YH-0YH49YH<=YHAEi}PYHilYHYHYHi}O0DOGHOYHiiYH!:WMAZWMgoL`>`pi@BNE EFiNOivzWMN O(-N.3OILiZ  LL S ]^NE  ` |WM } ~M WM M ^ _NE  ~ NE  _  i  i  i  i $i + ,i / 2i < ?i G Hi WM WM NE  d eLD  LD [6ZZZUVOOT WO WO 57KE>A_qrKEstLD _NE CD_bc__WWW:=___YHLJYHN\58_dfYHjkYHih@12_WM05W78W_ W;>ZYZ_WMWYHWMiiiID-OW-OW-deOfgi46_16W<=WWWWii  O> O>  O>  O> ! (O> 0 1Oj ; =b J LO> N Ob W mi O> O> O> O>!!O>! !O>!!O>!!O>!! O>!.!6O>!9!=O>!C!Db!X!O>!!O>!!O>!!O>!!O>!"O>""b"3"5O>"6"7b":"<O>"I"JO>"P"QO>"S"_O>"d"hd"k"li"n"wB2 "x"yi""O>""O>""O>""O>""b""O>""O>""O>""O>##b##b##O>##!O>#$#%O>#,#3O>#8#NO>#R#UO>#w#zO>#~#O>##O>##O>$$$%Nl$.$/Nl$2$3i$6$7Nl$:$;Nl$<$?N$A$Cj$D$EN$F$Ij $R$SN$T$Ui$_$`NE $a$bLD $c$dNE $e$hj$r$t_2$$O>$$O>$$O>$$O>$$j$$O>$$O>$$49 %% 17 %%48 %%O>% %!b%"%,O>%.%0O>%3%7Oj%:%;O>%=%@O>4245T 494;T 4G4Tj%aa(Wa*a-WhhV hWh hh hie ifj jj8 k0k6IM k7k8OS k:k;OS kW:@DW:JPW:RkLlՅW:Ն՟LՠչW:պL]s;[fej?AkBDOX EGkHJkKP]RTRM UXkY\k]dkeiLRjmLJorOtvejxzOX {}k~ـkفن]وّd&ْٔkٕ٘lٙٞl٠١ZXٴٶlٷٸd&ٹټkٽlld&klld&lRM l lf l"#g%&gHIfKLl%L SH 0PLQjWMkmL,WM06e 7<W@IJtMl0NE \/;M<=NE Y(Y(Y(170-8>1-?E2-FL3-MS4-TZ5-[a6-ci0-jp1-qw2-x~3-4-5-6-)WM+,W:0IWMPiW:pW:WMb;b@HJK iNL !J{YHNUT 9<YHrsT vwLJz{^l: lC lIlRl[la#$lg01lo35lxCDl\]lfilkllrsZmLdLdlUV^efY9mnY9uvY9}~Y9Y9YYedYHYHWMf%ZWWm;mBmB  !L 0 1d ; =SH  N OU  W mO>  dR !C!Ddv!i!jdj!u!wE !! !!M !!mK!! ""UM"["]HE "d"hO>"n"yO>""HE # # ## #,#- #2#32 #N#OmR$2$3O>$:$?mX$A$ImX$a$bma$$O>$$UG $$AR $$E $$O>%% O>%%O>% %!d4G4TT a*a,h@hhON h h ON hhA hhEN iiOQ e e O--. ND  M03mk78mkBMCKMLQMRSMTXMYaMbgM}~Yn1MW!MW!MW!MMMn7OOK[\pqYHz{YHYHn>rsW__RS__`_cd_noJstJuwJxyJz{J__YH nEghiime tuNvwOxyNz{OYHY Y !!YH% %MW%%ND %%L%%MW%%ND %%L%m%pND %%MW%%nQ''Jt))i)))*Y))nZ**R +<+=i+w+xO ++N//M3m3pnb33nb W hhjPABYHCDMTVOW WYN,-ND Z1WL_xZ1YHZ1diZ1Z1Z1QSYHU[YH]eYHghYHjmYHotYHvYHYHYHYHnjZ1npZ1YHYHYHstOND ND ND WW < =b Oj Oj!u!wOj!!Oj!!Oj!!Oj!!Oj"["]Oj##Oj#,#-Oj#2#3Oj$2$3AL $:$?Z`$A$IZ`$a$bNE $$U$$O>$$Oj$$Oj$$AP % %!O>hhnwh h A ]9ΐΓn}ΔΛmΜΟn}ΡήfГДnЩЪnI nPQMWTUanjP$?o$B$Co $$Ojh h JI ΔΛn}Ρήn}ШЪoo#&o%-/k01o-79k@AUT BCkXYo%؞؟knkkِّNOo5o5o5 R efajuvaj}~ajYf@[g<^^`jgqqOP ssLuyg{ghhNii[/i(iBl i  i  i  j   Fj H Jj L cj e kV k k l lZ  lx l l l  l l l  j  2  mR  ml  (mv * 0m 2 3m 5 6m 8 9n < <p > Bn  G Hn" K Mn, Q Q Y \n: ^ ^ f vnL n n n n o. oL oV ol o o  o o o WO-  p   p  p<  (pF * 0p 2 3p 5 9p < Dp G Hq K Mq U Wq \ ]q* _ cq4 f wqJ q q q q q _ q q q r r6 rL rZ o x rl r  r  (s * 9sd < Ds F Hs J Ms V VI  X Zs \ ]s ` ct f ot w t@ tj t t u u. uD uj ux I  u u u u u  v  Dv& F Hv J Ow T cw f w^ w w x  x  x  x E g x h x y:y"?[z zezz{{b{x{{ {G|Il|q}|}~~~ "&(+-JLFOj&0(^al^|H&JMPVXXdZ],`>|Z]]_df|z:T n  |||||#%359;;|==|??|AA|CC|EE|GH JPRV4XX|ZZ|\\|^^|``|bb|doJqs|uu|ww|yy|{{|}}|||||||||||||| 2||@j|||||||x||||||||||  |""|$*,.00|22|44|66|88|::|<= ?A*CM8OO|QZf\]__NaaNcgiz|\EnG LZr60@S`lnprs(2 xdPtnaaan +0;@@pDmPpt,ZYT[^F`bXdpfr|"\z (?:AL<Nnnp6@JXfpz7<<@>IMxz}LZ(2HRhN-/029;BDJ@LQ^SWxYqsrjj EHMPW8YYi[[]]_}Z>>*P3>v    ON-     ! !LJ # 1 3 4N 6 dX f q t H   v !! ! !(!!B!!%\!'!/!2!<!?!A!C!E!G!_!a!d!!!!!!.!!!!!"$" ""!"$@"&"*R","0h"3"B~"D"DOT "F"G"I"L"N"V"X"`"b"t("v"v""""""h""r""W"# „# #º##\##ņ#$p$$)Ɗ$@$A$$C$J.$`%mP%p%ˊ%%EFT%%4%%B%%%%%%%%%%(%%ۄ%%2%&9d&;&ir&l&{0&}&r&& &&&' '' ъ' 'Ѥ''Ѳ''N''N''''N''"'$','.'6 '8':0'<'C>'E'F`'H'Ij'K'St'U'YҚ'['[L']']L'_'aҰ'c'Ҿ''N''Ө''Ӻ''''z'())") )@))R))d))#n)')'L)*)?٠)A)s)u)))ۆ)))*;*=*A*D*U*Y*^@*`*Z******(**.**`**P **v***++++#+$>+&+)H+++3Z+5+8+:+;+=+E+G+J+L+]+_+f+i+s@+v+v )+y+n++ND ++ G++t++++\++,, ,',),8 ,:,WN,Y,r,t,u2,w,<,,b,-%0-'-' W---- p-0-5-7-<->-?-A-D$-F-Fb-H-I6-K-U@-W-bn-d-g-o-p------<--Z--x------------ A......]....\.... ..////~////2/0@0000202 040?0A0AL0C0CL0E0EL0G0GL0I0IL0K0cB0e000L00L00&00@00 Y00 Y00^00L00L00L00L00p0000L00L00T00n0011/111D\1F11112.2 4MNvЦ+@  ID  ID .001r3t|v| tȧ ͧ !,!$09"@u",wwLJ#Ϩ$ $NS$_v&x|&&˩ $hͩ $nϩ'ީ'6(t@A)RCM)\PY)\\ $^)۪+J+ ++ &, (.,(0=,F?@,BH,JM,OOAR Qk,p-(/" 'ףף 'װ׻/L׽/~// (Nۀ0l0v0m0p6H7868&8:8<< )>> )@A8CCZF8:~:&;(<( , ?:(?*Q@"T\@^^ +af@hiAknApqA suA*w{A8}~ANAXAfAp +AAAAAH B*BhB 2C 4DCZFJCLOCQRCTfChkD ptD2vDHDv 1FdHI4IZItIIIII J &J6(:J<=J?MJP]K6KpM^3Ml7EN"GMN`PcN~ehNjqNsOOvO 8OPdPQ#R-JRPzSSTFTUWWXL'X0cYozZR|ZZZZ[[V[t[~6\P@Ua.`ga =aaab  ?)bbb ?o 5b78cL<< ??UcVW]c_mcodZdZdhZZZZd~AWddde e  9e ? Yf  fz g8 gZ g  hv h  h  5h 8 :i& ? Hi4 P Qi^ S Uih W Xiv ` i j k  kB 5kL 9 ;l& = Ul4 X rl x m mr m i  m  m  m  #m % *n" , 1n< 3 >nV @ Hn n n o6 ox o p pB   A  'p 0 9p @ eq i jq l q r*`~r4rs\sjstssZs sstt't0ItNKLtNYtptNuVulu7v 9FwHHLJJMw<RuwNwLJx EKxyN4yx6@zNBGz|Pvz{4|J|}7}P9:}<A}~  F<~(~:~x~ (*0V23t59~;DGHKMPP FeWW Fp]] F_cflpt   F FJ F F *LJ@JJTL[]a"&HIU@zBDPY`dfill H;FXA+0<>F;B4  H 578J;FTPYACGP$ * Ig< Z`gd: 6`8@BE<PlNpF  6:: Jc<=?GPY`egh(j2X35:(>BBDDLJFHXJKfMM JOZp J L*  l " , . ; = CN E Pl R x { < j   0 v  !!! T!!v!!!!!!!!!n!!!!!!!!!!H!!!"""""+"-";"="O"Q"S^"U"[l"]"e"g"j"l"""p"###'t#)#M#P#bD#d#$$#l$%$-$/$5$$7$QB$S$n$p$q"$s$t,$$6$$$%)%+%C//>04B4D4H4J4M4O4O eY4Q4Q eh4S4U4`CDFF~aa9hj8 j@j^lj`jijojjjVjjjjjjkkEkPkY,k[k]Vk_kadkckdrkfkw|k}km@mmmomyn@nnnjnnooJ6oOotdovovUoxooo@oooopp 0 k0112"2&22 PR6UU dg6p6="=T$+=/5=7j=pu>w|> > >?/?245?:;?@|@̛@̝AtBFG>*GH,ΏGΠΠ hίγI0κIFI II I JJJJ&-J002J4FJPχJωϲKϴLvrLtЀNЂЂLLOЄСNУУ ХЧO6ЫODOP PjPt!P#&P)dPfѓQѕіRјѭRѯSETUUlVU`xWTWVԜXԞԟYԢԢ aԥԦZԩԬZ ԮԹZԻԻ ԽZNZl [r [[9[;>\6@D\HFF JP\^R֥\|֨a bGcfIׁdL׃׻e2׽ffVghg#g%3g67g9KgMM OO QSh@U\hN^nhpppNrrNth؁؁N؃؋h؍ؑiؙؓi$؛إiBادipرطiعijjLjjj|"j% kH ڋnڛڟpڡگpq8%*qq 2 q!r,#$rJ&'rT)*r^0mrh ,sb0=t@ItRNOt|t t ttt uv w0wwxxx.x@xJx{{G{IK}PY}^_}8q}B=~TJ\!"$$ '' )24799 ;; BB &GG FII eKK MOQRTT WW YY [[ ]] $__ Lab(dd sgj2lrDtwby|t~~ `+j0*ho  $;$@HPQ`e$ && ( #%"< ,*>4 3oqqNuvxx 7}} 8Y 8YBP^,> `!"$$ =&,./1PRVXXOT ZnpZ "0>H^Mlv @Z GPTWY`dglotw|*D @^ AA. V- WP`mp|$ N L~?BJMUX`ckm|B Q V ߦ V/ VQ?@\ V Vέέ Vΰΰ V W W3]] WVf d,JJ dOPP dq##4y4y d d l d d e e:**Z@**Z1**L**OdprYHhiWM**Z@**MkYHY02YOWMWM02WMprL89WM\]WMdgWMhi WMWMWMWMWMWMWMWMWMWMWMWM""O""O))M=**R **Z@**Z1**Z@**F +^+_ eW+z+}ZN++ZNDEWM__ e]!!dZmZm03ZN U02 UEGYND WMWM WM WM*-WM01 JKWMvwWMWMprJ WMWMWM./WM89 LSWM\] dg hiYHx{WMWM WM WM WM WM WM WM WM WM WM WM WM ""Z@""AR ""AR ##Y)) O)R)aY?))ax**O**ND ****O**O**Z1**R +^+_O+z+}_++_++WO-DE JKWMPQWMVWWMfgWMȧWMYHYHYHS  : =WO !!O>pw_ZmMOL /ZN03_Y\+02\+EG UMOO   WMWM !WM?@WMPQWMnqWMz}WM  YH YH WM&'WM*- ./WM01YHIJLvw ecWMWMWMWMWMWMWMWMWMHE  #WM()WMYHprWM x ~OR _NWM  WMWM WM WM"%WM*-WM./ 27WM89YH:=WM@KWMLS V[WM\]YH^cWMdgYHhiOT jwWMx{ ~WMWMWMWMWM YH YH YH YHWM YH YHWM YH YH YH YHWM YH YHWM!!L!!O"h"iZ@"u"vO""F ""Mk""F ""Z@""T ""T ##LJ&&WO-'7'8N'J'KN'O'PMW'n'oY'' 0|'' el''h))LJ)) ed)R)aYH))YH*{*~Z@**Mk** et**O**Z@**Z@****Y **Z1** et**Z1**Mk**F **O+^+_Y+n+sZN+z+}O++O++N++_,`,aWM.W.XM=PQWM\]WMWMOW :;WM>?WMBCWMDEYHHIWMJK PQ TUWMVW XYWM^_WMfg e|WMǧ ɧ []YHYHAH _AH _AH _ e : =_YH!! pw ̐̑Od̔̕_̦̩N̮̯NhhOd e j\ ej\NOi%*YH MEND NN OOO /_03ON UNE 02WO 3G\+KMYND  W! WM   WM WM ! "/WM46WM9>WM?@ AGWMLOWMPQ TmWMnq rwWM{| WMWMWMWMYHYHOT WMYHWMMWMYH         WM$%WM&' ()WM*-YH./ 01OT GIWMJK LNWM`|}WWhiWMlmWMvwYH|}WMOWMHE WMA WMWME WMgWMWMHE  eWMWMWMWMWMZWM WMYHWMWM !L "#N $'WM()N ./WM_YHAM prAH YHYHYHYH x {DD  | ~ e e    YH  WM YH YH  !WM"% &)WM*+ ,- ./YH01WM25 67 89OT := >?WM@C DK LSYHTUWMVW X[ \]OT ^_ `c deyIfgzhinpjq rw x{YH|}WM~ WM  WM WM  YHzYHzYH eYH e WMYHzYHz  YHzYHzYH eYH e YH eYH eWM WMND ND ND ND ND ND  9 :Y E FM= Y?!!LJ!!O!!O!!YH"d"gZ@"h"iUT "p"uZ@""F ""YH""F "" e""O ""F ""R ""UT ""ND ""ND ##ND ##ND ##O,%%P-%%h%%OM%%h%%L%%Zm&&N|&&AY '6'8Y'J'K$'O'P e'Q'RMW'['`z'l'mY'n'oY'p'qY'r'sU''ZN'' e'' e'' e''-''L''N''LJ))O))LJ)) O))O)) AR )?)@P)E)FO)R)aY)n)oY?))M=)) e))Y))RC ))Ld))N))Y*y*zZ@*{*|YH*}*~R **O **Od**Z@**Z1**Z1**Z@**Z@**Z@**Z@**d&**Z@** et**Od**Z1**OT **YH**O **F **Z1**AR **Z@++L+\+]O+^+_L+i+mZN+n+s_+z+}YH++ZN++Ld++YH++N++N++O,`,a ,g,lWM,,WM,,WM,,WM,,WM,,WM. .!O.U.VM=.W.Xax00N00LJPQ eXYWM\] AlmWME  _rh./WM:;V >?LZ@AWMBC DEZHI JKYHLMWMPQYHRSWMTU VWYHXY ^_ deWMfgYHWMWM     WMWMǧYḨ ΧWM֧WMWMIJ NOYHfgm[]JYH*,YH12YH:;YH_xYHYHYHYHYH e` : <bWO S-EFL!!bpw\Z̐̑YH̔̕ ẹ̢Y̦̩V̮̯V_Zm ZmYH   NOmPQiبتk%*ID- VfLYH<=Y>?MWCD eXYYZ[Y9\]Y^_Y9pqLvxzYNNNNlNiIX N YHYHOYH /O03YHMeOOP h elO\+ 802 83DWO EGNlKM fGJO NPO ]`O dfO hogM\MMWN\\    YH    YH   !YH"# $' (/ 45 67 9> ?@YHAB CG LO PQYHTY Za bg hm nqYHrs tu vw yz {|YH}~ WM   WM    WM    zzZ1E    ZH   Z1E ZYH $% &'YH() *+z,-O./YH01Z123 ;< ?@YHABWMFG HI JKYHLM NO  e_rOW  zrsWMvwWM{} fND WM f fdgWMhi AjkWMlm AvwLJz{WM|}h WMR HE YHHE E A YHA WMN WsYHWMS E WM A WsHE YHWMHE HE A L N WMM  WsE HE E WM  WM   YHHE HE  eZA WML WM #YH$%E &' f()YH./L JZ[LNlYHYHYHoqND qrMW{ND WO NlLLYHNl_ N x ~ fI _W]^WN f&lqYHtvYHYHYHYH f6 YH YH[YH f6YH ! "%YH&) *-YH./z01 27YH89np:=YH>? @KYHLOOPS[TU V[YH\]np^cYHdiND jwYHxyOz{[|} ~YH YH YH YHYHYHzND zND  eND  eND YH zND zND YHzND zND  eND  eND YH eND  eND  YH  f? u fG fMu fG fMu fG fMu fG fMu fG fMu fG fM  ER-  LR     LJ    9 :Y E Fax l mJ O YH!!O!!WO !!O!!O!!OP !!N!!O!!YH!!O!!O!!YH!!LJ!!M"C"D fZ"F"G fj"H"I ft"d"eR "f"gb"h"iOT "p"qOR "r"sR "t"uOR "|"R ""R ""OR ""OT ""R ""R "" f|""Z@""R ""R ""OT ""MW""F ""F ""M{#)#*Y##M^##O##M##M##M##U##Y##YH$'$( f%%O%% G%L%OLJ%%NE %%P-%%Y%%h%%Y%%h%%OM%%Y%%h%%Y%%h%%Zm%%N%%_2%%N&|&} f&&YH&&L&& f''N'#'$R'&''N'-'.T'7'8 f'9':Y';'=$'I'K'O'R e'S'T~'['`o{'b'con'l'mY'n'oo{'p'qY'r's^'t'uM^''_'' f''ND ''Ld''N''N''gL'' f''ej''N''LJ''U'' f''O))YH))O)) YH) ) LJ))O))O))LJ)) O )9);RC )@)AO)E)FYH)R)SP )T)UMW)V)Wa)X)YL)Z)[P )\)]MW)^)_a)`)aL)n)oYH)q)sZ1)x)yZ1))N))ax))N ))ax))O))U))Y))O ))LJ))YH))ZX**n*9*;W*Q*RYH*Z*]YH*u*v f*y*zYH*{*|~*}*~O**YH**Z@**OT **ND **O**L**Z1**YH**Z1**O**Z1**R **Od**OT **Z1**OT ** ft**Oj**Ow**YH**Z1** ft**OT **N**R **LJ**Z**R **N++_2++Me+@+AZ1+F+GL+K+L+S+Th+\+]YH+^+_i+`+fZN+i+m_+n+oN+p+sO+z+}LJ++ZN++_++ME++-++N++ND ++Y++Zm++Y++N++Zm++YH,`,aYH,g,h ,i,j ,k,l ,r,s ,~,YH,, f,,LD ,,WM,, f,,WM,,LD ,,WM,,LD ,,WM,, f,,LD ,,-,,LD ,,WM,,WM..W. . N..OW . .!AR .&.'V=.U.Vax.W.XYH0 0 LJ00N00Ld00U00N00U00N00 f0.0/OT 0304Wm00 _2H2ON DEWMJOWMPQYHRWWMXYOZ[WM\]O`kWMlmLJYHWM WjPPt"%WM./ f:;YH>? @A BCYHDEND FGWMHIYHJKNLM PQZRS TUYHVWZXYYHZ]WM^_YHbcWMde e|fgZy|WM~LWM   WMYH WMLD §WMǧO̧YHΧ`ЧOҧWM֧W!اWMLZ:<YH>? IJYHNOOfgYH:;AF CDE '(_[]_x_ EH ),EH 12EH :;_ST_EH iEH EH _EH _EH W9:U;<Ld=>LJCDN]^U _<=[D   e OT  : ? eCDYHYY^ g ]sHJO-PQYRSY9TUYVWY9X_Y`aYbcY9deYfgY9pqWsvxo{ g&-. g/ g5]sNNNiIX NYYYLN NLYHN /YH03Me47 g@@CNPTVWYV`dNptNx|NN gHYH e eed d- gP \+ gW02nb3G 8KM\+GHMIJMNPM]^M_`MdfMhkNlloNE NE ZmN fgO O ZmNE MWO O O ZmNE Zmf YH  OT  YHOT YH !OT "/YH23Ws47YH9>YH?@W!AHYHJKWMLOYHPQLJRSWsTmYHnoMpqLJrwYHyzYH{|OT }~YHWYHYHWMYHWYHYHYHWYHYHND ND YHND YHYHYHND YHND LJPtLJPt LJ  Pt  LJPtLJPtLJPtzWMYH"#WM$%YH&'OT ()YH*-ND ./OT 01ND 26YH:<YH?@ 7AB`FIYHJKd-LOYHfgYHYHZm`gZmW_rOW zW^aa W!"d-./ e23OW 56Z78 g_@AWMNOpqWMrs\tuY0vw gh{} gtYHYHYHYHd-\WMhWMWM gt`cWMde AfikjmIG nuWMvwlxyWMz{_|}YH~WMYH g{YHW!YHOYH gYHN W! eYHgYHE YHOWM eYHYH gYHYH YHWMYH eYHZYHLJYHND YH gLZYHWM g #W!$'YH()L*-WM./YH g#$W>?_Z[ __xPtOT -\]_oqWO W g$%OrsW!wx_z}OT ~L_Wm____L_NYH_P g V W g U V g x ~F  g g S- - g  IG  gR̭GO  eYH g]^ g!#ZmGHhe?@he gSS  g gOL YR  g hZ[OW WmZX aOpqYH;ER-yz h WMX_XaPYHNMZmKLNTUZmlvW!{YHu u YHMOT Od ND   OT OdYHzND zOND OT  !YH"%OT &)YH*+ e,-O./ND 01YH23OT 45Od67OT 89ND :;Od<=z>?YH@GOT HIOdJKzLSND TUYHV[OT \]ND ^_Od`mOT noOdpqzrsztuOvwzx{ND |}YH~OT YHOT YHOT YHOT OdMOT d-ND d-ND OT ND d-ND OT d-YHND d-ND OT d-OT d-ND d-ND OT ND d-ND OT d-ND d-ND OT YHOT d-YH hYHND  ND ND ND "'ND */ND 27ND :?ND BEND JMND RWND bgND joND ND ND   M   o{ $ %OT  9 :o{ E FYH X ZOT  j k h l mZ` n oJt Y? Od O M _ Y O! ! W:!!W:!!W:!&!'HM !!YH!!l!!_!!YH!!ed!!YH!! e!!N!! h'!!YH!!LJ!!O!! h/!!LJ!! 0|!!O !!N!!O !!O!!_"" Mr" " S "%"&O"2"3ĸ"C"JMk"M"N h9"V"WMk"_"`Mk"a"b hE"d"iMk"p"qMk"r"u h9"|"}Mk"~" h9""Mk""Mk""MW""m""Mk"" hP""YH""O""""R ""Mk"" h9""_2""M""M""YH# #!Zm#)#*Y#f#g h\#q#r hb## hi##]@##ap## ht##ax##OX ##YH##YH##ND ##M^##^##LJ##O##Y$%$&Z`$'$( h|$$-%% h%-%.a%1%2a%3%4ND %5%6P %9%:P %;%O%@%BM%C%Da%E%FP %G%HM%I%JO%L%O h%%Y%%L%%O%%Y%%L%%Y%%L%%Y%%L%%Y%%L%%Y%%Zm%%N%%Ld%%N%%Zm%%Zm%%Zm%%L%%MW%%N%%L&& h&&Y&:&;V&=&>f&p&qJ&|&} h&&N|&&Z&& h&&AY && h&& h''k''Ow''N(''J''\''J{'"'%'&''Y')'*N'-'.Ld'6'9Ld';'='J'K h'O'RN'S'UWm'X'ZO'['`Wm'b'cWm'h'kYi'l'max'n'oWm'p'uax''L''L''Y9''L''AG ''YH'' h''M=''Y''^''Y'' G''N''LJ''ed))O))ed)) M) ) O) ) h))O ))O))O)) h)) Ld)')(Y9)-)0Y9)9);P)@)AN)E)FOj)H)IL)R)YO )Z)aed)j)mN)n)oY)q)rL)s)tO)x)yL)|) e))M^))N))Ǭ)) h))YH))M))YH))Z@))^))YH))ND ))O))HE ))_2))Zm))Zm)) h))Zm))a))Y** h*-*.Zm*4*5Zm*9*;N *<*= h*L*MYH*Q*ROT *Z*[W!*\*]M*h*iO*u*vOE*y*zN*{*|Wm*}*~Mk**OT **R **Mk**OT **R **Od**O**OT **OE****Y **O**Mk**OE**Mk**OE**Mk**YH**W**OT **OE**O**Mk**OX **Mk**Z1**L**a**OT **Mk**O++N++ Ld++Zm++N++L+"+#Ld+%+(N+,+-M+.+/O+4+5O+9+:O+<+=O+@+AL+E+F G+K+LO+Q+RL+S+TY+\+]M+^+_L+`+f_+j+m 0|+n+oN+p+sO +z+}M+~+AB ++_++ h'++N++ f++ h++IP ++L++L++Ld++O,++Ld++Y++Ld++Zm++O,,(,)IG ,X,YIG ,`,aLJ,g,lYH,r,sYH,u,vZm,~, 7,,WM,, ,,J,, h,, ,, h,,J,,WM,, C,,J,, i,, ,,J,, f,,J,,b,, h,, i ,,~--IG .. i. . i#. . i2.. i<.. iD. .!YH.".%Zm.&.' .(.)LJ.,.-OT .:.;M .U.VYH.W.XLJ..bl..bl00 Y0 0ej00 iP00^00 iP00^00M=00o{0*0/W0304M00 i\00 100 12H2OLd33b@CWMDELZFIWMJK icLM inNOVPQ -RS ATULZVW AXYkZ[ iu\]k^_WM`aLZbg ehi i~jk ilm i~pr~yWMW!WMLJ C WWon"% i&-WM./YH29WM:;M<=WM>AYHBE_2FG 'HI_rJKZLMYHNOWMPQaRSYHTU iVWaXY_2Z[ \]UM ^__2`aWMbc ideYHfgahoWMylLlWMYHYH iOWMYH` i§ iǧZ̧_2Χ _ЧlҧLJ֧ iا iڧWMZmqrWMtu\Zb\:< i>?YHIJ iNOMWfgu 13YH56YH8<YH@AYHCDYHFJYHLNYHi} *Lc *LdZ^h@ *L,Z-3^4;h@GIS-RW^Z[Z\]^^_Z`a^fgZijZnoZrs^tvZx|ZZ^^ZZZ^ZZ^Z *L',Zm34OW 78M^9:^;< iP=@YADejEF iGHM=KLlMOOW [\M^]^^deZ@ *L_`Nbcej i\ i<=KL 8MN ARS 8TV A]^WO lpirsi} j j gYHYHYHwxY 8 gH : "P"Qd^"]"^Oj""b$J$NSH $]$^Z`$i$nmX4>4? j&4C4F j.4N4OM4S4TND EEZjjID nn\oo 1!"YH,- => prMsuOO-W j4 j; YM56f9:fBC jEHI_VY jQZ__`c jYehYknfpsNtwOx{ jà̃Y̎̏L̐̑ e̒̓_̔̕N̗̜U̞̟Y̡̠ jQ̢̣ ji̤̥Ţ̦N̨̩O̪̫V̬̭V̮̯N̰̱̲̹N̺Y J J]9YNN N  h eN  ϠϡLRϷϸLRNOEO ТУ jrФХ jzЬЭ jEO ZbxOd jkkW!23k:<W!LMmNONPQnTUn]^knokpqO rsk؀k؁؂O ؆؉W!ؓؖk؜؝kؠأkؤئW!ةتN0رسMعػMMW!MMkkWO ()l٦٬n٭ٳnnn78LopIP  u  YHu %*L()IG HIXX!F F F F F  JtWff%YHT j$% jFI jJLgOP jdeN km j^N j  jO23M=:=ED >?NCDNlFGJ{~ jY jY j j j j ( ( jL>@AT HJ jPWYX_ k`gYpqT tu kvxWm~ f k k k"bIF  ! k+%& k+,/F wzZ`MWNNLLJJNLdLdLdLdLdME O, h # k3$'N(+]s,3N47 j8;MNIGNIGNIGNIGNqyPyVrx r~  l yCsaqyPlyVyCr~yP !l"#q$%r~&'sa()p*+q,-yP./yV23J45r~67q9:rx;<q=>yC?@OTABsaCDrxEFqGHyCJKNGLMqNOyPPQrxRSETUrxVWqXYyCZ[rx\]r~^_q`ayCbcqdeyCfgsahipjkqlmyPnolpqrxrsyVtwr~yzrx{|l}~yCn7IXOOKOOKORNIOOKWOOOKORNOOKsaIVE ksyCyCqrxyCrrqsayCyVqyCrxrrrxrryPrryP rr  yP  rryPrryPrryP@OGHyC"#U$%OOK&'l()q*-q./l03q46URL89 >:<sa?@AILABTOPFIsaJKAILLOsaQR}abfgOOKqsOOK~xsa > > > ky kINGTOP kn>n>oINGACKIGNlARARK kONE kn>  ll@&@)1@23INE48R9<@@AARKGI@JLlMN@PQlSV@YZ@pqETArs ktuIGNvw k{} k k k k k k}@ k k k k  k k kHEIEIHEIORI k kEI k kHOAN k89`a}FbcATdefmUSnoSIpqSIrsITAtu vwn>xyKz{}F|}~H~T k kIGNAILIGNICK ksaOOK ksaA kHEOOKA ksa kSE ksaHHAHE kyPOOKAILOOKAILHEAILyPqEyPsqZEqqqqqrxq kqOOKsaEJEJEZJE JE  JE  JEJEEOOKHAHAAEAEA #OOK$' k()OOK*+ k,-CHE./ k[\ARK^_ARK`aYBIGNOTOTAFEMUNE kODOOT  IGNARK"$l>?lSTlZ[lklsl@lll@ll@lEU kEROTOP@TOPo l#$ l&'ESTl\_l`a@bclfg@kmloqOTSrvlx{lONEoIGNUT A!%&'(*Y[ARKpq9rssatuEwxOTz}l~ING}OT@l Cll@@ll@El@l@ z$      E G I K S Tn> d e l    l IGN l V WARK IGN U VARK x ~OUR z$ ARK ; <I l l" l* l2 l: lC lL lT l\ ld ll lt lz ltAMUNGA  GO HAD l>? l lAN lANEAT l lAIGNOTS l!"'(+,AJK lIGN&'/AIOS]`ARKefo l lO  EIIIOOOAAA!$ING45OO:;WE<=WI>?WII@AWOBCWOODEWAFHWAAIJQROOWXWEYZWI[\WII]^WO_`WOOabWAceWAApqOOtuWEvwWIxyWIIz{WO|}WOO~WAWAAOOWEWIWIIWOWOOWAWAAOOWEWIWIIWOWOOWAWAAOOWEWAWAAOOWEWIWIIWOWOOWAWAAOOWEWIWIIWOWOOWAWAAHWEHWI lHWO l!"HWA#$ l+,OO/0WE12WI34WII56WO78WOO9:WA;=WAA>@BCENOWAAPR[\WAA^_HE`aHIbcHIIhi{|UIFGARKR l k56 lNE l lWIWIIWOWOODEARKAUAOETOC?@AWXAIZ[AcdAqrI@l@lIGNll@A4EK #doq l}~ lAAAAAAAAAAAA;Ayz l~ lEJEIGN m G7 G7@ G7`gAIL) m lE./12:;CDKLRUXYlvp{saOOKOOKOOKOOKn>l@lqEFT@@l@ rx  l @q@rrrx@yPl !q"#l$%@&'q()q*-@.1rx27@89q:=@>?rx@AlBC@DElFK@LMrxNOqPQrrRUrxVYlZ[@\]q^_@`albc@dkllw@xyrxz{q|}p~@rrrxql@lqlr~@lsa@lrxrrlp@rxrrlp@lprxrrlp@l@lrxrrlp@rxrrlp@lrxrrlp@rr@lpLOOP&XIA{*  &  XIA{*&XIA&XIA"#&$%XIA&'{**+&,-XIA./{*23&45XIA67{*:;&<=XIA>?{*BC&DEXIAJK&LMXIARS&TUXIAVW{*bc&deXIAfg{*jk&lmXIAno{*{Nf{Nf{Nf{N{*{N{*{*{N UAD  oh m  ARK    ASH  INE  ARK ! m  " #b $ % m' ( )s * + m. - . m8 0 1IGN 2 7 k 9 %@%F%G%J%K%M%N%O؀%%n}%%n1%%n}%%mr%%%%ILL%%%% _%% m%%i%% m%%i%% m%%%%mk%% ?%%mk%%mk%%mk%% ?%% ?%%nQ%%nQ%%i%%&&TAR& & ODE&& m&& m&& &!&#IGN&9&;ACE&=&>OON&`&gUIT&i&jOTE&k&l m&m&oIGN&p&ql&s&y m&{&} k&&LAG&&IGN&&mk&& k&& m&& m&& m&& n&& k'' n ' ' AND'' 0''IB''ARK'''' l'"'%o'&''TAR')'0TAR'1'3o'4'9TAR':'=o'>'A n'D'F n'G'H n('I'Ko'O'R'S'Un 'X'ZAR'['cn 'h'un ''IGN''aj'' k''aj''aj'' n0''OT''OT''OIN''ACK''ACK''ICK'' k'' ''aj''aj''AR))sa))AR)) sa) )aj))AR))sa))sa))AIL)) )!)"aj)')*aj)+), )-)2aj)8);aj)>)Daj)E)F@)H)Imk)J)Q m})R)aAR)j)mASH)n)omr)q)raj)s)t m)x)yaj)|)AIL)) k)) )) k))7)) d))OT)) k)) ))7))P))OWN))l))AR))b))HAN))mr))̚)) ?)) ?))U)) n:)))) ?))aj))))))mk))o))LUS)) k** m** m**OLE** m*"*$l*%*&@*+*,OTS*-*.mk*4*5mk*9*;i*<*=(*I*JIJ*L*M n@*Q*Rl*X*YND*Z*[TEM*\*]ASH*_*a7*d*e nG*h*isa*q*rIGN*u*v nW*y*z n]*{*|l*}*~O** n]**l** nd**O** nd**HAN**u**HAN**u**HAN** n]**HAN**IGN**HAN**HAN** np**u**HAN**O**IGN**O**IGN**O**OT**@**l**IGN** m**O** m**O**?**?**ACK** m**ACK**IGN**@**HAN**O** m**AR++ aj++ ?++++ nv+!+# n+%+&+'+(+*+++,+/ n+4+5sa+9+:sa+<+=sa+@+Aaj+E+Gaj+K+L m+M+Oaj+P+RTAR+S+T nv+V+W n]+[+]AIL+^+_AST+`+faj+i+oaj+p+sAR+z+}sa+~+EY++aj++ mv++aj++ k++++++aj++P++OWN++ n++++ n++ n++ n++mk++USP++TAR++ ?++ n++ k, , ZHE,',)US,9,:ZHE,W,YUS,`,aAR,e,fsa,g,l k,q,sOOK,u,v,~,AIL,,LFA,,IDA,,h,, n,,IE,,OU,,ATA,,ATE,, n,, n,,APA,, n,,I,,I,,SI,,,,I,,O,,IMA,,AU,,A,,I,,HI,,SI,,OU,,LEF,,IN,,IE,,APA,,I,,OU,, k,,HEI,,SH,,HEI,,ORI,,A,,EI,,AT,, k,,JA,, k,,GI,,YI,,AU,,O,,O,,HEI,, k,,HEI,,ARK-5-6AJ-=->AK-@-BAH-E-FAKH-G-HAQ-J-LAZH-V-XAGH-c-dAZ-o-pARK--US..i#.. k. . k. . k.. n.. n.. k. .! mA.".' k.(.) .*., l.-..ARK.6.7 n.:.;ASH.M.NARK.P.Q {.S.TARK.U.Xsa.Y.\ ..ILK..ORN..VEN.. W.. ].. d// n//mr00ARK00 k00ARK00 k00ARK0*0/ARK0102ARK0305ALF0;0=ARK0A0B0C0D0E0F0G0H0I0J0c0dU00A00U00O00A00ARK000000000000U00A00U00O00A00ARK1D1EIOS11ARK222H2O2n2{33 [33 c33HM33MM @A nBC ,DEZEFGOTAHI #JKKLM}FNQERRSATTUUVWX]US^_N`aSEbcEdeLfgMhnprIGNWEZWEHWECHEZZEOOKWESWESSECHEWEHWEIGNING nUU ARARajARK !ONE"#LEF$%IN&'ENG()Z*+ n,- o./nj23A45O67U89V:;AR<=Y>?OT@EsaFGHIsaJKRLMOOPNOOPQ kRS o TUAILVW kXYsaZ] o^_sa`aYbcdesafg khiENDjkTlmSnoONuvUMyz{|} o kAROOK o saEEEsaETA}Fsa§ħOOKǧŖsaΧ o&ЧҧrԧYNN֧ڧ o069ARKqrAtuARKvwHADΨ lIYwx` o7ʩDEG̩ oABCG]_ lOHOHHOOGOOHOOYOOOHOOOOHOOOOOOOOARK23:?saABsaIJAILNOEGPQIfgOOKjkACK۫ oIYEK׼׽*-OT13/56/8</@A/CD/FJ/LNAFEPORM@ oP=ORM>? GJ oXP~ORMORMORMORMORMARK %ALF'-@./ALF12ASH34INE56 7D kEFOTGH kILzMOINEPQnjVWARKYZ [^ kdfIGNijIGNvORMARKIGN IGN_` bc kARKIOSIGNIGNaj o_OAT L8!"38? oiFGHN oqOV oyYZNE[\WO]^ obdENhijpqrstNASwIGNIGNEAD./SEASoOOKOOK >ELTOOKsa ks^_mnUNwx A- ?ETHEODHAPH ?EMUNHINOUR A   o Q Rmk V W l OT : ? l ARK     E B EB G  EG  D  Z  Y  EY  EK  EK  L $ %EN & 'NT ( )NC * +NY 2 3C 4 5Q 6 7Q 8 9Q : ;R ? @SH A BSH C DT E FET  E R E  E R E  A  A k ll IGNrzARKl@ oX ?ETHEYINFG@HJlMP@OTS ?AW89AGH lIJOTIGNARK l12ARKAB l lARK89 l;UVpw oz|OOKrxrrrxrr 2TEPART S  o o o pmrEFT46mk9;mk@EILLHI pJK pLMAWSNO pVYHIPZ_ p(`cOMBeh Ejkn lpw x{AVÈ̃ī̅ M̆̇ m̎̏̐̑ p.̒̓ISH̔̕ ̗̜AR̞̟ANK̡̠ p4̢̣AR̤̥ p<̦̩YES̪̭ACE̮̯ ̰̱ACE̵̲ +̶̹ pC̺̽ING̾ާOOKޭ޴AWN޴ k Fl:ROGmk mr n  p.mrEFT*,mrκο k EFT mr pQ34 pY>?METψω pQϞϟ Ϡϡ !ϲϳ cϷϸ !     " => BCLLOFHEONONOQREOXZEO^_EOst pcЀЁ ЃЄEOЋЍ pqТЦoЬЭ pyбгoноI p pESOATO pIGN p p!"LEF45IME:BESTCE pVW p]dOTEefTEMstEAMuvIEwxLURyz pрс /ъы gєѕ̚їјURNѪѫOWѮѰARKESTLEF pOTE}@ k }@ kGH}@PU kׁׂ}@׊׏ k׻׼}@ k k ENT e ENT om#$IDE01P23IDE68P:S qDLAG 8 ISH#% qL*+ qR-2ACE4?mkCDOTSFHlP[ q\g~ mENIGN ISK $ CON qiAD kg OgACEACEYES#ACE'-ACE25ACE>CACEEF qHJ $CP_EAF`gUDlo 7pqn txn |}o~ qUSARAXI q q k q k k q  qRON !RE"# q%& q)+RE,0 qQR qWX rYZ Ktop wzWOimkllܙoTARimk k k 3 r4GajPTajWYaj`dajglajotajw|ajaj kAILajESTajaj m}OTSOTS OOK OT  ACEACEACEANDIST!"ACE$%ACE,- GI r uvACEACEAIR r F r0G rHJ r&KM ruw ACEANDANDFQmr\gmrhon}n}n}n1ILLn}oYmroYoYANn} qi n}EFTmrmrmrmkn}mk!"ARK#%IGN() <>IGN . 8 B L V ` j t ~                 ( 2 < F P Z d n x                 " , 6 @ J T ^ h r |                 & 0 : D N X b l v                  * 4 > H R \ f p z                 $ . 8 B L V ` j t ~                 ( 2 < F P Z d n OOx                         " , 6 @ J T  ^  h * *r + +| , , - - . . / / _ _ ` ` f f g g h h i i !! $H$H $I$I +z+z +|+|  nn& 0 : D N X b l v             "" "" #'#' h h  hh hh* hh4 i}i}> nVnVH nWnWR nvnv\ nwnwf p z                           $ . 8 B L V ` j t ~            !! "" ## $$ %% && '' ((( ))2 **< ++F ,,P --Z ..d //n 00x 11‚ 22Œ 33– 44  55ª 66´ 77¾ 88 99 :: ;; << == >> ?? @@ AA" BB, CC6 DD@ EEJ FFT GG^ HHh IIr JJ| KKÆ LLÐ MMÚ NNä OOî PPø QQ RR SS TT UU VV WW XX YY ZZ [[& \\0 ]]: ^^D __N ``X aab bbl ccv ddĀ eeĊ ffĔ ggĞ hhĨ iiIJ jjļ kk ll mm nn oo pp qq rr ss tt uu* vv4 ww> xxH yyR zz\ {{f ||p }}z ~~ń Ŏ Ř Ţ Ŭ Ŷ           $ . 8 B L V ` j t ~ ƈ ƒ Ɯ Ʀ ư ƺ           ( 2 < F P Z d n x ǂ nj ǖ Ǡ Ǫ Ǵ Ǿ          " , 6 @ J T ^ h r | Ȇ Ȑ Ț Ȥ Ȯ ȸ           & 0 : D N X b l v ɀ Ɋ ɔ ɞ ɨ ɲ ɼ     09    `i    f o    f o   f o  r w    f o  x ~   X ^  f o  p x  PY   ) *3 @I  iq r|     FO     PY  @I PY  p p  t y  !P! !! $`$h $i$s $t$| $}$ $$ $$ $$ $$ $$ $$'v'~ '' '' '' '' '' ,, 00 0!0) 080: 11 2 2) 2H2O 2Q2_ 22 22  )  05 Ш  Щ  PY  kk ss xx      3 @x    # AA JJ   X_ y          @ C  D H  } ~    X _  x     0 9  @ I `h i~ & QT  RZ [e fo  6?    PY  PY   09 :;   PY  PY Zl PY   PY   8 9  y y "&"& "+"+ # # # # ## $$n a0a9 j`ji jj kPkY k[ka mpmy nn oo    `x  @I     PY q   - /=     09,6`iDnʘ f o   f o0 Z f o˄ r wˮ  f o x ~( F X ^p f x̎ PY0 3Z@Iͬi|R`ΊδFO6`PYϊϴ@IPY p p t y2 L!P!^v!_!`!a!~д!!000!!.!!8$`$N$$@'v'Қ,,/2000!0)080::11H2 2)Z2H2Oӄ2Q2_Ӧ2222 )Lv05ԠШԺ Щ8PYbՌkkss0xxѶӶ0ն3@W֖XZ[^__`d0ee0fi0jklp00qtuv/2wx( #זAA0JJ00ר׾X_y (6H  ^ x ؂  @ H~ } ~٤ ٮ ټ X _ x   4 0 9N @ Ix`~ڢ& QTJ\Roz6?HrPYPYBlݖ0;PYhޒPl޼PY2\߆PY߰ʱ/16ұ/2 8 9 y y"&"&/2"+"+# # # # ##$$#$$$$%$&$-$.$/$0$5$6$7$8$9$:$;$<$?$@$@$A$C$D$E$F$I$J$Q$R$S$T$U$V$a$b$c/4$d$nPa0a9~j`jijjkPkYk[ka&mpmyDnnnooV`x@I,VPYq-/=  jAZ"         !""#$$%&&'(()**+,,-../00i22344566799:;;<==>??@AABCCDEEFGGHJJKLLMNNOPPQRRSTTUVVWXXYZZ[\\]^^_``abbcddeffghhijjkllmnnoppqrrsttuvvwxy{{|}}~&4FP^hr|         ""#$$%&&'(()**+,,-../001223:;=>AABCFHHIJJKLLMNNOppqrrsvvw0V/```abbcddeffghhijjkllmnnoppqrrsttuvvwxxyzz{||}~~.         !""#$$%&&'(()**+,,-../1V8-'--lt         !""#$$%&&'(()**+,,-../001223445667889::;<<=>>?@@ABBCDDEFFGHHIJJKLLMNNOPPQRRSTTUVVWXXYZZ[\\]^^_``abbcddeffghhijjkllmnnoppqrrsttuvvwxxyzz{||}~~(/8?HMYYQ[[S]]U__Who>`!&!&!*!+!2!2!N!`!o!!!$$Z,,/,`,`,a,b,d,g,g,h,i,i,j,k,k,l,m,p,r,r,s,u,u,v,~,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,@@ABBCDDEFFGHHIJJKLLMNNOPPQRRSTTUVVWXXYZZ[\\]^^_``abbcddeffghhijjkllm""#$$%&&'(()**+,,-../223445667889::;<<=>>?@@ABBCDDEFFGHHIJJKLLMNNOPPQRRSTTUVVWXXYZZ[\\]^^_``abbcddeffghhijjkllmnnoyyz{{|}~e§ħɧ˧ΧЧҧԧ֧اڧܧ!:'ppz|. 8 P e`n@n_nnd!~azT        !! ##"%%$''&))(++*--,//.11I332554776::9<<;>>=@@?BBADDCFFEHHGKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonqqpssruutwwvzzy||{~>L Z        ##"%%$''&))(++*--,//.110332<<;?@dBBAGGFIIHKKJMMLOTnVWYY[\`acfhlooqruu}},dEEqqpssrwwv{}&l0_aa`ccbeedggfiihkkjmmloonqqpssruutwwvyyx{{z}}|~        !! ##"%%$''&))(++*--,//.a."yy}}},c        !! ##"%%$''&))(++*--,//.110332554776998;;:==<??>AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonqqpssruutwwvyyx{{z}}|~`$J 'd07@EQQYSS[UU]WW_`gp}@b!N!N!2!p!!!!$$,0,_N,a,a,`,e,f,h,h,g,j,j,i,l,l,k,s,s,r,v,v,u,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--%-'-'----AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmml##"%%$''&))(++*--,//.332554776998;;:==<??>AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonzzy||{~çȧʧͧϧѧӧէק٧ۧSSpAZ(Oj  ( 2 p Zn`nnn^"C~azN        !! ##"%%$''&))(++*--,//.11I332554776::9<<;>>=@@?BBADDCFFEHHGKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonqqpssruutwwvzzy||{~8F T        ##"%%$''&))(++*--,//.110332<<;?@^BBAGGFIIHKKJMMLOThVWYY[\`acfhlooqruu}},dEEqqpssrwwv{} f0_aa`ccbeedggfiihkkjmmloonqqpssruutwwvyyx{{z}}|~         !! ##"%%$''&))(++*--,//.a  (   " yy}}},c        !! ##"%%$''&))(++*--,//.110332554776998;;:==<??>AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonqqpssruutwwvyyx{{z}}|~`  D ' ^07 @E QQYSS[UU]WW_`g p}   : \ ~  !N!N!2!p! !!!$$ ,0,_ H,a,a,`,e,f ,h,h,g,j,j,i,l,l,k,s,s,r,v,v,u,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--%-'-'----AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmml##"%%$''&))(++*--,//.332554776998;;:==<??>AA@CCBEEDGGFIIHKKJMMLOONQQPSSRUUTWWVYYX[[Z]]\__^aa`ccbeedggfiihkkjmmloonzzy||{~çȧʧͧϧѧӧէק٧ۧSSpAZ(Od" , p Tn`nnnX"CaND  Odaa ^`/X LR JWCJ{J{J{J{J{J{0J{27J{9>J{AIJ{L~J{J{J{J{J{J{J{J{J{J{J{QSJ{UWJ{Z`J{fhJ{lnJ{qsJ{}J{J{J{J{JJJJ/AON-DEJJJJJJJJJ-/J89JMOJvyJ|}JJJJJJJ!&J(+J-.JIJJNQJpJJJJJJJJJJ\;:Kq?OKqZ[Kq Kw<=KwJLKw}KwKwK  LR  LJ t yJ } ~J Lv Lv ON- Y!!L!0!1L!S!^WC!!M!!M!!P !!a!!L!!P !!MW!!a!!L!!M!!M!!N"j"kM"n"oOT "p"qM$"t"uM$"x"yM$""Me""Mk$$! $$Jt$$M%% $%%P &k&lZ'v'N''ME''N''N''N''N''N''N''N00ON-1113K151@K1B1DK1H1MK1d1K11 +22M22 M22M2b2cME2h2lME2n2{ME33WMN3{3MNJ0D 5IO/Y^LprJvJ 5 QIQI;@QI[^QIacQTQTQTQTQTQIF h\ <OdaSE JtNE W:W:W:LLLHILxyW:W:W:W:W:LW:W:W:W:LWMLQSLUWLZ`LfhLlnLqsL}LLWMLWMWMWMWMA/DEON-/W:W:W:LLLW:LLW:-/W:89LMOLON-WM!&WM(+WM-.WMIJWMqWMWMWMWMWMWMWMWMWMWMJ.WM0:W@DWHKWJLWML t yJt Jt /!!Y(!!MW!!L!!O!!Y?!!MW!!L""M""O $$!OR % %a%%a%%P %%P %/%0a%7%8P %P%QLJ%R%Sa%U%Va%X%YP %[%\P %^%_O%a%bO%d%ea%g%hP %j%kO%m%wN%x%{N%|%}N%~%N%%Y'v'ME''V''ME'' ''Ld''Y''N00/1113WM151@WM1B1DWM1H1MWM1e1WM22K22 K22K2b2cK2h2lK2n2{K3{3~WO 33U 33 33AD WM0DOR OR >@/KKKKEXTWMWMWMWMWMWMHIWMxyWMWMWMWMWMWMWMWMWMWMQSWMUWWMZ`WMfhWMlnWMqsWM}WMWMWMOW  HLJDE/WMWMWMWMWMWMWM-/WM89WMMOWM/#& Rrsltx_ryzAA |AA AA AL A A AF _AW A A UdHO  HO HO HO (*O 0:W@DWHKAI JLLZWM!!aj!!YH!!YH!!LJ""R $$a$$ND $$a$$a% % N%%N%%N%%N%%N%%N%%N%%N%S%TLJ%V%WLJ%Y%ZLJ%\%]LJ%_%`LJ%b%cLJ%e%fLJ%h%iLJ%k%lLJ%m%pRC %q%s_2%%O,'v'~Jt''^''V''ZX''Y00P1516 J1:1@ Z1f1h J1i1m Z1n1o `1r1x a1z1~ n11 h11 q3{3~ w33b33b0DO WMWMWMWM             ZLZVW \]LZln rs     OWU#$N rs Rux RyzYH|YHYHYHYHYHYHYHYHYHJt29`@D`!!IP !!Y!!aj$$F $$h% %ND %%a%%ND %%ND %%P %%ND %m%na%o%pP %q%rM%%YH''Jt''^00P1t1u n3{3~RA 34/J J ZOOKOGH[\} Odd-}~NlW!W!WO NlLOT NlNlCDAI $$EXT% %MW%%ND %%L%%MW%%ND %%L%m%pND ''Jt3{3~b l}~_WO Nl___%n%oEFT_HR')./[`{}Y`   ~ e,n027l9>AGII Lxz~t %OOK 5 E   s  "p RSUVZZ ]`dd Jfhlnqq ssu vv h{{ }} LZ     / U x     2<FPZ t"$-/1$3A2DEptt zz z   K    ( & @ ZO%% u++ -/633 99OEE KK MODTT VV vyR|}dnPZBB 5ZZ Qrr z   d!"r$&|(+-.11 88 AA CC 0GG BIJNQpqs&8^hv@ Z    F: ?O Z[!2    LJ  55 77 =99 P<=!<JL!FNN f`` ee {{ }!T!f!x  "  "(  "6 9 :"@ > > U p p g t y"J { { ~ } ~"d "n  " " "!!"!! ! ! ! ! "!!#!!#!!L!!#"!!!"#4!$!(#>!*!-#T!0!0!2!3#f!5!8#p!S!^#!!#!! !!#!!#!!$!!$,!!$6!!$d!!$~!! !!$"T"U$"d"k$"n"t%"v"y% ""%2""%<""%J"" \""%T## #$#$ #&#'%^#)#+%h$$%v$$"%$$$$ $$%%%m&P%p%( %% %% '%%(L%%(&+&+ d&k&o(''N'+',('2'2 '<'< 'B'B 'v'(''M'')J''N'')X'')j'')'')'')'')00 !00)00)00 Y1213*1516*"181@*,1C1D*R1F1F q1I1M*\1d1w*r1y1*11+22 =22+`22 Y22 +j22+2`2` t2b2c+2e2e 2h2l+2n2{+22 33W,3{3-z /02/4D/ IJ/fLO/pRR Y^/hh pr/tt Gv// zW 11;@1[^1ac2 222(2N 2X2n""Z@JWMWMWMWMWMWMWM"h"iZ@"u"v \""F ""Mk""Z@'' 0|'' el''h8 RPQWMpqWMWMWMWMvwWMWMHE A WMWMN E WMHA HE WMWMHE !!O"d"gZ@"h"iUT "p"uZ@""R ""O ""UT %%P %%MW%%a%%L''ZN'' e'' e'' e00NJN mJF F /WM27WM9>WMAGWMLOWMPQ RoWMpq rwWMz~WMWMWMWMWMWM  WM `vw ecxyWM|}WME WMYHWMYHA WMLZYHWMYHgYHWMYHHE WME WMWMYH  z 9 :Y O!!O!!WO !!O!!O!!YH!!O"d"eR "f"gb"h"iOT "p"qOR "r"sR "t"uOR ""OT ""Z@""R ""OT %%O%% G%L%OLJ%%P %%Y%%MW%%Y%%MW%%a%%Y%%L%%Y%%L''N''_'' f''ND ''Ld''N''N''gL0 0 LJ00N00Ld00U00N00U00N00 _1x1yUN 9:U;<Ld=>LJCDN]^U8 RJJWs 5 ?    # $' (/ 23 45 67 9> AB CH LO PQLJRS TY Za bg ho pqLJrs tu vw y~             zzOT      HQRL~ N eZmzaa W!"d-#$OT ./ e56AR 78̈@AWWMvwLJxyK |}hYHE MWE MWOA E MWN E  S MW MWE MWOWME d-OA N LqrN _A   o{ 9 :LR Y? AR  O M _!5!8 X!!YH!!l!!_!!YH!!ed!!YH!! h'!!LJ!!O!! h/!!LJ!! 0|!!O "d"iMk"p"qMk"r"u h9""Mk""YH"" \"" V"" h9%% h%-%.a%1%2a%3%4ND %5%6P %9%:P %;%O%@%BM%C%Da%E%FP %G%HM%I%JO%L%O h%%Y%%L%%Y%%L%%Y%%L%%Y%%L%%Y%%Zm'' e''MW''MW00 Y0 0ej00 iP00^00 iP00^00M=00 i\1x1y m78M^9:^;< iP=@YADejKLl[\M^]^^N mN JAA J_xJAM bcej() EREREAREA uqyPyVrx r~  OT  DARqyPOTyV Dr~yP !OT"#q$%r~&'AR()p*+q,-yP./yV2345r~67q9:rx;<q=> DAB̚CDrxEFqGH DLMqNOyPPQrxRSTUrxVWqXY DZ[rx\]r~^_q`a Dbcqde DfgARhipjkqlmyPnoINGpqrxrsyVtwr~yzrx{|OT}~ Dn7OOKn7ORNOOKOOKORNOOKARIPE D Dqrx DrrqAR DyVq DQRVWOOKfgOOKqsOOK~ARINGl  ll@&@)1@23 48R9<@@AARK k k kq kq kHEIEIHEIORI k kEII89Ivwrrxy >|}~H k kAROOK kq kARA kEOOKq kAR kSE kAROOKyVHEOOKOOK kOD"#LEFqsLEF@l@AFlOAL@ HAD<= e  ARK 9 :  } ~   l R l R l! ! !!!!!!!1!2!5!8 !V!X mg!\!^ mn!!aj!!sa!!aj!!AIL!!AR!!OOK!!OOP!!AR!!aj!! mv!! m}!!aj!!aj!!sa!!aj!!AR!!aj"d"iO"j"kHAN"n"oHAN"p"uO"v"yHAN""O""OT""HAN""O#&#'EY$$s$$ %%%%؀%%%%؀%% % % ؀%% %!%"%&%(%)%*%-%.%1%2%3%4%5%6%9%:%;%<%=%>%@%F%G%J%K%M%N%O؀%%i%% m%%i%% m%% ?&k&l m''l'+',TAR''aj'' k''aj''aj00 k00 k00ARK1112 S1718 1B1C Z1H1I G1p1qUM1x1yUM11UM11`33 [33 c33HM12ASH34 56 7D kIL WMO YZ [^ kLEFAWLEFALEFAA AAHAAEEMAAHAAALHALAAINEENADADAHHAHINAAFAFAMEEMOONAAW ALEF bc k S  Z GSSSSSSNNNNNSMSMLSLNNSMSMSMSMSMSMTNSMSMSMSMTSMNSMSMSMSMSMSMSMSMSMNSRELEDFROLOSRILISIDINNNNNSTNSMSMSMSMSNSNSSSSNSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMSMNSM  a 23  '1o1 D41 D23 D4AAAAAA C'EEEEIIIINOOOOOUUUUYaaaaaa c'eeeeiiiinooooouuuuyyAaAaA(a(CcCcCcC c D d EeEeEeE(e(E e GgGgGgG'g'HhIiIiIiI(i(IIJijJjK'k'LlL'l'L l LlNnN'n'N n nOoOoO o RrR'r'R r SsSsS's'S s T't'T t UuUuUuU u U u U(u(WwYyYZzZzZ z sOoUuD}D~d~LJLjljNJNjnjA a I i O o U u   &'G g K k O(o(  j DZDzdzGgNnAaAaEeEeIiIiOoOoRrRrUuUuS&s&T&t&H h AaE'e'Oo./Yyhfjry{wy     (   clsx E; #8553V:8Ctu60056788>-M#C#C# C 'G+Ke'S'THT'UJT'tHttJtTTT ( < 0 < 3 <  <  <  <  < ! < " < + < / <      2 < 8 <  <  <  < + < G V G > G W ! < " <     F V      F > G > F W    M2 BLQV[@qrqtq%.55 5 5 55:5<5>5?5B5ABDEGHIJKLMNO"PRTUWaPQbdeY[\gkmKoTptuov%iruv=RcU\f_aehij{mqprstuxzA%a%BbB#b#B1b1DdD#d#D1d1D'd'D-d-E-e-E0e0()FfGgHhH#h#HhH'h'H.h.I0i0KkK#k#K1k1L#l#67L1l1L-l-MmMmM#m#NnN#n#N1n1N-n-LMLMPpPpRrR#r#Z[R1r1SsS#s#Z[`abcTtT#t#T1t1T-t-U$u$U0u0U-u-hijkVvV#v#WwWwWwWwW#w#XxXxYyZzZ#z#Z1z1h1tw y aA#a#A a     E#e#E e Ee  I i I#i#O#o#O o     ##U#u#U u   ##YyY#y#Y y YyBB  B B ! ! B!B()()(B)B01010B1B89898B9B@A@AHIHIPQPQPBQBYYYB`a`a`BaBhihihBiBEEEEEEEEE E E E E EEE E!E"E#E$E%E&E'E(E)E*E+E,E-E.E/E`EaEbEcEdEeEfEgEhEiEjEkElEmEnEoEpEEEBEE   BBtEEEBEEBBBBBB`|EEEBEE      3......  2 2 2 2 2 5 5 5 5 5!! ???!!? 2 2 2 2 0i456789+"=()n0123456789+"=()aeoxYhklmnpstRsa/ca/sCCc/oc/uFgHh'ILlNNoPQRSMTELTMZZKBCeEFMoiFAX"Ddeij1 D71 D91 D101 D32 D31 D52 D53 D54 D51 D65 D61 D83 D85 D87 D81 DIIIIIIIVVVIVIIVIIIIXXXIXIILCDMiiiiiiivvviviiviiiixxxixiilcdm0 D3!8!8!8!8!8!8"8"8" 8"#8"%8"+"+"+"+"+"."."."."."<8"C8"E8"H8=8"a8"M8<8>8"d8"e8"r8"s8"v8"w8"z8"{8"8"8"8"8"8"8"8"8"|8"}8"8"8"8"8"8"800 1234567891011121314151617181920(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)(o)(p)(q)(r)(s)(t)(u)(v)(w)(x)(y)(z)ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0"+"+"+"+::======*8jV-akNN(N6N?NYNNNNQ?QeQkQQQQQRRRSSS8SAS\SiSSSSVWXYY YY'Ys[P[[\\"\8\n\q]]]]^r^z^^^_ __P_a_s_bb6bKe/e4eeeeeefgg(k kbkykkkklll4pkr*r6r;r?rGrYr[rssttuuu(u0uuvvv}vvvwwwy:yyztzz|s|6Q 3 nrxMk@Lc~7FUxdpIwQ^bi%/2<Zu ;JR 0SASDSE0K00M00O00Q00S00U00W00Y00[00]00_00a00d00f00h00o00o00r00r00u00u00x00x00{00{00F0 0 000000000000000000000000000000000000000000000000000000000000000000000!     abcdefghijklmnopqrstu` "#')+,-./26@GLWXYNNN VN N-N u2NYNNY)W0N()()()()()()( )( )( )()()()()()(a)(a)(a)(a)(a)(a)( a)( a)( a)(a)(a)(a)(a)(a)( n)( i e)( in)(N)(N)(N )(V)(N)(Qm)(N)(Qk)(N])(SA)(g)(pk)(l4)(g()()(W)(e)(h*)(g )(y>)(T )(ry)()(y])(R)(N)(T|)([f)(v)(O)()(ST)(ym)(O)()()UO^|e{PTE212223242526272829303132333435   aaaaaa a a aaaaaaai n t nNNN VNQmNQkN]SAgpkl4g(Weh*g y>T ryy]Ryu7YsiQ*SplOQkcN N-N ]SS;[[fvOSTY3637383940414243444546474849501g2g3g4g5g6g7g8g9g10g11g12gHgergeVLTD00000000000000000000000000000000000000000000000NT000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000p1p2p3p4p5p6p7p8p9p10p11p12p13p14p15p16p17p18p19p20p21p22p23p24phPadaAUbaroVpcdmdmdmIU^sbf-TY'kcflh*_Oy>pAnAAmAkAKBMBGBcalkcalpFnFFgmgkgHzkHzMHzGHzTHz!m!d!k!fmnmmmmcmkmmmcmmkmmmcmmkmm"sm"sPakPaMPaGParadrad"srad"spsnssmspVnVVmVkVMVpWnWWmWkWMWkMa.m.BqcccdC"kgCo.dBGyhaHPinKKKMktlmlnloglxmbmilmolPHp.m.PPMPRsrSvWbV"mA"m1e2e3e4e5e6e7e8e9e10e11e12e13e14e15e16e17e18e19e20e21e22e23e24e25e26e27e28e29e30e31egalJLoSCFQ&S'7kRHfnN2SYQUYHavi?jmps=jNSukr-]Podb^gmjrOQRdjrv\2oxy}X_|`~rbxX\bjmo}/~7KRQQz}ubjN9[`supSxO_N lex}"SX^wIklbcueNQiQh|oRTBYs^eoy*jRfkwb^tabdo#qIty}o&#JRRTp^_c{k|>suNV[]`stiF4HOy`NP[\?ejqvB|f.Rg{gmAnt uYxk}^Qmb.xP+]m*_aDhsR)T\efgNhltuyS?nTqtWgmz{ |rpXN6R:R^b|[mf;LM^Q@UXZftQs*vy<y^yeyV|8(OPQMRRSQUVVhX@X\d\n`ahaaeOefhmwno"qnr+t"xy>yIyHyPyVy]yyz@z{}~ ~AryW98;`uBN&QQhOQEQRRUUUUUXZXYDYTZb[(^^_i_`aNaaa`ab4cddReVftgggVkykmAnno"pqnwr5rs*tquu;vvvvvwJw@xz{|{}[}>RyA98rv|V ;(J(D3;@@9RI\~Cfffiflffiffltsttvtetk~vtm+IIq{~zywI&'&&H&&&&&I&,&-&E&I&J(,(-(.(E(I(J*,*-*.*E*I*J+,+E+I+J,-,E-,-E.,.-.E3,3-3.3E5-5E6,6-6.6E7-7E8E9,9E:,:EA,A-A.AEAIAJB-BEBIBJC'C,C-C.CDCECICJD,D-D.DEDIDJE,E-E.EEEIEJF,F-F.FEFIFJG,GEGIGJJ,J-J.JEJIJJ0p1pIp LQ MQ NQ OQ PQ Qp&1&2&E&F&I&J(1(2(E(F(I(J*1*2*E*F*I*J+1+2+E+F+I+JAIAJBIBJC'CDCECICJDEDIDJE'EEF1F2FEFFFIFJIpJ1J2JEJFJIJJ&,&-&.&E&G(,(-(.(E(G*,*-*.*E*G+E,-,E-,-E.,.E3,3-3.3E5-5.5E6,6-6.6E7-8E9,9E:,:EA,A-A.AEB-BEC,C-C.CDCED,D-D.DEDGE,E-E.EEF,F-F.FEFGG,GEGpJ,J-J.JEJG&E&G(E(G*E*G+E+G3E3G4E4GCDCEDEFEFGJEJG@NQ@OQ@PQ7I7J9I9J:I:J3I3J4I4J-I-J,I,J.I.J5I5J6I6J4,4-4.4E413151617I7J9I9J:I:J3I3J4I4J-I-J,I,J.I.J5I5J6I6J4,4-4.4E413151614,4-4.4E3G4G7E3,3-3.4,4-4.7E8E'K*,E*-,*-E*.E*E,*E-*E.,E--EJ-EI3-,3,-3,I3E-3E,3EE5--5EE4-E4,J4E.4EE6-I6.E7E-7EE7EJ9,E9EE9EI:EE:EJ:EIA.EBE-BEED-ED-JD-ID,,D.EDE-E-,E-EE-JE,-E,EE.,E.EE,.GE,GEEF-EF-IF,EF,IFEJFEIJEE(.J*,J*,I*.J*.I*EJ*EI,EJ,-I,EI3.I5-J4-J6-JD,JDEJJ-JJ,JJEJEEJBEJF-JBE-D-E9EJCEJF,-E.JD,ECEED,EF,-,-J-,JE,JAEJ(-JCEE9,E5EE3.JF,J5DBD'DDG'C(1E-E/5D9E13HD9DJGH3DE5DI5DI 'DDG 9DJG H3DE,D ,D'DG1'D,00:;!?00 & %  _(){}00000 0 00 0 0 00[] >_,0.;:?! (){}00#&*+-<>=\$%@ K@K L M N@N O@O P@P Q@Q R@R!"#$%&'()*+,-./0123456789:ABCDEFGHIJD"D#D%D'!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~))00 0 0000000000000000000000000000000000000000000000000000000000001d1112131415161718191:1;1<1=1>1?1@1A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V1W1X1Y1Z1[1\1]1^1_1`1a1b1c %!!!!%%SfVWX^db`'glnvwqz}~g,q 1'2'G>GW50aaaa)aaa)aaa a!aa"aa!a mgmgmcmgmimgABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789WeXe_n_o_p_q_rѹeѺeѻnѼnѻoѼoABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzACDGJKNOPQSTUVWXYZabcdfhijklmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABDEFGJKLMNOPQSTUVWXYabcdefghijklmnopqrstuvwxyzABDEFGIJKLMOSTUVWXYabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz17""""""""""01234567890123456789012345678901234567890123456789012345678:;<>?@ABCDEFGHKMNVX012345678:;>?ACDEFGHJKVU_Q'(,/H2-7JCDEF39A5B14*+.068:no(,G-JCDEF39A5B4*+.6:,-JDF395B4.6:o(,G-7JCEF39A5B4*+.68:n'(,/GH2-7JDEF39A5B14*+.068:(,/H2-7JDEF39A5B14*+.068:0.0,1,2,3,4,5,6,7,8,9,(A)(B)(C)(D)(E)(F)(G)(H)(I)(J)(K)(L)(M)(N)(O)(P)(Q)(R)(S)(T)(U)(V)(W)(X)(Y)(Z)0S0CRCDWZABCDEFGHIJKLMNOPQRSTUVWXYZHVMVSDSSPPVWCMCMDMRDJ0{0K000bK[WS0NYY)Nf q!eRM_QeR}BuXT9obcUNN J]N-ScpbSyzzTng gu3RrUM0g,00N 00N00[00p00bS00v00R00eW0_S0123456789N=N8NA"O`OOPPzPPP4:QMQTQdQw4QgQKQQNQQQR4R;RFRrRw5RRRRSSSSISQSZSsS}S ,ppSS cSSTTT8THThTTUUSUcUUUUUWVWVQVtRXWWX WX2X1XXXYYY"YbYZZ'YZf66[[>[[[[[\_S\"7\`\n\\]C]n]k]|]]8/]^(^=^i8b!8|^^^^^#1_"82a_b_k8____`9:9`&`aHaLaNaLazaaaaaaabbb]bbcP+ c=bchcc+d"cc:.did~ddw:leOel0 effI;f;:QQgfCggg!g^gS3;IgghRh4mhhi;iBiij6j<k!8kTmwmAmimxm=m4n/nn=3nn>mon?^?op9pp=pJp}pwp%qEBcqCr(r5rPFrrG5Hszs>s>tGt\tqtt?u$L6u>Lup!vOOPD?@vPPQQ3wwwJ@9w@F@TxNxx@V&yVVVyyA/z@zJzOY|ZzB[{{B'\|B||}_}cC}~~EC4b(bGCYbzc>de#`ep3_CD >Zgg33DkRk<c#WSl6mklE+sdo,E]EaopEkP\giy(kEE`cvgF54xyfFFU|w/8.8|IwI]#EJnJv J )K3)K0@LLgLMV;JIJIIIIJIcIJ3J>J3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>J3J>J3J>J3J>J3J>J3J>J3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>J3J>JFJPJ3J>J3J>JFJPJ3J>JFJPJ3J>J3J> J3J>JFJPJ3J>J3J>J3J>!J>J3J>J3J>J3J>JFJPJFJPJ3J>J3J>J3J>J3J>J3J>J3J>J3J>JFJ3J>JFJ3J>JFJPJ>J3JFJ>J>JFJ>JFJ>JFJFJ>JFJFJ>JFJ>JFJ>JFJ3JPJ3 J3JPJ3JPJ3JPJ3JPJ3JP{J>J3J>J3J>J3J>J3J>JFJPJ3J>J3J>JFJPJ3J>J3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>J3J>J3J>J3J>J3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>JFJPJ3J>J3J>J3J>JFJPJ3J>J3J>J3J>J3J>seomodsoekcksmemso ookooimfokomklkoof7ulululululululululululululululululululululululululululuulululululululu.ululululululululululululululululululululululullululullululluullulouutlutlutlulululululululuululululululululuutlul:lululululululululululululululululululululululululululululuullulululumkmululmkulouuoulululululululululululuulmul#ulululululululululululululululululo6ululululululululululululululululululululululululululul lulululululu`ululululululululululululululululululululululululululululululululululululululululululululululululoddnoonofoofofonncnoomnonoocoonnonoocnocncoonoconooonnocnnoooo onononsesenocomooseconfnnocncncnnccnncnculululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululululuaululululululululululululululululululululululululululululululululululululululululululululululululutklifsfsilpifmsemocomsemselouuououoolomloulmomsesesesesesesesesesese seseseseseseseseseseseseseseseseseseseulululullublululululululululululululululululululululululululululululululululululululululululululululululululuulululmoifififoifdoif ifsesesesedos sesesesedomolsesesesese sesesesedsmoood0ulululululululululululululululululululululululonomulululululululululululululul ululululululu?ulululululululululululululululululululululululululululululululmulul lululululmululouluulululululululululullululululululullullulululululululuulocooonmncocncnoonocnocnsoonesseosesesesesesesesesedsesesemdocseomodsoekck smemseosemkomodmcncocnoooncncnonocnoncnooncncncnooncncnococnnooocconccnccnoonncnoocncnoonoomnulooom_ohono{MooooLMWoonjoooERONEWOoOURIVEIXooINEoopOEp pp'p5pIpYpnpppppppppqXEN qqqq)q8qSq}qqqqqWOoqqqqqqqrrDALFrLr[rrrxr~pqrErrrrxr~qrrrxr~qTHrrrrxr~pqrrrrrxr~qrrrrrrxr~pqrErrrrxr~qrrrxr~qTHrrrrxr~pqrrrrrxr~qrrrW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:Ls s,W:LW:LW:RAW:LW:LW:LW:LW:LW:LW:LW:0sCW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LrLW:LW:sZsaOOKshW:Ls}ssOOKsssss hsOTAssssttt:tGW:LW:Lt\W:LtftytW:Ltst LW:LZH"ttW:LtYNNuu uu Z u+uBJuSuiJuyuW:LW:LW:LW:LW:LW:LW:LW:uW:LW:LW:LW:LW:LW:LW:LW:LW: ZuuW:LuYNN:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LuuW:LW:LW:LW:LW:LW:LW:LW:LW: vB P ssv W:Lv3vAvGLW:W:LW:LW: LvYs}veAILOOKssvqvvvvLvhvv vsOTAvt:ELTvEZHw Lu ww w0w;HIw OOKw AIL PtwYSHwewwwwvAtwvvURLZHwwwxxx)x8xBvxWxkxtx~LZZ xxS xxxS Z xxxxxyyLJy'oy4MWLLZLMWP apnyCpqyIlpqlyIZmMWLP aOjOpyPOT MyVy]yiy}yhyb bIN yyyyaP LMWINGqyyyND yND NylyIzpqzyPzqd-MyiyCpz$z0LLZz?lyILMWzQORNzbP aOjOpzru OT zMzqyVzzzzzPtO["LJOONONzzM=z{{ {lyI{*{6{>{N{\{i{v{{{{{L{{zb{ {|||'|7|A|N|[yPq|gpz0|tW:LW:LMW:L{NLZLZp|Y ||hTA hWUh|}ETAh}}ETATA}&OTA},}2UUI}8IHO }@AUtHIHISI}FhWUhhTA h}L}ETAh}}ETATA}&OTA},}2UUI}8IHOZAUtHIHISI}FhWUhWUh}h}u}{yIzHI I AI LW:LW:LW:LW:LW:LW:LW:L}HO }}}LZW:L}L}LZLZ}OJEJE}ZE}IEJEJESHEJE~ ~ZHEEEHEEEHEEOALMNERSEFASEHEHA~~%ERU~/UAEEHEEEHEEOALMNERSEFASEHEHA~~%ERU~/UA}OJEJE}ZE}IEJEJESHEJE~ ~ZHEW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L~9~H~NYX~]~f~yW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L~W:LW:LW:LW:LW:LW:L~a~W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L&YBENIMACHAHTOHENIIWNEHAENOAHADHEHENIOWHAOHAEHHEHAEHEWIWNEHOIWNIWREHHEH~o~onnj~[L)ENIMACHAHTOHENIIWNEHAENOAHADHEHENIOWHAOHAEHHEHAEHEWIWNEHOIWNIWREHHEH~~ohh7%+6<BIOU\bho}LELUYEHI %"(/5%"(;AU\lrcIN MM LEFETEAVETETODZZYINZOFESHHINAVAV LJh}#%0@FM_emxnjAHAIN9?EoWMKX~p}m0LEFEHEHHEHEEMAHHAHALHALEHAINEENADADAHAHINWO NlEHAFAFAMEEMOONEHAWEH"9?E+28@FUduCPt~ERONEWOoOURIVEIXooINEEHAFl@}LEFAWTEH(EEHING/EHJPWVYEHYEHiDALING@UL/REHINGOT EH@AH IN .:EHA[OT amsINGzG}AFUEHOT OT ING OAL%;LccZErAIL|oAD AF EEMEENU*?R[AW&OONfOW _rvAL EH ERONEWOoOURIVEIXooINEcAD coMEFTmr:FMWJETHtzEAWAINETHETHUDHAPHIMUNZ$LZm#APHISHHINAWl@l@l@l@l@  l@l@l@)/7=ECa@ WO -lLOT ilAHW@B_EH AH WO NlWO NlWO NlWO Nl#AA;EAAAAKU[agmsHAAzAATAAHAAHAAAAOOINU (2:DL2V;ERONEWOoOURIVEIXooINEEOaAAAAHAAARAABAAAAlAYAAAAAvAHAA_rOW i_rOW i_rOW nj LAFITYAAENTITUTAAFIMUN NIUFISHHANAAFN%/6WmNGNGN6N2Q^fmAUszbAEFURUBGDHZTTTKSAKLMNSNPSZQRSHTADIN GAAYATANANNAHAALALLASA MWL+;Uj~UjMWLAWNOT a q$.-3DLS[hNsW_AH WOT  ,AL AD 5N[vEH EH EHAFOONEH EH c1cJ_~c@RAF(GAHlPbjADINAF!OW vIF09?E"ll"INGzLMWLPt)2O AIUiOIiO3UAHAAHAGAAHAAHAYATATHADADHANAAHAAHAANNAAHAAHAAAARAALALLAAHASAAAEOE:@AIURiOIiOUIPWM`glyIpEUEAHHAHHAA~HAAYARLLLJERONEWOoOURIVEIXooINEEOEWEUEHAGAJAwDDABANJIz$)2AIUIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAHASAAA :@AIURIUIRAHAYARLLERONEWOoOURIVEIXooINEW!MARKIGNNEWOoOUR"6=H^AIUEIOUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAALAAHAAAAIUEIOUIHHAHHAARAERONEWOoOURIVEIXooINERIRAz$)2 AIUIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAALAAHASAAA :@AIURIUIRLL ERONEWOoOURIVEIXooINE[W2+z$)2AIUIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAALAAHASAAA :@AIURIUI%I U RAHAYARLLERONEWOoOURIVEIXooINE63rDALFrL=GN)2AIUEIOUAGAAYATANAAANNAA AAARAALALLAAHASAAAAIUEIOUIERONEWOoOURIVEIXooINEENAY WM z$)2AIUEIOUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAARAALALLAAHASAAA :@AIUREIOUISAZARRARLL ERONEWOoOURIVEIXooINE LDNE WO NlNE WO Nl)/ )28AIUEIOUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAA AHAAHAAAARAALAAHASAAA :@AIUREIOUI@ARLL ERONEWOoOURIVEIXooINENZf z$)2AIUEI3OUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAANNAAHAAHAAAARAALALLAAHASAAATTAh@AIUREIOUILL)RLLERONEWOoOURIVEIXooINEENrDALFrL=GN4NRLz$>ISZbjsz!,AQct _-3h3h:ht ERONEWOoOURIVEIXooINEgnE:HAIHONHANHAN#)/9@JPY`lryUUALAUSIUAAMIEEEUEKHORI$09BERONEWOoOURIVEIXooINEJUO\xGOOYOYATATHADADHANAOOUNGAMOOOO HO OOOHASAO O AMIYUOYOIYIKHOI!39 ERONEWOoOURIVEIXooINEOOOYO =IU`l8$BMSYjtCIGSUMCIGERONEWOoOURIVEIXooINENEWOoOURIVEIXooINEEROYONYASYONYASAR AR AHAAHAGAAHAA$YATATHADADHANAAHAAHAAAHAAHAASASHAZAZHAAHAAAAAAHASAAASSAKARAAIURLEO I"1:BCI yIRAN ED XI PtAHAAHAGAAHAA$YATATHADADHANAAHAAHAAAHAAHAASASHAZAZHAAHAAAAAAHASAAASSAAAAHAgNNxU SUMhhhh>G!AHAAHAGAAHAAHAYANYATATHADADHANAAHAAHAAAHAAHAAAAAAAALAXcIUON UhIUIIQ)~2ISATAAAAYERONEWOoOURIVEIXooINEkzir|HASARLRLGAHABABEAAAHAWAUENAWAHWAEEAHAAAAYAAAHAAAHAAAQ)ERONEWOoOURIVEIXooINEINECNANANONNINENANNANASANARNARHARAEANARNHARHARHANARHINHINANILILHARANHANAEEIEEAROEWNANANONNINENANNANASANARNARHARAEANARNHARHARHANARHINHINANILILHARANHANAEEIEEAROEININENIOS)/5@HPX`fs~IOS`L7@PX)/@HPX`$4IIOSIQ/@PX\eqH`IOS/`<EAAEOEOEAAEEOEOEIUUIOUOEAAEEOE,EOEOEUI-UAUO2-EUA-UEO-AE=/`IOSPX``E )/@HPX``L IOSIP=Iu`IHIOSI@`X`IQV\IOSI@H`sAUIAAEEEOOAAUIAAEEEOWAHAHUHIHAAHEEHEHOHWAAUIAAEEEOWAZAZUZIZAAZEEZEZOZWAAUIAAEEEOWAAUIAAEEEOWAHAHUHIHAAHEEHEHOHWAAUIAAEEEOOAWAWIWAAWEEWEHAHUHIHAAHEEHEHOHWI{HWE)AUIAAEEEOWAAUIAAEEEOWAAUIAAEEEOWAAUIAAEEEOWAAUIAAEEEOOAWAWIWAAWEEWE!AUIAAEEEOWAYAYUYIYAAYEEYEYOYWAAEAAUIAAEEEOOAWAWIWAAWEEWEXAXUXIXAAXEEXEXOXWIXWEAUIAAEEEOOAAE9AUIAAEEEOWAHAHUHIHAAHEEHEHOHWAAUIAAEEEOOAAUIAAEEEOWADADUDIDAADEEDEDODWAAUIAAEEEOWAAUIAAEEEOOAWAWIWAAWEEWECGAGUGIGAAGEEGEGOHAHUHIHAAHEEHEHOHWAHAHUHIHAAHEEHEHOHWAHAHUHIHAAHEEHEHOHWASASUSISAASEESESOSWAZAZUZIZAAZEEZEZOZOAAUIAAEEEOWAAUIAAEEEOWAYAYAYA[onjopNEWOoOURIVEIXooINEEN WIWEEWE$WIWEEWE2WIWEEWE@WIWEEWENTOZ`fmURTVAAEIOUVAEIOUVAEIOUVAEIOUANAAHEIOUVUAUEUIUOUUUVAEIOUVAAEEIIOUVLALALELILOLULVSASESISOSUSVAEIOUVAEIOUVVEIOUVVAIItEA|` |`IwrxrrMOP MWrxqLUSNNNNEAAIIIIOtEEIAAA`-|EAAIIIIOtEEIAAA |`TETITOTAEAAIIIIOtAAA |`WEHIHOHAHEAAIIIIOtAAA |`EAAIIIIOtAAA|` |H`EAAIIIIOtAAA |`HEAAIIIIOtAAA|h@EAAIIIIOtAAA|`WKW-WPWATWAKWACWAHEHIHIIHOHOOHAHAA|HEAAIIIIOtAAA|`` 'AAIIIIOOO4AAAA |h@EAAIIIIOOOAAA|NHOHOOHAHAA|HTHETHITHOTHATHYEYIYOYAEIIIOOOAAAVKAAIIIIOOOAAALHELHILHOLHAEIOA_GIGIIGOGOOGAGAAGNGHEHIHOHAHEHIHOHAHHIHIIHOHOOHAHAAHHEHIHIIHOHOOHAHAAHeEIOAEIOAEIOAEIOAHUHOHEHEEHIHAUOEEEIAUOEEEIAWUWOWEWEEWIWAHUHOHEHEEHIHATUTOTETEETITAUOEEEIAUOEEEIAHUHOHEHEEHIHAKUKOKEKEEKIKAKUOEEEIAUOEEEIAUOEEEIA`OEEE,`AJUJOJEJEEJIJAUOEEEIALULOLELEELILAHUHOHEHEEHIHALHULHOLHEoLHILHALULOLELEELILAUOEEEIAT^ZUZOZEZEEZIZAUOEEEIAHUHOHEHEEHIHAHSUSOSESEESISAHUHOHEHEEHIHATSUTSOTSEuTSITSA{oAIGAINGINGONGAHWIHWOHWAUISAILIONATHAIROLLUINORTUISILMNNRR FIN"(7RATHVS OC AESC^kJENwENNGAR^kkER ".6kIkTkMdo^k{NGARORALCTAN^kLRN0HOSSHCESCAAGAAAAAAAAAAAAAIAAGAAAAAAAAAAAAALRLJAAGAAAAAAAAAAAAA AAGAAAAAAAAAAA5AHAOHOGOAHAOHOYOATHAOTHONOAHAOHOOAHAOHOOOOOOHASOAAAAAQAAIIIUUKUUUUVYYYYYYEAINEWOAUQ'IYUAEAEEIOU#1=ELR^flzHAN ERONEWOoOURIVEIXooINE ONUOYIIEIUONRAMUOYIIEIUONnjoo njo;NEWOoBRERONEWOoOURIVEIXooINEYEEEANGAAAAAAAHAAAHAAAAAAAHASAAAARAHAHIHIoEENGAAAAAAAHAASAAAAAAAAIAIAZAYENGAAAAHAAAAAAAAASAAAAHAHAAAAHAaYaP%NlAGAATATHADANAAAAHASAHAAHAHAHAGAAHATADHAAHASAYAHAAAYYAYAYOYAYWOYAYAYWAYAYOYAYAYOYAYHOYHAYOYAYAY)aWEEWIWIIWOWOOWAH\;`-OOAAHWEHWA HWEHOOOOWUAAWA*6GAHAAHAGAAHAAHAANAHAAHAAAHAAHAAAAAAHASAAAYANRA EIOUAAA AGA)AAAAAA\fA-I*on~ERONEWOoOURIVEIXooINEAAGASAAAAHAAAHAAAAAAHASHAAEHOEUEI,_rOW AAGAAAGASAAASAAAAHAAAHAAAHAAAHAAAAAAAAAAAAAAVAVAVAVA_rOW AIUEAEYAYYYAYEYYG ERONEWOoOURIVEIXooINE>AEAEVII EI II EI AP II EI II EI II EI AP II EI AAGAGKAAAAPAAAARAAAYAYCAAAAAAAE<AHAXAAXAHAGAAHAAAHAYAATAAANAAHAAHAAAAHAAAAHAAOW _rAUEAUEAHASAAALAIUEOAEAA AAA-3 hIEUEU;YEO XDMV^f vERONEWOoOURIVEIXooINE ERONEWOoOURIVEIXooINEEOWOYAANANG "2-X =LJNJLJ@RLZvz@ !5I]reeLMWzM=z@{iL@'-4:AGMZ`msEPAAAGAAAYAAAAAA!AAAAAAGAAPAAA,4LU;UKUDEPANEPA U-[hAF rxF E AL ~!IKIERONEWOoOURIVEIXooINEIKIONGENGUNGANGINGP ONGUGAGUKAKANGUNGLAKLUK#*2>GQEUAAAGAAAAYAAAAAAAAAAAAAAAA[envIAAHAYAERONEWOoOURIVEIXooINE@EUEUHAAAGAYAADABAEG <'2 ALAHAALAGAAHAAYAAHAAAALAHAALAALAALASASHAZAAAAALAAAHAAAAAOU8ANGAN: MUERONEWOoOURIVEIXooINE,TATHADAERONEWOoOURIVEIXooINEATGNGLAAAKAJAMAWISHNYRUCDNNYEPDDNRROTTBVH\U-gmHAD LJvh~%ATW:L+NANANONNINENANNANASANARNARHARAEANARNHARHARHANARHINHINANILILHARANHANAEEIEEAROEININ ENEU A A A  %LJOVOT WO Nlgz LZ\+NZLJ"DSTHN\j NruOP MLZLsZHINh}2IHOSIEZLZLZUL}sLNGNOP MV=sINETA}HIETAhHOHIHIE  4>Th fWU SH hxFLZ SH ZH veTHvvsOTAsxWu xtLu wHIwYSHvAt wvGvURLZH}&lyI!1>KXewkS R S EOVTHvWMN}ETAs $SHG jmrx{W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:i  z_2_r3JW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:]cXYXYXY]cXYXYXY]cXYXY]cXYXY&]cXYXYXY]cXYXYXY]cXYXYXY]cXYXYXY]cXYXY]cXYXY]cXYXYXY]cXYXYXY]cXYXYXY&XIA&XIA&XIA&XIA&XIA&XIA&XIA3XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY,q3 {*H,q&XIAf{6f]Y u{*H&XIA&XIAf&XIA{*,q&XIA|,q&XIA &XIA{*,q&XIA]c |,q&XIA&XIA& {*H&XIA&XIAfXIAcN M N NIX-]FW}]FN M OOW LMWOW-LMWOW-gNE WO  Od'BxLJO/LJOXhh^i}zLMW*LL@M`iNiWO  2LXmsLUS }EROOURIVEIXooINEoLMWERONEWOoOURIVEIXooINEoLMW s"W %+18WON @LRIP X`iw}OM LMWNOPLLMWLPNlNmk!2IPWpLLLMW  #;J]en}LL ' L7IR_jv PtL /9_xET AHObtIIW:,4:@WO NlNKUaNlij_&WOoOURIVEIXooINEENlsNE izNEWOoOURIVEIXooINEENlsNE iiEN WOoLLLL{Y. LLLLLLLLLLLLLLLLLL-8JakakvPLPLkaka AgLLL~¡ {LLLLL{Y/ºLLLLLLLLLLLLLLLLMOaj $8VÁLL{LL{LL{ÙáìLM{ (0:OpDS\k|7MuM=_e}MWOOčĕOT NDRĥIJLJOĸ]P,;KUOT OpdmOT ňřŦ ű&IVN cpzƉƕƤƻOT OT OOOOOOOc(?V_hrhr|DŽnjOnjOnjOnjOnjOǔǝIJǬdzǬdzAPUPLUSm\OT M|7ǽASHLUSmMWLaP RUE)2AhrtȇȣȷdzǬORANDORiNDRĥIJOOT PA"LMWLMW)RND?FĥIJOYOOOV_oxǬdzǬdzOhrɁɘɼO P aN z 7@N LlʆʔʣP aʩʴLMWLLMWLRC  0COULMWLMWOP M_ek˔˟˲hh%6DJVbiu{OTmk̂OT̠̈̏̚OLLLL!̪̽}EL%1@U\OOT Ncoz͆͑EL PAOT NaLOp ͚ͤͮʹaP OTAHO}Fhhhh}1=[fr~΁Ύεμ$0--OMP-<[tϏϬ϶ϼMMMMOZ"7OPLS _xLMWOP M:aP OaP OaP aP OP MЎPКСyPйUSEOP MOP MOP M(8Q^grъhhP-OMhhѢhhP-OM"4N <CULLQ&YfnELLz҄ҚҤҸUTNNEWOoOUR #*8C^JQfohY`mva~M=ӊӗOOKӥPtӫӷӿASHNEWOoOURIVEIXooINEENls%-5?HNEWOoOURIVEIXooINEENls%-5?HNE WO NlNiIX jNj EN Q_YcmvԊԔbԞls%-5?HNEWOoOURIVEIXooINEԩԴNNNNNNNNNNNNmrEFTmrEFT+Jc|Ֆկ/G`x֐֨ $:P\ $:fp׀פ׷+FY$:lNNNN؀؉ءز؉ءز؉ءز1EWmr*mroكlEFTPmrOWNEFTPmrOWNٗ٬پYfZm-ZmfY3NN?MMWEFTmrEFTEEFTULd%jMOڝڴLdNLdNLdNLdNLdNLdNLdNLdNLdNLdNLdNLdNLdNLdNLd NW#=FLMWMMWSMWbMMiiM ۄۓLMW۠۬۹LMWMCMLMWNLdNLd)=CLTLdNZdUNq|܈LdNOXܓܙܡܺNLdLMWLP MWa  +NKH4CKT^p}݈ݚݧݰAKEIREݷINDݿ/Ld #-5<CKQW^eEOlrxށލޗޠINGާOOKޭ޴AWNINGާOOKޭ޴AWN޻bBObBOfmeeeYY9  &;F[mw߀ߐANGINߟINANG߬NLd߸EAR %2mrEFTFO]e}=OMNLdUNO #/8GS\ANINGANINGh}AINNLdICK,3<LdNLdNK[~ѱhhPt(>LSZhtENT,6JyLdl:IST۬NLdNTNT $ .:LdNENME_r NNLdIX N_vNLdN 1CNR N[f|MMMMLdonNNLRLJ:bB(LMWLMWhhhhhhLMWLMWNEWOoOURIVEIXooINEԩNEWOoOURIVEIXooINEԩNEWOoOURIVEIXooINEԩDOjOpaLkwNLdOP-LLhhMMLLLLk&7NO^p?FLMW8UcNDR۬M(MW-P aACKMWLLLLLLMWLMWLMWLMWLMWLLPLLL{LL{LLL.=233234424434342345525535352355454524545345345C6626636362366464624646346346I6565625656356356O56456456U456[ag7727737372377474724747347347n7575725757357357t57457457z457ꌶ7676726767367367ꓴ67467467꙳467ꫵ67567567겳567Ĵ5678828838382388484824848348348858582585835835858458458458 868682686836836868468468%468+1768568568>568DJP568W]cjpw~8787827878378378놴78478478댳478략78578578륳578뷴57878678678678678 &-6785;AHNU\djqxLL{LLLLLLLLLLJAIL LJLLLLLLLL/Qs6akYsOP M~3L8LL`{9YLLLLLLLLLLLLLLLLvJ>H>HT{i/p nj=\LMWP a{POTLMWLMWLMWLMWLMWMWLLMWMWLLMW2NnEFTPLLZLZPOWNmrEFTmrEFTMWLMWLaMWLOpI-AmN8OimBoz7 /LMWRLMWNLdLMWLMW_ku%2LMW@NLdNLdNLdNLdXe~CLJOhhINYINYOT OjO>OTLUSOOND R (;Ncӊ}ĥIJa7OIN!zOOT O,:I~mBiLMWUz7mLMWOjOpOw<VlNDRwOOĥIJ3ND R NDRND^ND R ND R v*LJa7jeLJOz !HhWO NlOOOOOROOO,AOOOOOOOTP-ZFOOlulu}hrhrhrhrhrhrV_njOnjOnjOnjOnjOnjOnjOnjOLMW?FnjOOnj  %-LaP 8MLJLJhl   / ? VOO e  Y9YY9Y{LLLY9YY9Y{OP MM MWOP MWLdNLdNLdMNLdN LdNLdN LJ 2 DLJAIL LJ P Z{i |  FL    A Y {  LdNLdN  mk    { OLLLL{Y YLLLLLPLLLLA )LLLLMO K |  LLLLLLLLMWMLOP EFTmrEFTmr  C Z z    LLLLakakLLLLLLLLLLLLEFTmrEFTmrLMWLMW  ']sM=O ^ tP-OMhh OP M:\+   WOoOURIVE         ) > EEUS K R Z b kLMWLMWLLLLNEWO t z       TNs   ZUUKYEDE    $ , 2^ 9AKO @ H PNU V ] c iKU pERUTUEHTASI vHAERUERIATI }UUS O  ITA     ZUUKYEDE    $ , 2^ 9AKO @ H PNU V ] c iKU pERUTUEHTASI vHAERUERIATI }UUS O  ITA     W:L     !W:LW:LW:L}} 2~ M~ Y f s     sLW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LAII I AU HI W:LW:L   W:L-o   ! /o ANANANONNINENANNANASANARNARHARAEANARNHARHARHANARHINHINANILILHARANHANAEEIEEAROEAABABHAG ADADHADD EYAFb  bAHHAAbI bALAMANAGNANGAPUARARR b ASASSASHATATHACHATTAVAWAY AZZEO \ OAOAOAOAHOAOAOAOAOAYOA OAOADOAOAHOAHOAHOAOAGWAGWI GWESASUSISAASEESESOCACUCICAACEECECOZAZUZIZAAZEEZEZOCHACHUCHI  CHECHOYAYUYIYAAYEEYEYOYAYUYIYAAYEEYEYOYAYUYIYAAYEEYEYOYAYUYIYAAYEEYEYOEEHEEHEEALMNERSEASEHEHA~ITA E # )ATU 6kWLMWLMW KLMW `LMW nMLZ LL LMWl@LMWLMWLMWLMWLMW  1 Hi V{ i ty'OTnj LMW WO-N  y4  > T k r k MWL on~LMWLMWLMWLMW * 9 @NEWOo FOX MNEWO SEALNEWONEWOoOUR ^ dNEWONEWOANDAP kUNOON q w ~NEWOIRENEWO OWOGADE YENEWO  NEWOoOURESH AMWELDNEWOEAT NEWOo NEWO bl) OOT NEWOITY  NEWOONGATENEWOAINLUE 2EAFINDLYNEWOo AEAD RONE eISHIRDALT k q x--------NEINEOT̚ OOKWOIDANEGS o  CE Mm  RAP   EN SEAL @     O  IG  OOFNCH AME " ) 0ORK 6 >RY E R _ k uOW { TEP  OORAND AP  XEOTUNAYOONREEACKTOP q   URLAN ݿIRELAW    ANGOWOG ADE ILE IFESE    KINISHYE $aj * 0 7 =AVE C ICEILKARET ILDNDLOWAR QEAT WELF ` g nOAT u ~     ESTEEORN EANIG  EDUNOOTODYART  ALKITYINE  OLDONGATE   AINLUE ACE% EEK EAFINDLYATEAD  ONEALLAIR   / eISHIRDALTEER kEMP q 8 ? EROG PRUMATOSEVEN W ] d k q    l@mr  !M  ohnjo   1 < ELMWLMWLMWLMWLMW Q YLMWLMWLMWLMW _LZOW iNEWOoOURIVEIXooINEm;i z LRLJ     EN   # 5 IAAIIUUEEOOAAIIUUEEOOAAIILUEEOOAIUEOAAAIIIUUUEEEOOOAIUEOLAIUEOLIEOUAE _ g tLAAIIUUEEOOAAIIUUEEOOAAIILUEEOOAIUEOAAAIIIUUUEEEOOOAIUEOLAIUEOL IEOUAEAIEOq  _ +HHHHIIUUNNNGNGRUGNH N=/`IOSPX``EI)/5@HPX`EAAEOEOEAAEEOEOEIUUI`bsIOSI= IIOSI/P/IQ\IOSIAAEEOEhW V NE WO NlNOP W!Mb& e UAN UIIUENNONNRNNNNNNMGGINNUNNMMNGNNNHHY WWEHGGXGWZZZGPZWGZWGZTZZPPWGZWZZZPZGZWZTGDZNZZWGXWG GXGZP0 UIUOUAIUEOUAIUEOIOS)/@HPX` B J Q Y ` g n t {        HUNEWOoOURIVEIXooINEENOONIREݿOOD UN AVE AME     ALL     $ -ESTELF 6 < IOTOEN bbbac P W ` hNEWOoOURIVEIXooINENEWOoOURIVEIOS)/@HPX` B J Q Y ` g n t {      y   NEWOoOURIVEIXooINEENOONIREݿOOD UN AVE AME     ALE     TEMESTOPY IGHoYOWEFTmr       $ IXooINENEWOoOURIVEIXooINE    AYUNEULY  ! + 3  DEMU L UERONEWOoOURIVEIXooINEENls%-5?HNEWOoOURPAAUARVCM [ cU i p w   AU AAABBBALCALFFGGZHZHZHZHZU LLLLMMU MMMMM M M M M M APAPAPAAD SSU SSVVU VVV WWU WWW  MQCD OBYAPNK TMNOGX ILOLHMPMRRVB NEWOoOURIVEIXooINEENls%-5?HNEWOoOURIVEIXooINE   B  , < L h w                - < B R Y c p ~         ܈    ! * 7 F Y h s | /             0 7 ? VTXPETEXEEPTXPOXOOPTXPXUITIXIIPIETIEXIEIEPATAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIEXIEIEPATAXAAPUOXUOUOPOTOXOOPUTUXUUPURXURYTYXYYPYRXYRBITBIXBIBIP l rBIE xBATBAXBABAP ~BUO BOTBOXBOBOPBEXBEBEPBUTBUXBUBUP BURBYTBYXBYBYPBITBIXBIBIP BIE BATBAXBABAPBOTBOXBOBOPBUTBUXBUBUP BURBYTBYXBYBYP BYRMITMIXMIMIP MIE MATMAXMAMAP MUO MOTMOXMOMOPMUTMUXMUMUP MURMYXMYMYP MYRITIXIIPIEXIEIEPATAXAAPUOTUOXUOUOPOTOXOOPEXEUTUXUUPURXURYTYXYYPITIXIIPATAXAAPOXOOPUTUXUUPURXURYTYXYYPITIXIIPIETIEXIEIEPATAXAAPOTOXOOPEXEPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIEXIEIEPATAXAAPUOXUOOTOXOOPEXEEPUTUXUUPURXURITIXIIPIEXIEIEPATAXAAPUOTUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURDITDIXDIDIP DIE DATDAXDADAP DUO DOTDOXDODOPDEXDEDEPDUTDUXDUDUP DURDITDIXDIDIP DIEDATDAXDADAPDOTDOXDODOPDEXDEDEPDUTDUXDUDUP DURNITNIXNINIP  NIE NATNAXNANAP NUONOTNOXNOPNEXNENEPNUTITIXIIPIEXIEIEPAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURLITLIXLILIP LIE LATLAXLALAP LUO  LOXLOLOPLEXLELEPLUTLUXLULUP &LURLYTLYXLYLYP ,LYRITIXIIPIETIEXIEIEPATAXAAPUOTUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIETIEXIEIEPATAXAAPUOTUOXUOUOPOTOXOOPETEXEEPUTUXUUPURXURITIXIIPIEXIEIEPATAXAAPUOXUOUOPOTOXOOPETEXEEPUTUXUUPURXURGITGIXGI 2GIE 8GATGAXGAGAP > DGUO JGOTGOXGOGOPGETGEXGEGEPGUTGUXGUGUP PGUR VGIEGATGAXGAGAP \GUO bGOTGOXGOGOPGEXGEGEPGUTGUXGUGUP hGURXITXIXXIXIP n tXIE zXATXAXXAXAP  XUO XOTXOXXOXOPXEXXEXEP GIE GATGAXGAGAP  GUOGOTGOXGOGOPGEXGEGEPITIEXIEATAXAAPUOTUOXUOUOPOTOXOOPEXEEPATAXAAPUOXUOUOPOXOOPEXEEPITIXIIPIEXIEIEPATAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIETIEXIEIEPATAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRZITZIXZIZIP  ZIE ZATZAXZAZAPZOXZOZOPZEXZEZEPZUXZUZUP ZURZYTZYXZYZYP ZYRZITZIXZIZIP ZIE ZATZAXZAZAP ZUOZOXZOPZEXZEZUXZUZUP ZURZYTZYXZYZYP ZYRITIXIIPIEXIEIEPATAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRSITSIXSISIP SIE SATSAXSASAPSOTSOXSOSOPSEXSESEPSUTSUXSUSUPSYTSYXSYSYP SYRHATHAXHAHAP HUO HOTHOXHOHOPHETHEXHEHEPHUTHUXHUHUP HURHYTHYXHYHYP  HYRHATHAXHAHAP  HUO HOTHOXHOHOPHETHEXHEHEPHUXHUHUP "HURHYTHYXHYHYP (HYRRAXRA .RUOROTROXROROPRETREXREREPRUTRUXRURUP 4RURRYTRYXRYRYP :RYRRATRAXRARAPROXROROPRETREXREREPRUTRUXRURUP @RURRYTRYXRYRYP FRYRHATHAXHAHAP LHUO RHOTHOXHOHOPHETHEXHEHEPHUTHUXHUHUP XHURHYTHYXHYHYP ^HYRATAXAAPUOXUOUOPOTOXOOPEXEEPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIETIEXIEIEPUOTUOXUOUOPOTOXOOPUTUXUUPURXURYTYXYYPYRXYRITIXIIPIETIEXIEIEPUOTUOXUOUOPOTOXOOPUTUXUUPURXURYTYXYYPYRXYRJITJIXJIJIP d jJIE p vJUO |JOTJOXJOJOPJUTJUXJUJUP JURJYTJYXJYJYPJITJIXJIJIP  JIE  JUOJOTJOXJOJOPJUXJUJUP JURJYTJYXJYJYP JYRYITYIXYIYIP  YIE  YUO YOTYOXYOYOPYUTYUXYUYUPITIXIIPIETIEXIEIEPUOXUOOTOXOOPYTYXYYPYRXYRITIXIIPIETIEXIEIEPUOTUOXUOUOPOTOXOOPUTUXUUPURXURYTYXYYPYRXYR7OTIITYIPYPSIGOPEPIXITYRBUTOPOUTXUOATAUPYTDURURGUOYOPUPJUTOTYTMOITURHYEPAOZUPJYOTJIEOUHURIEYUOPIPXOPHATURHOPHE BIEE\AAHAAAHAAAHAAAHAZASASHAAAAAHAAGAAAHAAAHAAHAEUEHE  YAOAEUnjoEENEEEEEENEEHEEEEBEEPEE BEEEEEEEEHEEHEE EEEEEEDEEEEHEEEEHEEEEEEJEEEEEE EEEEEEYEENIINIINIHIIBIPIGBIBIIIIHIHIHHIIIIDIIHIIHIIIJIIIGGIIIIYINGANAANAANAHAABAPAPANGBABAAAAHAHAHHAAAADAAHAAHAAAJAAAANGGAAAAYAOONOOOOOONOOHOOOOBOOPOO BOOOOOOOOHOOHOO OOOOOODOOOOHOOOOHOOOOOOJOOOOOO OOOOOOYOONUUNUUNUHUUBUPUGBUBUUUUHUHUHHUUUUDUUHUUHUUUJUUUGGUUUUYUNGONOONOONOHOOBOPOGBOBOBONOOOHOHOHHOOOODOOHOOHOOOJOOOGGOOOOYONGENEENEENEHEEBEPEPENGBEBEBENEEEHEHEHHEEEEDEEHEEHEEEJEEEGGE EENEEYEG njopAAOO  INGIIANGAAAAANG UNGONGO-OONGERONEWOoOURIVEIXooINEAOW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L  2EN 8 A K}I~%ERU~/}F k ] k ]W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L eF kAUEEEAEYIAAIIIEE v |AADAA UUUHIII EUXYEEETUAEU OQHUUQASHAEUXEUXJEETEEUEUEEEEEUUIIEUXAEEN GGAGAHOUAEUOMAAIIOQOBENENENAIIOBAAETPAENTUU       oonjop IN yIN yIN yIN ybbO̚ P aOW _rOW W:LW:LW:LW:LW:LW:LW:BLW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L UMUMUMUMvUMMW:LW:LsW:LW:LW:LW:L o 0W:L B Z W:L  W:LW:LW:LW:LW:LW:LW:LW:LW:LW:Lx xWHILW:LW:LW:LW:LW:LW:LW:L LW:LvsW:LW:LW:LW:LW:LW:LW:L 7L ! !* !@ !L !] !h !p !z !OHOOHO !OHOOHOTOTHODODHOOHOOHOOOHOOHOOOOROOOO ! rDALFrL=GNf !W !6AHAAGAAHAAYAAHAAAAHAAASASHAZAAHAA !AAAHAAAAAAGAEAATATHADANA ! ! ! !X? " "LRLJF)2AIURLEIOUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALA "*AIURLEIOUIz$ LJERONEWOoOURIVEIXooINEERONEWOoOURIVEIXooINEAAAAI "? "M`LJWOo@ "a "jX "u "WM "ERONEWOoOURIVEIXooINEAHAAGAAHAAYAATAAAHAAAAAAAAHAAAAEOEE " " "WIHYAAAGAAAAAAAAAYAAAAAAABAGGADAYJAIUUAGI "IOS/IOS/HIOS "H` " " " " # #J #" #, #2 #8 #@I #G #P #VIA #d #jA #pGAA #yA # #YATA #DA # #A #A #AA #A #AAA #AA #jAA # # $ULU $UKU $N $- $* $0 $8LMW $@ $F $L $R $Z $a ${ERONEWOoOURIVEIXooINE! $ $HAHAHANAHA $ $YAAAHAAHADADHANAERONEWOoOURIVEIXooINELAAHAAHA7IAHAAHAGUEGAHAHHAAHAHUEHAHJAAHAAHAUEADAAPAHAAHAUEABAAAAASAAAAIIEIUEAAAA $HS ERONEWOoOURIVEIXooINEeLJOAAHAAHAYATATHADADHAHAAAAHAA $AAAAYNMCNEWO % %"HAHAOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rOW _rMAE %1AEAAUEYNMK %:HOONGON %:AM %@ %GHAYATATHADADHANAHASAIUAIUAU %O %XNJIX[6 %eITHUTHI %xTHETHODHUDHI %~ %DHEDHOZUZIZAAZEEZEZO % % % % % % %BABUBIBAABEEBEBO % %i=Z % % %; & & NG N &'Mr &3 &= &\ &mLJ &v &L &HI & & &EG & & & &ENG;t: & ' k 'O ' '&Z S 'G 'bLMW~AAEIOUVAEIOUVAEIOUVAEIOUANAAHEIOUVUAUEUIUOUUUVAEIOUVAAEEIIOUVLALALELILOLULVSASESISOSUSVAEIOUVAOKAMAIITAAHILILHOUGOUHOUAIANGUKNHAM 'qOKHAMAIAILILHOUHOUHAMOK AI IT A A IL 'w NAPNAPNAP '} 'NAP 'UNG 'UM ' ERONEWOoOURIVEIXooINE EO-IEOEO-IEO A-AEEOE-IOU@ ',IOS '/@P ' ' ( X\ (s () / (4 (B/@I/@P``5IOSP (v ( ( ( ( )o )&90090190290390490590690790890990A90B90C90D90E90F91091191291391491591691791891991A91B91C91D91E91F92092192292392492592692792892992A92B92C92D92E92F93093193293393493593693793893993A93B93C93D93E93F94094194294394494594694794894994A94B94C94D94E94F95095195295395495595695795895995A95B95C95D95E95F96096196296396496596696796896996A96B96C96D96E96F97097197297397497597697797897997A97B97C97D97E97F98098198298398498598698798898998A98B98C98D98E98F99099199299399499599699799899999A99B99C99D99E99F9A09A19A29A39A49A59A69A79A89A99AA9AB9AC9AD9AE9AF9B09B19B29B39B49B59B69B79B89B99BA9BB9BC9BD9BE9BF9C09C19C29C39C49C59C69C79C89C99CA9CB9CC9CD9CE9CF9D09D19D29D39D49D59D69D79D89D99DA9DB9DC9DD9DE9DF9E09E19E29E39E49E59E69E79E89E99EA9EB9EC9ED9EE9EF9F09F19F29F39F49F59F69F79F89F99FA9FB9FC9FD9FE9FFA00A01A02A03A04A05A06A07A08A09A0AA0BA0CA0DA0EA0FA10A11A12A13A14A15A16A17A18A19A1AA1BA1CA1DA1EA1FA20A21A22A23A24A25A26A27A28A29A2AA2BA2CA2DA2EA2FA30A31A32A33A34A35A36A37A38A39A3AA3BA3CA3DA3EA3FA40A41A42A43A44A45A46A47A48A49A4AA4BA4CA4DA4EA4FA50A51A52A53A54A55A56A57A58A59A5AA5BA5CA5DA5EA5FA60A61A62A63A64A65A66A67A68A69A6AA6BA6CA6DjA70A71A72A73A74A75A76A77A78A79A7AA7BA7CA7DA7EA7FA80A81A82A83A84A85A86A87A88A89A8AA8BA8CA8DA8EA8FA90A91A92A93A94A95A96A97A98A99A9AA9BA9CA9DA9EA9FAA0AA1AA2AA3AA4AA5AA6AA7AA8AA9AAAAABAACAADAAEAAFAB0AB1AB2AB3AB4AB5AB6AB7AB8AB9ABAABBABCABDABEABFAC0AC1AC2AC3AC4AC5AC6AC7AC8AC9ACAACBACCACDACEACFAD0AD1AD2AD3AD4AD5AD6AD7AD8AD9FILFIFL ):TOWCHNI )C )K )S )i ) )LEFEAF )ESHAV )cIN cIN "( )ET AH )AV )ET OD ZUN *u *OF *#cAV *)ET AF E *8 *LZ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ *LZ *LZ *LZ *LZ *LZ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ *LZ^h@ *LZ *LZ^h@ *LZ^h@ *LZ *LZl@l@l@l@l *Vl@INGl@ *k *w * * * * * * * * * + + + +B +e *LZ^h@ *LZ *LZ *LZ +vHZ *LZ *LZ *LZ^h@^h@ *LZ *LZ *LZ *LZ *LZ *LZ *LZ^ *LZ^ *LZ^h@_AH _ +EH _AH c_ +EH _AH c_ +EH __ +EH AH ____AH __AH c_AH __AH c_AH +_____AH c_ +EH AH _ +EH _x_AH cAM _ +EH _AH c_ +EH _AH c_ +EH _AH c_ +EH __ +EH _AH c_ +EH cEH + + +W[[ +EH c__ +EH EH c__ +EH EH c__ +EH EH c__ +EH +EH +EH _xAM _ +EH _ +EH _x_EH c__ +EH +EH c__ +EH _AH c_EH _AH c_EH _AH c_EH +AH ______AH c_AH c__AH c_ + , _____AH c_AH __AH cAM __AH c_EH _AH c__AH c_EH __ +_AH c_EH _EH _EH _EH _EH _EH _EH AM EH _EH W[[ +EH +EH +EH +EH +EH +EH +EH +EH +EH +EH _AH c__AD AD +EH +EH +EH +EH +EH +EH +EH +EH +EH +EH _AH c_(_AD AD _AH c__c ,#_AH c_AH cAH AH Z *LLMW ,2NH ,B ,H ,N ,V ,^ ,z , , , , , , , - -Z --_AH cZ^EH + -8_Z^Z^ -C^ -N^Z^ -]^Z_EH -t^ +_EH +^ -EH +^^Z __ -AH ___ - - -^ +EH +^ - +EH +EH +EH AH _ -AD cAD __AH _ AF _ - -IN AF . .! .@ .aAM _ .p .z .a . . - . .NH ,B ,N . . /% /< /N /U /[ /b /i /s /z / / /N / / / / / /0123456oooon~ 0 0)LMWLMWLMW 0HLMWLMWLMW 0ZLMW 0mM N lLMWLMWLMWLMWLMWLMWLMWLMWNLMW 0| 0LJ 0| 0lPooo~on 0LMWLMWLMWooooOOEpIoop' 0 0 0 0 0 *Lh@ *Lh@ *Lh@ *Lh@ *Lh@W{Z *LZ *LZ *LZ *LZ^h@ *LZ *LZ^h@ *LZ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ *LZ *LZ *LZ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ^h@ *LZ *LZ *LZ^h@ *LZ *LZ *LZ *LZono{MooooLMWoonjoooERONEWOoOURIVEIXooINEoopOEp pp'p5pIpYpnppppppLMW 1!LMW 17qOAUOU 1IAIUEOAIUEOAIUEOAIUEOAIUEOAIUEOAUOAIUEOA Y`b=/`IOSPX``E )/5@HPX`EAAEOEOEAAEEOEOEIUUIpqOT qqEN ON  1pLLLL 1 1s 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2% 2- 25 2= 2E 2M 2U 2] 2e 2m 2u 2} 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3% 3- 35 3= 3E 3M 3U 3] 3e 3m 3u 3} 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3018019022034047049056063064079082083086089{ 4 4 4 4& 41 4< 4K 4U 4_ 4j 4t 4~ 4 4 4 4 4 4 4 4 4 4 4132 5 5 5 5"142 5,146150 56152153154 5@157158 5T160161 5_ 5l164165166167168169170171172 5x174 5177178179180181182183184185189190 5 5 5 5 5232 5234236 5 5 5 5245246 6248249251252253 6255256257258259155200201202203204205206207208209210211212213214215216217218219221222226227228229250305INEOT 6&-NEWOoOURIVEIXooINEENNE WO NlNiIX jNj NE WO NlNiIX jNj EN bbbac P W ` 61 69b& eRY 6Cb& rDALF 6KIVEaciEN acNE iNE EN acNE iNE EN ac 6S 6\d 6q 6}d 6 6}IVEEN 6 6q 6 6 6qNE Nl 6}cd 6 6NE  6 6IGN 6 7 7` 7WO NlNi 7 7* 78 7? 7G 7O 7W 7_ 7gLD 7v 7 7 7 7 7 7 7 7 7 7 7 7S 7 8. 8& 81 89 8C   8K 8R 8[ajOW 8aLUB 8h 8qAWID 8y 8 8OMB 8 8 8HIPORNIDE 8ATAM 8OVE 8EE 8INE 8 8ILY 8 k 8 8 8 9 9 HHMNKTNN12UUD22HH2-18NT2SUUU2DU2TT2GI-39TUU2RBB2B3B4D22UU3 9%NEWOoOURIVEIXooINEENNE WO NlNiIX jNj $EEEEEEHEALMNSHEHEURSEKSHEHEFRSHEIUSSNEIVEENEHSA 94IBAAGS 9< 9CUJAAGL 9LIS 9S 9Y 9_ 9eERRUS 9l 9u 9{ 9 9 9 9u 9 9+NURAIOIHOI 9ATA 9OKEEI 9 9OOIEEIEIIIAI 9 9 9RYERUOFASIUERERERIATEUAANOIATA 9IILPAETA 9HA}OOETAOTAETODAFHIN}2EMHALUNU 9INUADEOPA 9 9OSU% 9AUAUAAAIAUAIUHAAAAAUAIUAAIAUAAAHASAA : : : :, :9 :CAGA :O :WNEWOENHOHOYWUEEEEEEEEEEHEEEEAYAYFEETHHEESEESHHEERLMNNGIWHOHOYWUEEEEEEEEEEHEEEEAYAYFEETHHEESEESHHEERLMNNGIWEEPOTICKEE :dOURELEAUNGIBEADAGOWHEYOO :j :rOE :xOLLIMEFGGSHDONOOLUTHOARUNATGECEPAKOZEILWERERIRRR :~ARANEWLEFAAAAHAEELAA :HAAYNAAAAFAAFAANIINUUNAWAAAEO ERONEWOoOURIVEIXooINE$IINHRAHA :INAYAAHKAYAAAAINAHPAAHAAHTASA :SHAHAAHAHAAHA$IINHRAHA :INAYAAHKAYAAAAINAHPAAHAAHTASA :SHAHAAHAHAAHA(EEHEEDEHEIEEJEEEEELEEEAJEEEEREEHEEHEEEEHEHE :HE4LTETIMATBARLYNHILASHAOWDHARBHAANNYAEYNYANARHOXARYITEYTAYORHOYHIYAYAQAROWC :HAKAYNNYAYAMZAYHATEN :ATEYKEYZIWRHOYWNYAWAYNAYDIWRIW :BEEEHEEHEIEAAHAJEEAALAEEJEEAEEHEEHEEEE BEEEHEEHEIEAAHAJEEAALAEEJEEAEEHEEHEEEE4SABAAHAADAHAIAAGAJAGJAAJAAAALAAAJANAAARAAHAHTAAHAAAXAHAXHAYAHAHATAKANHASAO7 : : : : : : : : : ; ; ; ; ; ; ;$ ;* ;1 ;8 ;> ;E ;L ;R ;Y ;_ ;e ;k ;q ;w ;} ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; < < < < < < <% <+ <1 <7 <= =D =J =P =V =\ =b501502503504505506508509510511512513515516520521523524525526527528529530531532534535536537538539540541542545547548549550551552553554555556557559563564565566568569570571572573574575576577578579580581582583584585586587588589591592594595596598600601602603604606608609610611612613614615616617618619620621622623624626627628629634637638640642643644645646648649651652653654655656657658659660661662663664 =h =o =v =} = = = = = L2 L3 L4 L6 = = = = = = = = =800801802803804805806807ZmEx8vY >vURL > AILOOK >LZ >& ><v >IW: >S >a >k >vS Z W: >EZH > >rw0w;EG >AILx >x > > ?t ?LZxuu u ?9 ?]A,AEIOUAEIOUAEIOUAEIOUAEIOUAEIOUAEIOUAEIOUAEIOAE ? ?ETH ?EAWETHETHODHAPH ?EMUNYINEm#OPHESHHINAWqNEWOoENEN ?ETH ?EAWETHETHODHAPH ?EMZYINEm#OPHESHHINAWhhNEWOoOURIVEENZ ?ZAWETHETHZYINEm#OPHESHZNEWOo ?IVEEN ? ?ETH ?EAWAYNETHETHODHAPH ?EMUNYNEm#OPHHINAW!NEIVEEN ?LFETAMLELTEAUAIETETODAFAMDEMUNEMKINEADEOFOSHHINAUNEEN ?WOo ?STNNYN @0102030405060708091011121314151617181920212223242526/AAAA-2AAAA-2EE-2AA-2AHAHAAA-2EAAAA-2EE-2OAIDJ @AAAAAAEAAHAHA\EAAAEOA @! @1MTMNNEWOoOURIVEIXooINEEN2NE WO NlNiIX jNj NE WO NlNiIX jNj EN bbbac P W ` 61NE WO NlNiIX jNj @:WO NlNiIX jNj EN @F @O @Y @k)2AHAAHAAHAAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAAAKA @}TTAHA @ @~ INEWOoOUREN /OTL @ @ @LJ @@E ?ETHEMOPHAWHINESHETHAWATAPHUN @m#ELEFYN @ ? @ETHAYN @ODHHAW @NE @EHAMAHEEMAFAWS-2EHEHEHS-1AFOONHAHADS-3EHLEFINADEEMALAHAINHALEHHEHAHNEEN' ?ETH @ ?EAW @ @ @ AETHETHODHAPHAPH= ? A AEMUNYIN AEEm#OPHOPH A!ESHHIN A'AWl@NEIVEEN ?TAR A-LJw A56AOAONANEEEEOIUEEYEVEEGEHEEEEHEEHETEEEEHEGEGYEGVEEYENEEMEYEEEEEEEHEHEHYESHEE AA A[L Aa Ao A ?ETH ?EAWETHETHODHAPH ?EMUNYINEm#OPHESHHINAWNEWOoOUREN ?ETH ?E AETHETHODHAPH ? AUNEm#HINAWNEWOoOUREN ?ETH ?E AETHODHAPH ? AUNEm#HINAWLlOTNEWOoOUREN ?Ei iiiiiiiiiiiEDiiiiiiiiiiiELLTMNiiiiiiNG A APPC iiiiiiiiiERSES iiiiiiiTASH ABMBCNCCSDND AEFGGYHIJKKNKLLYMNNYO A AEEPMPOSSZTNTTYCHU A AVZZS AS ABMBCNCCSDND AEFGGYHIJKKNKLLYMNNYO A AEEPMPOSSZTNTTYCHU A AVZZS ASNEIVEENAAATAAAAHAAADAARAAAHAAAAAA AGAYAA B B B BANA B% ERONEWOoOURIVEIXooINE&ERONEWOoOURIVEIXooINEE B+2AAAAAAAAAAAAAAYAAAAAAA B7 BDLJ B^ BzAAAAAAAAAAAAAAYAAAAAAAOjOpNEWOoOURIVEIXooINEENNE WO NlNiIX jNj ALFrD:@*LIFEEHEHEEIMHIM BHAAALALAHAAAINHINADADAEYN BAA BAFAFHAFAFAMIMUNMAWWWAYOTTWm B B BAL AH AF B B B C C& , , C/ CF CO CZ Cn C C CASR CZZAWETHODHAPH ?EM C\E C CHIN DNEWOoOURIVEEN ? / D% ?ETHEAWETHODHAPH ?EMUNYINEm# D:HINAWETHESH DDOT OT @l DU *#ZNEEN ?ARS D` Do D D ?ETH DAW DODHAPH ?EMUNEm#ESHHINAWESHl@l@ARARSLETH ?E DETHODHAPH ?EMUNYINEESHHINAWNEWOoOUREN ? ?ETH ?EAWETHETHODHAPH ?EMUNYINEm#OPHESHHINAW D8z$)2NZAIURLIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALALLARANNA DIURLIUILJINE @ @$NEWOoOURIVEIXooINEENERONEWOoOURIVEIXooINE D D? Ez$)2AIUIUAHAAHAGAAHAAHAYATATHADA~DHAHANAAHAAHAAAHAAHAAAAAAHASAAAAIUIUI:[ E)MLJ E6AHAHAHAHAHAHAHGAHAHAHAHAHAHAHAHAHAHYAHHEHHHHHAE ERONEWOoOURIVEIXooINE5z$)2AAAHAAAAHAAGAAAAHAAAAHAAYAATAADAA %~NAAAAHAAAAHAAAAAAHAAAAHAAAAYAAAAAAAAAAAAAAIUIUI U I Ed ERONEWOoOURIVEIXooINE ElLJp EyAI E'AHAAHAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAARA E El EEz$)2AIURLIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAALAAHASAAAAIURLIUI@NZMLJs^ E E E E E EERONEWOoOURIVEIXooINEKAM "u FNEWOoOURIVEIXooINEENAIUAHAAGAHAGAAHAAJA%YATATHADADHANAAHAADDAHAAAHAABAHAAAAAAAALAAIIU)I:+LJ FLJ F)A F4 E6AHAAAHAAJAYATATHADADDADHANAAHAAHAAAHAA HAAAAAAAARAHA El;AIUIUAHAAGAHAGAAHAAJAHAYATATHADADDARADHANAAHAAHAAAHAABAHAAAAAAHAAA)AIUIU:I ERONEWOoOURIVEIXooINEz$)2AIUEIOUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAALAAHASAAA FO:@AIUREIOUILJRLLERONEWOoOURIVEIXAAIA AIURL&OUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALARALLA @AIURLOU F)2g_ G G G FM G0 G7gKAIURLIUAHAAHAGAGHAAHAAHAYAYHATATHADADHANAAHAAHAAHAAHAAHAAHAAAHAAHAAHASAAAAIURLIUIz$)2:@ G?M GNLJnj "jERONEWOoOURIVEIXooINE GU Gb Gs^HNZ9NJIAIURLIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAAAIURLOI OUz$)2I:@ GM ERONEWOoOURIVEIXooINE6AIURLIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAAAIUR IUz$)2I:8LJOTAR G G LJOING GLJO G GAYSWO N GAAIURLIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALAAIURLIU)2I GLJ G ERONEWOoOURIVEIXooINE G HLJOLJLJ H :AIUIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHAAARA)2AIUIUI: HT ERONEWOoOURIVEIXooINEERONEWOoOURIVEIXooINEERONEWOoOURIVEIXooINEAHAGAA\AHAAAAHAHAAAAYAAAHA\HAHAHA Hg HtAIUWIM H~ ERONEWOoOURIVEIXooINEENL H HATATHADADHANALA<AIUIUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAARAAIURIU)2I:SGAAIUAOIUNGAONYUJCNNDDTEUNGATMUUIYOOLOORRARSUUIIIYOGAAIUAOIUNGAONYUJCNNDDTEUNGATMUUIYOOLOORRARSUUIIIYOERONEWOoOURIVEIXooINEEN HAIUAHAAHAGAAHAAYATADADHANAAHAAHAAAHAAHAAAYAAAAHASAAALAAAIUI )z$:I H H^h@ E H "j G ERONEWOoOURIVEIXooINEAIUR.IUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALARAAIUR IU)2I@8 "u EB @FEEIU H B+AHAAHAGAAHAAYATATHADADHANAAHAAHAAAHAAHAASASHAZAZHAHAAAAAAAHASAAASSA HIz$bi)2 IAAAA^ < ILJ I^ < I'K @FEEIU B+AHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAASASHAZAHAAAAAAAHASAAASSANZAAHAAGHA)2 G I' ILJ I1OUN9IIIOOOAAAHRI I7HRO I=HRA ICPEPIPOPAAAAAAAAGAAAHAAAAAHAAHAAAHAAAG IIONE ISN Ig IIONEN Iu INONGONEwNARK I I I I I ILZ IEOEEUE"EVI IKOMAREU IIKA IIPIL I IAHURYAH I I I JATVAAL J JHARGARHA J J J! J' J- J3 ERONEWOoOURIVEIXooINE AIUR-IUAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAAAIUR IUz$)2I@LJ FERONEWOoOURIVEIXooINENEWOoOURIVEIXooINEEN J< JO JYAHAAGAAHAAYAAHAAAAHAAASASHAZAAHAAAAAAHAAAAHAAGAAHAAYAAHAAAAHAAASASHAZAAHAAAAAHAAAA)z$AIUI,UAHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAALASSANYARAAIU @OI J~)2:-:I G J ERONEWOoOURIVEIXooINEAIUEI%OUAAAHAAAHAAHAAAHAAHAAAHATATHALAAHADADHAGAAHAAAAAIUEIOU)2IM ERONEWOoOURIVEIXooINE,AHHHHTTHDDHNHHYHHGNYRRHELA J J ERONEWOoOURIVEIXooINEAAGAAAAAAAAAYAAAAAA J Jz$) G2AIURLI"AHAAHAGAAHAAHAYATATHADADHANAAHAAHAAAHAAHAAAAAAHASAAANYA\IU @OIU H~ G\ JLJO I3IB VGIGIZ2UU5 VU VaUM Vg Vs V V VAG3 V VUDHE VSH2E22IGUSH LSH3ISHUD VUMAHULUR2 V U WHUESH WA4ININ9ALI W" W>IR2 WMI2 W` U$WO NlNiIX jNj NlNiIX jNj NiIX jNj NE WO NlNiIX jNj NE WO NlNiWO WlNiIX jNj NE WO  WNiISHINNE WO  WNi W W W W W WSSU W W W W WWO NlNiIX NE WO Nl WAN2 W X XNE WO X% 7 X0 X% 7Yf X=rDfZm XC@NiIX jNj  XMO Xg4 XqHU2 Xz XB2IA X X XGI X X LSH XINUN LAI P ISHAI Lg NjUR Q X YAM Y YASHESIIIHE TURAP Y$ Y,SHI LgAALEES> MZIM GI NjRENAIE Y? XAM YUHUSHE2IHIMIZ2 YI Ye Yu Y Y Y YUA XR Y03212530505162 Z80 Z92304210192025283865664347488384904149UGI5 Z) Z35057708390929395500817SHAD Z>U3AARE2DmR3648UBAGI LgI ZM ZcDmR2449 ZqISHALAP ZMAK4 ZAAK ZISHULI Qe ZASH M ZmR ZN ZAK4 Z ZUB2AM2AR Z Z Z Z LH [ SaD M [U3A7 [ [.c [H [N [T [Z [` [f [l [r [x [~ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ \ \ \ \ \ \! \' \- \3 \9 \? \E \K \Q \W \] \c \i \o \u \{ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ] ] ] ] ] ] ]$ ]* ]0 ]6 ]< ]B ]H ]N ]T ]Z ]` ]f ]l ]r ]x ]~ ] ] ] ]C001002003004005 ]006 ] ]007008009010011012013014 ]015016017 ]018019020021022023024025026027028029030031032 ]033034035036037038039040 ]041042 ]043 ]044045 ]046047048049050051052053054055056057058059060061062063064065066067068069070001002003004005 ]006007008009001002 ] ] ]003004005006007008009010 ]011012013014015016017018019020021022023024001002003004005006007008 ]009010011012013014015016017018019020021022023024025026027 ]028029030031 ^032033034 ^035036037038039040041042043044045046 ^047048 ^049050 ^ ^ ^& ^, ^2 ^8 ^> ^D ^J051052 ^P053054 ^V055056057058059060061062063064065066067 ^\ ^b ^h ^n ^t ^z ^ ^001002003004005006007008 ^009 ^010011012013014015016 ^017 ^018019020 ^021022023024025026027028 ^029030031032033034 ^036037038001 ^002003004005006007008009010011012013 ^014015016017018019020021 ^022023024025026027028029030031 ^032033034035036037 ^038 ^039040041042043044045 ^046 ^047 ^048049050051 ^ ^ ^052053001002003004005006 ^007 _ _ 008009010011 _012013014015016017018019020 _021022023024025026 _027028029030031032033034035036 _"037 _(038039040041042043 _.044045 _4046047048049050051052053054001002003004005006 _:007008001002003004005 _@006007008009 _F010 _L011 _R012013014015001002003004005006007008001002 _X003004005006 _^007008001 _d _j002003 _p004005006007008009010 _v011012 _| _ _ _ _ _ _ _013014015 _016 _017 _018019020021022 _023024 _025026027028 _029030031 _032033 _ _034035036037038039040 _041042043044001002003004005006007008009010011012013014015016017018 _ _019020021022023024025 _026027028029030031032033 _034 `035 `036037 ` 038039040041042 ` ` ` `$ `* `0 `7 `= `C `I `O `U `[ `a `g `m `s `y ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` a a a a a a a% a+ a1001 a8002003004005 a>006 aD aJ aP aV a\ ab007008009010 ah an at011012013014015016017018019 az020 a021022023024 a025 a026027028029 a030 a031032033 a034035036 a a a a037038039040041042043044045046047048049050 a a051001 a002003 a004005006007008009010011001002003004005006007001002 a003 a a004005006007008009010 a011012013014015016 a017018019020021022023024025026027028029001002 a003004005006 a007008009010011012013014 a b015016017 b 018019020021022023024025026 b b027028029030031032033034035 b036037038039040041042043044045046001002003 b"004005006007 b(008 b.009 b4010011 b:012013014015016 b@017018019020021022023024025026027028029030031032 bF033 bL034035036001002003004005006 bR bX007008009010011012013014015016017018019020021022023 b^024025026027028029 bd030031032 bj033034035036037038039040041042001 bp bv b| b b b b b b002 b003004005006007 b b008009010011 b b b012 b b013014015016017018019020 b b b b b b b c c c c c021022023 c024025026027028 c$029 c*030 c0031 c6032033 c<034035036037 cB038039040 cH001002003 cN004005006007008009 cT010 cZ011012013014 c`015016017 cf018 cl019020021022023024 cr025001002003004 cx c~005006 c007008 c001 c002003004005006007008001002 c c c c003 c c004 c005 c006007008009010011012013014015 c c c c c c c c c016 c d d d d d d d& d, d2 d8 d> dD dJ dP dV d] dd dj dp dv d| d d d d d d d d d d d d d d d d d d d d dOMOP MOP M eyND eOPLyND yND e-ZmZmhc OP M e*OP e2 eKOP M es e{ e e e e e e+ e e e e e e e e e e e e e e e e f f f f f f# f) f/ f5 f; fA fG fM fS fY f_ fe fk fq fw f} f f f f f f f f f f f f f f f f f f f f f g g g g g g g% g+ g1 g7 g= gC gI gO gU g[ ga gg gm gs gy g g g g g g g g g g g g g g g g g g g g g g h h h h h h! h' h- h3 h9 h? hE hK hQ hW h] hc hi ho hu h{ h h h h h h h h h h h h h h h h h h h h h h i i i i i i# i) i/ i5 i; iA iG iM iS iY i_ ie ik iq iw i} i i i i i i i i i i i i i i i i i i i i i j j j j j j j% j+ j1 j7 j= jC jI jO jU j[ ja jg jm js jy j j j j j j j j j j j j j j j j j j j j j j k k k k k k! k' k- k3 k9 k? kE kK kQ kW k] kc ki ko ku k{ k k kD k k k k k k k k k k k k k k k k k k k l l l l l l# l) l/ l5 l; lA lG lM lS lY l_ le lk lq lw l} l l l l l l l l l l l l l l l l l l l l l m m m m m m m% m+ m1 m7 m= mC mI mO mU m[ ma mg mm ms my m m m m m m m m m m m m m m m m m m m m m m n n n n n n! n' n- n3 n9 n? nE nK nQ nW n] nc ni no nu n{ n n n n n n n n n n n n n n n n n n n n n n o o o o o o# o) o/ o5 o; oA oG oM oS oY o_ oe ok oq ow o} o o o o o o o o o o o o o o o o o o o o o p p p p p p p% p+ p1 p7 p= pC pI pO pU p[ pa pg pm ps py p p p p p p p p p p p p p p p p p p p p p p q q q q q q! q' q- q3 q9 q? qE qK qQ qW q] qc qi qo qu q{ q q q q q q q q q q q q q q q q q q q q q q r r r r r r# r) r/ r5 r; rA rG rM rS rY r_ re rk rq rw r} r r r r r r r r r r r r r r r r r r r r r s s s s s s s% s+ s1 s7 s= sC sI sO sU s[ sa sg sm ss sy s s s s s s s s s s s s s s s s s s s s s s t t t t t t! t' t- t3 t9 t? tE tK tQ tW t] tc ti to tu t{ t t t t t t t t t t t t t t t t t t t t t t u u u u u u# u) u/ u5 u; uA uG uM uS uY u_ ue uk uq uw u} u u u u u u u u u u u u u u u u u u u u u v v v v v v v% v+ v1 v7 v= vC vI vO vU v[ va vg vm vs vy v v v v v v v v v v v v v v v v v v v v v v w w w w w w! w' w- w3 w9 w? wE wK wQ wW w] wc wi wo wu w{ w w w w w w w w w w w w w w w w w w w w w w x x x x x x# x) x/ x5 x; xA xG xM xS xY x_ xe xk xq xw x} x x x x x x x x x x x x x x x x x x x x x y y y y y y y% y+ y1 y7 y= yC yI yO yU y[ ya yg ym ys yy y y y y y y y y y y y y y y y y y y y y y y z z z z z z! z' z- z3 z9 z? zE zK zQ zW z] zc zi zo zu z{ z z z z z z z z z z z z z z z z z z z z z z { { { { { {# {) {/ {5 {; {A {G {M {S {Y {_ {e {k {q {w {} { { { { { { { { { { { { { { { { { { { { { | | | | | | |% |+ |1 |7 |= |C |I |O |U |[ |a |g |m |s |y | | | | | | | | | | | | | | | | | | | | | | } } } } } }! }' }- }3 }9 }? }E }K }Q }W }] }c }i }o }u }{ } } } } } } } } } } } } } } } } } } } } } } ~ ~ ~ ~ ~ ~# ~) ~/ ~5 ~; ~A ~G ~M ~S ~Y ~_ ~e ~k ~q ~w ~} ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~       % + 1 7 = C I O U [ a g m s y                           ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {  ‡  “ ™ Ÿ ¥ « ± · ½ G001002003004005006007008009010 011012013014015016017018019020021022023024025026 027028029030031032033034035036037038039 040041 042043044045 ]046 047048049050051052053054055056057058059060061062063064065066   #067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097 )098 /099100 5101 ;102 A103104 G M S105 Y _106107 e k q108109110 w }111112113114115 Ã116117118119120121122123124125 É126127128129130131132133134135 Ï136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 Õ Û203204205206207 á208209 ç210211212213214215 í216 ó217218219220221222223224225226227 ù228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 ÿ268269270271272273274275276277278279280281282283284285286287288289 290291292293294 295296297298299 300301302303304305306307308309 <310311312313314315316317318319320321322323324325326327328329 330331 333334335336 337338339340341342343344345346347348349350351352353354355356357358359 360361362363364 365366367368 369370371 372373374375376377378379380381 382  -384385386 3387388389390391392 9394395396397398399400401402403404405406407408409 D P411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 [451452453454455456457 a458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530:AHAAHAGAAHAAHAATATHADADHAAAHAAHAAAHAAHAAAAAAAIUEIOU B+AAA) g ĀERONEWOoOURIVEIXooINE9 Ď ę ģ į ĸ ZA ģ į   ( 3UU : E K S ] e l v ~ ŋ ŕ ş ŬISA Ŷ Ž AFAA DA ET IKAUP ET UOQ HUM IRIOMPOQOQ  %TAP , ; K R Z  bJAM hYET oOTAAM vAEMYIAQSHAEEUENAQBAQ } ƄIEE Ƒ Ƙ Ƣ ƭ Ƴ ƺAM IT    % 1 > H O X ` gEUM m z DŽ NJAAMEUQ ǒ Ǚ ǦUE ǭ Ǵ ǽ EUX EE ET SENAIQGOM ZAUM    " ) 2 8 J S Y a h zHAP ȅ Ȍ ȖBUE ȜBITEUQ ȤAAEUX ȫ ȱ ȹ ȿ EUX TAA AP   UE SA $UNG * 3U AM : B METGGU b TUUTJAMGOMUP [SOMTEN cSUNDAM pAADAP y BI Ɇ h ɍ ɕEUM ɛ ɧ ɭIEEUAEHIQAW ɳGAQAQIQINENETBUOAPJIFON ɻIEE YAM HEE EUT JAPUEET UOMAP   EUT EN  % 1UHAA 9 @DEE J RDONONI YUUT `FOUM gBAA nYET oOT ɧEUMAEM t z ʃ ʊEUPIP ʑYUEET ʘ ʞUOMAPUOPDAM ʦUAEUN ʬ ʳUOTEUNUQSUMEUN ʺ EUM ȹ U AEOQYIII v |UUUHII YEEUHUTEEEEIHOQUQVOPOQ ITUU AQAADAPOON SAPOMOONAAOMAQ DUNUAEAMGKA UOEE AAMOOUOPOM vGOPAEM GOQ   ɭEEMAA "GBA * 0 APOOT 9DIQ AETUM L ZIEE jUAE pO v | ˂ ˈ ˏEUXAAMUAAQ ˕ ˝ ˦ ˮBEEZAQKOMBETUMUETAP ˴IT UEQ UE ETAE HETATUMEUTEUM ZUQOONIEEUETAEUAE U IVIUAQ UTIETTAP    OMJEEOQAQ &AAAQ 0HIQEUX > D J UQUNEUXEUX SUEUEEEEEUIEUXAE ^GAHOHOQ eAIOQOENAAQEUIONENAQHOMAUEEEAEYIAIIIEE |AADAA UUHIIIEUXYEEETUAEU OQHUASHAEUXTEEUEEEUIEUXEN GGAHOUAEOMAIOQOBENENAOBAAETPA UEQAGIOIMAAHIHAIAOAIHU oLAEMINAOOHIHEAAAOANAAIIEK ERONEWOoOURIVEIXooINEPLJZCQXZCQXZCQXZCQXZCQXZCQXWZWCWQWXIZICIQIX u ~EZWXECEZEQEXIUZIUCIUQIUXZCQXAHAAGAAAAAYAHAAAAAATAAAAHAHAASAHATTAHAAAHAHAA ERONEWOoOURIVEIXooINENNIAEABEIEAHHIIPAHOWAHAOBUOEWUOAUEINA ̇OE_rOW OW- ̍oFEEBEEVIBIVAUBAUVUBUVEBEVAIBAIVOOBOOVAWBAWVUABUAVOBOVIABIAVABAVWBWVAABAAVAU ̗AUAULAUAUKAUHAUAULAUAUHAU ̝NAU ̣ ̩AUUAUAUUBOESHAVUAMOMAUMHOM ̯ ̺ EEM HOOVAIB AUS ERONEWOoOURIVEIXooINEENS  8  $ .YOO 6 CNUBQIGIABTUJV L XAUOSUS c vXWV ͂ ͌ ͕ ͞EEGISAUJ ͥOOAWJUASHOJSABHABHABAMAJAJAJSWBWMWJ.) ͫ2AHAAHAGAAHAAHAYATATHADADHAAHAAHAAAHAAHAAAAAAAHAAAEIUIAATUPI LJERONEWOoOURIVEIXooINE[TIUPUPYEITIUPUPYEIERONEWOoOURIVEIXooINEENls%-5?HNE WO Nlnjo ͱ ͽ L H JAIOBO ERIININAGAYII ERIHEP I Y L H JAIOBO ERIININAGAYII ERIHEP I YKAA LAAHA AAFAAATAATADAAHA ) 0NANHAAYAHAHYALHALHA ; AAA GAGAGAGHA MAAHAHHASSAZZAYAYHASHAZHASHAZHA YHASAHASHASAZA gAASAZAZSA nZYA zAHHARIYIZYIESETE& ΀ Μ ΰy ΰAHHNNGOONNGEYAANANGOEIUNGAANANGUEINGIEEEUIIUUGOGUIGERWGAONGIOP l@TETad- 1 λAHAYbl\w WO  010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798990001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989900010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798990001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989900010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768  $ * 0 6 < B H N T Z ` f l r x ~ τ ϊ ϐ ϖ Ϝ Ϣ Ϩ Ϯ ϴ Ϻ      & , 2 8 > D J P V \ b h n t z Ѐ І Ќ В И О Ф Ъ а ж м     " ( . 4 : @ F L R X ^ d j p v | т ш ю є њ Ѡ Ѧ Ѭ Ѳ Ѹ Ѿ     $ * 0 6 < B H N T Z ` f l r x ~ ҄ Ҋ Ґ Җ Ҝ Ң Ҩ Ү Ҵ Һ      & , 2 8 > D J P V \ b h n t z Ӏ ӆ ӌ Ӓ Ә Ӟ Ӥ Ӫ Ӱ Ӷ Ӽ     " ( . 4 : @ F L R X ^ d j p v | Ԃ Ԉ Ԏ Ԕ Ԛ Ԡ Ԧ Ԭ Բ Ը Ծ     $ * 0 6 < B H N T Z ` f l r x ~ Մ Պ Ր Ֆ ՜ բ ը ծ մ պ      & , 2 8 > D J P V \ b h n t z ր ֆ ֌ ֒ ֘ ֞ ֤ ֪ ְ ֶ ּ     " ( . 4 : @ F L R X ^ d j p v | ׂ ׈ ׎ ה ך נ צ ׬ ײ ׸ ׾     $ * 0 6 < B H N T Z ` f l r x ~ ؄ ؊ ؐ ؖ ؜ آ ب خ ش غ      & , 2 8 > D J P V \ b h n t z ـ ن ٌ ْ ٘ ٞ ٤ ٪ ٰ ٶ ټ     " Fs69707172737475767778798081828384858687888990919293949596979899000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283# ڏ کO01EIOAEO01AO IEUIEOIEO    # ) / 5 ; A G M S Y _ e k q w } ۃ ۉ ۏ ە ۛ ۡ ۧ ۭ ۳ ۹ ۿ      % + 1 7 = C I O U [ a g m s y  ܅ ܋ ܑ ܗ ܝ ܣ ܩ ܯ ܵ ܻ     ! ' - 3 9 ? E K Q W ] c i o u { ݁ ݇ ݍ ݓ ݙ ݟ ݥ ݫ ݱ ݷ ݽ     # ) / 5 ; A G M S Y _ e k q w } ރ މ ޏ ޕ ޛ ޡ ާ ޭ ޳ ޹ ޿      % + 1 7 = C I O U [ a g m s y  ߅ ߋ ߑ ߗ ߝ ߣ ߩ ߯ ߵ ߻     ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S Y _ e k q w }      % + 1 7 = C I O U [ a g m s y      ! ' - 3 9 ? E K Q W ] c i o u {     # ) / 5 ; A G M S N S N M SHe9K YLHH N J  aOT~  w S R R4 H R R AOUE F4IE EUW NN H OHWUAOIEIOWNMNNN LID MWOW ID _r AIL NOTmkINEAVE؀NOTmkINEAVE؀aj WM 3aP 0P-hhhOM ? Q۬ aMOLW!MWhhPN NP iMORND t { MM ك23323442443434234 LMW =MO _2OMhhYH NONOmrEFT hP-hOMherhherhhP-hOM hP-hOM ) 0LMMWM 8hP-hOMhP-hOMhP-hOMEFTEFThP-hOMOMLMW E d m w NOMhhhh hP-hOMM` hhhhhhLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWLMWERONEWOoOURIVEIXooINE ^332342443434552535352355454524545345345C662663636236464624646346346I6565625656356356O56456456U456[a7727737372377474724747347347n575725757357t57457z457ꆶ7676726767367367ꓴ67467467꙳467ꫵ67567567겳567Ĵ5678828838382388484824848348348858582585835835858458458458 68682686836868468%468+168568568>568DJP568W]cjpw~787827878378378놴78478478댳478략78578578륳578뷴57878678678678678 &-5;AHU\djxOP MOP MOP MOP MOP M OMhLOM ) > TMM i LMWLMW ELMWMMOP MOP MRC d k tRM { RM t d TEM dM  , J V m  {  k dRC t $ = IRC d Z t534543423432233234424434342345525535352355454524545345345C6626636362366464624646346346I6565625656356356O56456456U456[ag   1 7 > FEBERIS R X ^ i r y       ( 3 B K R Z aUER oIA ~          -ELON < B J R Y c i q x ~    % , 7ZX K Q m KOG8 |   ! + 1 7 ? F P Y c l P Y c l x Y c l B P c   % 0 KOGITA 9 @ H O* X d w P  ( 8 E Zj n    - A P ` p c lj v UDA AUKs] {* XO    - 5 ;j C J S Y _ h s |  "YORIA ( 0 : H X b t ANA  Y ;j   # 3 C h _ P W c y j    ) / < E P ] n ~ SOXO   ATONO * 2 = PLI D K{6 TYO a h r ATONO RGI ESI  #  ( 4 @ K T [ g y AANA m EOATONO K @   ! ' . 5 Lk' a o y o y  AOUAIEOI h _ h _ LRLJ 0|OLMW  + 5 =ODA{ C Q ] e kNE-WO-N ILEFLTA s LTA s< y LATPOWNPOWNPOWN LAT UT LTA sLTA s ZmfYm Oj  ?  ?  ?  ?  ?  ?  ?  ?Yi   ?yP ZmfYm .  yND yND yND yND n> / 8 ? M U ^ fPOWNOITIPLIP lENDLJO r ~ O RPt̚P01 aP

AR   , < ONG ` j ZH   ZUUKYEDE    $^ 9AKO @ H PNU V ] c iKU pERUHTASI vHAERUERIATIU O  ITA>EEHEEEHEEALMERSEFASEHEHAERUUZZEs}E ~EEHEEEHEEALESFASEHEHA~%ERU }ZEZHE -ASATAAAAAKAAAAACATSAAAYARAATXAXAAAAAQAAYAPALAPLAAHLALAARAAOE F T Z c j w } ERONEWOoOURIVEIXooINE AAAAAAAAGAAHAAAAAAA   :AAAAAAHAAAAAHAAAHAAAAAAUAAHAAGALHASARANGANGNGNGNNANYAENIHUP OI ERONEWOoOURIVEIXooINE*PLYNGJBNYHSDDTHCDKRNNGMNTTLLJOD KIR ERONEWOoOURIVEIXooINE+MNGRROYDBHLWTPTTDNKDDJNYRSHCNNGUKIR ERONEWOoOURIVEIXooINEOW _rOW _rOGOOOW _rOW _rOOW _rHOOOOW _rHOOW _rOOOOOW _rOOW _rAWE AEAAOUEYNGNMKTP  % 3HYAHYUHYI ; AHYEHYO GHWI SHWEWIWEEWIWEEWEWIWEEWIWEEWEWIWEEWEWIWEEWIWEE Y a i q z     ' 0 : D L T \ e m v ~                      ( 0 9 A J R _ g o w                     & / 7 @ H P X ` i q z                   ! * 3 < F P Z d o y                & . 6 > G O X ` i r {                 " + 4 > G Q Z b k t }                  ! + NEWOoOURIVEIXooINE 5ENS EN 8 ;HLIF DAAMIIMA JEHEAAHAHEAWUNAFAIIMHIAAAFAYAUHAAHABEALPOHALIF DAAMIIMA JEHEAAHAHEAWUNAFAIIMHIAAAFAYAUHAAHABEALPOHA UW G } [: ERONEWOoOURIVEIXooINEon~DNEWOoOURIVEIXooINEENNE WO NlNiIX jNj NE WO NlNiIX jNj EN bbbac P W ` 61AKH e l v |NEWOoOURIVEIXooINE rDALFrL NEWO l=NEWOoOURIVEIXooINEENNE WO NlNiIX jNj NE WO NlNiIX jNj EN bbbac P W ` 61 WOoOURIVEIXooINEENNIX WO EN ALF X=LEFEHEEMALAWAINAHAHEHAFAMEEMOONEENINEHADAFEHEHHEHHAHHALADAHEHOONEHAFEHEEM EHAFAMEEMOONEENINEHADAFEHHEHHAHOONEENINADAFEHEEMAHAHEHAFEEMOONEENINEHADAFEHHEHHAHADAH  LEFEHEEMALEHAWAINAHAHEHAMEEMOONEENINEHADAFEHEHHEHHAHHALADAHEHEEMALAWAINAHAHEHAMEEMOONEENINEHADAFEHEHHEHHAHHALADAH  ,Y9LYLED NNE WO NlNiIX jNj NE WO NlNiIX jNj NE WO NlNiIX jNj LUM      $ +ACKd 10123456012345601234560123456012345601234560123456 A0123456012345601234560123456012345601234560123456ACKCE WO NlNiIX jNj EN O U ] dCE WO NlNiIX jNj EN O U ] d jCE WO NlNiIX jNj EN O U ] d t%CE WO NlNiIX jNj EN O U ] d OOL012345678901 NE WO NlNiIX jNj M    DZ VVDSPVCC D R C  . ;CAABC kLOOLREEDEWGKOS uS  WO NNij  P  CDR  HVHDOD  OKOA,24BB573CC E8C91A9E3929EA462012159924DF8C18D5B021DD4251FCA98F0439F14295355E00E0904ADE6E2D3F3307D70253981A7A408E807097085332725B614D 72CE09E8CB890B92536D72DD557 $ .UUHOUI 5AI% > F L \ m            EW  / >- N ^ l }EW  -UN    UN NOWZ OG  ACO     W " ) 4 :OSE I R \ dICEERB j {            ED EAR      " / ;ALL C K V d n t  DEN             $ . 8 B N V e {            ( 6 E T e o             , G Z i y   q      ! , 9 @ J Y a m t ! ! ! !+ !3 !: !H !` !x ! ! ! ! ! ! ! ! ! ! ! " " "AR " "5 "@ "\ "v " " " " " " " # # # #$ #2 #: #C #OU #_ #iANK #r # # I # # #U #_NLdNLd)Ld # # # $-2AT $ X $OW $ $&AT ] $- $7 $= ^ AMOAT $C $J $ROGIGOAR $Z $c $kUGNT $x $ $ $ d $ $IRD $ $ $ $ $ $ $OW $ $AT % % % %OG IG %& %, %5 %; %A %H %Q %\YESYEAROSE  gP aLMW %eUK P a %mN %w %} % % % % % % % % % % % % % % % & & & &OYIRLAN  &" &)EN &8 &? &N &d &t & >AN ABY & &GRE & e & & &MP & & ' ' ' '" '. '; 'C 'OILL 'W 'aING 'mISS 'w ' ' ' ' ' ' ' ' '  ' ' ' ( ( ($ (D (XOMB (e (o (z ( ( ( ( ( ( ( ( ( ( ) ) )(EN oRq )4 )EEAT )k )} ) ) )VDN ) ) ) )LL ) )_ )gg ) ) * *ON  ' *- *5 *; *FEMO *M *` *f *r * * * * * * * * +  + + +" +. +8 +> +b +q + + + + + + + + + + , , POW _r ,J ,k ,s , , ,hh , ,}NELL , , , - -ND - -> -T -f -W:L - + -IRE - - - - - - - - - - . .;LdNED ' *- ' *- 'P-OMP-OMMM .J ._ .}LMW .NN . . . . . . . .NE WO NlNiIX jNj EN Q_NE-WO-N IIX- . / / EN- / / ,k ,s , /# /, /FOOK /S /Z /l /OLE / / / / / / / / 0 00NLd 0N 0h 0 0 0T 0 0 0 0 0 0 0 1 1 1)P a 1* 17 1X 1LMWLMWLMWP aP aP a  1 1 1 1 1LdN e 1 2NE WO Nl 2 2' 2=I 2GAX 2PEXT 2^ 2oN XLd/N 2uOX 2OTEAGEADOTEAGEAD 2AGE 2 2AGE 2 2V^ 2 2 2 2 2 2 3 3 3 3( 34 3< 3P 3g 3sIPS 3l@EFTmrLMWWO NlLMWLMWOOD 3y 3 3 3 3 3 3 4 4 4)ACE 4/ 4<  4/ 4I 4TALO 4h 4n 4{ 4 4 4 4 4V 4 4 5 5 5% 5/V 5;VO g 5K 4T 5W 5e 5n 5u 5~ 5 5 5 5 5 5 5 6 6 6 6 6. 6C 6O 6n 6 6 (e 6 6 6 6 4< 6 4 6 6 5u 5~ 5V 7 7$ 71K 7:EE- 7O 7U 7\ 7z 7 7 7LLLLLLLLLLLLLLLLLLLLLLLLn 7n 7LLLL 7L  7 7 7 8 8 8 8 87 8= 8HRAM 8P 8Y 8c 8n 8w 8 8 8Y 8 8 8 8 8 8 8 8 9HIP 9 9MO 9% 97 9SOOR 9kO 9y 9ON- 9 9$ 8 8& 9 9 9 9 9 9 9 : : ATH : : :- :5 :C :P :n :~ : : : : : :ED : : ; ; ; ;%UT ;2 ;; ;E ;N ;_ ;e ;o 8a ; ; ; ; ; ; ; ; ; < < <# <*LED <0 <> ALX > > >+ >+ >4OAP >> >D >O >Y >a >i >s > > > > > > >ARY > >OURAY- >RAM > > > > ? ? ? ? ?, ?3 ?< ?E ?LhP-hOM ?RN Me ?b ?m ? A[ ?RNN]sMe ?b ?N ? A[MeNMeN ? A[MeN ?NN ?bNN]sMe ?bNN]sMe ?bNN]sMe ?bNN]sMeNN ?NNNNNN ?NMe @ @%M @; *- '  ' @SED ' *- '  ' @S LLLLLLLLLLLL8LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLYY{LLLLY @lLLLLYYLLLLY @xLLLLYYLLLLYLLLLLLLLLLLLNE@ALF: @ @LL @LL @LLLLNE@ @ @ A A$LLLL AALL AU Au A A A P A ANWO B$NNlWO OTmkMV- B+N @S B; BI BQ BX Bn Bt B~jI B B B Bhh B B B C C( C/ C: CX Cb Ci Cs C C C C C C D D8 DY Dh Dw D D D D D D D D D D D E E E E- EB ES  Ea Ejb&  Ep E} E E E E E E E E E E E F F F+GG F= FK FS F] Ff Fo F~ F F F F FIE F F F F F F G G G G@ GM Gd G} G G G G G GARI G G G HRAB H H H# H* 8UCKAT H7WL H= HFEER HP HX H_ Hj Hq Hw H H H H H H H H H H H H H H WAN HODO H I I I I I I' I.EAL I4 I>ED M^ALD IKONEEGOOT W IV I` Im Iy I IRMEG I I I I I I I I I I I J J J J! J+ J1 JC  JI JU Jd Js J JAGE J J JLF J J J J J J JOAT J J K K K% K/ K: KK KS KZ Kl Kt Kz K K K K K K K K K K K K LINGާOOKޭ޴AWNNLdV d ] L L U L d ] L L U L d ] L L U LNLdVINGާOOKޭ޴AWNINGާOOKޭ޴AWNINGާOOKޭ޴AWNNLdV d ] L L U L d ] L L U L d ] L L U LNLdVNLdVNLdVާOOKޭާOOKޭERZ L!ERZ L! L' L/ $Z  L8 L@ LG L' L/ $Z  L8 L@ LG LO L\ Lo Lv L} L L L L L L L L LITE L 8y L L L M kARP M9 M M* M1ӥ M?XE ME MO MU Me MoOIN My M MOOK M M M MNOT M M M M MOCK M M N N N N0 N:LYORM NA NH NROOD I @ N_ Ne Np N NING N N N N NAN F N NRCA N N O O O O$ O. O5 O< OC ORAR OX Od Ol O{ O O O O O O O O O P P P* P6LLaP P_ P|LL@2332344244343423455255352355454524545345345C66266363623664624646346346I6565625656356356O56456456U456[aoYmroYmr mroYmroY P\L\L P\L\W!oYmroYmr mroYmroY P\L\L P\L\ P P P P QMMWM Q( Q? QJ 7vNli 7vNliLMWMM Qk QN QڴMMW\ QEFTmrLMWLMWMM R R%EFTmr R6 RT Rz R RLMW RLLLLLMW R Sl S S8LW!MW Sa S SEFTmr S S[ S S 7 X% SMWL T T% T: TP Tf T{MW T T T T U U) U> UT UlMMLMW U) U> UT Ul U U U UERONEWOoOURIVEIXooINE U Vt V} Wx W~ W W W W W W W W W W W W W W W W W W W W W X X X X X X X& X, X2 X8 X> XD XJ XP XV X\ Xb Xh Xn Xt Xz X X X X X X X X X X X X X X X X X X X X X X Y Y Y Y Y Y" Y( Y. Y4 Y: Y@ YF YL YR YX Y^ Yd Yj Yp Yv Y| Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Z Z Z Z Z Z Z$ Z* Z0 Z6 Z< ZB ZH ZN ZT ZZ Z` Zf Zl Zr Zx Z~ Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z [ [ [ [ [ [ [& [, [2 [8 [> [D [J [P [V [\ [b [h [n [t [z [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ \ \ \ \ \ \" \( \. \4 \: \@ \F \L \R \X \^ \d \j \p \v \| \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ] ] ] ] ] ] ]$ ]* ]0 ]6 ]< ]B ]H ]N ]T ]Z ]` ]f ]l ]r ]x ]~ ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ ^ ^ ^ ^ ^ ^& ^, ^2 ^8 ^> ^D ^J ^P ^V ^\ ^b ^h ^n ^t ^z ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ _ _ _ _ _ _" _( _. _4 _: _@ _F _L _R _X _^ _d _j _p _v _| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ` ` ` ` ` ` `$ `* `0 `6 `< `B `H `N `T `Z `` `f `l `r `x `~ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` a a a a a a a& a, a2 a8 a> aD aJ aP aV a\ ab ah an at az a a a a a a a a a a a a a a a a a a a a a a b b b b b b" b( b. b4 b: b@ bF bL bR bX b^ bd bj bp bv b| b b b b b b b b b b b b b b b b b b b b b c c c c c c c$ c* c0 c6 c< cB cH cN cT cZ c` cf cl cr cx c~ c c c c c c c c c c c c c c c c c c c c c d d d d d d d& d d`ohono{MooooLMWoonjoooERONEWOoOURIVEIXooINEoopOEp pp'p5pIpYpnpppppp d7890123456789012345678901234567890123456789012345678901234567890123456789012345678900010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556ULL r1UL r9 rF r1OH r9 rW r1TX r9 re r1TX r9 rq r1OT r9f r1NQ r9n r1CK r9 r r1EL r9z r1S r9 r r1҄ r1T r9AB r9Қ r1 r r1 r r1F r9L r9OL r9 r r1Ҥ r1T r9Ҹ r1F r9 r1R r9 r r1 r r1O r9 r r1 r r1I r9 r1LE r9 r r1C1 r9 s r1C2 r9 s# r1C3 r9 s8 r1C4 r9 r1AK r9 r1YN r9 r1TB r9# r1AN r9* r1OM r9M r98 r1UB r9C r1SC r9 sL r1 sg r1S r9 sv r1 s r1S r9 s r1 s r1S r9 s r1 s r1S r9P r9Y r1EL r9 s tAD r9 t tOP r9 t" r1PH r9 t7 r1BH r9  r1ND r9 tE r1EL r9 tO r1SA r9 tf r1SA r9 t{ r1 t r1TS r9 t r1 t r1TJ r9 t r1 u r1TS r9 u+ r1 u@ r1LD r9 uR r1 uh r1LU r9 ux r1 u r1I r9 u r1 u r1S2 r9 u r1 u r1S3 r9 u r1CS r9 u r1 v r1U1 r9 v r1 v r1U2 r9 v, r1TS r9 v? r1CH r9 vP r1W r9 v` r1 vv r1PA r9 v r1 v r1PA r9 v r1OS r9 v tGC r9 v r1CI r9 w r1SI r9 w$ r1T r9 w6 r1SC r9 wO r1M r9 w_ r1PC r9BSP r9HY r9 w{ w w wGJ r9 w wLM r9 w w x w x w x/ w xA w xO w x] w x w x w x w x wVS1 r9VS2 r9VS3 r9VS r9VS4 r9 y wWSP r9WNJ r9WJ r9RM r9LM r9RE r9LE r9DF r9RO r9LO r9 y$ r9MSP r9J r9RI r9LI r9SI r9DI r9 y* w yH w yZ w yk w y w y w y wS1 r9S2 r9S3 r9S4 r9S5 r9S6 r9S7 r9S8 r9S9 r9S10 r9S11 r9S12 r9S13 r9S14 r9S15 r9S16 r9 z w zW zgOM r9 zq r9 zx w z w z w z w z w { w {) w {F w {a w {~ w { w { w { w { w | w |> wS17 r9S18 r9S19 r9S20 r9S21 r9S22 r9S23 r9S24 r9S25 r9S26 r9S27 r9S28 r9S29 r9S30 r9S31 r9S32 r9S33 r9S34 r9S35 r9S36 r9S37 r9S38 r9S39 r9S40 r9S41 r9S42 r9S43 r9S44 r9S45 r9S46 r9S47 r9S48 r9S49 r9S50 r9S51 r9S52 r9S53 r9S54 r9S55 r9S56 r9S57 r9S58 r9S59 r9S60 r9S61 r9S62 r9S63 r9S64 r9S65 r9S66 r9S67 r9S68 r9S69 r9S70 r9S71 r9S72 r9S73 r9S74 r9S75 r9S76 r9S77 r9S78 r9S79 r9S80 r9S81 r9S82 r9S83 r9S84 r9S85 r9S86 r9S87 r9S88 r9S89 r9S90 r9S91 r9S92 r9S93 r9S94 r9S95 r9S96 r9S97 r9S98 r9S99 r9 |_ r9 |e r9 |k r9 |q r9 |w r9 |} r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 | r9 } r9 } r9 } r9 } r9 } r9 } r9 }% r9 }+ r9 }1 r9 }7 r9 }= r9 }C r9 }I r9 }O r9 }U r9 }[ r9 }a r9 }g r9 }m r9 }s r9 }y r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 } r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~! r9 ~' r9 ~- r9 ~3 r9 ~9 r9 ~? r9 ~E r9 ~K r9 ~Q r9 ~W r9 ~] r9 ~c r9 ~i r9 ~o r9 ~u r9 ~{ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9 ~ r9  r9  r9  r9  r9  r9 # r9 ) r9 / r9 5 r9 ; r9 A r9 G r9 M r9 S r9 Y r9 _ r9 e r9 k r9 q r9 w r9 } r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9  r9   /4/2/4 /16/8/16/4/46 /4/2/4/16/8/16 000000   #/40/80/20/10/20/5000000/4/2/4/16/8/16 /2/2/2/2/21/23/25/27/21/2 00000000000 )789  /7/9/10/3/3/5/5/5/5/6/6/8/8/8/80120000000001200000000 )0 / 5<01234567890012345678900123456789012345678900000 000 000000000123456789012345 0678901234567890 /4/2/4/16/8/16 -000000000000000000000000000000000000000000000000000000 ) < B H / N T Z `/4/2000000 /000000000000000000000 ) /000000000000/3/4/4000000000000000000000000000000000 0000000 )00000000000000 f/20000000.000000000000000000000000000000000000000000000 ) < B H / N T Z ` 5 l s z /12/12/12/12/12/12/12/12/12 0000000/200000000000000000000000000000000 000000000000000000000000000/2/4/3/3 00000/20000000000000000000000 00000000000000  00000000000 00000000000 #/80/64/40/32/80/64/20/10/8/20/16/5/4/4 $  /3/3/6/3/3/8/4/6 /2/3/300 000 ) 0123456789/2 012345678901234567890000000002 ;000000000000000000000000000000000000000000000000000000 ) < B H / N T Z ` 5 l 5 /4/2/4 ) 5-000000000000000000000000000000000000000000000000000000 ) < B H / N T Z `00000000 )/2/6 abcdefghijklmnopqrstuvwxyzzSTVWY[`cihoru,e<,fG 3{|}PQRSTUVWXYZ[\]^_0123456789:;<=>?@ABCDEFGHIJKLMNO&abcdefghijklmnopqrstuvwxyz{|}~&---------- - - - - ------------------- -!-"-#-$-%Vpqrstuvwxyz{|}~+ !"#$%&'01234567@ABCDE`abcdefgpqrstuvwz{xy|}k!p!q!r!s!t!u!v!w!x!y!z!{!|!}!~!$$$$$$$$$$$$$$$$$$$$$$$$$$0,0,1,2,3,4,5,6,7,8,9,:,;,<,=,>,?,@,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,[,\,],^,_k}}QqPR?@,yf\aljSdABCDEFGHIJKLMNOPQRSTUVWXYZ(()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO$ 3                                                    p q r s t u v w x y z { | } ~        n`nanbncndnenfngnhninjnknlnmnnnonpnqnrnsntnunvnwnxnynzn{n|n}n~nnnnnnnnnnnnnnnnnnnnnnnnnn""#$%&'()*+,-./0123456789:;<=>?@ABCABCDEFGHIJKLMNOPQRSTUVWXYZx}SC=,~,N,o,m,p,b,nDE 0 !"#$%&'()*+,-./     &123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV+!*bJ      ()*+,-./89:;<=>?HIJKLMhijklmno!`!a!b!c!d!e!f!g!h!i!j!k!l!m!n!o$$$$$$$$$$$$$$$$$$$$$$$$$$0,,,,,,,,,, , , , , ,,,,,,,,,,,,,,,,,,, ,!,",#,$,%,&,',(,),*,+,,,-,.,/:>&P!"#$%&'()*+,-./0123456789:(      !"#$%&'$ pqrstuvwxyz|}~3                                                    P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e  n@nAnBnCnDnEnFnGnHnInJnKnLnMnNnOnPnQnRnSnTnUnVnWnXnYnZn[n\n]n^n_nnnnnnnnnnnnnnnnnnnnnnnnn"      !ABCDEFGHIJKLMNOPQRSTUVWXYZx}SC=,~,N,o,m,p,b,nDE 0 !"#$%&'()*+,-./     &123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV+!*bJ      ()*+,-./89:;<=>?HIJKLMhijklmno!`!a!b!c!d!e!f!g!h!i!j!k!l!m!n!o$$$$$$$$$$$$$$$$$$$$$$$$$$0,,,,,,,,,, , , , , ,,,,,,,,,,,,,,,,,,, ,!,",#,$,%,&,',(,),*,+,,,-,.,/:>&P!"#$%&'()*+,-./0123456789:(      !"#$%&'$ pqrstuvwxyz|}~3                                                    P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e  n@nAnBnCnDnEnFnGnHnInJnKnLnMnNnOnPnQnRnSnTnUnVnWnXnYnZn[n\n]n^n_nnnnnnnnnnnnnnnnnnnnnnnnn"      !ULLQYfnELLz r UTNNEWOoOUR #*8COURoWONE a < ̚ ̠ r~ rr  , 9 O ` jaND ET z o` uxWOo uNEWO v, v? vPaND v w$ w6 wO w_   5 DWOo W t  rDALFrLrrrxr~pqINGrrrxr~qrrrxr~q rrrxr~pq rrrxr~q rrrxr~pqINGrrrxr~qrrrxr~q rrrxr~pq rrrxr~q 2 W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L W:LW:LW:LW:LW:LW:LW:LW:LW:LW:-W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L LW:LW:L OOKW:L} c j  o0LW:LW:L  W:L LW:L LJ I Y k 5 W:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L  u    5 C v ELTvOGHvURLOGH K LZOGH SH r~ DrxrrrrrxMWLyPOT MyVp J rrrxr~pq WyPzqd-M J Drrz$z0LLZz?lyILMWzQORNzbP aOjOpzru LJMzqyVzzz azPtO[LJOONONzzM=z{{ hlyI y z hTA hWUh hWUhhTA h 8hWUhWUh e qOOK kq ~ W:LW:LW:LW:LW:LW:LW:   sUAsUAW:LW:LW:L~H~NYXW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:LW:L ,W:LW:LW:LW:LAV LJ AW AA AAHAAAAHAA SA a h o v ~ m LEFAW A ING @  OTS؀l 3 <l@l AHINGOT WO NlN O:l@N 7INGOT OON  AR h ~   -AILVa 8 ERONEWOoOURIVEIXooINE:HAIHONHANHAN#)/9@JPY`lryUUALAUSIUA l wAMIEEEU EUAN  KHORI$ 9BJULMWAHAA J~)2  z$I 'NANANONNINENANNANASANARNARHARAEANARNHARHARHANARHINHINANILILHARANHANAEEIEEAROEI  L ' 3L 7 DLMWOURIVEIXooINEa < ERONEWOoOURIVEIXooINEa <LMWNOPLLMW LPNlNmk  L &L @ I YL ` m w >HMHO  L b& e XC@WO NlNKUaNlijLP MWa MWLMWLP MWaLMWLP MWaLMWLMW EFTmrEFTmr  * D POWNmrEFTPOWNmrEFT k P MWa  LP MWaMWLMWP aLP MWaLMWLP MWa , > J V \ V \ V \ V \ V \ V \ V \ V e s njO V \ V V \ V \ RAET ULLQYfnELLz҄ҚҤҸUTNNEWOoOUR #*8C^JQfohY=NE WO NlNiIX jNj EN Q_YcmvԊԔbnNNNNNNNNNNNNmrEFTmrEFT+Jc|Ֆկ/G`x֐֨ $:P\ $:fp׀פ׷+FY$:lNNNN؀؉ءز؉ءز؉ءز1EWmrmroكlEFTPmrOWNEFTPmrOWNٗ٬پLdNLdNLdNLdNLdNLdNLdNLdNLdNLdN @LMWYmLAT s  { NEWOoOURIVEIXooINEԩNEWOoOURIVEIXooINEԩNEWOoOURIVEIXooINEԩ MwNLdOP- aP hhMMMMMM&7NO a <a <a <a <a <a <a <a <a < 4 ; G` 4 M S ZIOS `` 4 f 4/ ` IOS ; f ZIOS S S G ` S Z G IOS  4 OYA "OI (UYEUIE .ETIIANIYOUYUUEOUTUEIEIENIIN M G/ `AAAAAAAAAAAAAU M G/ `AAAAAAAAAAAAAX k r yARU NTION  NSUOMU     IGA   IRO           # + 4 < B HESIORUONANO N T Z c i q {IKOIRU     ESO       ON  OON      IRI EGA  " * 0UAN 6IRA > DEMU L Uc i p w  AU AAABBBALCALFFGGZHZHZHZHZU LLLLMMU MMMMM M M M M M APAPAPAAD SSU SSVVU VVV WWU WWW  MQCD OBYAPNK TMNOGX ILOLHMPMRRVB / / 0mM N la <a <a <a <a <a <a <a < 0| LJ 0| la <a <a <  " 6 _ n {Z Z Z Z Z^h@ Z Z^h@ Z Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z Z Z Z Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z^h@ Z Z Z^h@ Z Z Z Za < ̚ ̠ r~ rr  , 9  !a < 4 ; G` 4 M S ZIOS `` 4 f 4/ ` 5 Bidi_Class Bidi_MirroredBlockCanonical_Combining_ClassDecomposition_MappingDecomposition_TypeGeneral_CategoryName Name_Alias Numeric_Type Numeric_ValueSimple_Lowercase_MappingSimple_Titlecase_MappingSimple_Uppercase_MappingUnicode_1_Name Basic LatinLatin-1 SupplementLatin Extended-ALatin Extended-BIPA ExtensionsSpacing Modifier LettersCombining Diacritical MarksGreek and CopticCyrillicCyrillic SupplementArmenianHebrewArabicSyriacArabic SupplementThaana SamaritanMandaicSyriac SupplementArabic Extended-BArabic Extended-A DevanagariBengaliGurmukhiGujaratiOriyaTamilTeluguKannada MalayalamSinhalaTibetanMyanmarGeorgian Hangul JamoEthiopicEthiopic SupplementCherokee%Unified Canadian Aboriginal SyllabicsOghamRunicTagalogHanunooBuhidTagbanwaKhmer Mongolian.Unified Canadian Aboriginal Syllabics ExtendedLimbuTai Le New Tai Lue Khmer SymbolsBugineseTai Tham$Combining Diacritical Marks ExtendedBalinese SundaneseBatakLepchaOl ChikiCyrillic Extended-CGeorgian ExtendedSundanese SupplementVedic ExtensionsPhonetic ExtensionsPhonetic Extensions Supplement&Combining Diacritical Marks SupplementLatin Extended AdditionalGreek ExtendedGeneral PunctuationSuperscripts and SubscriptsCurrency Symbols'Combining Diacritical Marks for SymbolsLetterlike Symbols Number FormsArrowsMathematical OperatorsMiscellaneous TechnicalControl PicturesOptical Character RecognitionEnclosed Alphanumerics Box DrawingBlock ElementsGeometric ShapesMiscellaneous SymbolsDingbats$Miscellaneous Mathematical Symbols-ASupplemental Arrows-ABraille PatternsSupplemental Arrows-B$Miscellaneous Mathematical Symbols-B#Supplemental Mathematical Operators Miscellaneous Symbols and Arrows GlagoliticLatin Extended-CCopticGeorgian SupplementTifinaghEthiopic ExtendedCyrillic Extended-ASupplemental PunctuationCJK Radicals SupplementKangxi Radicals"Ideographic Description CharactersCJK Symbols and PunctuationHiraganaKatakanaBopomofoHangul Compatibility JamoKanbunBopomofo Extended CJK StrokesKatakana Phonetic ExtensionsEnclosed CJK Letters and MonthsCJK Compatibility"CJK Unified Ideographs Extension AYijing Hexagram SymbolsCJK Unified Ideographs Yi Syllables Yi RadicalsCyrillic Extended-BBamumModifier Tone LettersLatin Extended-D Syloti NagriCommon Indic Number FormsPhags-pa SaurashtraDevanagari ExtendedKayah LiRejangHangul Jamo Extended-AJavaneseMyanmar Extended-BMyanmar Extended-ATai VietMeetei Mayek ExtensionsEthiopic Extended-ALatin Extended-ECherokee Supplement Meetei MayekHangul SyllablesHangul Jamo Extended-BHigh SurrogatesHigh Private Use SurrogatesLow SurrogatesPrivate Use AreaCJK Compatibility IdeographsAlphabetic Presentation FormsArabic Presentation Forms-AVariation SelectorsVertical FormsCombining Half MarksCJK Compatibility FormsSmall Form VariantsArabic Presentation Forms-BHalfwidth and Fullwidth FormsSpecialsLinear B SyllabaryLinear B IdeogramsAegean NumbersAncient Greek NumbersAncient Symbols Phaistos DiscLycianCarianCoptic Epact Numbers Old ItalicGothic Old PermicUgaritic Old PersianDeseretShavianOsmanyaOsageElbasanCaucasian AlbanianVithkuqiTodhriLinear ALatin Extended-FCypriot SyllabaryImperial Aramaic Palmyrene NabataeanHatran PhoenicianLydianSideticMeroitic HieroglyphsMeroitic Cursive KharoshthiOld South ArabianOld North Arabian ManichaeanAvestanInscriptional ParthianInscriptional PahlaviPsalter Pahlavi Old Turkic Old HungarianHanifi RohingyaGarayRumi Numeral SymbolsYezidiArabic Extended-C Old SogdianSogdian Old Uyghur ChorasmianElymaicBrahmiKaithi Sora SompengChakmaMahajaniSharadaSinhala Archaic NumbersKhojkiMultani KhudawadiGrantha Tulu-TigalariTirhutaSiddhamMongolian SupplementTakriMyanmar Extended-CDogra Warang Citi Dives Akuru NandinagariZanabazar SquareSoyombo0Unified Canadian Aboriginal Syllabics Extended-A Pau Cin HauDevanagari Extended-ASharada SupplementSunuwar BhaiksukiMarchen Masaram Gondi Gunjala Gondi Tolong SikiMakasarLisu SupplementTamil Supplement Cuneiform!Cuneiform Numbers and PunctuationEarly Dynastic Cuneiform Cypro-MinoanEgyptian Hieroglyphs#Egyptian Hieroglyph Format ControlsEgyptian Hieroglyphs Extended-AAnatolian Hieroglyphs Gurung KhemaBamum SupplementTangsa Bassa Vah Pahawh Hmong Kirat Rai Medefaidrin Beria Erfe#Ideographic Symbols and PunctuationTangutTangut ComponentsKhitan Small ScriptTangut SupplementTangut Components SupplementKana Extended-BKana SupplementKana Extended-ASmall Kana ExtensionNushuDuployanShorthand Format Controls'Symbols for Legacy Computing Supplement Miscellaneous Symbols SupplementZnamenny Musical NotationByzantine Musical SymbolsMusical SymbolsAncient Greek Musical NotationKaktovik NumeralsMayan NumeralsTai Xuan Jing SymbolsCounting Rod Numerals!Mathematical Alphanumeric SymbolsSutton SignWritingLatin Extended-GGlagolitic SupplementCyrillic Extended-DNyiakeng Puachue HmongWancho Nag MundariOl OnalTai YoEthiopic Extended-B Mende KikakuiAdlamIndic Siyaq NumbersOttoman Siyaq Numbers&Arabic Mathematical Alphabetic Symbols Mahjong Tiles Domino Tiles Playing Cards Enclosed Alphanumeric SupplementEnclosed Ideographic Supplement%Miscellaneous Symbols and Pictographs EmoticonsOrnamental DingbatsTransport and Map SymbolsAlchemical SymbolsGeometric Shapes ExtendedSupplemental Arrows-C$Supplemental Symbols and Pictographs Chess Symbols"Symbols and Pictographs Extended-ASymbols for Legacy Computing"CJK Unified Ideographs Extension B"CJK Unified Ideographs Extension C"CJK Unified Ideographs Extension D"CJK Unified Ideographs Extension E"CJK Unified Ideographs Extension F"CJK Unified Ideographs Extension I'CJK Compatibility Ideographs Supplement"CJK Unified Ideographs Extension G"CJK Unified Ideographs Extension H"CJK Unified Ideographs Extension JVariation Selectors Supplement Supplementary Private Use Area-A Supplementary Private Use Area-B      DIGIT LATIN SUPERSCRIPT VULGAR MODIFIER COMBINING GREEK COPTIC CYRILLIC ARMENIAN HEBREW ARABIC ARABIC- EXTENDED SYRIAC THAANA SAMARITAN MANDAIC DEVANAGARI BENGALI GURMUKHI GUJARATI ORIYA TAMIL TELUGU KANNADA MALAYALAM SINHALA THAI TIBETAN MYANMAR GEORGIAN HANGUL ETHIOPIC CHEROKEE CANADIAN OGHAM RUNIC TAGALOG HANUNOO PHILIPPINE BUHID TAGBANWA KHMER MONGOLIAN LIMBU BUGINESE BALINESE SUNDANESE BATAK LEPCHA VEDIC ZERO DOUBLE SINGLE REVERSED BLACK INVISIBLE SUBSCRIPT SCRIPT PLANCK DOUBLE-TURNED ROMAN SMALL NORTH SOUTH LEFT UPWARDS DOWNWARDS LEFTWARDS RIGHTWARDS THERE LOGICAL CLOCKWISE APPROXIMATELY RING MUCH NEITHER DOES MULTISET SQUARE CIRCLED SQUARED RIGHT CURLY VERY EQUAL ELEMENT CONTAINS BOTTOM OPEN-PASSIVE-UPPER SUMMATION HORIZONTAL DENTISTRY METRICAL POWER SYMBOL PARENTHESIZED NUMBER NEGATIVE LOWER QUADRANT WHITE CIRCLE INVERSE BALLOT CROSS TRIGRAM BEAMED MUSIC RECYCLING MONOGRAM DIGRAM THREE DOUBLED MALE MEDIUM RESTRICTED GEAR RAISED FOUR EIGHT HEAVY LIGHT DINGBAT THREE-BLACK-OPEN LARGE LONG MATHEMATICAL BRAILLE ARROW SPHERICAL OBLIQUE MEASURED EMPTY TRIANGLE BOWTIE TIMES EQUALS DOWN-ERROR- INTEGRAL LINE PLUS MINUS MULTIPLICATION UNION INTERSECTION CLOSED SLOPING TRIPLE TILDE SLANTED SIMILAR GREATER- SUPERSET SHORT VERTICAL PARALLEL DIAMOND ANTICLOCKWISE RETURN NEWLINE RIBBON OVERLAPPING PLUTO STAR ERIS RUSSIAN GLAGOLITIC TIFINAGH DAGGER INVERTED MEDIEVAL KANGXI IDEOGRAPHIC HANGZHOU HIRAGANA KATAKANA- KATAKANA BOPOMOFO HEXAGRAM LISU BAMUM SYLOTI PHAGS- SAURASHTRA KAYAH REJANG JAVANESE CHAM MEETEI ORNATE VARIATION PRESENTATION FULLWIDTH HALFWIDTH INTERLINEAR LINEAR AEGEAN PHAISTOS LYCIAN CARIAN GOTHIC UGARITIC DESERET SHAVIAN OSMANYA OSAGE ELBASAN CAUCASIAN VITHKUQI TODHRI CYPRIOT IMPERIAL PALMYRENE NABATAEAN HATRAN PHOENICIAN LYDIAN SIDETIC MEROITIC KHAROSHTHI MANICHAEAN AVESTAN INSCRIPTIONAL PSALTER HANIFI GARAY RUMI YEZIDI SOGDIAN CHORASMIAN ELYMAIC BRAHMI KAITHI SORA CHAKMA MAHAJANI SHARADA KHOJKI MULTANI KHUDAWADI GRANTHA TULU-NEWA TIRHUTA SIDDHAM MODI TAKRI AHOM DOGRA WARANG DIVES NANDINAGARI ZANABAZAR SOYOMBO SUNUWAR BHAIKSUKI MARCHEN MASARAM GUNJALA TOLONG MAKASAR KAWI CUNEIFORM CYPRO- EGYPTIAN ANATOLIAN GURUNG TANGSA BASSA PAHAWH KIRAT MEDEFAIDRIN BERIA MIAO VIETNAMESE CHINESE YANGQIN TANGUT KHITAN HENTAIGANA NUSHU DUPLOYAN SHORTHAND LOGIC SEPARATED SPARSE DENSE SPECKLE FLYING ALIEN STRIPED OUTLINED BLOCK EXPLOSION GEOMANTIC ZNAMENNY BYZANTINE MUSICAL KAKTOVIK MAYAN TETRAGRAM COUNTING TALLY SIGNWRITING NYIAKENG TOTO WANCHO MENDE ADLAM INDIC OTTOMAN MAHJONG DOMINO PLAYING REGIONAL TORTOISE ROUNDED EARTH CLOUD RICE RACING HOUSE WAVING EMOJI THUMBS WOMANS OLDER JAPANESE BANKNOTE PAGE CHART MOBILE SPEAKER INPUT NOTCHED CLOCK SIDEWAYS DOCUMENT FRAME CARD NOTE SPIRAL LIGHTNING GRINNING SMILING KISSING FACE SLIGHTLY PERSON HOLLOW SOLID SANS-HIGH- AIRPLANE ALCHEMICAL WIDE- DOWNWARD MECHANICAL NEUTRAL XIANGQI PREGNANT PALM STICK MIDDLE SEGMENTED DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BARWITH SUPERIMPOSED X+CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGNUP ARROW THROUGH CIRCLETWO HORIZONTAL STROKES SMALL CIRCLETWO JOINED SQUARES S IN TRIANGLETRIANGLE WITH SERIFS AT BOTTOM"RIGHT TRIANGLE ABOVE LEFT TRIANGLE!LEFT TRIANGLE BESIDE VERTICAL BAR"VERTICAL BAR BESIDE RIGHT TRIANGLE BLACK BOWTIE INCOMPLETE TIE OVER "INFINITY NEGATED WITH VERTICAL BARDOUBLE-ENDED MULTIMAPSQUARE WITH CONTOURED OUTLINE INCREASES ASSHUFFLE PRODUCTPARALLEL WITH TILDE ABOVE!IDENTICAL TO AND SLANTED PARALLEL GLEICH STARK THERMODYNAMICDIAMOND WITH DOWN ARROW RULE-DELAYEDREVERSE SOLIDUS OPERATORSOLIDUS WITH OVERBAR&REVERSE SOLIDUS WITH HORIZONTAL STROKEREVERSE N-ARY TIMES MODULO TWO SUMSUMMATION WITH INTEGRALQUADRUPLE INTEGRAL OPERATORFINITE PART INTEGRALWITH DOUBLE STROKEAVERAGE WITH SLASHCIRCULATION FUNCTIONANTICLOCKWISE INTEGRATION SEMICIRCULAR NOT INCLUDING THE INTEGRAL AROUND A POINT QUATERNION INTEGRAL LEFTWARDS ARROW WITH HOOK TIMES SIGNLARGE LEFT TRIANGLE OPERATOR COMPOSITIONPIPING PROJECTION SUBSCRIPT TWOBLACK TRIANGLE COMMA ABOVEVECTOR OR CROSS PRODUCT%SEMIDIRECT PRODUCT WITH BOTTOM CLOSED SMASH PRODUCT2CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT$MULTIPLICATION SIGN IN DOUBLE CIRCLECIRCLED DIVISION SIGN RIGHTHAND !Z NOTATION RELATIONAL COMPOSITIONAMALGAMATION OR COPRODUCTINTERSECTION WITH DOT MINUS SIGNABOVE INTERSECTIONINTERSECTION ABOVE UNION"UNION ABOVE BAR ABOVE INTERSECTIONINTERSECTION ABOVE BAR ABOVE UNION BESIDE AND JOINED WITH 0INTERSECTION BESIDE AND JOINED WITH INTERSECTION*CLOSED UNION WITH SERIFS AND SMASH PRODUCTOR OVERLAPPING LOGICAL DOUBLE OVERBARSMALL VEE WITH DOMAIN EQUALS SIGN WITH DOT BELOWIDENTICAL WITH DOT ABOVE RISING DOTSSIMILAR MINUS SIMILARCONGRUENT WITH DOT ABOVEEQUALS WITH ASTERISK&ALMOST EQUAL TO WITH CIRCUMFLEX ACCENTAPPROXIMATELY EQUAL OR EQUAL TOEQUALS SIGN ABOVE PLUS PLUS SIGN ABOVE EQUALS EQUALS SIGN ABOVE TILDE OPERATORDOUBLE COLON EQUAL2EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOWEQUIVALENT WITH FOUR DOTS ABOVE2LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT4GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFTLESS-THAN ABOVE SIMILAR ABOVE &GREATER-THAN ABOVE SIMILAR ABOVE LESS-LESS-THAN ABOVE GREATER-GREATER-THAN ABOVE LESS-,LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-'GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN WITH UNDERBARSMALLER LARGER EQUALS SIGN WITH BUMPY ABOVESUBSET ABOVE SUPERSETABOVE SUPERSETAND JOINED BY DASH WITH ELEMENT OF OPENING DOWNWARDSPITCHFORK WITH TEE TOPTRANSVERSAL INTERSECTIONFORKING NONFORKINGPERPENDICULAR WITH SVERTICAL BAR TRIPLE RIGHT -LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICALDOWN TACK WITH OVERBAR WITH UNDERBAR ABOVE SHORT REVERSED DOUBLE ,DOES NOT DIVIDE WITH REVERSED NEGATION SLASHDOWN TACK WITH CIRCLE HORIZONTAL STROKEBINARY RELATIONWITH HORIZONTAL STROKECOLON OPERATORTRIPLE SOLIDUS BINARY RELATIONLARGE TRIPLE VERTICAL BAR DOUBLE SOLIDUS N-ARY WHITE SMALL LEFT ARROW WITH SMALL CIRCLETHREE LEFTWARDS ARROWSLEFT ARROW WITH CIRCLED PLUSLONG LEFTWARDS SQUIGGLE ARROWTRIPLE DASH ARROW DOTTED STEM THROUGH X!WAVE ARROW POINTING DIRECTLY LEFTREVERSE TILDE OPERATOR -LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO GREATER-THANREVERSE TILDE OPERATOR ABOVE .RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO$TILDE OPERATOR ABOVE LEFTWARDS ARROWRIGHTWARDS ARROW ABOVE !DOWNWARDS TRIANGLE-HEADED ZIGZAG SLANTED NORTH BACKSLANTED SOUTH WHITE MEDIUM OVAL WITH OVAL CIRCLE WITH CIRCLE CIRCLED SALTIRE$SLANTED NORTH ARROW WITH HOOKED HEAD$BACKSLANTED SOUTH ARROW WITH HOOKED !WEST TRIANGLE-HEADED ARROW TO BAR0LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS 5UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS 0RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS 5DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS )FOUR CORNER ARROWS CIRCLING ANTICLOCKWISERIGHTWARDS BLACK ARROWEQUALS SIGN WITH INFINITY ABOVESYMBOL FOR TYPE A ELECTRONICSTOP-LIGHTED LEFTWARDS RIGHT-LIGHTED UPWARDS TOP-LIGHTED RIGHTWARDS LEFT-LIGHTED DOWNWARDS 0UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BARUP ARROWHEAD IN A RECTANGLE BOXBALLOT BOX WITH LIGHT TURNED BLACK PENTAGONHORIZONTAL BLACK NEPTUNE FORM TWOSQUARE POSITION INDICATORUNCERTAINTY SIGN GROUP MARK TRANSPLUTO PROSERPINAASTRAEAHYGIEAPHOLUSNESSUSWHITE MOON SELENABLACK DIAMOND ON CROSSTRUE LIGHT MOON ARTACUPIDOHADESKRONOSAPOLLONADMETOSVULCANUSPOSEIDONSEDNA VIGINTILENOVILEQUINTILEBINOVILESENTAGON TREDECILEEQUALS SIGN WITH INFINITY BELOWUNITED PASSED REVERSED RIGHT ANGLEHELLSCHREIBER PAUSE SYMBOLGLAGOLIDOBROYESTUZHIVETEDZELOZEMLJADJERVILJUDIJEMYSLITENASHIPOKOJIRITSISLOVOTVRIDOFRITUCHRIVI SPIDERY HA YUS WITH TAILIOTATED SMALL IOTATED IZHITSASHTAPIC TROKUTASTI ALATINATE MYSLITECAUDATE CHRIVIL WITH MIDDLE TILDE P WITH STROKE R WITH TAILA WITH T WITH DIAGONAL SMALL LETTER V WITH RIGHT V WITH CURL TAILLESS PHI E WITH NOTCHTURNED R WITH TAILO WITH LOW RING INSIDESMALL CAPITAL TURNED ESUBSCRIPT SMALL LETTER JMODIFIER LETTER CAPITAL VSTAUROS SHIMA SIMANI ABOVEASPERLENISDIRECT INDIRECT VERSE DIVIDERFRACTION ONE HALFMORPHOLOGICAL DIVIDERGEORGIAN SMALL LETTER YNGEORGIAN SMALL LETTER AENYAGHHBERBER ACADEMY YADDHYAKHHAHAGGAR AYER TAWELLEMET MODIFIER LETTER LABIALIZATION TIFINAGH CONSONANT JOINER GLOTTAL OAGGWEECCHAACCHEEES-TEDJERV MONOGRAPH UK IOTIFIED A IOTIFIED TRANSPOSITION MARKER RAISED SQUAREEDITORIAL CORONIS HYPODIASTOLE DOTTED OBELOSDOTTED RIGHT-POINTING ANGLEDOUBLE OBLIQUE HYPHENINVERTED INTERROBANG PALM BRANCHHYPHEN WITH DIAERESISTILDE WITH RING ABOVETWO DOTS OVER ONE DOT ONE DOT OVER TWO DOTS SQUARED FOUR REVERSED QUESTION RING POINTWORD SEPARATOR MIDDLE DOTTURNED SEMICOLON TURNED DAGGERTOP HALF SECTION SIGNSTENOGRAPHIC FULL STOPVERTICAL SIX DOTSWIGGLY VERTICAL LINE CAPITULUM DOUBLE HYPHEN$DOUBLE LOW-REVERSED-9 QUOTATION MARKDASH WITH LEFT UPTURNDOUBLE SUSPENSION MARKKAVYKAKAVYKA WITH KAVYKA ABOVEKAVYKA WITH DOTDOUBLE STACKED COMMADOTTED SOLIDUS TRIPLE DAGGERMEDIEVAL COMMA PARAGRAPHUS PUNCTUS ELEVATUS CORNISH VERSE DIVIDERTIRONIAN SIGN CAPITAL ETOBLIQUE HYPHENREPEATCLIFFPERSONTABLE DIVINATIONSNAKETHREADCHOKEDEATHMOTHERCIVILIANSIMPLIFIED HALF TREE TRUNK BOLT OF CLOTHBAMBOO C-SIMPLIFIED SHEEPMORTARTIGERCLOTHESC-SIMPLIFIED SEESPEECHSHELLC-SIMPLIFIED CARTSIMPLIFIED WALKC-SIMPLIFIED GOLDTANNED LEATHERC-SIMPLIFIED EATC-SIMPLIFIED HORSEGHOSTWHEATYELLOWC-SIMPLIFIED FROGSECONDENTERDOWN BOXCOVERKNIFEPOWERSPOONRIGHT OPEN BOXHIDING ENCLOSUREPRIVATEAGAINMOUTH ENCLOSURESCHOLAR GO SLOWLYEVENINGWOMANCHILDSMALLCORPSESPROUTRIVERONESELFTURBAN SHORT THREAD DOTTED CLIFF LONG STRIDE TWO HANDSSHOOTSNOUTBRISTLEHEARTHALBERDBRANCHSCRIPTDIPPERWEAPONDO NOTCOMPARESTEAMFATHERDOUBLE XHALF TREE TRUNKSLICEPROFOUNDMELONSWEETFIELDSICKNESS DOTTED TENTWHITESPEARSTONESPIRITTRACKGRAINSTANDFEATHERBRUSHMINISTERARRIVETONGUEOPPOSESTOPPINGCOLORGRASSINSECTBLOODWALK ENCLOSUREVALLEYBADGERBITTERMORNING DISTINGUISHVILLAGEMOUNDSLAVESHORT TAILED BIRDWRONGTANNED SOUNDFRAGRANTHORSEFIGHTSACRIFICIAL WINECAULDRONMILLETBLACK EMBROIDERYTRIPODTOOTHDRAGONTURTLEFLUTE LEFT TO RIGHTABOVE TO BELOWLEFT TO MIDDLE AND RIGHTABOVE TO MIDDLE AND BELOW FULL SURROUND LOWER LEFTOVERLAIDHORIZONTAL REFLECTIONROTATION DITTO MARK#JAPANESE INDUSTRIAL STANDARD SYMBOL ITERATION CLOSING NUMBER ZEROPOSTAL GETA WAVE DASHPOSTAL MARK FACE DEPARTING ENTERING WAVY DASHWITH VOICED SOUND MARK LOWER CIRCLED POSTAL MARK0IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOLVERTICAL IDEOGRAPHIC ITERATION MASU PART ALTERNATION VARIATION INDICATORHALF FILL SPACESEMI-VOICED DIGRAPH YORIKATAKANA-HIRAGANA DOUBLE HYPHEN"KATAKANA-HIRAGANA PROLONGED SOUND DIGRAPH KOTOO WITH DOT ABOVE PIEUP-SIOSARAEAELINKING THIRD HEAVEN FINAL LETTER GHZZZG-IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTIONKIYEOK NIEUN TIKEUT RIEUL MIEUM PIEUP SIOS IEUNG CIEUC CHIEUCH KHIEUKH THIEUTH PHIEUPH HIEUH CIEUC UOJEONMETALSTOCKSOCIETYSPECIAL FINANCIALCONGRATULATIONLABOR REPRESENTSTUDY SUPERVISE ENTERPRISERESOURCEALLIANCEFESTIVALREACH KINDERGARTENSCHOOLSIXTY SEVENTY EIGHTY PARTNERSHIP SIGNCHAMKOJUEUIHANGUL IEUNG UKOREAN STANDARD SYMBOLSECRETFEMALESUITABLE EXCELLENTPRINT ATTENTIONCORRECTMEDICINERELIGIONNIGHTJANUARYFEBRUARYMARCHAPRILAUGUST SEPTEMBEROCTOBERNOVEMBERDECEMBERLIMITED LIABILITY SIGNERA NAME REIWAAPAATOARUHUAANPEAININGUESUKUUDOEEKAAKAIRIKARATTOKARORIIGARONGANMAGINIIKYURIIGIRUDAA KIROGURAMU KIROMEETORU KIROWATTOGURAMU GURAMUTON KURUZEIROKUROONEKEESUKORUNAKOOPOSAIKURUSANTIIMUSIRINGUSENTISENTODAASUNOTTOHAITUPAASENTOPAATUBAARERU PIASUTORUPIKURUHUARADDOHUIITOBUSSYERUHURAN HEKUTAARUPENIHIHERUTUPENSUPEEZIBEETAPOINTOBORUTOPONDOHOORUMAIKUROMAIRUMAHHAMARUKUMANSYONMIKURON MIRIBAARUMEGATONMEETORUYAADOYAARURITTORURUPIIRUUBURURENTOGENWATTOSQUAREDCUBEDHEISEISYOUWATAISYOUMEIZI CORPORATIONPA AMPS S SQUAREDMV MEGAMW MEGA C OVER KG KM CAPITALMB SMALL THIRTY-ONE SQUARE GAL"!CREATIVE HEAVENRECEPTIVE EARTHDIFFICULTY AT THE BEGINNINGYOUTHFUL FOLLYWAITINGCONFLICTTHE ARMYHOLDING TOGETHER SMALL TAMINGTREADINGPEACE STANDSTILL FELLOWSHIPGREAT POSSESSIONMODESTY ENTHUSIASM FOLLOWINGWORK ON THE DECAYEDAPPROACH CONTEMPLATIONBITING THROUGHGRACESPLITTING APARTRETURN INNOCENCE GREAT TAMING MOUTH CORNERSGREAT PREPONDERANCE ABYSMAL WATER CLINGING FIRE INFLUENCEDURATIONRETREAT GREAT POWERPROGRESSDARKENING OF THE LIGHT THE FAMILY OBSTRUCTION DELIVERANCEDECREASEINCREASE BREAKTHROUGHCOMING TO MEETGATHERING TOGETHERPUSHING UPWARD OPPRESSIONTHE WELL REVOLUTIONAROUSING THUNDERKEEPING STILL MOUNTAIN DEVELOPMENTTHE MARRYING MAIDEN ABUNDANCEWANDERER GENTLE WIND JOYOUS LAKE DISPERSION LIMITATION INNER TRUTHSMALL PREPONDERANCEAFTER BEFORE BBIETBBIEXBBIEPBBUOXBBUOPBBURXNBIEXNBIEPNBURXNBYRXHMIEXHMIEPHMUOXHMUOPHMURXHMYRXDDIEXDDIEPDDUOXDDUOPDDURXNDIEXNDURXHNIETHNIEXHNIEPHNUOXHLIEXHLIEPHLUOXHLUOPHLURXHLYRXGGIEXGGIEPGGUOTGGUOXGGUOPGGURXMGIEXMGUOXMGUOPMGURXHXIETHXIEXHXIEPHXUOTHXUOXHXUOPNGIEXNGIEPNGUOTNGUOXZZIETZZIEXZZIEPZZURXZZYRXNZIEXNZIEPNZUOXNZURXNZYRXSSIEXSSIEPSSYRXZHUOXZHUOPZHURXZHYRXCHUOTCHUOXCHUOPCHURXCHYRXRRUOXRRURXRRYRXNRURXNRYRXSHUOXSHUOPSHURXSHYRXJJIETJJIEXJJIEPJJUOXJJUOPJJURXNJIETNJIEXNJIEPNJUOXNJURXNJYRXNYIETNYIEXNYIEPNYUOXNYUOPMYA TINA POMGBEEDHHEENGGEEMGBOODHHOONGGOONGGEN LENGTHENERFEENGKEENGDOONGLETTER MULTIOCULAR VZMETHUNDRED THOUSAND SLAVONIC ASTERISKPAYEROKSOFT IOTIFIED ELEEEEMEEEENJAEMSHEUXNJUAENGKWAENSAMBAFAAMAEKOVUUKOGHOMKOQNDON TUKWENTISNJAEMLIMID DOTTED LEFT-STEM TONE BARLOWER RIGHT CORNER ANGLEMODIFIER LETTER USLOW CIRCUMFLEX ACCENTSHORT EQUALS SIGNCAPITAL LETTER TURNED H+SMALL LETTER L WITH RETROFLEX HOOK AND BELTLETTER SINOLOGICAL DOTCAPITAL LETTER C H WITH L WITH BELTC WITH PALATAL S WITH Z WITH PALATAL !CAPITAL LETTER LAMBDA WITH STROKEEPIGRAPHIC LETTER SIDEWAYS ICAPITAL H WITH STROKE LIGATURE OECAPITAL TURNED M INVERTED MI LONGA ARCHAIC M SIGN DVISVARA SIGN HASANTA SIGN ANUSVARASIGN ALTERNATE HASANTA PLACEHOLDER QUANTITY SMALL A ALTERNATE YA VOICELESS SHA VOICED HA ASPIRATED FA SUPERFIXED LETTER CANDRABINDUCONSONANT SIGN HAARU SIGN AVAGRAHASPACING CANDRABINDUPUSHPIKA GAP FILLER HEADSTROKEJAIN OM VOWEL SIGN PLOPHUCALYA CALYA PLOPHUREJANG SECTION MARK SIOS-THIEUTHSSANGSIOS-PIEUP SSANGCIEUC- SSANGTHIEUTH PHIEUPH-HIEUH HIEUH-SIOSSSANGYEORINHIEUH PANYANGGACECAKLAYARWIGNYANI KAWIPA CEREKLELET LELET RASWADISASAKMURDAGA MURDACA MURDA NYA MURDA JA MAHAPRANA TTA MAHAPRANA DDA MAHAPRANANA MURDATA MURDA DA MAHAPRANAPA MURDABA MURDARA AGUNG CECAK TELUTARUNGTOLONG WULU MELIK SUKU MENDUT DIRGA MUREKERETPENGKALPANGKONANDAPMADYALUHURPANGKATLINGSALUNGSIADEG TURNED PADA PANGRANGKEP TIRTA TUMETES ISEN-ISEN SIGN SHAN SAW"MODIFIER LETTER SHAN REDUPLICATIONCONSONANT SIGN FINAL SPIRAL$MODIFIER LETTER KHAMTI REDUPLICATIONLETTER AITON RAPAO KAREN TONEMAI KHITNUENGHO HOIKOI KOICHEIKHAN AHANG KHUDAMVOWEL SIGN VISARGATTHEEDDHAADDHEECCHHACCHHUCCHHICCHHAACCHHEECCHHECCHHO BARRED ALPHAA REVERSED-SCHWAE WITH FLOURISHLENIS FSCRIPT G WITH CROSSED-TAILDOUBLE MIDDLE TILDE MIDDLE RING INVERTED OE STIRRUP RSMALL CAPITAL R WITH RIGHT LEGR WITHOUT HANDLEDOUBLE R R WITH RING BASELINE ESHU WITH LEFT HOOK RIGHT RING LEFT SERIFAND LOW RIGHT RING WITH SERIFY WITH SHORT RIGHT LEGBREVE WITH INVERTED BREVE SAKHA YATOPEN OEINVERTED ALPHA GREEK LETTER SMALL CAPITAL OMEGATURNED R WITH MIDDLE TILDESMALL TURNED WATIYANGOU YENAPSOUNAPCHEINAPCHEIKHEIAPUN  SSANGTIKEUT- SIOS-KIYEOK KIYEOK-HIEUHSSANGRIEUL-KHIEUKH MIEUM-HIEUHYEORINHIEUH-HIEUH SSANGMIEUM RIEUL-PHIEUPH SIOS-TIKEUT'&#"LONG S TVEW NOWMEN XEHLETTER YOD WITH HIRIQPOINT JUDEO-SPANISH VARIKALIGATURE YIDDISH YOD YOD PATAHALTERNATIVE AYIN FINAL MEMALTERNATIVE PLUS SIGNMAPIQ HE WITH MAPIQZAYIN LAMED HEBREW LETTER MEM WITH DAGESHSAMEKH TSADI RESH VAV WITH HOLAMLIGATURE ALEF LAMED ISOLATED DOUBLE VERTICAL BAR WASLA ABOVE JALLA WA-ALAADAAMAT BARAKAATUHUM TAAALAA ALAYHALAYHIM ALAYHIMAARAHIMAHUM ALLAAHU TAAALAAALLAAHALLAAHU TAAALAARADI ALLAAHU TAAALAA ANHUM HAFIZAHUM HAFIZAHUMAA $SALLALLAAHU TAAALAA ALAYHI WA-SALLAM"AJJAL ALLAAHU FARAJAHU ASH-SHAREEFALAYHI AR-RAHMAHU WITH HAMZA ABOVE ALEF MAKSURA ZAH WITH DAMMATAN KASRATAN SUPERSCRIPT ALEF #ALEF MAKSURA WITH SUPERSCRIPT ALEF THEH WITH MEEM TAH WITH HAH ZAH WITH MEEM LAM WITH TAH WITH MEEM RAHIMAHU ALLAAHANHAAANHUMANHUMAAANHUNNASALLALLAAHU ALAYHI WA-AALIHALAYHI ALAYHIM ALAYHIMAA ALAYHI AS-SALAATU WAS-QUDDISA SIRRAH%SALLALLAHU ALAYHI WAAALIHEE WA-SALLAMALAYHAA AS-SALAAMTABAARAKA WA-TAAALAARAHIMAHUM ALLAAHWITH MEEM INITIAL KHAH WITH WITH JEEM WITH MEEM JEEM WITH YEH HAH WITH ALEF MAKSURA JEEM WITH MEEM HAH FINAL YEH FINAL ALAYHALAYHAAWITH KHAH INITIAL FORMBEH WITH KHAH WITH SEEN WITH KHAH QAF WITH MEEM LAM WITH HAH NOON WITH JEEM WITH HAH INITIAL MEEM WITH KHAH WITH YEH FINAL LAM WITH JEEM WITH MEEM INITIAL KAF WITH MEEM FEH WITH BEH WITH HAH AIN WITH JEEM SAD WITH MEEM NOON WITH JEEM RAHIMAHU ALLAAH TAAALAA+SALLALLAHU ALAYHI WA-ALAA AALIHEE WA-SALLAM*AJJAL ALLAAHU TAAALAA FARAJAHU ASH-SHAREEFKARRAMA ALLAAHU WAJHAHSALAAMUHU ALAYNAASALLA QALA ALLAH AKBAR MOHAMMAD SALAM RASOUL ALAYHE WASALLAM SALLALLAHOU ALAYHE WASALLAMJALLAJALALOUHOU RIAL SIGNBISMILLAH AR-RAHMAN AR-RAHEEMSUBHAANAHU WA TAAALAA AZZA WA JALLLEFT WHITE LENTICULAR BRACKETRIGHT WHITE LENTICULAR BRAKCETCONJOINING MACRONCONJOINING MACRON TWO DOT LEADERDASHED CENTRELINE EM DASHFATHATAN ISOLATED FORMTATWEEL WITH FATHATAN ABOVEDAMMATAN ISOLATED FORM TAIL FRAGMENTKASRATAN ISOLATED FORMZERO WIDTH NO-BREAK SPACEIDEOGRAPHIC FULL STOPIDEOGRAPHIC COMMA&KATAKANA-HIRAGANA PROLONGED SOUND MARKFORMS LIGHT VERTICAL BLACK SQUARE WHITE CIRCLE TERMINATOROBJECT B008 AB038 EB028 IB061 OB010 UB001 DAB045 DEB007 DIB014 DOB051 DUB057 JAB046 JEB036 JOB065 JUB077 KAB044 KEB067 KIB070 KOB081 KUB080 MAB013 MEB073 MIB015 MOB023 MUB006 NAB024 NEB030 NIB052 NOB055 NUB003 PAB072 PEB039 PIB011 POB050 PUB016 QAB078 QEB021 QIB032 QOB060 RAB027 REB053 RIB002 ROB026 RUB031 SAB009 SEB041 SIB012 SOB058 SUB059 TAB004 TEB037 TIB005 TOB069 TUB054 WAB075 WEB040 WIB042 WOB017 ZAB074 ZEB020 ZOB025 A2B043 A3B085 AUB071 DWEB090 DWOB048 NWAB029 PU2B062 PTEB076 RA2B033 RA3B068 RO2B066 TA2B087 TWEB091 TWOB100 MAN B102 WOMAN B104 DEER B105 EQUID B105F MAREB105M STALLION B106F EWE B106M RAM B107F SHE- B107M HE- B108F SOW B108M BOAR B109F COW B109M BULL B120 WHEAT B121 BARLEY B122 OLIVE B123 SPICE B125 CYPERUS B127 KAPO B128 KANAKOB130 OIL B131 WINE B133 AREPA B135 MERI B140 BRONZE B141 GOLD B145 WOOL B151 HORNMONOGRAM B156 TURO2 B159 CLOTH B162 GARMENT B163 ARMOUR B173 MONTH B176 TREE B191 HELMETB220 FOOTSTOOL B225 BATHTUB B230 SPEAR B231 ARROW B233 SWORD B240 WHEELED B241 B242 CHARIOT FRAME B243 WHEELMONOGRAM B247 DIPTE B254 DART CHECK MARKNINETY BASE UNITLIQUID DRACHMATEN MNASHERAEUM ONE PLETHRON HERMIONIAN EPIDAUREAN CYRENAIC TEN ALTERNATE FORM MESSENIAN FIFTY ALTERNATE FORM CARYSTIAN NAXIAN DELPHIC STRATIAN FIFTY SIGN ALTERNATE FORM TWO THIRDS TALENT OBOL METRETES KYATHOS BASE LITRA OUNKIA XESTES ARTABE AROURA GRAMMA TRYBLION BASE ONE QUARTER SINUSOID INDICTION NOMISMA SEXTANS UNCIA SEMUNCIA DIMIDIA SILIQUA DENARIUS QUINARIUS SESTERTIUS DUPONDIUS CENTURIAL ASCIA SYMBOLGREEK SYMBOL TAU RHO PEDESTRIANPLUMED TATTOOED CAPTIVEHELMETGAUNTLETTIARASHIELDMANACLESMATTOCK BOOMERANGCARPENTRY PLANEDOLIUMSLINGCOLUMNBEEHIVE BULLS LEGEAGLETUNNY PLANE TREEPAPYRUSROSETTEOX BACKGRATERSTRAINER SMALL AXE WAVY BANDCOMBINING OBLIQUE STROKETHOUSANDS MARKBAIRKANAIHVUSQAIRTHRATHIUTHKUSMALAGUSMANNANAUTHSPAIRTHRARAIDASAUILTEIWSWINJAFAIHUIGGWSOTHAL NINE HUNDREDDZHOIDZITAMENOENENOECHERYSHOOISHCHOOIGAMLASAMKARASHATHANNAUGARITIC WORD DIVIDER AURAMAZDAA AURAMAZDAA-2 AURAMAZDAAHA XSHAAYATHIYA DAHYAAUSH DAHYAAUSH-2BUUMISH WORD DIVIDERTHIGHMEASUREJUDGEHA-HAARRAYSHIINEHCHAEHTSAGHAMMADZYAYGHEYS CAUCASIAN ALBANIAN CITATION MARKAB001AB002AB003AB004AB005AB006AB007AB008AB009AB010AB011AB013AB016AB017AB020AB021AB021FAB021MAB022AB022FAB022MAB023AB023MAB024AB026AB027AB028A028BAB029AB030AB031AB034AB037AB038AB039AB040AB041AB044AB045AB046AB047AB048AB049AB050AB051AB053AB054AB055AB056AB057AB058AB059AB060AB061AB065AB066AB067AB069AB070AB073AB074AB076AB077AB078AB079AB080AB081AB082AB085AB086AB087A100-102AB118AB120A120BAB122AB123AB131AAB131BA131CAB164AB171AB180AB188AB191A309AA309BA309CA313AA313BA313CA400-A401-A402-A403-A404-A405-A406-A407-A408-A409-A410-A411-A412-A413-A414-A415-A416-A417-A418-A701 AA702 BA703 DA704 EA705 FA706 HA707 JA708 KA709 LA710 WA711 XA712 Y A713 OMEGAA714 ABBA715 BBA717 DD A726 EYYYA732 JESMALL CAPITAL AADIGRAPH DEZH DIGRAPH HOOK AND TAILCLOSED REVERSED OPEN FENG DIGRAPH CAPITAL G H WITH STROKE CAPITAL H HENG WITH DOTLESS J WITH STROKE AND L WITH RETROFLEX HOOK AND LEZH WITH RETROFLEX HOOK Y WITH BELTLEG AND RETROFLEX HOOK CAPITAL RDIGRAPH WITH RETROFLEX HOOK TESH DIGRAPH V WITH RIGHT SMALL CAPITAL Y#RETROFLEX CLICK WITH RETROFLEX HOOKSMALL S WITH CURLCYPRIOT SYLLABLE JOCYPRIOT SYLLABLE ZACYPRIOT SYLLABLE ZOALEPHDALETHLAMEDHCRUCIFORM NUMBER ONE HUNDRED DALETH-RESHPHOENICIAN WORD SEPARATORLYDIAN TRIANGULAR MARKVIDJ-2ELEVEN TWELFTHSONE HALF ONE TWELFTHLETTER A VOCALIC RVOWEL LENGTH MARKDOUBLE RING BELOWTTTHA BAR ABOVECAUDA CRESCENT BARMANGALAMLOTUSLINESKHETHDHADHEGHAYNDHALETHTHETHNUMERIC INDICATORGHIMELSIGN UDZHAYINJAYINJHAYINDHAMEDHTHAMEDHAAYINQHOPHSSHINFLEURON LINE FILLERAVESTAN ABBREVIATION MARKTINY ONE DOT OVER TWO RINGS OVER ONE RING ONE RING OVER TWO RINGS WAW-AYIN-RESHMEM-QOPH ORKHON ENG YENISEI AENGCLOSE NIKOLSBURG RUDIMENTA ENT-SHAPED SIGNKINNA SAKIN NA KHONNAHARBAHAYTAHALATASSI LENGTH MARK VOWEL SIGN ECONSONANT GEMINATION MARKCONSONANT NASALIZATION MARKREDUPLICATION MARKCHHIMXHEYNVA ALTERNATE FORM HYPHENATION LAM WITH DOT YOT WITH CIRCUMFLEX SMALL YEH BARREE THIN NOONYEH WITH FOUR DOTS BELOWBIBLICAL END OF VERSEALAYHAA QADDASA ALLAAHU SIRRAHSIRRUHUM SIRRUHUMAAQUDDISAT ASRAARUHUMNAWWARA ALLAAHU MARQADAHDOUBLE VERTICAL BAR BELOWSMALL LOW NOONCOMBINING ALEF OVERLAYMADDANUN WITH VERTICAL TAILSADHE WITH VERTICAL TAILRESH-AYIN-DALETHTAW WITH VERTICAL TAILLIGATURE AYIN-DALETH RESH-AYININDEPENDENT SHIN LONG HOOK BARS WITH DOTSCIRCLE WITH DOTTWO CIRCLES WITH DOTSHALF CIRCLE WITH DOT GIMEL-HETH FINAL HETHCURLED LIGATURE ZAYIN-YODH BHATTIPROLU SIGN OLD TAMIL VIRAMALETTER OLD TAMIL LLABRAHMI NUMBER JOINER ENUMERATION VOWEL SIGN VOCALIC RKAITHI NUMBER SIGN ABOVEMAAYYAA SECTION MARK LETTER LHAA LETTER VAA SIGN NUKTA LIGATURE SHRIVOWEL MODIFIER EXTRA SHORT VOWEL SUTRA VOWEL SIGN PRISHTHAMATRA ESIGN INVERTED CANDRABINDUCONTINUATION SIGNWORD SEPARATOR SIGN SUKUNSHORT IMULTANI LETTER GHACOMBINING BINDU BELOW GRANTHA OMGRANTHA AU LENGTH MARK SIGN PLUTATULU-TIGALARI LETTER EETULU-TIGALARI LETTER AITULU-TIGALARI VOWEL SIGN EETULU-TIGALARI VOWEL SIGN AISIGN CANDRA ANUNASIKA CONJOINERREPHAGEMINATION MARKSHRII SVARITAFINAL ANUSVARASIDDHI DOUBLE COMMAPLACEHOLDER MARKINSERTION SIGNGVANGEND OF TEXT MARKU-SHAPED ORNAMENTSRING WITH RAYS QUADRUPLE SEPTUPLE THREE-CIRCLE ALTERNATE ARDHACANDRA SIGN HUVABIRGA WITH ORNAMENT ROTATED BIRGABIRGA WITH DOUBLE ORNAMENTTURNED SWIRL BIRGA WITH LETTER ARCHAIC KHA ALTERNATE BA LIGATING KILLERRULAI SYMBOL VIWARANG CITI OMDIVES AKURU LETTER OPREFIXED NASAL SIGN MEDIAL YA DOUBLE DANDA REVERSED IFINAL CONSONANT MARKINITIAL LETTER RATSHEG LONG TSHEG SUBJOINERPLUTASHRIISHROOSHRAA TONE LONGSANDHI GLOTTAL STOP GLOTTAL STOP MID-LEVEL TONEGLOTTAL STOP VARIANTMARK WITH HEADSTROKEBHALEBHALE WITH HOOKFIVE-MINDUTASLAUTTHIAPPHOHAMSOCARMILOACHAOTTHISHYELEVARCADONGATHARISHYERCHELAPTENTUTHELEKLOKOSIGN PVOHUNDREDS UNIT MARK HEAD MARK MARK SHADMASARAM GONDI VOWEL SIGN E VOWEL SIGN AURA-KARAHECAKAUNGGAANGKA PASSIMBANG SPACE FILLERFILLED LISU LETTER YHATHREE-HUNDRED-AND-TWENTIETH EIGHTIETH SIXTY-FOURTH THIRTY-SECOND EIGHTIETHS SIXTY-FOURTHS TWENTIETHS SIXTEENTHSFIFTHDOWNSCALING FACTOR KIIZHCEVITU AAZHAAKKUUZHAKKU MUUVUZHAKKUKURUNIPATHAKKU MUKKURUNIKAACUPANAMVARAAKANPAARAMKUZHILAND SALT PAN CURRENT AND ODD SPENT TOTAL IN POSSESSION STARTING FROM MUTHALIYA VAKAIYARAATAMIL PUNCTUATION END OF TEXT GAN2 TENU LAGAR GUNU DUN3 GUNUIGI GUNULAGABSHESHU PLUS U PLUS UBALAG ME PLUS ENERIN2SHITA PLUS GISHAMAR TIMES SHE THREE TIMESOPPOSING AN PLUS NAGAANSHEARAD TIMES KURARKABASAL2ZIDA KABA !TUG2 OVER TUG2 TUG2 OVER TUG2 PAPASH CROSSING ASH OVER ASH OVER ASHGABBAHAR2 BAL OVER BARA2 CROSSING BU BULUG OVER A PLUS MASH GA PLUS MASH IR PLUS LU LU PLUS MASH2 PAP PLUS PAP U2 PLUS GIR2DARA3DARA4 DIM TIMES SHEDIN KASKAL U GUNU SHESHIGDUB TIMES ESH2DUGUDGUNU TIMES PAPOVER E NUN OVER NUNA PLUS HA PLUS DA OPPOSING LAL TIMES KASKALKASKAL SQUARED LAL TIMES LALGA GUNUDA PLUS AB2 TENU PLUS TAB ASH2 PLUS GAL BAR PLUS RA BUR PLUS RA EL PLUS LA EN TIMES GI4 PLUS A GIR2 PLUS SUHA PLUS LU PLUS ESH2 HAL PLUS LA HI PLUS LIISH PLUS HU PLUS ASH KID PLUS LAL KU3 PLUS AN NUN OVER SHE PLUS TUR UD PLUS DUOVER GA2GABA CROSSING GAD OVER GAD GAR OVER GARGAL GAD OVER GAD GAR OVER GARGALAMGASHANGESHTINGESHTIN TIMES KUR CROSSING GIGIDIM GIR2 GUNU A PLUS IGILU PLUS GISAL GU CROSSING KAK TIMES IGI GUNU SAL PLUS TUG2A PLUS OVER GUD LUGAL GUM TIMES SHEGURUNGURUSH"OVER IGI SHIR OVER SHIR UD OVER UDIL TIMES GAN2 TENU TIMES TAK4 AD PLUS KU3GAR PLUS SHA3 PLUS APLUS SAR CROSSING GISH MI PLUS NUNUZSUHUR UMUM TIMES PA KA2 CROSSING KAD5 OVER TIMES BAD CROSSING KAL OVER KASKAL KESH2KISAL KISIM5 OVER +KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2KU4 VARIANT FORMKUL GUNU KUR OPPOSING KUSHU2KWU318 DA PLUS HA ASH ZIDA TENU GUD PLUS HI TIMES NUNKUL PLUS HI PLUS A SHE PLUS SUM PLUS ERIN2 SHU2 PLUS TE PLUS A PLUS SU PLUS NAU PLUS U U2 PLUS ASHLAGARGUNU OVER LAGAR GUNU SHELAHSHU KUR PLUS RULIMMU2 LU TIMES BADESH2 HI TIMES BAD KAD3 PLUS ASH LA PLUS ASH SI PLUS ASH SIK2 PLUS BULUM GAR OVER GARMASH2MU OVER MUG GUNUMUNSUBMURGU2MUSH TIMES A PLUS NA CROSSING MUSHMUSH3INVERTEDTIMES SHU TENU OPPOSING NAGANAGAR NAM NUTILLU NI TIMES E GAR PLUS NINDA2 ASH PLUS ME PLUS GAN2 TENUNISAGSAL OVER NUN LAGAR TIMES NUN LAGAR OVER LAGARNUNUZSILA3PESH2 CROSSING PIPIRIGOPPOSING PIRIG SAG NUTILLUOVER SAGSAL LAGAB TIMES ASH2SANGA2U PLUS ASHAB6SHAR2 GAD OVER GAD TAB OVER TAB SHEG9SHESH2SHESHLAMBULUGSHINIGOVER SHIR BUR OVER BURSHITASHU OVER INVERTED SHUBURSI GUNUSIG4 OVER SIG4 SHU2SU OVER SUMASH"OVER TAB NI OVER NI DISH OVER DISHTE GUNUTI TENUTIR GAD OVER GAD GAR OVER GARTUR OVER TUR ZA OVER ZAPA OVER PA GAR OVER GAR SUR OVER SURU REVERSED OVER U REVERSEDSHESHIG TIMES BAD ME PLUS DAUMBINUN GUNU U PLUS GUD URUDA TIMES UUSHUMXUTUKIUZ3 TIMES KASKALSQUARED TIMES KURZI OVER ZIB KABA TENU ZU5 TIMES AZUBUR KAP ELAMITE AB TIMES NUN AB2 TIMES AAMAR TIMES KUGDAG KISIM5 TIMES U2 PLUS MASH DISH PLUS SHU DUB TIMES SHEAN PLUS KAK PLUS A HI TIMES ASH2LAGAB TIMES GI ESH2 PLUS LALMUSH3 TIMES ZANU11 ROTATED NINETY DEGREESPESH2 ASTERISKSAG TIMES IGI GUNU UM TIMES MESHAR2 VARIANT FORMSHARU VARIANT FORMBURU VARIANT FORMESH16ESH21LIMMULIMMU4SIX VARIANT FORM ASH9IMIN3USSU3ILIMMUILIMMU3ILIMMU4ILIMMU ABAN2 VARIANT FORM NIGIDAMIN NIGIDAESH ONE THIRD FIVE SIXTHS SIXTH ONE THIRDOLD ASSYRIAN WORD DIVIDER QUADCOLONNUN TENU AD TIMES ESH2BAD TIMES DISH TENUBU OVER BU TIMES NA2 DA TIMES TAK4 DAG TIMES KURU U U DIM2 TIMES UD ASH AT LEFTKUSHU2 PLUS KASKALLAK-020 LAM TIMES KUR LUH PLUS GISHERIN2 XESH2 CROSSING ESH2 HA PLUS AGABA ROTATED NINETY DEGREESGESHTIN TIMES UGISH TIMES GISH CROSSING GISHGU2 TIMES IGI GUNUGUD PLUS GISH TIMES TAK4 HA TENU GUNUHI TIMES ASH OVER HI TIMES ASHLAGAB TIMES ZU OVER ZU079 OVER LAK-079 GUNU081 OVER LAK-081 PAP PLUS U2 PLUS BADUN3 GUNU GUNUPAP PLUS PAP PLUS LU3 SHESH PLUS KIGUNU TIMES ASH MI PLUS ZA7DIM GUNULAK-050U PLUS GUNU TIMES HA SHE AT LEFT SHA6 TENUOVER SHE DUG TIMES NI E2 TIMES AN SI TIMES TAK4 TAK4 PLUS SAG THREE DISHLAK-668ZU OVER ZU PLUS SARZU5 TIMES THREE DISH TENUCM001CM002CM004CM005CM006CM007CM008CM009CM010CM011CM012CM012BCM013CM015CM017CM019CM021CM023CM024CM025CM026CM027CM028CM029CM030CM033CM034CM035CM036CM037CM038CM039CM040CM041CM044CM046CM047CM049CM050CM051CM052CM053CM054CM055CM056CM058CM059CM060CM061CM062CM063CM064CM066CM067CM068CM069CM070CM071CM072CM073CM074CM075CM075BCM076CM078CM079CM080CM081CM082CM083CM084CM085CM086CM087CM088CM089CM090CM091CM092CM094CM095CM096CM097CM098CM099CM100CM101CM102CM103CM104CM105CM107CM108CM109CM110CM112CM114CM301CM302A005AA006AA006BA014AA017AA032AA040AA042AA043AA045AB005AC002AC002BC002CC010AD008AD027AD031AD034AD046AD048AD050AD050BD050CD050DD050ED050FD050GD050HD050ID052AD054AD067AD067BD067CD067DD067ED067FD067GD067HE008AE009AE016AE017AE020AE028AE034AF001AF013AF021AF031AF037AF038AF045AF046AF047AF051AF051BF051CG006AG007AG007BG011AG020AG026AG036AG037AG043AG045AH006AI005AI009AI010AI011AL002AL006AM001AM001BM003AM010AM012AM012BM012CM012DM012EM012FM012GM012HM015AM016AM017AM022AM024AM028AM031AM033AM033BM040AN018AN018BN025AN033AN034AN035AN037ANL001NL002NL003NL004NL005NL005ANL006NL007NL008NL009NL010NL011NL012NL013NL014NL015NL016NL017NL017ANL018NL019NL020NU001NU002NU003NU004NU005NU006NU007NU008NU009NU010NU010ANU011NU011ANU012NU013NU014NU015NU016NU017NU018NU018ANU019NU020NU021NU022NU022AO001AO005AO006AO006BO006CO006DO006EO006FO010AO010BO010CO019AO020AO024AO025AO029AO030AO033AO036AO036BO036CO036DO050AO050BP001AP003AR002AR003AR003BR010AR016AS002AS006AS014AS014BS017AS026AS026BS035AT003AT007AT008AT009AT011AT016AT032AT033AU006AU006BU023AU029AU032AV001AV001BV001CV001DV001EV001FV001GV001HV001IV002AV007AV007BV011AV011BV011CV012AV012BV020AV020BV020CV020DV020EV020FV020GV020HV020IV020JV020KV020LV023AV028AV029AV030AV031AV033AV037AV040AW003AW009AW010AW014AW017AW018AW024AX004AX004BX006AX008AY001AZ002AZ002BZ002CZ002DZ003AZ003BZ004AZ005AZ015AZ015BZ015CZ015DZ015EZ015FZ015GZ015HZ015IZ016AZ016BZ016CZ016DZ016EZ016FZ016GZ016HAA001AA002AA003AA004AA005AA006AA007AA007AAA007BAA008AA009AA010AA011AA012AA013AA014AA015AA016AA017AA018AA019AA020AA021AA022AA023AA024AA025AA026AA027AA028AA029AA030AA031AA032V011DOVERLAY MIDDLEMIDDLEMIRROR HORIZONTALLYTOP ENDBOTTOM START AND TOP END START AND TOPTOP START AND START AND DAMAGED13460134611346213463134641346513466134691346A1346B1346C1346D1346E1346F1347013471134721347313474134751347613477134791347A1347B1347C1347D1347E1347F134801348113482134831348413485134861348713488134891348A1348B1348C1348D1348E1348F134901349113492134931349413495134961349713498134991349A1349B1349C1349D1349E1349F134A0134A1134A2134A3134A4134A5134A6134A7134A8134A9134AA134AB134AC134AD134AE134AF134B0134B1134B2134B3134B4134B5134B6134B7134B8134B9134BA134BB134BC134BD134BE134BF134C0134C1134C2134C3134C4134C5134C6134C7134C8134C9134CA134CB134CC134CD134CE134CF134D0134D1134D2134D3134D4134D5134D6134D7134D8134D9134DA134DB134DC134DD134DE134DF134E0134E1134E2134E3134E4134E5134E6134E7134E8134E9134EA134EB134EC134ED134EE134EF134F0134F1134F2134F3134F4134F5134F6134F7134F8134F9134FA134FB134FC134FD134FE134FF135001350113502135031350413505135061350713508135091350A1350B1350C1350D1350E1350F135101351113512135131351413515135161351713518135191351A1351B1351C1351D1351E1351F135201352113522135231352413525135261352713528135291352A1352B1352C1352D1352E1352F135301353113532135331353413535135361353713538135391353A1353B1353C1353D1353E1353F135401354113542135431354413545135461354713548135491354A1354B1354C1354D1354E1354F135501355113552135531355413555135561355713558135591355A1355B1355C1355D1355E1355F13560135611356213563135641356513566135691356A1356B1356C1356D1356E1356F1357013571135721357313574135751357613577135791357A1357B1357C1357D1357E1357F135801358113582135831358413585135861358713588135891358A1358B1358C1358D1358E1358F135901359113592135931359413595135961359713598135991359A1359B1359C1359D1359E1359F135A0135A1135A2135A3135A4135A5135A6135A7135A8135A9135AA135AB135AC135AD135AE135AF135B0135B1135B2135B3135B4135B5135B6135B7135B8135B9135BA135BB135BC135BD135BE135BF135C0135C1135C2135C3135C4135C5135C6135C7135C8135C9135CA135CB135CC135CD135CE135CF135D0135D1135D2135D3135D4135D5135D6135D7135D8135D9135DA135DB135DC135DD135DE135DF135E0135E1135E2135E3135E4135E5135E6135E7135E8135E9135EA135EB135EC135ED135EE135EF135F0135F1135F2135F3135F4135F5135F6135F7135F8135F9135FA135FB135FC135FD135FE135FF136001360113602136031360413605136061360713608136091360A1360B1360C1360D1360E1360F136101361113612136131361413615136161361713618136191361A1361B1361C1361D1361E1361F136201362113622136231362413625136261362713628136291362A1362B1362C1362D1362E1362F136301363113632136331363413635136361363713638136391363A1363B1363C1363D1363E1363F136401364113642136431364413645136461364713648136491364A1364B1364C1364D1364E1364F136501365113652136531365413655136561365713658136591365A1365B1365C1365D1365E1365F136601366113662136631366413665136661366713668136691366A1366B1366C1366D1366E1366F1367013671136721367313674136751367613677136791367A1367B1367C1367D1367E1367F136801368113682136831368413685136861368713688136891368A1368B1368C1368D1368E1368F136901369113692136931369413695136961369713698136991369A1369B1369C1369D1369E1369F136A0136A1136A2136A3136A4136A5136A6136A7136A8136A9136AA136AB136AC136AD136AE136AF136B0136B1136B2136B3136B4136B5136B6136B7136B8136B9136BA136BB136BC136BD136BE136BF136C0136C1136C2136C3136C4136C5136C6136C7136C8136C9136CA136CB136CC136CD136CE136CF136D0136D1136D2136D3136D4136D5136D6136D7136D8136D9136DA136DB136DC136DD136DE136DF136E0136E1136E2136E3136E4136E5136E6136E7136E8136E9136EA136EB136EC136ED136EE136EF136F0136F1136F2136F3136F4136F5136F6136F7136F8136F9136FA136FB136FC136FD136FE136FF137001370113702137031370413705137061370713708137091370A1370B1370C1370D1370E1370F137101371113712137131371413715137161371713718137191371A1371B1371C1371D1371E1371F137201372113722137231372413725137261372713728137291372A1372B1372C1372D1372E1372F137301373113732137331373413735137361373713738137391373A1373B1373C1373D1373E1373F137401374113742137431374413745137461374713748137491374A1374B1374C1374D1374E1374F137501375113752137531375413755137561375713758137591375A1375B1375C1375D1375E1375F137601376113762137631376413765137661376713768137691376A1376B1376C1376D1376E1376F137701377113772137731377413775137761377713778137791377A1377B1377C1377D1377E1377F137801378113782137831378413785137861378713788137891378A1378B1378C1378D1378E1378F137901379113792137931379413795137961379713798137991379A1379B1379C1379D1379E1379F137A0137A1137A2137A3137A4137A5137A6137A7137A8137A9137AA137AB137AC137AD137AE137AF137B0137B1137B2137B3137B4137B5137B6137B7137B8137B9137BA137BB137BC137BD137BE137BF137C0137C1137C2137C3137C4137C5137C6137C7137C8137C9137CA137CB137CC137CD137CE137CF137D0137D1137D2137D3137D4137D5137D6137D7137D8137D9137DA137DB137DC137DD137DE137DF137E0137E1137E2137E3137E4137E5137E6137E7137E8137E9137EA137EB137EC137ED137EE137EF137F0137F1137F2137F3137F4137F5137F6137F7137F8137F9137FA137FB137FC137FD137FE137FF138001380113802138031380413805138061380713808138091380A1380B1380C1380D1380E1380F138101381113812138131381413815138161381713818138191381A1381B1381C1381D1381E1381F138201382113822138231382413825138261382713828138291382A1382B1382C1382D1382E1382F138301383113832138331383413835138361383713838138391383A1383B1383C1383D1383E1383F138401384113842138431384413845138461384713848138491384A1384B1384C1384D1384E1384F138501385113852138531385413855138561385713858138591385A1385B1385C1385D1385E1385F138601386113862138631386413865138661386713868138691386A1386B1386C1386D1386E1386F138701387113872138731387413875138761387713878138791387A1387B1387C1387D1387E1387F138801388113882138831388413885138861388713888138891388A1388B1388C1388D1388E1388F138901389113892138931389413895138961389713898138991389A1389B1389C1389D1389E1389F138A0138A1138A2138A3138A4138A5138A6138A7138A8138A9138AA138AB138AC138AD138AE138AF138B0138B1138B2138B3138B4138B5138B6138B7138B8138B9138BA138BB138BC138BD138BE138BF138C0138C1138C2138C3138C4138C5138C6138C7138C8138C9138CA138CB138CC138CD138CE138CF138D0138D1138D2138D3138D4138D5138D6138D7138D8138D9138DA138DB138DC138DD138DE138DF138E0138E1138E2138E3138E4138E5138E6138E7138E8138E9138EA138EB138EC138ED138EE138EF138F0138F1138F2138F3138F4138F5138F6138F7138F8138F9138FA138FB138FC138FD138FE138FF139001390113902139031390413905139061390713908139091390A1390B1390C1390D1390E1390F139101391113912139131391413915139161391713918139191391A1391B1391C1391D1391E1391F139201392113922139231392413925139261392713928139291392A1392B1392C1392D1392E1392F139301393113932139331393413935139361393713938139391393A1393B1393C1393D1393E1393F139401394113942139431394413945139461394713948139491394A1394B1394C1394D1394E1394F139501395113952139531395413955139561395713958139591395A1395B1395C1395D1395E1395F139601396113962139631396413965139661396713968139691396A1396B1396C1396D1396E1396F139701397113972139731397413975139761397713978139791397A1397B1397C1397D1397E1397F139801398113982139831398413985139861398713988139891398A1398B1398C1398D1398E1398F139901399113992139931399413995139961399713998139991399A1399B1399C1399D1399E1399F139A0139A1139A2139A3139A4139A5139A6139A7139A8139A9139AA139AB139AC139AD139AE139AF139B0139B1139B2139B3139B4139B5139B6139B7139B8139B9139BA139BB139BC139BD139BE139BF139C0139C1139C2139C3139C4139C5139C6139C7139C8139C9139CA139CB139CC139CD139CE139CF139D0139D1139D2139D3139D4139D5139D6139D7139D8139D9139DA139DB139DC139DD139DE139DF139E0139E1139E2139E3139E4139E5139E6139E7139E8139E9139EA139EB139EC139ED139EE139EF139F0139F1139F2139F3139F4139F5139F6139F7139F8139F9139FA139FB139FC139FD139FE139FF13A0013A0113A0213A0313A0413A0513A0613A0713A0813A0913A0A13A0B13A0C13A0D13A0E13A0F13A1013A1113A1213A1313A1413A1513A1613A1713A1813A1913A1A13A1B13A1C13A1D13A1E13A1F13A2013A2113A2213A2313A2413A2513A2613A2713A2813A2913A2A13A2B13A2C13A2D13A2E13A2F13A3013A3113A3213A3313A3413A3513A3613A3713A3813A3913A3A13A3B13A3C13A3D13A3E13A3F13A4013A4113A4213A4313A4413A4513A4613A4713A4813A4913A4A13A4B13A4C13A4D13A4E13A4F13A5013A5113A5213A5313A5413A5513A5613A5713A5813A5913A5A13A5B13A5C13A5D13A5E13A5F13A6013A6113A6213A6313A6413A6513A6613A6713A6813A6913A6A13A6B13A6C13A6D13A6E13A6F13A7013A7113A7213A7313A7413A7513A7613A7713A7813A7913A7A13A7B13A7C13A7D13A7E13A7F13A8013A8113A8213A8313A8413A8513A8613A8713A8813A8913A8A13A8B13A8C13A8D13A8E13A8F13A9013A9113A9213A9313A9413A9513A9613A9713A9813A9913A9A13A9B13A9C13A9D13A9E13A9F13AA013AA113AA213AA313AA413AA513AA613AA713AA813AA913AAA13AAB13AAC13AAD13AAE13AAF13AB013AB113AB213AB313AB413AB513AB613AB713AB813AB913ABA13ABB13ABC13ABD13ABE13ABF13AC013AC113AC213AC313AC413AC513AC613AC713AC813AC913ACA13ACB13ACC13ACD13ACE13ACF13AD013AD113AD213AD313AD413AD513AD613AD713AD813AD913ADA13ADB13ADC13ADD13ADE13ADF13AE013AE113AE213AE313AE413AE513AE613AE713AE813AE913AEA13AEB13AEC13AED13AEE13AEF13AF013AF113AF213AF313AF413AF513AF613AF713AF813AF913AFA13AFB13AFC13AFD13AFE13AFF13B0013B0113B0213B0313B0413B0513B0613B0713B0813B0913B0A13B0B13B0C13B0D13B0E13B0F13B1013B1113B1213B1313B1413B1513B1613B1713B1813B1913B1A13B1B13B1C13B1D13B1E13B1F13B2013B2113B2213B2313B2413B2513B2613B2713B2813B2913B2A13B2B13B2C13B2D13B2E13B2F13B3013B3113B3213B3313B3413B3513B3613B3713B3813B3913B3A13B3B13B3C13B3D13B3E13B3F13B4013B4113B4213B4313B4413B4513B4613B4713B4813B4913B4A13B4B13B4C13B4D13B4E13B4F13B5013B5113B5213B5313B5413B5513B5613B5713B5813B5913B5A13B5B13B5C13B5D13B5E13B5F13B6013B6113B6213B6313B6413B6513B6613B6713B6813B6913B6A13B6B13B6C13B6D13B6E13B6F13B7013B7113B7213B7313B7413B7513B7613B7713B7813B7913B7A13B7B13B7C13B7D13B7E13B7F13B8013B8113B8213B8313B8413B8513B8613B8713B8813B8913B8A13B8B13B8C13B8D13B8E13B8F13B9013B9113B9213B9313B9413B9513B9613B9713B9813B9913B9A13B9B13B9C13B9D13B9E13B9F13BA013BA113BA213BA313BA413BA513BA613BA713BA813BA913BAA13BAB13BAC13BAD13BAE13BAF13BB013BB113BB213BB313BB413BB513BB613BB713BB813BB913BBA13BBB13BBC13BBD13BBE13BBF13BC013BC113BC213BC313BC413BC513BC613BC713BC813BC913BCA13BCB13BCC13BCD13BCE13BCF13BD013BD113BD213BD313BD413BD513BD613BD713BD813BD913BDA13BDB13BDC13BDD13BDE13BDF13BE013BE113BE213BE313BE413BE513BE613BE713BE813BE913BEA13BEB13BEC13BED13BEE13BEF13BF013BF113BF213BF313BF413BF513BF613BF713BF813BF913BFA13BFB13BFC13BFD13BFE13BFF13C0013C0113C0213C0313C0413C0513C0613C0713C0813C0913C0A13C0B13C0C13C0D13C0E13C0F13C1013C1113C1213C1313C1413C1513C1613C1713C1813C1913C1A13C1B13C1C13C1D13C1E13C1F13C2013C2113C2213C2313C2413C2513C2613C2713C2813C2913C2A13C2B13C2C13C2D13C2E13C2F13C3013C3113C3213C3313C3413C3513C3613C3713C3813C3913C3A13C3B13C3C13C3D13C3E13C3F13C4013C4113C4213C4313C4413C4513C4613C4713C4813C4913C4A13C4B13C4C13C4D13C4E13C4F13C5013C5113C5213C5313C5413C5513C5613C5713C5813C5913C5A13C5B13C5C13C5D13C5E13C5F13C6013C6113C6213C6313C6413C6513C6613C6713C6813C6913C6A13C6B13C6C13C6D13C6E13C6F13C7013C7113C7213C7313C7413C7513C7613C7713C7813C7913C7A13C7B13C7C13C7D13C7E13C7F13C8013C8113C8213C8313C8413C8513C8613C8713C8813C8913C8A13C8B13C8C13C8D13C8E13C8F13C9013C9113C9213C9313C9413C9513C9613C9713C9813C9913C9A13C9B13C9C13C9D13C9E13C9F13CA013CA113CA213CA313CA413CA513CA613CA713CA813CA913CAA13CAB13CAC13CAD13CAE13CAF13CB013CB113CB213CB313CB413CB513CB613CB713CB813CB913CBA13CBB13CBC13CBD13CBE13CBF13CC013CC113CC213CC313CC413CC513CC613CC713CC813CC913CCA13CCB13CCC13CCD13CCE13CCF13CD013CD113CD213CD313CD413CD513CD613CD713CD813CD913CDA13CDB13CDC13CDD13CDE13CDF13CE013CE113CE213CE313CE413CE513CE613CE713CE813CE913CEA13CEB13CEC13CED13CEE13CEF13CF013CF113CF213CF313CF413CF513CF613CF713CF813CF913CFA13CFB13CFC13CFD13CFE13CFF13D0013D0113D0213D0313D0413D0513D0613D0713D0813D0913D0A13D0B13D0C13D0D13D0E13D0F13D1013D1113D1213D1313D1413D1513D1613D1713D1813D1913D1A13D1B13D1C13D1D13D1E13D1F13D2013D2113D2213D2313D2413D2513D2613D2713D2813D2913D2A13D2B13D2C13D2D13D2E13D2F13D3013D3113D3213D3313D3413D3513D3613D3713D3813D3913D3A13D3B13D3C13D3D13D3E13D3F13D4013D4113D4213D4313D4413D4513D4613D4713D4813D4913D4A13D4B13D4C13D4D13D4E13D4F13D5013D5113D5213D5313D5413D5513D5613D5713D5813D5913D5A13D5B13D5C13D5D13D5E13D5F13D6013D6113D6213D6313D6413D6513D6613D6713D6813D6913D6A13D6B13D6C13D6D13D6E13D6F13D7013D7113D7213D7313D7413D7513D7613D7713D7813D7913D7A13D7B13D7C13D7D13D7E13D7F13D8013D8113D8213D8313D8413D8513D8613D8713D8813D8913D8A13D8B13D8C13D8D13D8E13D8F13D9013D9113D9213D9313D9413D9513D9613D9713D9813D9913D9A13D9B13D9C13D9D13D9E13D9F13DA013DA113DA213DA313DA413DA513DA613DA713DA813DA913DAA13DAB13DAC13DAD13DAE13DAF13DB013DB113DB213DB313DB413DB513DB613DB713DB813DB913DBA13DBB13DBC13DBD13DBE13DBF13DC013DC113DC213DC313DC413DC513DC613DC713DC813DC913DCA13DCB13DCC13DCD13DCE13DCF13DD013DD113DD213DD313DD413DD513DD613DD713DD813DD913DDA13DDB13DDC13DDD13DDE13DDF13DE013DE113DE213DE313DE413DE513DE613DE713DE813DE913DEA13DEB13DEC13DED13DEE13DEF13DF013DF113DF213DF313DF413DF513DF613DF713DF813DF913DFA13DFB13DFC13DFD13DFE13DFF13E0013E0113E0213E0313E0413E0513E0613E0713E0813E0913E0A13E0B13E0C13E0D13E0E13E0F13E1013E1113E1213E1313E1413E1513E1613E1713E1813E1913E1A13E1B13E1C13E1D13E1E13E1F13E2013E2113E2213E2313E2413E2513E2613E2713E2813E2913E2A13E2B13E2C13E2D13E2E13E2F13E3013E3113E3213E3313E3413E3513E3613E3713E3813E3913E3A13E3B13E3C13E3D13E3E13E3F13E4013E4113E4213E4313E4413E4513E4613E4713E4813E4913E4A13E4B13E4C13E4D13E4E13E4F13E5013E5113E5213E5313E5413E5513E5613E5713E5813E5913E5A13E5B13E5C13E5D13E5E13E5F13E6013E6113E6213E6313E6413E6513E6613E6713E6813E6913E6A13E6B13E6C13E6D13E6E13E6F13E7013E7113E7213E7313E7413E7513E7613E7713E7813E7913E7A13E7B13E7C13E7D13E7E13E7F13E8013E8113E8213E8313E8413E8513E8613E8713E8813E8913E8A13E8B13E8C13E8D13E8E13E8F13E9013E9113E9213E9313E9413E9513E9613E9713E9813E9913E9A13E9B13E9C13E9D13E9E13E9F13EA013EA113EA213EA313EA413EA513EA613EA713EA813EA913EAA13EAB13EAC13EAD13EAE13EAF13EB013EB113EB213EB313EB413EB513EB613EB713EB813EB913EBA13EBB13EBC13EBD13EBE13EBF13EC013EC113EC213EC313EC413EC513EC613EC713EC813EC913ECA13ECB13ECC13ECD13ECE13ECF13ED013ED113ED213ED313ED413ED513ED613ED713ED813ED913EDA13EDB13EDC13EDD13EDE13EDF13EE013EE113EE213EE313EE413EE513EE613EE713EE813EE913EEA13EEB13EEC13EED13EEE13EEF13EF013EF113EF213EF313EF413EF513EF613EF713EF813EF913EFA13EFB13EFC13EFD13EFE13EFF13F0013F0113F0213F0313F0413F0513F0613F0713F0813F0913F0A13F0B13F0C13F0D13F0E13F0F13F1013F1113F1213F1313F1413F1513F1613F1713F1813F1913F1A13F1B13F1C13F1D13F1E13F1F13F2013F2113F2213F2313F2413F2513F2613F2713F2813F2913F2A13F2B13F2C13F2D13F2E13F2F13F3013F3113F3213F3313F3413F3513F3613F3713F3813F3913F3A13F3B13F3C13F3D13F3E13F3F13F4013F4113F4213F4313F4413F4513F4613F4713F4813F4913F4A13F4B13F4C13F4D13F4E13F4F13F5013F5113F5213F5313F5413F5513F5613F5713F5813F5913F5A13F5B13F5C13F5D13F5E13F5F13F6013F6113F6213F6313F6413F6513F6613F6713F6813F6913F6A13F6B13F6C13F6D13F6E13F6F13F7013F7113F7213F7313F7413F7513F7613F7713F7813F7913F7A13F7B13F7C13F7D13F7E13F7F13F8013F8113F8213F8313F8413F8513F8613F8713F8813F8913F8A13F8B13F8C13F8D13F8E13F8F13F9013F9113F9213F9313F9413F9513F9613F9713F9813F9913F9A13F9B13F9C13F9D13F9E13F9F13FA013FA113FA213FA313FA413FA513FA613FA713FA813FA913FAA13FAB13FAC13FAD13FAE13FAF13FB013FB113FB213FB313FB413FB513FB613FB713FB813FB913FBA13FBB13FBC13FBD13FBE13FBF13FC013FC113FC213FC313FC413FC513FC613FC713FC813FC913FCA13FCB13FCC13FCD13FCE13FCF13FD013FD113FD213FD313FD413FD513FD613FD713FD813FD913FDA13FDB13FDC13FDD13FDE13FDF13FE013FE113FE213FE313FE413FE513FE613FE713FE813FE913FEA13FEB13FEC13FED13FEE13FEF13FF013FF113FF213FF313FF413FF513FF613FF713FF813FF913FFA13FFB13FFC13FFD13FFE13FFF140001400114002140031400414005140061400714008140091400A1400B1400C1400D1400E1400F140101401114012140131401414015140161401714018140191401A1401B1401C1401D1401E1401F140201402114022140231402414025140261402714028140291402A1402B1402C1402D1402E1402F140301403114032140331403414035140361403714038140391403A1403B1403C1403D1403E1403F140401404114042140431404414045140461404714048140491404A1404B1404C1404D1404E1404F140501405114052140531405414055140561405714058140591405A1405B1405C1405D1405E1405F140601406114062140631406414065140661406714068140691406A1406B1406C1406D1406E1406F140701407114072140731407414075140761407714078140791407A1407B1407C1407D1407E1407F140801408114082140831408414085140861408714088140891408A1408B1408C1408D1408E1408F140901409114092140931409414095140961409714098140991409A1409B1409C1409D1409E1409F140A0140A1140A2140A3140A4140A5140A6140A7140A8140A9140AA140AB140AC140AD140AE140AF140B0140B1140B2140B3140B4140B5140B6140B7140B8140B9140BA140BB140BC140BD140BE140BF140C0140C1140C2140C3140C4140C5140C6140C7140C8140C9140CA140CB140CC140CD140CE140CF140D0140D1140D2140D3140D4140D5140D6140D7140D8140D9140DA140DB140DC140DD140DE140DF140E0140E1140E2140E3140E4140E5140E6140E7140E8140E9140EA140EB140EC140ED140EE140EF140F0140F1140F2140F3140F4140F5140F6140F7140F8140F9140FA140FB140FC140FD140FE140FF141001410114102141031410414105141061410714108141091410A1410B1410C1410D1410E1410F141101411114112141131411414115141161411714118141191411A1411B1411C1411D1411E1411F141201412114122141231412414125141261412714128141291412A1412B1412C1412D1412E1412F141301413114132141331413414135141361413714138141391413A1413B1413C1413D1413E1413F141401414114142141431414414145141461414714148141491414A1414B1414C1414D1414E1414F141501415114152141531415414155141561415714158141591415A1415B1415C1415D1415E1415F141601416114162141631416414165141661416714168141691416A1416B1416C1416D1416E1416F141701417114172141731417414175141761417714178141791417A1417B1417C1417D1417E1417F141801418114182141831418414185141861418714188141891418A1418B1418C1418D1418E1418F141901419114192141931419414195141961419714198141991419A1419B1419C1419D1419E1419F141A0141A1141A2141A3141A4141A5141A6141A7141A8141A9141AA141AB141AC141AD141AE141AF141B0141B1141B2141B3141B4141B5141B6141B7141B8141B9141BA141BB141BC141BD141BE141BF141C0141C1141C2141C3141C4141C5141C6141C7141C8141C9141CA141CB141CC141CD141CE141CF141D0141D1141D2141D3141D4141D5141D6141D7141D8141D9141DA141DB141DC141DD141DE141DF141E0141E1141E2141E3141E4141E5141E6141E7141E8141E9141EA141EB141EC141ED141EE141EF141F0141F1141F2141F3141F4141F5141F6141F7141F8141F9141FA141FB141FC141FD141FE141FF142001420114202142031420414205142061420714208142091420A1420B1420C1420D1420E1420F142101421114212142131421414215142161421714218142191421A1421B1421C1421D1421E1421F142201422114222142231422414225142261422714228142291422A1422B1422C1422D1422E1422F142301423114232142331423414235142361423714238142391423A1423B1423C1423D1423E1423F142401424114242142431424414245142461424714248142491424A1424B1424C1424D1424E1424F142501425114252142531425414255142561425714258142591425A1425B1425C1425D1425E1425F142601426114262142631426414265142661426714268142691426A1426B1426C1426D1426E1426F142701427114272142731427414275142761427714278142791427A1427B1427C1427D1427E1427F142801428114282142831428414285142861428714288142891428A1428B1428C1428D1428E1428F142901429114292142931429414295142961429714298142991429A1429B1429C1429D1429E1429F142A0142A1142A2142A3142A4142A5142A6142A7142A8142A9142AA142AB142AC142AD142AE142AF142B0142B1142B2142B3142B4142B5142B6142B7142B8142B9142BA142BB142BC142BD142BE142BF142C0142C1142C2142C3142C4142C5142C6142C7142C8142C9142CA142CB142CC142CD142CE142CF142D0142D1142D2142D3142D4142D5142D6142D7142D8142D9142DA142DB142DC142DD142DE142DF142E0142E1142E2142E3142E4142E5142E6142E7142E8142E9142EA142EB142EC142ED142EE142EF142F0142F1142F2142F3142F4142F5142F6142F7142F8142F9142FA142FB142FC142FD142FE142FF143001430114302143031430414305143061430714308143091430A1430B1430C1430D1430E1430F143101431114312143131431414315143161431714318143191431A1431B1431C1431D1431E1431F143201432114322143231432414325143261432714328143291432A1432B1432C1432D1432E1432F143301433114332143331433414335143361433714338143391433A1433B1433C1433D1433E1433F143401434114342143431434414345143461434714348143491434A1434B1434C1434D1434E1434F143501435114352143531435414355143561435714358143591435A1435B1435C1435D1435E1435F143601436114362143631436414365143661436714368143691436A1436B1436C1436D1436E1436F143701437114372143731437414375143761437714378143791437A1437B1437C1437D1437E1437F143801438114382143831438414385143861438714388143891438A1438B1438C1438D1438E1438F143901439114392143931439414395143961439714398143991439A1439B1439C1439D1439E1439F143A0143A1143A2143A3143A4143A5143A6143A7143A8143A9143AA143AB143AC143AD143AE143AF143B0143B1143B2143B3143B4143B5143B6143B7143B8143B9143BA143BB143BC143BD143BE143BF143C0143C1143C2143C3143C4143C5143C6143C7143C8143C9143CA143CB143CC143CD143CE143CF143D0143D1143D2143D3143D4143D5143D6143D7143D8143D9143DA143DB143DC143DD143DE143DF143E0143E1143E2143E3143E4143E5143E6143E7143E8143E9143EA143EB143EC143ED143EE143EF143F0143F1143F2143F3143F4143F5143F6143F7143F8143F9143FAA010AA026AA039AA041AA046AA046BA066AA066BA066CA097AA098AA100AA101AA102AA104AA104BA104CA105AA105BA107AA107BA107CA110AA110BA115AA125AA135AA202AA202BA207AA209AA215AA216AA227AA267AA289AA294AA299AA329AA332AA332BA332CA336AA336BA336CA359AA364AA368AA371AA381A A383 RA OR RIA383AA386A A393 EIGHT A410 BEGIN A410A END A450AA457ACONSONANT SIGN MEDIAL RA SIGN THOLHOMA NGKUE MFON GBIEE FON PIPAEMGBIEEPIPAEMBANAA MFON SHUENSHUETTITA SHINDA PA NJI MAEMBGBIEE TU MAEMBANGANGUMAEMVEUXMANSUAE MVEUAENGAMSEUNYAMNTOQPEN KEUKEUTNDANKINDI NGKUENZEUMLAPAQLET KUT NTAP MFAAMAEKEUPPASHAE GHEUAERAEPAMSHAE MON NGGEUAET NZUN MEUT U YUQ NAE GHEUAEGHEUAE NTAP NTAAMGBASA MEUNJOMNDEUQMOOMPUQMAEMKPENTUAEPLUAEPSONJAM TEUTEUWENMAENYI NDAANGGEUAETMOOMEUTLOMMAE MAP PIEETSHIRAESHOQ NSHUT YUMNYIT MONGKEUAEQPAARAENKAARAEUNKNOWNMAESIMBANYITEUAENNSHIEENSHUET TU MAEMGBIEESET TU LOM NTEUM MBA MAELEEKIEEMYEURAEMBAARAEPEESHI YAFU LEERAEWALAM NSHUT NYAM NTIEE SHEUOQNDU NJAA GHEUGHEUAEMTU NSIEE SHET NJAQ SHEUAEQTU MFON TEUAEQ MBIT MBAAKET NYI NTEUMKEUPUQGHEUGHENKEUYEUXLAANAEPARUM NGKINDI MVOP NGGEU MBUWUAETSAKEUAENGGUOQ NGGUOQ LARGEMFIYAQMBEURIMONTIEENNYAEMAEPUNGAAM MEUT NGGEETMBUOQKEUAEMNJEUAENANJUQANGGAAM NGKUE MAEMBAWANGKUOQ NDEUAEREENGKAQGHARAEMBEEKEETGBAYINYIR MKPARAQ MEUNNTU MBITMBEUMPIRIEENNDOMBUMBAA CABBAGE-TREE KEUSHEUAEPKEUKAQ YU MUOMAENZEUMNSEUAENKPARAQNDIDATAASHAENJUEQTITA YUESUAET NGGUAEN NYAMNANSANAQ MA KEUAERINGGUONMBIRIEENMGBASAQNTEUNGBATEUTEUXNGGUMNDEUTNSHAQVEUAEPENMBERAETITUAEP NSUOT NGOMNJEEEEMBUAEMNGGUEET KUOP NKAARAEMA NSIEESHUEQSETFONMAEMBAKEUSEUXMBEUX MBAA PICKETYUWOQNJEUXFATIGUENJIEENJEUTNSHEENGGAAMAEWUAENNGKUNNGKAP KEUAETMEUNSHEUAEYAEMMAEMFEUTNDEUXMALEERISEUAEQNJEUAEM KEUOT MBUAENGKEURINGKYEE FEUFEUAETMGBOFUMLEUAEPMGBEUNMGBIEENSIEEPKWAETTEEEENGKEUAEQMFEUAENSIEETPEUTAEMFIEENGGWAENNTEUMNGGEUXNGKIEEMAENJETNGGAPNGGUOMNSHUTGHEUAEREN OLDREN MUCH MBAA SEVENNSHUOPKPEUXNGGEUAETNGKEUXNSHUERIMGBANGGURAEGHEUXNGKEUAEMNGGEEEE TAEN NTEUM NDAA SOFTNESSNGGUAESHAE NYAMGHEUNYEUAETUMAEKEUAESUAENTEUAEQVEUAEGHAAMAENGEUREUTSHEUAEQMGBEN NYI CLEAVERMFEUQNDIAQPIEEQLEUAEMGBEUXNGKUPNGKAAMINGGEUAE NYI BETWEENNGKUMYEUAETNGGUP PA PEOPLEFU CALL PA PLURAL NDAA MY HOUSENGUAEYUAENSWIMMING NJEE EPOCHNGUAET FU REMEDYKEAAEFINAL NGLONG UEXWADDA HIGH-LOW NTSAUNCHAUPLHAUNTHAU TSHAB CEEB CIM CHEEMTHIABNTXIVVOS SEEV MEEJ SUABVOS NRUAIB YAM CIM TSOV ROGHUNDREDS TEN THOUSANDS TEN BILLIONS TRILLIONSVOS LUB THIRD-STAGE ZWJ THAJ TXHEEJ CEEV MEEJ TSEEBHAIS LUS NTOG NTOG CUAM TSHOOJ TXWV CHWVPUB DAWBNRES TOSTSHEEJXYOOJTONPI SYMBOL AIVAEXCLAMATION OHBASIGNADARBAIFITKOGOWAYHIRDEABOLAKKOERIGO ERIGO TAMURATATASOUEWASSEYI PA ARCHAIC MAYI NNA ARCHAIC NATLHYADLHYAYI KA ARCHAIC NGA REFORMED TSHAYI TSA ARCHAIC ZZAZZSYASIGN CONSONANT MODIFIER BARLETTER NASALIZATION ASPIRATIONKHITAN SMALL SCRIPT FILLERONE BEAT THREE HALF 18B0018B0118B0218B0318B0418B0518B0618B0718B0818B0918B0A18B0B18B0C18B0D18B0E18B0F18B1018B1118B1218B1318B1418B1518B1618B1718B1818B1918B1A18B1B18B1C18B1D18B1E18B1F18B2018B2118B2218B2318B2418B2518B2618B2718B2818B2918B2A18B2B18B2C18B2D18B2E18B2F18B3018B3118B3218B3318B3418B3518B3618B3718B3818B3918B3A18B3B18B3C18B3D18B3E18B3F18B4018B4118B4218B4318B4418B4518B4618B4718B4818B4918B4A18B4B18B4C18B4D18B4E18B4F18B5018B5118B5218B5318B5418B5518B5618B5718B5818B5918B5A18B5B18B5C18B5D18B5E18B5F18B6018B6118B6218B6318B6418B6518B6618B6718B6818B6918B6A18B6B18B6C18B6D18B6E18B6F18B7018B7118B7218B7318B7418B7518B7618B7718B7818B7918B7A18B7B18B7C18B7D18B7E18B7F18B8018B8118B8218B8318B8418B8518B8618B8718B8818B8918B8A18B8B18B8C18B8D18B8E18B8F18B9018B9118B9218B9318B9418B9518B9618B9718B9818B9918B9A18B9B18B9C18B9D18B9E18B9F18BA018BA118BA218BA318BA418BA518BA618BA718BA818BA918BAA18BAB18BAC18BAD18BAE18BAF18BB018BB118BB218BB318BB418BB518BB618BB718BB818BB918BBA18BBB18BBC18BBD18BBE18BBF18BC018BC118BC218BC318BC418BC518BC618BC718BC818BC918BCA18BCB18BCC18BCD18BCE18BCF18BD018BD118BD218BD318BD418BD518BD618BD718BD818BD918BDA18BDB18BDC18BDD18BDE18BDF18BE018BE118BE218BE318BE418BE518BE618BE718BE818BE918BEA18BEB18BEC18BED18BEE18BEF18BF018BF118BF218BF318BF418BF518BF618BF718BF818BF918BFA18BFB18BFC18BFD18BFE18BFF18C0018C0118C0218C0318C0418C0518C0618C0718C0818C0918C0A18C0B18C0C18C0D18C0E18C0F18C1018C1118C1218C1318C1418C1518C1618C1718C1818C1918C1A18C1B18C1C18C1D18C1E18C1F18C2018C2118C2218C2318C2418C2518C2618C2718C2818C2918C2A18C2B18C2C18C2D18C2E18C2F18C3018C3118C3218C3318C3418C3518C3618C3718C3818C3918C3A18C3B18C3C18C3D18C3E18C3F18C4018C4118C4218C4318C4418C4518C4618C4718C4818C4918C4A18C4B18C4C18C4D18C4E18C4F18C5018C5118C5218C5318C5418C5518C5618C5718C5818C5918C5A18C5B18C5C18C5D18C5E18C5F18C6018C6118C6218C6318C6418C6518C6618C6718C6818C6918C6A18C6B18C6C18C6D18C6E18C6F18C7018C7118C7218C7318C7418C7518C7618C7718C7818C7918C7A18C7B18C7C18C7D18C7E18C7F18C8018C8118C8218C8318C8418C8518C8618C8718C8818C8918C8A18C8B18C8C18C8D18C8E18C8F18C9018C9118C9218C9318C9418C9518C9618C9718C9818C9918C9A18C9B18C9C18C9D18C9E18C9F18CA018CA118CA218CA318CA418CA518CA618CA718CA818CA918CAA18CAB18CAC18CAD18CAE18CAF18CB018CB118CB218CB318CB418CB518CB618CB718CB818CB918CBA18CBB18CBC18CBD18CBE18CBF18CC018CC118CC218CC318CC418CC518CC618CC718CC818CC918CCA18CCB18CCC18CCD18CCE18CCF18CD018CD118CD218CD318CD418CD5#KHITAN SMALL SCRIPT CHARACTER-18CFF$#KATAKANA LETTER ARCHAIC EHIRAGANA LETTER ARCHAIC YEHIRAGANA LETTER ARCHAIC WUHIRAGANA LETTER SMALL KOKATAKANA LETTER SMALL KO1B1701B1711B1721B1731B1741B1751B1761B1771B1781B1791B17A1B17B1B17C1B17D1B17E1B17F1B1801B1811B1821B1831B1841B1851B1861B1871B1881B1891B18A1B18B1B18C1B18D1B18E1B18F1B1901B1911B1921B1931B1941B1951B1961B1971B1981B1991B19A1B19B1B19C1B19D1B19E1B19F1B1A01B1A11B1A21B1A31B1A41B1A51B1A61B1A71B1A81B1A91B1AA1B1AB1B1AC1B1AD1B1AE1B1AF1B1B01B1B11B1B21B1B31B1B41B1B51B1B61B1B71B1B81B1B91B1BA1B1BB1B1BC1B1BD1B1BE1B1BF1B1C01B1C11B1C21B1C31B1C41B1C51B1C61B1C71B1C81B1C91B1CA1B1CB1B1CC1B1CD1B1CE1B1CF1B1D01B1D11B1D21B1D31B1D41B1D51B1D61B1D71B1D81B1D91B1DA1B1DB1B1DC1B1DD1B1DE1B1DF1B1E01B1E11B1E21B1E31B1E41B1E51B1E61B1E71B1E81B1E91B1EA1B1EB1B1EC1B1ED1B1EE1B1EF1B1F01B1F11B1F21B1F31B1F41B1F51B1F61B1F71B1F81B1F91B1FA1B1FB1B1FC1B1FD1B1FE1B1FF1B2001B2011B2021B2031B2041B2051B2061B2071B2081B2091B20A1B20B1B20C1B20D1B20E1B20F1B2101B2111B2121B2131B2141B2151B2161B2171B2181B2191B21A1B21B1B21C1B21D1B21E1B21F1B2201B2211B2221B2231B2241B2251B2261B2271B2281B2291B22A1B22B1B22C1B22D1B22E1B22F1B2301B2311B2321B2331B2341B2351B2361B2371B2381B2391B23A1B23B1B23C1B23D1B23E1B23F1B2401B2411B2421B2431B2441B2451B2461B2471B2481B2491B24A1B24B1B24C1B24D1B24E1B24F1B2501B2511B2521B2531B2541B2551B2561B2571B2581B2591B25A1B25B1B25C1B25D1B25E1B25F1B2601B2611B2621B2631B2641B2651B2661B2671B2681B2691B26A1B26B1B26C1B26D1B26E1B26F1B2701B2711B2721B2731B2741B2751B2761B2771B2781B2791B27A1B27B1B27C1B27D1B27E1B27F1B2801B2811B2821B2831B2841B2851B2861B2871B2881B2891B28A1B28B1B28C1B28D1B28E1B28F1B2901B2911B2921B2931B2941B2951B2961B2971B2981B2991B29A1B29B1B29C1B29D1B29E1B29F1B2A01B2A11B2A21B2A31B2A41B2A51B2A61B2A71B2A81B2A91B2AA1B2AB1B2AC1B2AD1B2AE1B2AF1B2B01B2B11B2B21B2B31B2B41B2B51B2B61B2B71B2B81B2B91B2BA1B2BB1B2BC1B2BD1B2BE1B2BF1B2C01B2C11B2C21B2C31B2C41B2C51B2C61B2C71B2C81B2C91B2CA1B2CB1B2CC1B2CD1B2CE1B2CF1B2D01B2D11B2D21B2D31B2D41B2D51B2D61B2D71B2D81B2D91B2DA1B2DB1B2DC1B2DD1B2DE1B2DF1B2E01B2E11B2E21B2E31B2E41B2E51B2E61B2E71B2E81B2E91B2EA1B2EB1B2EC1B2ED1B2EE1B2EF1B2F01B2F11B2F21B2F31B2F41B2F51B2F61B2F71B2F81B2F91B2FA1B2FBSLOAN JDOTS INSIDE AND ABOVEWITH DOTSLOAN OWSLOAN EH ROMANIAN ISLOAN EELONG I ROMANIAN SLOAN U VOCALIC MTANGENTTANGENT TIGHT SIGN O WITH CROSSTHICK LETTER SELECTOR DOUBLE MARKPUNCTUATION CHINOOK FULL STOP CONTINUING LOWER HORIZONTAL RIGHT VERTICAL ANTENNA RECEPTACLEINPUTSOUTPUTBUFFERBUFFER WITH INVERTED INPUTTOP AND UPPER BOTTOM AND RIGHT TO MIDDLE LEFT TWELFTH MIDDLE RIGHT TWELFTH ORTHOGONAL WITHOUT CROUCHINGSPREADMUSHROOM CLOUDINWARDOUTWARD NEUTRAL FACETWO RINGS ALIGNED HORIZONTALLYSALTIRES DIAGONALSBLACK TRIANGLESAPERTUREINVERSE BLACK DIAMOND+LEFT AND UPPER ONE EIGHTH BLOCK CONTAINING FLAPPING BIRDGO-KARTSNAKE FLYING SAUCER TOP HALF FORWARD-FACING RUNNER MOON LANDERRIGHT HALF AND LEFT LOWER HALF AND UPPER EXPLOSION AT HORIZON/HEAVY WHITE SQUARE CONTAINING BLACK VERY SMALL ,WHITE VERTICAL RECTANGLE WITH HORIZONTAL BAR+TOP LEFT BLACK LEFT-POINTING SMALL TRIANGLEFUNNEL%LOWER LEFT TO MIDDLE CENTRE TO LOWER %UPPER LEFT TO MIDDLE CENTRE TO UPPER HORIZONTAL LINE WITH TICK MARKCORNERTERMINALCROTCHCROSSBARCROSSBAR WITH LOWER STEMUPPER HALF VERTEX OF MDIAGONAL LOWER LEFTSHORT UPPER TERMINALUPPER RIGHT ARCSTEM WITH RIGHT CROSSBARRIGHT AND LOWER SHORT LOWER TERMINALLOWER LEFT AND UPPER LEFT ARC CENTRE OF KLOWER HALF VERTEX OF MUPPER HALF VERTEX OF WZ WITH CROSSBARRAISED UPPER LEFT ARCSTEM WITH LEFT CROSSBARLOWER RIGHT AND UPPER RIGHT ARC"DIAGONAL UPPER LEFT AND LOWER LEFT LEFT JOINTDIAGONAL UPPER LEFTCROSSBAR WITH UPPER STEM VERTEX OF VHALF VERTEX OF W ARC WITH TAILHALF LOWER ONE QUARTER BLOCKHALF RIGHT ONE QUARTER BLOCKHORIZONTAL ZIGZAG LINEKEYHOLE:OLD PERSONAL COMPUTER WITH MONITOR IN PORTRAIT ORIENTATIONBLACK RIGHT TRIANGLE CARETFRAGILE OFFICE BUILDING TREE APPLE CHERRY STRAWBERRY FLORAMETIS PARTHENOPEVICTORIAEGERIAIRENEEUNOMIAPSYCHETHETIS MELPOMENEFORTUNA+ASTRONOMICAL SYMBOL FOR ASTEROID PROSERPINABELLONA AMPHITRITE LEUKOTHEAPOPULUS TRISTITIAALBUS FORTUNA MAJORRUBEUS ACQUISITIO CONJUNCTIOCAPUT DRACONISLAETITIACARCERAMISSIOPUELLA FORTUNA MINORCAUDA DRACONIS-MEDIUM SMALL WHITE CIRCLE WITH HORIZONTAL BARGORAZDO TSATA SREDNE MALO VYSOKO MALO POVYSHE STRANNO MALO POVYSHE S KRYZHEMSTRANNOVYSOKO S KRYZHEMMALO POVYSHE STRANNOGORAZDO VYSOKORAVNOTIKHAYABORZAYAUDARKA PODVERTKALOMKAKUPNAYAKACHKAZEVOKSKOBARAZSEKA KRYZH ON LEFTMRACHNOSVETLO TRESVETLO DEMESTVENNY OTSECHKA PODCHASHIEPODCHASHIE WITH VERTICAL STROKECHASHKACHASHKA POLNAYAOBLACHKOSOROCHYA NOZHKATOCHKA DVOETOCHIEATTACHING VERTICAL KRYZHLOWER TONAL RANGE INDICATORDIRECTION FLIPKRYUK KRYUK TIKHYPARAKLIT DVA V CHELNUKLYUCHZANOZHEKSTOPITSASTOPITSA S OCHKOM PEREVODKAPEREVODKA NEPOSTOYANNAYASTOPITSA WITH SOROCHYA NOZHKA CHELYUSTKAPALKA ZAPYATAYABORZYTIKHYMRACHNYSVETLY TRESVETLYPROSTAYA MRACHNAYASVETLAYA TRESVETLAYADOUBLE ZAPYATAYAREVERSED CHELYUSTKADERBITSAKHAMILODEMESTVENNY KLYUCHKLYUCHEVAYA SVETLAYAKLYUCHENEPOSTOYANNAYAKLYUCHEVAYA TIKHAYANEPOSTOYANNAYA KLYUCHEVAYA SLOZHITIE S ZAPYATOYZAKRYTOEKOBYLAZMEYTSASTATYAZAPYATOY ZAPYATOY I KRYZHEM I ZAPYATOY ZAKRYTAYAZAKRYTAYA S ZAPYATOYROGOMDVUMYA ZAPYATYMIZAPYATOY I PODCHASHIEM POLKULIZMYSTATYA NEPOSTOYANNAYAMRACHNOTIKHAYA KRYZHEVAYA POLUPOVODNAYA POVODNAYAKLYUCHEPOVODNAYATIKHAYA PUTNAYA DVOECHELNAYADVOECHELNOKRYZHEVAYADVOECHELNOPOVODNAYADVOECHELNOPOVODNAYA GROMNAYA GROMOPOVODNAYA GROMNAYAGROMOPOVODNAYA$GROMOPOVODNAYA WITH DOUBLE ZAPYATAYAGROMOKRYZHEVAYAGROMOKRYZHEVAYA POVODNAYAMECHIKPOVODNY KLYUCHEVOYKLYUCHEPOVODNYKLYUCHENEPOSTOYANNYTRYASOGLASNAYATRYASOPOVODNAYATRYASOSTRELNAYAOSOKA KRYUKOVAYATRYASKAKUFISMAOBLAKONEMKADASEIA EKFONITIKONDIPLIKATHISTI SYRMATIKI PARAKLITIKI YPOKRISISYPOKRISIS DIPLIKREMASTIAPESO TELEIA KENTIMATA APOSTROFOSAPOSTROFOS DIPLISYNEVMATHITAOLIGON PSILONCHAMILONVATHYISON KENTIMA KENTIMATA SAXIMATAPARICHONSTAVROS APODEXIAOXEIAI VAREIAI APODERMA APOTHEMAKLASMAREVMAPIASMA ARCHAIONTINAGMA ANATRICHISMASEISMAARCHAION META STAVROUOYRANISMA ARCHAIONTHEMALEMOITESSERA KRATIMATA APESO EXO NEOFTHORA ARCHAION IMIFTHORATROMIKON ARCHAIONKATAVA TROMIKONPELASTON PSIFISTONKONTEVMACHOREVMA ARCHAIONRAPISMA PARAKALESMA PARAKLITIKI ICHADINPETASMA KONTEVMA TROMIKON STRAGGISMATA GRONTHISMATAPETASTIKOUFISMAPETASTOKOUFISMAKRATIMOKOUFISMA PELASTON NEOYPSILI APOSTROFOS APOSTROFOI SYNDESMOS YPORROIKRATIMOYPORROONELAFRONCHAMILI MIKRON ISONPIASMA PSIFISTON OMALON ANTIKENOMALYGISMAETERON PARAKALESMAKYLISMAANTIKENOKYLISMA TROMIKON NEO EKSTREPTON SYNAGMA NEOSYRMA CHOREVMA NEOEPEGERMA SEISMA NEO XIRON KLASMATROMIKOPSIFISTONPSIFISTOLYGISMATROMIKOLYGISMATROMIKOPARAKALESMAPSIFISTOPARAKALESMATROMIKOSYNAGMAPSIFISTOSYNAGMAGORGOSYNTHETONETERON OYRANISMA NEO THEMA APLOUNTHES KAI APOTHES KATAVASMA ENDOFONONSTAVROS KLASMA ANODIPLI TRIPLITETRAPLI ENOS CHRONOUTRION TESSARON IMISEOS CHRONOUNEO ANOARISTERADEXIADIGORGON TRIGORGONARGON IMIDIARGONDIARGON POLI ARGIARGOTERIMETRIAGORGI GORGOTERI POLI GORGIALLI TRITOS TRIFONIAS PLAGIOS ICHOSISAKIA APOSTROFOI TETRAFONIAS MONOFONIASDIFONIASVARYS PROTOVARYS PLAGIOS TETARTOS APLOUNDIPLOUNENARXIS KAI FTHORA VOUIMIFONON IMIFTHORONARCHAION DEYTEROU ICHOU NAOS ICHOSSKLIRON DIATONON FHTORA SKLIRON CHROMA VASISSKLIRON CHROMA SYNAFINENANOZYGOSKLITONSPATHII YFESIS TETARTIMORIONENARMONIOS ANTIFONIA TETARTIMORION APLI DYO MONOGRAMMOS TESSERA DIGRAMMOS EX TRIGRAMMOS OKTO DIESISYFESISMIKRIMEGALIDISIMOUTRISIMOU TETRASIMOUARSEOS DIGRAMMA GG DIFTOGGOS OUSTIGMAKLASMA GORGON NEO REPEAT DOTS DAL SEGNODA CAPOSEGNO FERMATA BELOW BREATH MARKCAESURABRACEBRACKETBASSAMULTIPLE MEASURE RESTSHARPCOMMON MULTI WHOLE THIRTY-SECOND SIXTY-FOURTH ONE HUNDRED TWENTY-EIGHTH CIRCLE X VOID NOTEHEAD BLACK NULL NOTEHEAD SPRECHGESANG AUGMENTATION DOTSTACCATOTENUTO STACCATISSIMOMARCATOMARCATO-ACCENT-LOURESMEAR RINFORZANDOSUBITOPIANOMEZZOFORTE CRESCENDO DECRESCENDO HAUPTSTIMME NEBENSTIMME END OF STIMME DEGREE SLASHHARMONICSNAP PIZZICATO HALF PEDAL WITH FINGERNAILSDAMP ALLMAXIMALONGABREVISMINIMA MINIMA BLACK PERFECTA BREVIS MINIMA PERFECTA IMPERFECTAPERFECTA DIMINUTION-1CROIXSQUARE BVIRGAPODATUSCLIVIS SCANDICUSCLIMACUSTORCULUS PORRECTUS PORRECTUS SCANDICUS TORCULUS RESUPINUSPES SUBPUNCTISC CLEF END OF PIECE FINAL NOTERECITATIVE MARK FLAT SIGNKORONLEIMMA MONOGRAM FOR HEAVENLY HUMAN HUMAN FULL CIRCLEMIREDBARRIER KEEPING SMALL CONTRARIETYASCENT BRANCHING OUTDEFECTIVENESS OR DISTORTION DIVERGENCE YOUTHFULNESS PENETRATIONCONTACT HOLDING BACKADVANCERELEASE RESISTANCE CONTENTION ENDEAVOURDUTIESCHANGE DECISIVENESSBOLD RESOLUTIONPACKINGLEGION CLOSENESSKINSHIP GATHERINGSTRENGTHPURITYFULLNESS RESIDENCE LAW OR MODEL GOING TO MEET ENCOUNTERSSTOVE GREATNESS ENLARGEMENTPATTERNRITUALFLIGHTVASTNESS OR WASTING CONSTANCYETERNITYUNITY DIMINISHMENT CLOSED MOUTH GUARDEDNESS GATHERING INMASSING ACCUMULATION EMBELLISHMENTDOUBTSINKINGINNER DEPARTURE DARKENINGDIMMING EXHAUSTION SEVERANCESTOPPAGEHARDNESS COMPLETIONCLOSUREFAILURE AGGRAVATION COMPLIANCE ON THE VERGE DIFFICULTIES LABOURING FOSTERINGSCRIPT CAPITAL AMATHEMATICAL SCRIPT CAPITAL GMATHEMATICAL SCRIPT SMALL F$MATHEMATICAL DOUBLE-STRUCK CAPITAL O THETA SYMBOL THUMB UNDER RAISED KNUCKLECUPPEDHINGED HINGED LOWCIRCLE INDEX HINGERAISED KNUCKLES UP MIDDLE HINGED MIDDLE UP CONJOINEDCIRCLE INDEX MIDDLE MIDDLE BENT OVER INDEXBENT OVER MIDDLE CIRCLE INDEX STRAIGHT THUMB BENTBENT THUMB STRAIGHT THUMB BENT SPREAD THUMB MIDDLE UP THUMB SIDEUP SPREAD THUMB FORWARDCIRCLEDHOOKEDBETWEEN INDEX MIDDLE STRAIGHTCONJOINED HINGED CROSSED CONJOINED HINGED ANGLED OUTANGLEDCROSSEDTHUMB HOOKED MIDDLE HINGEDFINGERSCONJOINED SPLITCLAW FOUR FINGERS CONJOINED FIST FOUR FINGERS CONJOINED BENTHINGE FOUR FINGERS CONJOINEDHEEL SPREAD THUMB FORWARDHINGE FIVE FINGERS OVAL FIVE FINGERS SPREAD THUMB SIDENO THUMBBETWEEN PALM FACINGSINDEX THUMB SIDE SIDE BENTLITTLE THUMB FORWARD HOOK CURLICUECUP OPEN CURLICUE OPENCURLICUEOPEN THUMB FORWARDHINGESIDE TOUCHING INDEXBETWEEN MIDDLE RINGANGLE HINGE LITTLEHINGE INDEX MIDDLE RING STRAIGHTCURVEDOTHERS CIRCLEDTOUCHES THUMB OUTFIST RING DOWN'HINGE RING DOWN INDEX THUMB HOOK MIDDLE(ANGLE RING DOWN MIDDLE THUMB INDEX CROSSINDEXCURLICUE INDEX RING LITTLE ONUNDER LITTLE OUTFIST MIDDLE DOWN HINGE MIDDLE UP THUMB SIDEHOOK MIDDLE THUMBCIRCLE MIDDLE CURLICUE MIDDLE RING LITTLE ONCIRCLE MIDDLE RING LITTLE BENTHINGE INDEX HINGEDDIAGONALBOTH CLAW INDEX THUMB CURVE THUMB UNDERLARGE INDEX MIDDLE RING LITTLEOVER FOUR RAISED KNUCKLES FIST HEELSINGLEMULTIPLESYMBOLSSQUEEZE FLICK ALTERNATINGSIDE TO SIDE SCISSORSMEDIUMLARGEST WRIST FLEX ALTERNATINGALTERNATING WRIST FLEXSTRAIGHT MOVEMENTDOUBLESHAKINGTRIPLEMOVEMENT SMALL DOUBLE THEN STRAIGHT ALTERNATECOMBINEDSHAKING PARALLELTENSERELAXED SIMULTANEOUSSIMULTANEOUS ALTERNATINGEVERY OTHER TIMEGRADUALFLOORPLANE STRAIGHTMOVEMENT CIRCLEFORWARD TILTING DOWN TILTINGNEUTRAL NEUTRAL UPWRINKLEDSQUEEZEDCLOSED HALF CLOSEDWIDENING MOVEMENTEYE WINK FLUTTERINGWALLPLANE CIRCLINGPUFFEDSUCKEDWRINKLESWIGGLES BLOWING OUT SUCKING INBLOW SUCK INHALEEXHALE RECTANGLELIPS PRESSED TOGETHERLOWER OVER UPPERUPPER OVER LOWERCORNERSSTICKING OUT FARLICKING TOUCHING INSIDE MOUTHINSIDE MOUTH RELAXEDMOVES AGAINST CHEEK STICKING OUT INSIDE MOUTHTEETHTONGUE MOVEMENT LIPS MOVEMENT BITE LIPS EXCITEMENTSPINE POSITIONSSHOULDER TILTING FROM WAISTSTRAIGHT STRETCH CURVED BENDFLOORPLANE TWISTING"UPPER BODY TILTING FROM HIP JOINTS COMBINATIONFINGERHEIGHTWIDTHDEPTH HEAD NECKTORSO LIMBS DIGITS PARENTHESISFENG DIGRAPH WITH TRILLREVERSED SCRIPT CAPITAL TURNED LETTER REVERSED KCAPITAL L WITH BELTTURNED Y WITH BELT REVERSED ENGTURNED R WITH LONG LEG T WITH HOOK RETROFLEX CLICK WITH BAR AND TURNED T INVERTED GLOTTAL STOP STRETCHED C SMALL CAPITAL TURNED KL WITH FISHHOOKDEZH DIGRAPH WITH L WITH BELT AND TURNED R R WITH FISHHOOK AND TESH DIGRAPH DEZH DIGRAPH I WITH STROKE AND S WITH CURL SMALL YUS STRAIGHT UGHE WITH UPTURNES WITH DESCENDERYERU WITH BACK YERSTRAIGHT U WITH STROKE8COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN ITHINGLOCATIONANIMAL INVERTEBRATEXW XWSYLLABLE LENGTHENER LOGOGRAM NYAJ CIRCLED CABREATHY SIGN RISING TONETUPNIKOINIWANCHO NGUN SIGNMUHORTOYORSUTUHHODDONDOL ONAL ABBREVIATION SIGNSIGN AUSIGN OM SYMBOL MUEANGXAM LAIHHYAAHHYEE GURAGE HHWAHHWEEM001 KIM002 KAM003 KUM065 KEEM095 KEM076 KOOM048 KOM179 KUAM004 WIM005 WAM006 WUM126 WEEM118 WEM114 WOOM045 WOM194 WUIM143 WEIM061 WVIM049 WVAM139 WVEM007 MINM008 MANM009 MUNM059 MENM094 MON M154 MUAN M189 MUENM010 BIM011 BAM012 BUM150 BEEM097 BEM103 BOOM138 BOM013 IM014 AM015 UM163 EEM100 EM165 OOM147 OM137 EIM131 M135 M195 ANM178 ENM019 SIM020 SAM021 SUM162 SEEM116 SEM136 SOOM079 SOM196 SIAM025 LIM026 LAM027 LUM084 LEEM073 LEM054 LOOM153 LO M110 LONG LEM016 DIM017 DAM018 DUM089 DEEM180 DOOM181 DOM022 TIM023 TAM024 TUM091 TEEM055 TEM104 TOOM069 TOM028 JIM029 JAM030 JUM157 JEEM113 JEM160 JOOM063 M175 LONG M031 YIM032 YAM033 YUM109 YEEM080 YEM141 YOOM121 YOM034 FIM035 FAM036 FUM078 FEEM075 FEM133 FOOM088 FOM197 FUAM101 FANM037 NINM038 NANM039 NUNM117 NENM169 NONM176 HIM041 HAM186 HUM040 HEEM096 HEM042 HOOM140 HO M083 HEEI M128 HOOUM053 HINM130 HANM087 HUNM052 HENM193 HON M046 HUAN M090 NGGI M043 NGGA M082 NGGU M115 NGGEE M146 NGGE M156 NGGOO M120 NGGO M159 NGGAA M127 NGGUAM086 LONG NGGEM106 LONG NGGOOM183 LONG NGGOM155 GIM111 GAM168 GUM190 GEE M166 GUEI M167 GUAN M184 NGEN M057 NGON M177 NGUANM068 PIM099 PAM050 PUM081 PEEM051 PEM102 POOM066 POM145 MBIM062 MBAM122 MBUM047 M188 M072 MBE M172 MBOOM174 MBO M187 MBUU M161 LONG MBEM105 LONG MBOO M142 LONG MBOM132 KPIM092 KPAM074 KPU M044 KPEEM108 KPE M112 KPOOM158 KPOM124 GBIM056 GBAM148 GBU M093 GBEEM107 GBE M071 GBOOM070 GBOM171 RAM123 NDIM129 NDAM125 NDU M191 NDEEM119 NDE M067 NDOOM064 NDOM152 NJAM192 NJU M149 NJEE M134 NJOOM182 VIM185 VAM151 VUM173 VEEM085 VEM144 VOOM077 VO M164 NYIN M058 NYAN M170 NYUN M098 NYEN M060 NYONTEENSMILLIONSDAALI SINNYIIYHEALIF GEMINATE LAKHAN LAKH MARKKARORKARORAN PLACEHOLDER RUPEE MARKMARRATANARABIC MATHEMATICAL INITIAL HEHARABIC MATHEMATICAL INITIAL HAHARABIC MATHEMATICAL INITIAL DAD!ARABIC MATHEMATICAL INITIAL GHAINARABIC MATHEMATICAL TAILED JEEMARABIC MATHEMATICAL TAILED HAHARABIC MATHEMATICAL TAILED YEHARABIC MATHEMATICAL TAILED LAM ARABIC MATHEMATICAL TAILED SHEENARABIC MATHEMATICAL TAILED KHAHARABIC MATHEMATICAL TAILED DAD ARABIC MATHEMATICAL TAILED GHAIN'ARABIC MATHEMATICAL TAILED DOTLESS NOON&ARABIC MATHEMATICAL TAILED DOTLESS QAF!ARABIC MATHEMATICAL STRETCHED HEH DOTLESS BEH)ARABIC MATHEMATICAL STRETCHED DOTLESS FEHMEEM WITH HAH WITH TATWEEL HAH WITH DALGREEN ORCHID CHRYSANTHEMUMSPRINGSUMMERAUTUMNWINTERJOKERHORIZONTAL BACK VERTICAL BACKJACK KNIGHT QUEEN KING RED JOKER BLACK JOKER WHITE JOKERZERO WITH SLASHANTICLOCKWISE ARROW#DOLLAR SIGN WITH OVERLAID BACKSLASH/TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER SCOPYLEFT SYMBOLC WITH OVERLAID BACKSLASH HUMAN FIGURE/CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P SQUARE DJUP WITH EXCLAMATION MARKTHREE D SECOND SCREENTWENTY-TWO POINT TWOONE HUNDRED TWENTY LATIN SMALL LETTER DHI-RESLOSSLESSMASK WORK SYMBOLSQUARE HIRAGANA HOKA KATAKANA DE ADVANTAGEACCEPTSHUANGXICYCLONEFOGGYCLOSED UMBRELLANIGHT WITH STARSSUNRISE OVER MOUNTAINSSUNRISECITYSCAPE AT DUSKSUNSET OVER BUILDINGSRAINBOWBRIDGE AT NIGHT WATER WAVEVOLCANO MILKY WAY EUROPE-AFRICAAMERICASASIA-AUSTRALIAWITH MERIDIANSWAXING CRESCENT FIRST QUARTER WAXING GIBBOUS WANING GIBBOUS LAST QUARTER WANING CRESCENT CRESCENT MOONGLOWING SHOOTING THERMOMETER BLACK DROPLET WITH SMALL CLOUD WITH TORNADOWIND BLOWING FACEHOT DOGBURRITOCHESTNUTSEEDLING EVERGREEN DECIDUOUS CACTUS HOT PEPPERTULIPCHERRY BLOSSOMHIBISCUS SUNFLOWERBLOSSOMMAIZEFOUR LEAF CLOVERMAPLE FALLEN LEAF FLUTTERING IN WINDMUSHROOMTOMATO AUBERGINEGRAPES WATERMELON TANGERINELEMONBANANA PINEAPPLEPEACHCHERRIES STRAWBERRY HAMBURGERSLICE OF PIZZA MEAT ON BONE POULTRY LEGCRACKERCOOKED CURRY AND STEAMING BOWL SPAGHETTIBREAD FRENCH FRIESROASTED SWEET POTATODANGOSUSHI FRIED SHRIMPFISH CAKE WITH SWIRL DESIGNSOFT ICE CREAM SHAVED ICE ICE CREAMDOUGHNUTCOOKIE CHOCOLATE BARCANDYLOLLIPOPCUSTARD HONEY POT SHORTCAKE BENTO BOX POT OF FOODCOOKINGFORK AND KNIFETEACUP WITHOUT HANDLESAKE BOTTLE AND CUPWINE COCKTAIL TROPICAL DRINKBEER MUGCLINKING BEER MUGS BABY BOTTLEFORK AND KNIFE WITH PLATEBOTTLE WITH POPPING CORKPOPCORNRIBBONWRAPPED PRESENT BIRTHDAY CAKEJACK-O-LANTERNCHRISTMAS TREEFATHER CHRISTMAS FIREWORKSFIREWORK SPARKLERBALLOON PARTY POPPER CONFETTI BALL TANABATA TREE CROSSED FLAGSPINE DECORATIONJAPANESE DOLLS CARP STREAMER WIND CHIMEMOON VIEWING CEREMONYSCHOOL SATCHELGRADUATION CAPHEART WITH TIP ON THE LEFTBOUQUET OF FLOWERSMILITARY MEDALREMINDER RIBBONMUSICAL KEYBOARD WITH JACKSSTUDIO MICROPHONE LEVEL SLIDER CONTROL KNOBS FILM FRAMESADMISSION TICKETSCAROUSEL HORSE FERRIS WHEELROLLER COASTERFISHING POLE AND FISH MICROPHONE MOVIE CAMERACINEMA HEADPHONEARTIST PALETTETOP HAT CIRCUS TENTTICKET CLAPPER BOARDPERFORMING ARTS VIDEO GAME DIRECT HIT SLOT MACHINE BILLIARDSGAME DIEBOWLINGFLOWER PLAYING CARDS MUSICAL NOTEMULTIPLE MUSICAL NOTES SAXOPHONEGUITARMUSICAL KEYBOARDTRUMPETVIOLIN MUSICAL SCORERUNNING SHIRT WITH SASHTENNIS RACQUET AND BALLSKI AND SKI BOOTBASKETBALL AND HOOPCHEQUERED FLAG SNOWBOARDERRUNNERSURFER SPORTS MEDALTROPHY HORSE RACING AMERICAN RUGBY SWIMMER WEIGHT LIFTERGOLFER MOTORCYCLECRICKET BAT AND BALL VOLLEYBALLFIELD HOCKEY STICK AND BALLICE HOCKEY STICK AND PUCKTABLE TENNIS PADDLE AND BALLSNOW CAPPED MOUNTAINCAMPINGBEACH WITH UMBRELLABUILDING CONSTRUCTIONHOUSE BUILDINGS CITYSCAPEDERELICT HOUSE CLASSICAL DESERT DESERT ISLAND NATIONAL PARKSTADIUMBUILDING WITH GARDENOFFICE BUILDING EUROPEAN HOSPITALAUTOMATED TELLER MACHINELOVE CONVENIENCE STOREDEPARTMENT STOREFACTORYIZAKAYA LANTERNLABEL!BADMINTON RACQUET AND SHUTTLECOCK BOW AND ARROWAMPHORAMOUSE WATER BUFFALOLEOPARDRABBIT CROCODILEWHALESNAILMONKEYROOSTERCHICKENELEPHANTOCTOPUS SPIRAL SHELLHONEYBEE LADY BEETLE TROPICAL BLOWFISH HATCHING FRONT-FACING PENGUINKOALAPOODLE DROMEDARY BACTRIAN DOLPHINMOUSE TIGER RABBIT DRAGON SPOUTING WHALEHORSE MONKEY FROG HAMSTER WOLF BEAR PANDA PIG NOSE PAW PRINTSCHIPMUNKFISTED CLAPPING CROWN WOMANS HAT EYEGLASSESNECKTIET-SHIRTJEANSDRESSKIMONOBIKINIWOMANS CLOTHESPURSEHANDBAGPOUCHMANS ATHLETIC HIGH-HEELED SANDALBOOTS FOOTPRINTSBUST BUSTS FAMILYMAN AND WOMAN WOMEN POLICE OFFICERWOMAN WITH BUNNY EARSBRIDE WITH VEILPERSON WITH BLOND HAIR GUA PI MAOCONSTRUCTION WORKERPRINCESSGOBLIN BABY ANGELEXTRATERRESTRIAL ALIEN ALIEN MONSTERSKULLINFORMATION DESK PERSON GUARDSMANDANCERLIPSTICK NAIL POLISH FACE MASSAGEHAIRCUT BARBER POLESYRINGE KISS MARK LOVE LETTER GEM STONEBOUQUETCOUPLE WITH HEARTWEDDINGBEATING BROKEN TWO HEARTS SPARKLING GROWING HEART WITH ARROWBLUE YELLOW PURPLE HEART WITH RIBBONREVOLVING HEARTSHEART DECORATIONDIAMOND SHAPE WITH A DOT INSIDEELECTRIC LIGHT BULB ANGER SYMBOL SLEEPING COLLISION SPLASHING SWEAT DROPLET DASH SYMBOL PILE OF POO FLEXED BICEPS DIZZY SYMBOLSPEECH THOUGHT WHITE FLOWERHUNDRED POINTS SYMBOL MONEY BAGCURRENCY EXCHANGEHEAVY DOLLAR SIGN CREDIT CARDMONEY WITH WINGS%CHART WITH UPWARDS TREND AND YEN SIGNPERSONAL COMPUTER BRIEFCASEMINIDISC FLOPPY DISK OPTICAL DISC WITH CURL FACING UP TEAR-OFF CARD INDEX BAR CHART CLIPBOARD PAPERCLIP BOOKMARK TABSLEDGERNOTEBOOKNOTEBOOK WITH DECORATIVE COVERORANGE BOOKS NAME BADGESCROLLTELEPHONE RECEIVERPAGER FAX MACHINESATELLITE ANTENNAPUBLIC ADDRESS LOUDSPEAKERCHEERING MEGAPHONEOUTBOX INBOX PACKAGE E-MAIL SYMBOLINCOMING ENVELOPE#ENVELOPE WITH DOWNWARDS ARROW ABOVE LOWERED FLAGPOSTBOX POSTAL HORN NEWSPAPERPHONE#PHONE WITH RIGHTWARDS ARROW AT LEFTVIBRATION MODEMOBILE PHONE OFFNO MOBILE PHONESANTENNA WITH BARSCAMERACAMERA WITH FLASH VIDEO CAMERA TELEVISIONRADIO VIDEOCASSETTEFILM PROJECTORPORTABLE STEREO PRAYER BEADSTWISTED RIGHTWARDS ARROWS WITH CIRCLED ONE OVERLAY SPEAKER WITH CANCELLATION STROKESPEAKERONE SOUND WAVETHREE SOUND WAVESBATTERY ELECTRIC PLUGLOCK WITH INK PENCLOSED LOCK WITH BELL WITH CANCELLATION STROKEBOOKMARK LINK SYMBOL RADIO BUTTONBACK )ON WITH EXCLAMATION MARK WITH LEFT RIGHT SOON WITH RIGHTWARDS TOP WITH UPWARDS NO ONE UNDER EIGHTEEN SYMBOL KEYCAP TENNUMBERS LATIN LETTERSELECTRIC TORCHWRENCHHAMMER NUT AND BOLTHOCHOPISTOL MICROSCOPE TELESCOPE CRYSTAL BALL SIX POINTED STAR WITH MIDDLE DOTJAPANESE SYMBOL FOR BEGINNERTRIDENT EMBLEMCIRCLED CROSS POMMEEPOMMEE WITH HALF-CIRCLE BELOWPOMMEESYMBOL FOR MARKS CHAPTERCELTIC OM SYMBOL DOVE OF PEACEKAABAMOSQUE SYNAGOGUEMENORAH WITH NINE BRANCHESBOWL OF HYGIEIASEVEN-EIGHT-NINE-ELEVEN-TWELVE-BULLHORNBULLHORN WITH SOUND WAVES RINGING BELLCANDLEMANTELPIECE CLOCKBLACK SKULL AND CROSSBONES NO PIRACYMAN IN BUSINESS SUIT LEVITATING SLEUTH OR SPYDARK SUNGLASSESSPIDER SPIDER WEBJOYSTICK MAN DANCINGLEFT HAND TELEPHONE RECEIVERTELEPHONE RECEIVER WITH PAGERIGHT HAND TELEPHONE RECEIVERTELEPHONE ON TOP OF MODEMCLAMSHELL MOBILE PHONEBACK OF STAMPED ENVELOPE WITH LIGHTNINGPEN OVER STAMPED LINKED PAPERCLIPS BLACK PUSHPINPENCIL BALLPOINT FOUNTAIN PAINTBRUSHCRAYON WRITING HANDTURNED OK HAND SIGN VICTORY HAND HAND WITH MIDDLE FINGER EXTENDED5RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERSDOWN POINTING LEFT HAND DESKTOP COMPUTERKEYBOARD AND MOUSETHREE NETWORKED COMPUTERSPRINTERPOCKET CALCULATORTAPE CARTRIDGEWIRED KEYBOARD TRACKBALLOLD PERSONAL COMPUTER HARD DISKPRINTER OPTICAL DISC TEXT AND PICTURETILESINDEX DIVIDERSCABINETDOCUMENTPAGES WASTEBASKET CALENDAR DESKTOP WINDOWMINIMIZEMAXIMIZEOVERLAP*CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWSCANCELLATION X INCREASE DECREASE COMPRESSIONOLD KEYROLLED-UP NEWSPAPERPAGE WITH CIRCLED TEXT STOCK CHART DAGGER KNIFESPEAKING HEAD IN SILHOUETTEBOX WITH BALLOT BOX WITH LIGHT CHECK MARKBALLOT BOX WITH BOLD CHECK WORLD MAP MOUNT FUJI TOKYO TOWERSTATUE OF LIBERTYSILHOUETTE OF JAPANMOYAI SMILING EYES TEARS OF JOY COLD SWEATTIGHTLY-CLOSED EYESHORNS WINKING FACESMILING FACE WITH SMILING EYESFACE SAVOURING DELICIOUS FOOD RELIEVED FACEHEART-SHAPED EYES SUNGLASSES SMIRKING EXPRESSIONLESS UNAMUSED FACE WITH COLD SWEATPENSIVE CONFUSED CONFOUNDED THROWING A KISS WINKING EYE DISAPPOINTED WORRIED ANGRY POUTING CRYING PERSEVERING FACE WITH LOOK OF TRIUMPHDISAPPOINTED BUT RELIEVED FACEFROWNING FACE WITH OPEN MOUTH ANGUISHED FEARFUL WEARY SLEEPY TIRED GRIMACING LOUDLY CRYING FACE WITH OPEN MOUTH HUSHED FACEWITH OPEN MOUTH AND COLD SWEATSCREAMING IN FEAR ASTONISHED FLUSHED DIZZY WITHOUT MOUTHWITH MEDICAL MASK#GRINNING CAT FACE WITH SMILING EYES OPEN MOUTH WRY SMILE!KISSING CAT FACE WITH CLOSED EYES UPSIDE-DOWN ROLLING EYESNO GOOD PERSON BOWING DEEPLYHEAR-SPEAK-HAPPY PERSON RAISING ONE HAND!RAISING BOTH HANDS IN CELEBRATIONFROWNING POUTING FACE FOLDED HANDSORNAMENT IN BLACK SQUARESWASH LOW DOUBLE ROCKET HELICOPTERSTEAM LOCOMOTIVE RAILWAY CARTRAINTRAIN WITH BULLET NOSEMETRO LIGHT RAILSTATIONTRAM CAR ONCOMING TROLLEYBUSBUS STOPMINIBUS AMBULANCE FIRE ENGINERECREATIONAL VEHICLEDELIVERY TRUCKARTICULATED LORRYTRACTORMONORAIL MOUNTAIN SUSPENSION MOUNTAIN CABLEWAYAERIAL TRAMWAYROWBOAT SPEEDBOATCONSTRUCTION SIGNPOLICE CARS REVOLVING LIGHTTRIANGULAR FLAG ON POST NO ENTRY SIGNPUT LITTER IN ITS PLACE DO NOT LITTER BICYCLE NO BICYCLESNO PEDESTRIANSCHILDREN CROSSINGMENS WOMENS RESTROOM BABY SYMBOLTOILET WATER CLOSETSHOWERBATHTUBPASSPORT CONTROLCUSTOMS BAGGAGE CLAIM LEFT LUGGAGETRIANGLE WITH ROUNDED CORNERSPROHIBITED SIGNCIRCLED INFORMATION SOURCEBOYS GIRLS COUCH AND LAMPSLEEPING ACCOMMODATION SHOPPING BAGS BELLHOP BELLPLACE OF WORSHIPOCTAGONAL SIGNSHOPPING TROLLEYSTUPAPAGODA HINDU TEMPLEELEVATOR LANDSLIDEWIRELESSPLAYGROUND SLIDEWHEEL RING BUOYHAMMER AND WRENCHOIL DRUMMOTORWAY RAILWAY TRACK MOTOR BOATMILITARY AIRPLANENORTHEAST-POINTING AIRPLANEARRIVING SATELLITEONCOMING FIRE ENGINEDIESEL LOCOMOTIVEPASSENGER SHIPMOTOR CANOE FLYING SAUCER SKATEBOARD AUTO RICKSHAW PICKUP TRUCK ROLLER SKATE QUINTESSENCE AQUAFORTISREGIAREGIA-2VITAEVITAE-2VINEGAR PHILOSOPHERS SUBLIMATECINNABARNITREVITRIOL VITRIOL-2SALT-2SILVERORE-2IRON- SUBLIMATE OF COPPER-2SALT OF SUBLIMATE OF SALT OF COPPER VERDIGRISLEAD ANTIMONY SUBLIMATE VINEGAR ANTIMONY-2REGULUSALKALIALKALI-2 MARCASITE SAL-AMMONIACARSENICREALGAR REALGAR-2 AURIPIGMENT BISMUTH ORETARTARTARTAR-2 QUICK LIMEBORAXTINCTUREPOWDERTUTTY CAPUT MORTUUMSCEPTER OF JOVESTARRED LODESTONEURINE HORSE DUNG POWDERED AMALGAMSTRATUM STRATUM-2 SUBLIMATION PRECIPITATEDISTILLDISSOLVE DISSOLVE-2PURIFY PUTREFACTIONCRUCIBLEVAPOURSRETORTMONTHOUNCELOT OF FORTUNE OCCULTATION LUNAR ECLIPSEVESTA ASTRAEA HYGIEA PARTHENOPE HAUMEAMAKEMAKEGONGGONGQUAOARORCUSSLIGHTLY SMALL EXTREMELY $WHITE CIRCLE CONTAINING BLACK SMALL ROUND TARGET VERY SMALL TARGETWHITE LOZENGE CONTAINING BLACK MEDIUM THREE POINTED PINWHEEL SIX POINTED PINWHEEL HEAVY EIGHT POINTED PINWHEEL LIGHT TWELVE POINTED NINE POINTED WHITE STARBROWN HEAVY EQUALS SIGN WEST LIGHT WEST MEDIUM WEST VERY HEAVY BARB ARROWLEFTWARDS BOTTOM-RIGHTWARDS BOTTOM LEFTWARDS LEFT-RIGHTWARDS LEFT-UPWARDS THEN NORTH THEN CURVING SOUTH ARROW WITH LOWER HOOKDOWNWARDS BLACK ARROW TO BARWEST ARROW FROM BARARROW OVER LONG LEFTWARDS ARROW OVER LONG $SHORT RIGHTWARDS HARPOON ABOVE LONG #LONG LEFTWARDS HARPOON ABOVE SHORT #SHORT LEFTWARDS HARPOON ABOVE LONG WITH DOUBLE SLASH$LEFT RIGHT ARROW WITH DEPENDENT LOBEFORMEEPINCHED FINGERS PINCHING HANDZIPPER-MONEY-FACE WITH THERMOMETERNERD THINKING FACE WITH HEAD-BANDAGEHUGGING SIGN OF THE HORNSCALL ME RAISED BACK OF HANDSHAKE*HAND WITH INDEX AND MIDDLE FINGERS CROSSEDI LOVE YOU HAND SIGNFACE WITH COWBOY HATCLOWN NAUSEATED ROLLING ON THE FLOOR LAUGHING DROOLING LYING FACE PALM SNEEZING FACEONE EYEBROW RAISED STAR EYESONE LARGE AND ONE SMALL EYEFINGER COVERING CLOSED LIPSSERIOUS FACE WITH SYMBOLS (SMILING FACE WITH SMILING EYES AND HAND FACE WITH OPEN MOUTH VOMITING SHOCKED FACE WITH EXPLODING HEADPREGNANT WOMANBREAST-FEEDINGPALMS UP TOGETHERSELFIEPRINCE MAN IN TUXEDOMOTHER CHRISTMASSHRUGPERSON DOING CARTWHEELJUGGLINGFENCERMODERN PENTATHLON WRESTLERS WATER POLOHANDBALL DIVING MASK WILTED FLOWERDRUM WITH DRUMSTICKSCLINKING GLASSES TUMBLER GLASSGOAL NETRIFLE BOXING GLOVEMARTIAL ARTS UNIFORM CURLING STONELACROSSE STICK AND BALLSOFTBALL FLYING DISC CROISSANTAVOCADOCUCUMBERBACONPOTATOCARROTBAGUETTE BREAD GREEN SALADSHALLOW PAN OF FOODSTUFFED FLATBREAD GLASS OF MILKPEANUTS KIWIFRUITPANCAKESDUMPLINGFORTUNE COOKIE TAKEOUT BOX CHOPSTICKSBOWL WITH SPOONCUP WITH STRAWCOCONUTBROCCOLIPRETZEL CUT OF MEATSANDWICH CANNED FOOD LEAFY GREENMANGO MOON CAKEBAGEL/SMILING FACE WITH SMILING EYES AND THREE HEARTS YAWNING FACESMILING FACE WITH TEARPARTY HORN AND PARTY HATUNEVEN EYES AND WAVY MOUTH OVERHEATED FREEZING NINJADISGUISED FACEHOLDING BACK TEARSWITH PLEADING EYESLAB COATGOGGLES HIKING BOOT FLAT SHOE LION FACESCORPIONTURKEY UNICORN FACESHARKFOX FACE BUTTERFLYGORILLALIZARD RHINOCEROSSHRIMPSQUIDGIRAFFE ZEBRA HEDGEHOGSAUROPODT-REXCRICKETKANGAROOLLAMAPEACOCK HIPPOPOTAMUSPARROTRACCOONLOBSTERMOSQUITOMICROBEMAMMOTHSLOTHOTTER ORANGUTANSKUNKFLAMINGOOYSTERBEAVERBISON GUIDE DOG PROBING CANE WHITE HAIR SUPERHERO SUPERVILLAIN SAFETY VESTEAR WITH HEARING AID MOTORIZED MANUAL CHEESE WEDGECUPCAKE SALT SHAKER BEVERAGE BOXGARLICONIONFALAFELWAFFLEBUTTER MATE DRINKICE CUBE BUBBLE TEATROLL STANDING KNEELING DEAF FACE WITH MONOCLEADULT OLDER ADULTBEARDED PERSONWITH HEADSCARFIN STEAMY ROOMCLIMBINGIN LOTUS POSITIONFAIRYVAMPIRE MERPERSONGENIEZOMBIEBRAIN ORANGE HEART BILLED CAPSCARFGLOVESSOCKSRED GIFT ENVELOPE FIRECRACKERJIGSAW PUZZLE PIECE TEST TUBE PETRI DISHDNA DOUBLE HELIXCOMPASSABACUSFIRE EXTINGUISHERTOOLBOXBRICKMAGNETLUGGAGE LOTION BOTTLESPOOL OF THREAD BALL OF YARN SAFETY PIN TEDDY BEARBROOMBASKET ROLL OF PAPER BAR OF SOAPSPONGERECEIPT NAZAR AMULETROOK BISHOP PAWN ALFILGENERALMANDARINCHARIOTCANNONSOLDIER BALLET SHOESONE-PIECE SWIMSUITBRIEFSSHORTS THONG SANDAL LIGHT BLUE GREY PINK DROP OF BLOODADHESIVE BANDAGE STETHOSCOPEX-RAYCRUTCHYO-YO PARACHUTE MAGIC WANDPINATA NESTING DOLLSMARACASTROMBONETREASURE CHESTSHOVEL RINGED PLANETRAZOR DIYA LAMPBANJOMILITARY HELMET ACCORDION LONG DRUM CARPENTRY SAW SCREWDRIVERLADDERMIRRORWINDOWPLUNGER SEWING NEEDLEBUCKET MOUSE TRAP TOOTHBRUSH HEADSTONEPLACARD MIRROR BALLIDENTIFICATION CARD LOW BATTERYHAMSAFOLDING HAND FAN HAIR PICKKHANDABEETLE COCKROACH POTTED PLANTCORAL EMPTY NESTNEST WITH EGGSHYACINTH JELLYFISH LEAFLESS TREEGOOSEANATOMICAL HEARTLUNGSPEOPLE HUGGINGPERSON WITH CROWN FINGERPRINTHAIRY CREATUREMOOSEDONKEY BLUEBERRIES BELL PEPPEROLIVE FLATBREADTAMALEFONDUETEAPOTPOURING LIQUIDBEANS GINGER ROOTPEA PODROOT VEGETABLESPLATTERMELTING SALUTING OPEN EYES AND HAND OVER MOUTH PEEKING EYEDIAGONAL MOUTHDOTTED LINE FACE BITING LIPBUBBLES SHAKING FACEFACE WITH BAGS UNDER EYESDISTORTED FACE FIGHT CLOUD(HAND WITH INDEX FINGER AND THUMB CROSSEDINDEX POINTING AT THE VIEWER HEART HANDSMIDDLE LEFT TO UPPER LEFT TO UPPER MIDDLE LEFT TO LOWER MIDDLE AND RIGHT AND LOWER LEFT AND LOWER AND RIGHT UPPER AND LEFT AND LOWER AND UPPER AND RIGHT LOWER ONE EIGHTH BLOCK UPPER AND HORIZONTAL ONE EIGHTH BLOCK-1358BLOCK AND LOWER HALF )INVERSE MEDIUM SHADE AND LOWER HALF BLOCK3LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCKHEAVY HORIZONTAL LEFT TRIANGULAR MEDIUM SHADELEFT AND MIDDLE RIGHT AND MIDDLE LEFT UPPER CENTRE TO MIDDLE RIGHT %RIGHT TO UPPER CENTRE TO MIDDLE LEFT HORIZONTAL WITH VERTICAL STROKEARROWHEAD-SHAPED POINTERINVERSE CHECK MARK*INVERSE DOWNWARDS ARROW WITH TIP LEFTWARDSVOIDED GREEK CROSSRIGHT OPEN SQUARED DOTMIDDLE RIGHT TO LOWER CENTRE(WHITE HEAVY SALTIRE WITH ROUNDED CORNERSNEGATIVE SQUARED QUESTION MARKFIGUREWITH ARMS RAISED WITH DRESSUP-POINTING CHEVRON RAISED SMALL LEFT SQUARE BRACKETBLACK SMALL UP-POINTING CHEVRONMIDDLE RIGHT TO LOWER MIDDLE LEFT TO LOWER LEFT TO LOWER CENTRECENTRE TO LOWER RIGHTRIGHT TO LOWER CENTRECENTRE TO LOWER LEFTLEFT TO MIDDLE CENTRE TO UPPER MIDDLE CENTRE TO LOWER LEFTLOWER CENTRE TO UPPER RIGHT TO MIDDLE LEFT LOWER LEFT TO UPPER CENTRE (UPPER LEFT TO MIDDLE RIGHT TO LOWER LEFTTOP JUSTIFIED LOWER RIGHT JUSTIFIED LEFT BOTTOM JUSTIFIED UPPER LEFT JUSTIFIED RIGHT TOP RIGHT JUSTIFIED LOWER LEFT LEFT JUSTIFIED UPPER RIGHT RIGHT JUSTIFIED UPPER LEFT TOP LEFT JUSTIFIED LOWER RIGHT ALARM BELL SYMBOL"!"C, Last> D, First>!"!"!"!2F8002F8012F8022F8032F8042F8052F8062F8072F8082F8092F80A2F80B2F80C2F80D2F80E2F80F2F8102F8112F8122F8132F8142F8152F8162F8172F8182F8192F81A2F81B2F81C2F81D2F81E2F81F2F8202F8212F8222F8232F8242F8252F8262F8272F8282F8292F82A2F82B2F82C2F82D2F82E2F82F2F8302F8312F8322F8332F8342F8352F8362F8372F8382F8392F83A2F83B2F83C2F83D2F83E2F83F2F8402F8412F8422F8432F8442F8452F8462F8472F8482F8492F84A2F84B2F84C2F84D2F84E2F84F2F8502F8512F8522F8532F8542F8552F8562F8572F8582F8592F85A2F85B2F85C2F85D2F85E2F85F2F8602F8612F8622F8632F8642F8652F8662F8672F8682F8692F86A2F86B2F86C2F86D2F86E2F86F2F8702F8712F8722F8732F8742F8752F8762F8772F8782F8792F87A2F87B2F87C2F87D2F87E2F87F2F8802F8812F8822F8832F8842F8852F8862F8872F8882F8892F88A2F88B2F88C2F88D2F88E2F88F2F8902F8912F8922F8932F8942F8952F8962F8972F8982F8992F89A2F89B2F89C2F89D2F89E2F89F2F8A02F8A12F8A22F8A32F8A42F8A52F8A62F8A72F8A82F8A92F8AA2F8AB2F8AC2F8AD2F8AE2F8AF2F8B02F8B12F8B22F8B32F8B42F8B52F8B62F8B72F8B82F8B92F8BA2F8BB2F8BC2F8BD2F8BE2F8BF2F8C02F8C12F8C22F8C32F8C42F8C52F8C62F8C72F8C82F8C92F8CA2F8CB2F8CC2F8CD2F8CE2F8CF2F8D02F8D12F8D22F8D32F8D42F8D52F8D62F8D72F8D82F8D92F8DA2F8DB2F8DC2F8DD2F8DE2F8DF2F8E02F8E12F8E22F8E32F8E42F8E52F8E62F8E72F8E82F8E92F8EA2F8EB2F8EC2F8ED2F8EE2F8EF2F8F02F8F12F8F22F8F32F8F42F8F52F8F62F8F72F8F82F8F92F8FA2F8FB2F8FC2F8FD2F8FE2F8FF2F9002F9012F9022F9032F9042F9052F9062F9072F9082F9092F90A2F90B2F90C2F90D2F90E2F90F2F9102F9112F9122F9132F9142F9152F9162F9172F9182F9192F91A2F91B2F91C2F91D2F91E2F91F2F9202F9212F9222F9232F9242F9252F9262F9272F9282F9292F92A2F92B2F92C2F92D2F92E2F92F2F9302F9312F9322F9332F9342F9352F9362F9372F9382F9392F93A2F93B2F93C2F93D2F93E2F93F2F9402F9412F9422F9432F9442F9452F9462F9472F9482F9492F94A2F94B2F94C2F94D2F94E2F94F2F9502F9512F9522F9532F9542F9552F9562F9572F9582F9592F95A2F95B2F95C2F95D2F95E2F95F2F9602F9612F9622F9632F9642F9652F9662F9672F9682F9692F96A2F96B2F96C2F96D2F96E2F96F2F9702F9712F9722F9732F9742F9752F9762F9772F9782F9792F97A2F97B2F97C2F97D2F97E2F97F2F9802F9812F9822F9832F9842F9852F9862F9872F9882F9892F98A2F98B2F98C2F98D2F98E2F98F2F9902F9912F9922F9932F9942F9952F9962F9972F9982F9992F99A2F99B2F99C2F99D2F99E2F99F2F9A02F9A12F9A22F9A32F9A42F9A52F9A62F9A72F9A82F9A92F9AA2F9AB2F9AC2F9AD2F9AE2F9AF2F9B02F9B12F9B22F9B32F9B42F9B52F9B62F9B72F9B82F9B92F9BA2F9BB2F9BC2F9BD2F9BE2F9BF2F9C02F9C12F9C22F9C32F9C42F9C52F9C62F9C72F9C82F9C92F9CA2F9CB2F9CC2F9CD2F9CE2F9CF2F9D02F9D12F9D22F9D32F9D42F9D52F9D62F9D72F9D82F9D92F9DA2F9DB2F9DC2F9DD2F9DE2F9DF2F9E02F9E12F9E22F9E32F9E42F9E52F9E62F9E72F9E82F9E92F9EA2F9EB2F9EC2F9ED2F9EE2F9EF2F9F02F9F12F9F22F9F32F9F42F9F52F9F62F9F72F9F82F9F92F9FA2F9FB2F9FC2F9FD2F9FE2F9FF2FA002FA012FA022FA032FA042FA052FA062FA072FA082FA092FA0A2FA0B2FA0C2FA0D2FA0E2FA0F2FA102FA112FA122FA132FA142FA152FA162FA172FA182FA192FA1A2FA1B2FA1C2FA1D"!"H, Last> J, First>! LANGUAGE TAG CANCEL TAGBENT USED IZHITSA TILTED SINGLE-THORN KORANIC NIZKO ABKHASIAN EVEN SVASTI BREVE HORN NORMAL DROP-SHADED SHADOWED WEDGE-TICK YERU STOP FISH SEMICIRCLE EQUIHOPPER LUNATE SHHA POWERS CENTRALIZATION CEDILLA MIDDLE-OXIA PERISPOMENI ASYMPTOTICALLY ACTUALLY ALMOST FACTOR CHECKER RECYCLED HANDED RECTILINEAR LIGHTED SHAPED GAPPED CONSECUTIVE DIALECT-PRIME CUATRILLO SALAATU LINED ROLLER KRYZHEM KHOKHLOM HEIGHT FONT POTABLE SALT ISOSCELES FINGER-WITHIN FORTY-THIRTY-SOLIDUS PAMPHYLIAN SIGMA SEMISOFT BASHKIR KHAKASSIAN KOMI ALEUT ETERNITY EPENTHETIC NUKTA LENGTH AEDA-SHAD TSHEG MCHAN FEATHER HAGALL NAUD BJARKAN MADR GAAHLAA WELSH SYMMETRIC PAIRED SQUIGGLE EQUIVALENT IDENTICAL SEMIDIRECT SHOE CARET UNDERLINE SCREEN BOARD DASH SHOGI PAPER LANE INTERLACED PROPELLER OUTER ARROW-BINDING WIGGLY AROUND INTERIOR EQUILATERAL CRYPTOGRAMMIC AKHMIMIC BOHAIRIC SUBSTITUTION TRANSPOSITION OMISSION FORKED PARAPHRASE LENTICULAR SOUND MONOGRAPH BROAD BLENDED MONOCULAR BINOCULAR EGYPTOLOGICAL SQUIRREL VISIGOTHIC VOLAPUK POLISH ANGLICANA SCOTS SIGMOID CROSSED-SESAME REPLACEMENT OBOLS SEXTULA LIKE CULTIVATION WALLED LOST RULER RESISTOR CROSSHATCH ROCKET ATOMIC ENERGY COASTER PROTOS DEYTEROS TELOUS STRING POST BABY BACKHAND HANDS HOLDING BRIGHTNESS MAGNIFYING TOUCHTONE FLOPPY BUTTON SIZE ANGER EVIL VINE AMPERSAND POLICE TRAFFIC SMOKING COPPER NARROW COMPRESSED COVERING PLACE PUSHING EIGHTHS RUNNING CLICK PERCUSSIVEPRIME ARROWHEADSHELFSAMPIDIGAMMASYMBOLTONOS DIALYTIKAKOPPAGANGIASHIMAPNEUMATAUPTURN DESCENDERDZZHETSADIMAKSURAALAPHSEMKATHDANDABINDIKAYANNAGAYANNACAYANNAJAYANNATTAYANNADDAYANNATAYANNADAYANNAPAYANNABAYANNASAYANNAPILLAKOMBUVARTAGSTSHESRGYINGSKHYILRGYANSECTIONRIKRIKHIDETSHWIISHWOOSHWAA PUNCTUATIONUBADAMABALUDAJEGOGANLANTANGTTUDDAAGMUCAADSATANGA ARDHAVISARGAJOINERDAGGERLEADER EMBEDDINGOVERRIDEQUILLISOLATESWAPPINGSHAPINGSHAPESFIFTHSEIGHTHSARROWSHARPOONMEMBEROPERATORINTEGRAL TURNSTILERELATIONCEILINGFLOOR PARALLELOGRAMPOINTER TELEPHONEPIECENOTESPLASTICSTRAFFICMERGE PENTAGRAMSCISSORSFLORETTE SNOWFLAKESPARKLE DELIMITERFENCESERIFSANTIRESTRICTIONSIGNSINSIDE APPROXIMATECURVEPENTAGONHEXAGONELLIPSESQUARESCENTREDOCTAGON ARROWHEADSDALDATHETHEIAUDALAULA PARAGRAPHOSANCORAGUARDLEATHERZEMLYASHANGTRESILLO CUATRILLOFLOURISHROTUNDASALTILLO FRICATIVELAMBDA RERENGGANPISELEHLONSUMTAAALAASALAAM CHARACTERSUBUNITTALENTSSTATERSDRACHMASTWELFTHS ENCLOSURESFLAMEFINALKISIM5LUGALGESH2GESHUSHARUESHE3STARTLEERAEWABEATSSECANTINDUCTORDIODE TRANSISTOR CAPACITORBASSINETBEAMS TENTACLESROBOTMARKSBOOSTERSAUCER MICROCOMPUTERKRYZHEM ZADERZHKA ARGOSYNTHETONCHRONON ICHIMATOS TRITIMORIONDODEKATABARLINESTAFF FRETBOARDNOTEHEADPHRASEFLEXUSCHEST ROTATIONS THOUSANDSMODIFIER CHARACTERSBAMBOOSCIRCLESSPADESHEARTSDIAMONDSCLUBSAPPLEGLASSFOOTBALLOFFICEHOTELPENNANTCHICKCAMEL SILHOUETTEHANDSFOLDERCALENDARTRENDPUSHPINRULERLETTERSBUTTONOCLOCKGESTUREBOARD AUTOMOBILERAILWAY BICYCLISTSCOOTERSULFURCOPPER ANTIMONIATEANTIMONYTRIDENTASHESSHAFTMEDAL WHEELCHAIRDEGREES EQUIHOPPERcontrol abbreviationSTART OF HEADING START OF TEXT END OF TEXTEND OF TRANSMISSIONALERTCHARACTER TABULATIONNEW LINE END OF LINELINE TABULATION SHIFT OUTLOCKING-SHIFT ONESHIFT INLOCKING-SHIFT ZERODEVICE CONTROL ONEDEVICE CONTROL TWODEVICE CONTROL THREEDEVICE CONTROL FOURINFORMATION SEPARATOR FOURFILE SEPARATORINFORMATION SEPARATOR THREEGROUP SEPARATORINFORMATION SEPARATOR TWORECORD SEPARATORINFORMATION SEPARATOR ONEUNIT SEPARATORPADDING CHARACTERfigmentHIGH OCTET PRESETBREAK PERMITTED HERE NO BREAK HERE NEXT LINESTART OF SELECTED AREAEND OF SELECTED AREACHARACTER TABULATION SETHORIZONTAL TABULATION SET'CHARACTER TABULATION WITH JUSTIFICATION(HORIZONTAL TABULATION WITH JUSTIFICATIONLINE TABULATION SETVERTICAL TABULATION SETPARTIAL LINE FORWARDPARTIAL LINE DOWNPARTIAL LINE BACKWARDPARTIAL LINE UPREVERSE LINE FEED REVERSE INDEXSINGLE SHIFT TWOSINGLE-SHIFT-2SINGLE SHIFT THREESINGLE-SHIFT-3DEVICE CONTROL STRINGPRIVATE USE ONE PRIVATE USE-1PRIVATE USE TWO PRIVATE USE-2SET TRANSMIT STATECANCEL CHARACTERMESSAGE WAITINGSTART OF GUARDED AREASTART OF PROTECTED AREAEND OF GUARDED AREAEND OF PROTECTED AREASTART OF STRING#SINGLE GRAPHIC CHARACTER INTRODUCERSINGLE CHARACTER INTRODUCERCONTROL SEQUENCE INTRODUCERSTRING TERMINATOROPERATING SYSTEM COMMANDPRIVACY MESSAGEAPPLICATION PROGRAM COMMANDLATIN CAPITAL LETTER GHA correctionLATIN SMALL LETTER GHA/ARABIC SMALL HIGH LIGATURE ALEF WITH YEH BARREE"SYRIAC SUBLINEAR COLON SKEWED LEFTKANNADA LETTER LLLALAO LETTER FO FONLAO LETTER FO FAY LAO LETTER RO LAO LETTER LO#TIBETAN MARK BKA- SHOG GI MGO RGYAN HANGUL JONGSEONG YESIEUNG-KIYEOK%HANGUL JONGSEONG YESIEUNG-SSANGKIYEOKHANGUL JONGSEONG SSANGYESIEUNG!HANGUL JONGSEONG YESIEUNG-KHIEUKHSUNDANESE LETTER ARCHAIC INNBSPWEIERSTRASS ELLIPTIC FUNCTIONMICR ON US SYMBOLMICR DASH SYMBOL;LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE VERTICAL STROKE?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_            ! " & 0 2 3 9 : < > D  !!!!"!&!.![!\!]!^!!!!!!!""""""""""")"+"H"`"a"d"e### #!%%% %%%%%$%,%4%<%P%Q%R%S%T%U%V%W%X%Y%Z%[%\%]%^%_%`%a%b%c%d%e%f%g%h%i%j%k%l%%%%%%%%%%%%%%%%%%%%%%%&:&;&<&@&B&`&c&e&f&j&kbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/000077500000000000000000000000001506470510200263715ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/FontMapController.java000066400000000000000000000065401506470510200326510ustar00rootroot00000000000000package com.kreative.unicode.fontmap; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import javax.swing.JFrame; public class FontMapController { private static FontMapController instance; public static FontMapController getInstance() { if (instance == null) { instance = new FontMapController(); } return instance; } private List entries; private FontMapFrame frame; private FontMapController() { this.entries = new ArrayList(); this.frame = null; try { File file = getPreferencesFile(); if (file.exists()) { Scanner in = new Scanner(new FileInputStream(file), "UTF-8"); while (in.hasNextLine()) { String[] fields = in.nextLine().split("=", 2); if (fields.length == 2) { FontMapEntry e = new FontMapEntry(); e.setCodePointsString(fields[0].trim()); e.setFontString(fields[1].trim()); entries.add(e); } } in.close(); } } catch (IOException ioe) { ioe.printStackTrace(); } } public List getEntries() { return this.entries; } public void setEntries(List entries) { this.entries.clear(); this.entries.addAll(entries); if (entries.isEmpty()) { getPreferencesFile().delete(); } else try { FileOutputStream fos = new FileOutputStream(getPreferencesFile()); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); PrintWriter out = new PrintWriter(osw, true); for (FontMapEntry e : entries) { out.println(e.getCodePointsString() + " = " + e.getFontString()); } out.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } public FontMapEntry entryForString(String s) { for (FontMapEntry e : entries) { if (e.containsAllCodePoints(s)) { return e; } } return null; } public FontMapEntry entryForCodePoint(int cp) { for (FontMapEntry e : entries) { if (e.codePoints().get(cp)) { return e; } } return null; } public FontMapFrame getFrame() { if (frame == null) { frame = new FontMapFrame(entries); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { setEntries(frame.getFontMap()); frame.dispose(); frame = null; } }); } return frame; } private static File getPreferencesFile() { if (System.getProperty("os.name").toUpperCase().contains("MAC OS")) { File u = new File(System.getProperty("user.home")); File l = new File(u, "Library"); if (!l.exists()) l.mkdir(); File p = new File(l, "Preferences"); if (!p.exists()) p.mkdir(); return new File(p, "com.kreative.mapedit.fontmap.txt"); } else if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) { File u = new File(System.getProperty("user.home")); File a = new File(u, "Application Data"); if (!a.exists()) a.mkdir(); File k = new File(a, "Kreative"); if (!k.exists()) k.mkdir(); return new File(k, "MapEdit.FontMap.txt"); } else { File u = new File(System.getProperty("user.home")); return new File(u, ".mapedit.fontmap.txt"); } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/FontMapEntry.java000066400000000000000000000056401506470510200316270ustar00rootroot00000000000000package com.kreative.unicode.fontmap; import java.awt.Font; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import javax.swing.JLabel; public class FontMapEntry { private BitSet codePoints; private Font font; public FontMapEntry() { this.codePoints = new BitSet(); this.font = new JLabel().getFont(); } public BitSet codePoints() { return this.codePoints; } public String getCodePointsString() { int[] lastRange = null; List ranges = new ArrayList(); for (int i = 0; (i = codePoints.nextSetBit(i)) >= 0; i++) { if (lastRange != null && lastRange[1] == (i - 1)) lastRange[1]++; else ranges.add(lastRange = new int[]{i, i}); } boolean first = true; StringBuffer sb = new StringBuffer(); for (int[] range : ranges) { if (first) first = false; else sb.append(", "); sb.append(toHexString(range[0])); if (range[0] != range[1]) { sb.append("-"); sb.append(toHexString(range[1])); } } return sb.toString(); } public void setCodePointsString(String s) { codePoints.clear(); for (String r : s.split(",")) { if (r.contains("-")) { String[] p = r.split("-", 2); try { int i = parseHexInt(p[0]); int j = parseHexInt(p[1]); codePoints.set(i, j + 1); } catch (NumberFormatException nfe) { // ignored } } else { try { int i = parseHexInt(r); codePoints.set(i); } catch (NumberFormatException nfe) { // ignored } } } } public Font getFont() { return this.font; } public void setFont(Font font) { this.font = font; } public String getFontString() { return font.getFamily(); } public void setFontString(String name) { font = new Font(name, font.getStyle(), font.getSize()); } public boolean containsAllCodePoints(String s) { int i = 0, n = s.length(); while (i < n) { int cp = s.codePointAt(i); if (!codePoints.get(cp)) return false; i += Character.charCount(cp); } return true; } public boolean containsAnyCodePoints(String s) { int i = 0, n = s.length(); while (i < n) { int cp = s.codePointAt(i); if (codePoints.get(cp)) return true; i += Character.charCount(cp); } return false; } @Override public boolean equals(Object o) { if (o instanceof FontMapEntry) { FontMapEntry that = (FontMapEntry)o; return this.codePoints.equals(that.codePoints) && this.font.equals(that.font); } return false; } @Override public int hashCode() { return codePoints.hashCode() ^ font.hashCode(); } @Override public String toString() { return getCodePointsString() + " -> " + getFontString(); } private int parseHexInt(String s) { s = s.trim(); if (s.startsWith("U+") || s.startsWith("u+")) { s = s.substring(2).trim(); } return Integer.parseInt(s, 16); } private String toHexString(int i) { String h = Integer.toHexString(i).toUpperCase(); while (h.length() < 4) h = "0" + h; return h; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/FontMapFrame.java000066400000000000000000000016241506470510200315560ustar00rootroot00000000000000package com.kreative.unicode.fontmap; import java.awt.BorderLayout; import java.util.Collection; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; public class FontMapFrame extends JFrame { private static final long serialVersionUID = 1L; private final FontMapPanel panel; public FontMapFrame() { this(new FontMapPanel()); } public FontMapFrame(Collection c) { this(new FontMapPanel(c)); } private FontMapFrame(FontMapPanel panel) { super("Font Map"); this.panel = panel; JPanel outerPanel = new JPanel(new BorderLayout(8, 8)); outerPanel.add(panel, BorderLayout.CENTER); outerPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); setContentPane(outerPanel); pack(); setResizable(false); setLocationRelativeTo(null); } public FontMapTableModel getFontMap() { return panel.getFontMap(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/FontMapPanel.java000066400000000000000000000066101506470510200315630ustar00rootroot00000000000000package com.kreative.unicode.fontmap; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; public class FontMapPanel extends JPanel { private static final long serialVersionUID = 1L; private final FontMapTableModel model; private final JTable table; private final JButton addButton; private final JButton removeButton; private final JButton upButton; private final JButton downButton; public FontMapPanel() { this(new FontMapTableModel()); } public FontMapPanel(Collection c) { this(new FontMapTableModel(c)); } private FontMapPanel(FontMapTableModel model) { this.model = model; this.table = new JTable(model); squareOff(this.addButton = new JButton("+")); squareOff(this.removeButton = new JButton("\u2212")); squareOff(this.upButton = new JButton("\u2191")); squareOff(this.downButton = new JButton("\u2193")); JPanel botPanel = new JPanel(new FlowLayout()); botPanel.add(addButton); botPanel.add(removeButton); botPanel.add(upButton); botPanel.add(downButton); JScrollPane pane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ); JPanel mainPanel = new JPanel(new BorderLayout(8, 8)); mainPanel.add(botPanel, BorderLayout.PAGE_END); mainPanel.add(pane, BorderLayout.CENTER); mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); setLayout(new GridLayout(1, 1, 0, 0)); add(mainPanel); addActionListeners(); } private void addActionListeners() { addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = table.getSelectedRow(); index = (index < 0) ? model.size() : (index + 1); model.add(index, new FontMapEntry()); table.getSelectionModel().setSelectionInterval(index, index); } }); removeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = table.getSelectedRow(); if (index < 0) return; model.remove(index); table.clearSelection(); } }); upButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = table.getSelectedRow(); if (index <= 0) return; FontMapEntry removed = model.remove(index); index--; model.add(index, removed); table.getSelectionModel().setSelectionInterval(index, index); } }); downButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = table.getSelectedRow(); if (index < 0 || index >= (model.size() - 1)) return; FontMapEntry removed = model.remove(index); index++; model.add(index, removed); table.getSelectionModel().setSelectionInterval(index, index); } }); } public FontMapTableModel getFontMap() { return model; } private static void squareOff(JComponent c) { int h = c.getPreferredSize().height + 8; c.setMinimumSize(new Dimension(h, h)); c.setPreferredSize(new Dimension(h, h)); c.setMaximumSize(new Dimension(h, h)); c.putClientProperty("JButton.buttonType", "bevel"); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/fontmap/FontMapTableModel.java000066400000000000000000000104501506470510200325310ustar00rootroot00000000000000package com.kreative.unicode.fontmap; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import javax.swing.table.AbstractTableModel; public class FontMapTableModel extends AbstractTableModel implements List { private static final long serialVersionUID = 1L; private final List entries; public FontMapTableModel() { entries = new ArrayList(); } public FontMapTableModel(Collection c) { entries = new ArrayList(); entries.addAll(c); } @Override public Class getColumnClass(int col) { return String.class; } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Code Point Range"; case 1: return "Font Name"; default: return null; } } @Override public int getRowCount() { return entries.size(); } @Override public Object getValueAt(int row, int col) { switch (col) { case 0: return entries.get(row).getCodePointsString(); case 1: return entries.get(row).getFontString(); default: return null; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public void setValueAt(Object val, int row, int col) { switch (col) { case 0: entries.get(row).setCodePointsString(val.toString()); break; case 1: entries.get(row).setFontString(val.toString()); break; } } @Override public boolean add(FontMapEntry e) { int len = entries.size(); if (entries.add(e)) { fireTableRowsInserted(len, len); return true; } return false; } @Override public void add(int i, FontMapEntry e) { entries.add(i, e); fireTableRowsInserted(i, i); } @Override public boolean addAll(Collection c) { int len = entries.size(); if (entries.addAll(c)) { fireTableRowsInserted(len, len + c.size() - 1); return true; } return false; } @Override public boolean addAll(int i, Collection c) { if (entries.addAll(i, c)) { fireTableRowsInserted(i, i + c.size() - 1); return true; } return false; } @Override public void clear() { if (entries.isEmpty()) return; int len = entries.size(); entries.clear(); fireTableRowsDeleted(0, len - 1); } @Override public boolean contains(Object e) { return entries.contains(e); } @Override public boolean containsAll(Collection c) { return entries.containsAll(c); } @Override public FontMapEntry get(int i) { return entries.get(i); } @Override public int indexOf(Object e) { return entries.indexOf(e); } @Override public boolean isEmpty() { return entries.isEmpty(); } @Override public Iterator iterator() { return Collections.unmodifiableList(entries).iterator(); } @Override public int lastIndexOf(Object e) { return entries.lastIndexOf(e); } @Override public ListIterator listIterator() { return Collections.unmodifiableList(entries).listIterator(); } @Override public ListIterator listIterator(int i) { return Collections.unmodifiableList(entries).listIterator(i); } @Override public boolean remove(Object e) { int i = entries.indexOf(e); if (entries.remove(e)) { fireTableRowsDeleted(i, i); return true; } return false; } @Override public FontMapEntry remove(int i) { FontMapEntry e = entries.remove(i); fireTableRowsDeleted(i, i); return e; } @Override public boolean removeAll(Collection c) { if (entries.removeAll(c)) { fireTableDataChanged(); return true; } return false; } @Override public boolean retainAll(Collection c) { if (entries.retainAll(c)) { fireTableDataChanged(); return true; } return false; } @Override public FontMapEntry set(int i, FontMapEntry e) { e = entries.set(i, e); fireTableRowsUpdated(i, i); return e; } @Override public int size() { return entries.size(); } @Override public List subList(int i, int j) { return Collections.unmodifiableList(entries).subList(i, j); } @Override public Object[] toArray() { return entries.toArray(); } @Override public T[] toArray(T[] a) { return entries.toArray(a); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/000077500000000000000000000000001506470510200265435ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/BOM.java000066400000000000000000000010341506470510200300210ustar00rootroot00000000000000package com.kreative.unicode.mappings; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class BOM { public static List getResourceNames() { List names = new ArrayList(); Scanner scan = new Scanner(BOM.class.getResourceAsStream("BOM.txt")); while (scan.hasNextLine()) names.add(scan.nextLine().trim()); scan.close(); return names; } public static InputStream getResource(String name) { return BOM.class.getResourceAsStream(name); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/BOM.txt000066400000000000000000000024461506470510200277270ustar00rootroot00000000000000Cybiko.txt FZXDesktop.txt FZXKOI8.txt FZXLatin1.txt FZXLatin5.txt FZXLatin9.txt FZXPUA.txt FZXSuperLatin.txt IBM00037.txt IBM00437.txt IBM00500.txt IBM00737.txt IBM00775.txt IBM00850.txt IBM00852.txt IBM00855.txt IBM00857.txt IBM00860.txt IBM00861.txt IBM00862.txt IBM00863.txt IBM00864.txt IBM00865.txt IBM00866.txt IBM00869.txt IBM00874.txt IBM00875.txt IBM01026.txt ISO885901.txt ISO885902.txt ISO885903.txt ISO885904.txt ISO885905.txt ISO885906.txt ISO885907.txt ISO885908.txt ISO885909.txt ISO885910.txt ISO885911.txt ISO885913.txt ISO885914.txt ISO885915.txt ISO885916.txt KKSuper437.txt KKSuper437C0.txt KKSuperLatin.txt KKSuperLatinC0.txt KKSuperRoman.txt KKSuperRomanC0.txt MacCeltic.txt MacCentralEuropean.txt MacCroatian.txt MacCyrillic.txt MacDingbats.txt MacGaelic.txt MacGreek.txt MacIcelandic.txt MacInuit.txt MacRoman.txt MacRomanian.txt MacTurkish.txt MacVT100.txt MouseDesk.txt MouseDesk.da.txt MouseDesk.de.txt MouseDesk.en.txt MouseDesk.epo.txt MouseDesk.es.txt MouseDesk.fr.txt MouseDesk.it.txt MouseDesk.nl.txt MouseDesk.pt.txt MouseDesk.qmk.txt MouseDesk.sv.txt U8MAppleII.txt U8MAtariST.txt U8MATASCII.txt U8MPETSCII.txt U8MRISCOS.txt U8MSpectrum.txt Windows1250.txt Windows1251.txt Windows1252.txt Windows1253.txt Windows1254.txt Windows1255.txt Windows1256.txt Windows1257.txt Windows1258.txtbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/Cybiko.txt000066400000000000000000000222431506470510200305270ustar00rootroot00000000000000# Name: Cybiko # Aliases: x-cybiko # ASCII 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE # Cybiko Symbols 0x7F 0x2026 # horizontal ellipsis 0x80 0x2665 # black heart suit 0x81 0x25CF # black circle 0x82 0x25B6 # black right-pointing triangle 0x83 0x25B7 # white right-pointing triangle 0x84 0xFFC22 # white right-pointing triangle, duplicate? 0x85 0xFFC23 # cy-sign # Windows CP-1252 0x86 0x2020 # dagger 0x87 0x2021 # double dagger 0x88 0x02C6 # modifier letter circumflex accent 0x89 0x2030 # per mille sign 0x8A 0x0160 # latin capital letter s with caron 0x8B 0x2039 # single left-pointing angle quotation mark 0x8C 0x0152 # latin capital ligature oe 0x8D 0x0141 # latin capital letter l with stroke 0x8E 0x017D # latin capital letter z with caron 0x8F 0x0131 # latin small letter dotless i 0x90 0x20AC # euro sign 0x91 0x2018 # left single quotation mark 0x92 0x2019 # right single quotation mark 0x93 0x201C # left double quotation mark 0x94 0x201D # right double quotation mark 0x95 0x2022 # bullet 0x96 0x2013 # en dash 0x97 0x2014 # em dash 0x98 0x02DC # small tilde 0x99 0x2122 # trade mark sign 0x9A 0x0161 # latin small letter s with caron 0x9B 0x203A # single right-pointing angle quotation mark 0x9C 0x0153 # latin small ligature oe 0x9D 0x0142 # latin small letter l with stroke 0x9E 0x017E # latin small letter z with caron 0x9F 0x0178 # latin capital letter y with diaeresis # ISO 8859-1 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic) 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic) 0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German) 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic) 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic) 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXDesktop.txt000066400000000000000000000131211506470510200313030ustar00rootroot00000000000000# Name: FZX Desktop # Aliases: FZX_Desktop, x-fzx-desktop # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0x80 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x81 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0x82 0x011B # LATIN SMALL LETTER E WITH CARON 0x83 0x011A # LATIN CAPITAL LETTER E WITH CARON 0x84 0x0161 # LATIN SMALL LETTER S WITH CARON 0x85 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0x86 0x010D # LATIN SMALL LETTER C WITH CARON 0x87 0x010C # LATIN CAPITAL LETTER C WITH CARON 0x88 0x0159 # LATIN SMALL LETTER R WITH CARON 0x89 0x0158 # LATIN CAPITAL LETTER R WITH CARON 0x8A 0x017E # LATIN SMALL LETTER Z WITH CARON 0x8B 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0x8C 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0x8D 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0x8E 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0x8F 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0x90 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0x91 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0x92 0x010F # LATIN SMALL LETTER D WITH CARON 0x93 0x010E # LATIN CAPITAL LETTER D WITH CARON 0x94 0x0148 # LATIN SMALL LETTER N WITH CARON 0x95 0x0147 # LATIN CAPITAL LETTER N WITH CARON 0x96 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0x97 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0x98 0x0165 # LATIN SMALL LETTER T WITH CARON 0x99 0x0164 # LATIN CAPITAL LETTER T WITH CARON 0x9A 0x016F # LATIN SMALL LETTER U WITH RING ABOVE 0x9B 0x016E # LATIN CAPITAL LETTER U WITH RING ABOVE 0x9C 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0x9D 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0x9E 0xF09E 0x9F 0xF09F 0xA0 0xF0A0 0xA1 0xF0A1 0xA2 0xF0A2 0xA3 0xF0A3 0xA4 0xF0A4 0xA5 0xF0A5 0xA6 0xF0A6 0xA7 0xF0A7 0xA8 0xF0A8 0xA9 0xF0A9 0xAA 0xF0AA 0xAB 0xF0AB 0xAC 0xF0AC 0xAD 0xF0AD 0xAE 0xF0AE 0xAF 0xF0AF 0xB0 0xF0B0 0xB1 0xF0B1 0xB2 0xF0B2 0xB3 0xF0B3 0xB4 0xF0B4 0xB5 0xF0B5 0xB6 0xF0B6 0xB7 0xF0B7 0xB8 0xF0B8 0xB9 0xF0B9 0xBA 0xF0BA 0xBB 0xF0BB 0xBC 0xF0BC 0xBD 0xF0BD 0xBE 0xF0BE 0xBF 0xF0BF 0xC0 0xF0C0 0xC1 0xF0C1 0xC2 0xF0C2 0xC3 0xF0C3 0xC4 0xF0C4 0xC5 0xF0C5 0xC6 0xF0C6 0xC7 0xF0C7 0xC8 0xF0C8 0xC9 0xF0C9 0xCA 0xF0CA 0xCB 0xF0CB 0xCC 0xF0CC 0xCD 0xF0CD 0xCE 0xF0CE 0xCF 0xF0CF 0xD0 0xF0D0 0xD1 0xF0D1 0xD2 0xF0D2 0xD3 0xF0D3 0xD4 0xF0D4 0xD5 0xF0D5 0xD6 0xF0D6 0xD7 0xF0D7 0xD8 0xF0D8 0xD9 0xF0D9 0xDA 0xF0DA 0xDB 0xF0DB 0xDC 0xF0DC 0xDD 0xF0DD 0xDE 0xF0DE 0xDF 0xF0DF 0xE0 0xF0E0 0xE1 0xF0E1 0xE2 0xF0E2 0xE3 0xF0E3 0xE4 0xF0E4 0xE5 0xF0E5 0xE6 0xF0E6 0xE7 0xF0E7 0xE8 0xF0E8 0xE9 0xF0E9 0xEA 0xF0EA 0xEB 0xF0EB 0xEC 0xF0EC 0xED 0xF0ED 0xEE 0xF0EE 0xEF 0xF0EF 0xF0 0xF0F0 0xF1 0xF0F1 0xF2 0xF0F2 0xF3 0xF0F3 0xF4 0xF0F4 0xF5 0xF0F5 0xF6 0xF0F6 0xF7 0xF0F7 0xF8 0xF0F8 0xF9 0xF0F9 0xFA 0xF0FA 0xFB 0xF0FB 0xFC 0xF0FC 0xFD 0xF0FD 0xFE 0xF0FE 0xFF 0xF0FFbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXKOI8.txt000066400000000000000000000145261506470510200304160ustar00rootroot00000000000000# Name: FZX KOI-8 # Aliases: FZX_KOI-8, x-fzx-koi8 # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0x80 0xF080 0x81 0xF081 0x82 0xF082 0x83 0xF083 0x84 0xF084 0x85 0xF085 0x86 0xF086 0x87 0xF087 0x88 0xF088 0x89 0xF089 0x8A 0xF08A 0x8B 0xF08B 0x8C 0xF08C 0x8D 0xF08D 0x8E 0xF08E 0x8F 0xF08F 0x90 0xF090 0x91 0xF091 0x92 0xF092 0x93 0xF093 0x94 0xF094 0x95 0xF095 0x96 0xF096 0x97 0xF097 0x98 0xF098 0x99 0xF099 0x9A 0xF09A 0x9B 0xF09B 0x9C 0xF09C 0x9D 0xF09D 0x9E 0xF09E 0x9F 0xF09F 0xA0 0xF0A0 0xA1 0xF0A1 0xA2 0xF0A2 0xA3 0xF0A3 0xA4 0xF0A4 0xA5 0xF0A5 0xA6 0xF0A6 0xA7 0xF0A7 0xA8 0xF0A8 0xA9 0xF0A9 0xAA 0xF0AA 0xAB 0xF0AB 0xAC 0xF0AC 0xAD 0xF0AD 0xAE 0xF0AE 0xAF 0xF0AF 0xB0 0xF0B0 0xB1 0xF0B1 0xB2 0xF0B2 0xB3 0xF0B3 0xB4 0xF0B4 0xB5 0xF0B5 0xB6 0xF0B6 0xB7 0xF0B7 0xB8 0xF0B8 0xB9 0xF0B9 0xBA 0xF0BA 0xBB 0xF0BB 0xBC 0xF0BC 0xBD 0xF0BD 0xBE 0xF0BE 0xBF 0xF0BF 0xC0 0x044E # CYRILLIC SMALL LETTER YU 0xC1 0x0430 # CYRILLIC SMALL LETTER A 0xC2 0x0431 # CYRILLIC SMALL LETTER BE 0xC3 0x0446 # CYRILLIC SMALL LETTER TSE 0xC4 0x0434 # CYRILLIC SMALL LETTER DE 0xC5 0x0435 # CYRILLIC SMALL LETTER IE 0xC6 0x0444 # CYRILLIC SMALL LETTER EF 0xC7 0x0433 # CYRILLIC SMALL LETTER GHE 0xC8 0x0445 # CYRILLIC SMALL LETTER HA 0xC9 0x0438 # CYRILLIC SMALL LETTER I 0xCA 0x0439 # CYRILLIC SMALL LETTER SHORT I 0xCB 0x043A # CYRILLIC SMALL LETTER KA 0xCC 0x043B # CYRILLIC SMALL LETTER EL 0xCD 0x043C # CYRILLIC SMALL LETTER EM 0xCE 0x043D # CYRILLIC SMALL LETTER EN 0xCF 0x043E # CYRILLIC SMALL LETTER O 0xD0 0x043F # CYRILLIC SMALL LETTER PE 0xD1 0x044F # CYRILLIC SMALL LETTER YA 0xD2 0x0440 # CYRILLIC SMALL LETTER ER 0xD3 0x0441 # CYRILLIC SMALL LETTER ES 0xD4 0x0442 # CYRILLIC SMALL LETTER TE 0xD5 0x0443 # CYRILLIC SMALL LETTER U 0xD6 0x0436 # CYRILLIC SMALL LETTER ZHE 0xD7 0x0432 # CYRILLIC SMALL LETTER VE 0xD8 0x044C # CYRILLIC SMALL LETTER SOFT SIGN 0xD9 0x044B # CYRILLIC SMALL LETTER YERU 0xDA 0x0437 # CYRILLIC SMALL LETTER ZE 0xDB 0x0448 # CYRILLIC SMALL LETTER SHA 0xDC 0x044D # CYRILLIC SMALL LETTER E 0xDD 0x0449 # CYRILLIC SMALL LETTER SHCHA 0xDE 0x0447 # CYRILLIC SMALL LETTER CHE 0xDF 0x044A # CYRILLIC SMALL LETTER HARD SIGN 0xE0 0x042E # CYRILLIC CAPITAL LETTER YU 0xE1 0x0410 # CYRILLIC CAPITAL LETTER A 0xE2 0x0411 # CYRILLIC CAPITAL LETTER BE 0xE3 0x0426 # CYRILLIC CAPITAL LETTER TSE 0xE4 0x0414 # CYRILLIC CAPITAL LETTER DE 0xE5 0x0415 # CYRILLIC CAPITAL LETTER IE 0xE6 0x0424 # CYRILLIC CAPITAL LETTER EF 0xE7 0x0413 # CYRILLIC CAPITAL LETTER GHE 0xE8 0x0425 # CYRILLIC CAPITAL LETTER HA 0xE9 0x0418 # CYRILLIC CAPITAL LETTER I 0xEA 0x0419 # CYRILLIC CAPITAL LETTER SHORT I 0xEB 0x041A # CYRILLIC CAPITAL LETTER KA 0xEC 0x041B # CYRILLIC CAPITAL LETTER EL 0xED 0x041C # CYRILLIC CAPITAL LETTER EM 0xEE 0x041D # CYRILLIC CAPITAL LETTER EN 0xEF 0x041E # CYRILLIC CAPITAL LETTER O 0xF0 0x041F # CYRILLIC CAPITAL LETTER PE 0xF1 0x042F # CYRILLIC CAPITAL LETTER YA 0xF2 0x0420 # CYRILLIC CAPITAL LETTER ER 0xF3 0x0421 # CYRILLIC CAPITAL LETTER ES 0xF4 0x0422 # CYRILLIC CAPITAL LETTER TE 0xF5 0x0423 # CYRILLIC CAPITAL LETTER U 0xF6 0x0416 # CYRILLIC CAPITAL LETTER ZHE 0xF7 0x0412 # CYRILLIC CAPITAL LETTER VE 0xF8 0x042C # CYRILLIC CAPITAL LETTER SOFT SIGN 0xF9 0x042B # CYRILLIC CAPITAL LETTER YERU 0xFA 0x0417 # CYRILLIC CAPITAL LETTER ZE 0xFB 0x0428 # CYRILLIC CAPITAL LETTER SHA 0xFC 0x042D # CYRILLIC CAPITAL LETTER E 0xFD 0x0429 # CYRILLIC CAPITAL LETTER SHCHA 0xFE 0x0427 # CYRILLIC CAPITAL LETTER CHE 0xFF 0x042A # CYRILLIC CAPITAL LETTER HARD SIGNbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXLatin1.txt000066400000000000000000000160521506470510200310300ustar00rootroot00000000000000# Name: FZX Latin-1 # Aliases: FZX_Latin-1, x-fzx-latin1 # Include: C0, C1 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic) 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic) 0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German) 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic) 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic) 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESISbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXLatin5.txt000066400000000000000000000160261506470510200310350ustar00rootroot00000000000000# Name: FZX Latin-5 # Aliases: FZX_Latin-5, x-fzx-latin5 # Include: C0, C1 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x011E # LATIN CAPITAL LETTER G WITH BREVE 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE 0xDE 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x011F # LATIN SMALL LETTER G WITH BREVE 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x0131 # LATIN SMALL LETTER DOTLESS I 0xFE 0x015F # LATIN SMALL LETTER S WITH CEDILLA 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESISbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXLatin9.txt000066400000000000000000000161131506470510200310360ustar00rootroot00000000000000# Name: FZX Latin-9 # Aliases: FZX_Latin-9, x-fzx-latin9 # Include: C0, C1 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x20AC # EURO SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xA7 0x00A7 # SECTION SIGN 0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x0152 # LATIN CAPITAL LIGATURE OE 0xBD 0x0153 # LATIN SMALL LIGATURE OE 0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESISbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXPUA.txt000066400000000000000000000110541506470510200303220ustar00rootroot00000000000000# Name: FZX # Aliases: FZX PUA, FZX_PUA, x-fzx, x-fzx-pua # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0x80 0xF080 0x81 0xF081 0x82 0xF082 0x83 0xF083 0x84 0xF084 0x85 0xF085 0x86 0xF086 0x87 0xF087 0x88 0xF088 0x89 0xF089 0x8A 0xF08A 0x8B 0xF08B 0x8C 0xF08C 0x8D 0xF08D 0x8E 0xF08E 0x8F 0xF08F 0x90 0xF090 0x91 0xF091 0x92 0xF092 0x93 0xF093 0x94 0xF094 0x95 0xF095 0x96 0xF096 0x97 0xF097 0x98 0xF098 0x99 0xF099 0x9A 0xF09A 0x9B 0xF09B 0x9C 0xF09C 0x9D 0xF09D 0x9E 0xF09E 0x9F 0xF09F 0xA0 0xF0A0 0xA1 0xF0A1 0xA2 0xF0A2 0xA3 0xF0A3 0xA4 0xF0A4 0xA5 0xF0A5 0xA6 0xF0A6 0xA7 0xF0A7 0xA8 0xF0A8 0xA9 0xF0A9 0xAA 0xF0AA 0xAB 0xF0AB 0xAC 0xF0AC 0xAD 0xF0AD 0xAE 0xF0AE 0xAF 0xF0AF 0xB0 0xF0B0 0xB1 0xF0B1 0xB2 0xF0B2 0xB3 0xF0B3 0xB4 0xF0B4 0xB5 0xF0B5 0xB6 0xF0B6 0xB7 0xF0B7 0xB8 0xF0B8 0xB9 0xF0B9 0xBA 0xF0BA 0xBB 0xF0BB 0xBC 0xF0BC 0xBD 0xF0BD 0xBE 0xF0BE 0xBF 0xF0BF 0xC0 0xF0C0 0xC1 0xF0C1 0xC2 0xF0C2 0xC3 0xF0C3 0xC4 0xF0C4 0xC5 0xF0C5 0xC6 0xF0C6 0xC7 0xF0C7 0xC8 0xF0C8 0xC9 0xF0C9 0xCA 0xF0CA 0xCB 0xF0CB 0xCC 0xF0CC 0xCD 0xF0CD 0xCE 0xF0CE 0xCF 0xF0CF 0xD0 0xF0D0 0xD1 0xF0D1 0xD2 0xF0D2 0xD3 0xF0D3 0xD4 0xF0D4 0xD5 0xF0D5 0xD6 0xF0D6 0xD7 0xF0D7 0xD8 0xF0D8 0xD9 0xF0D9 0xDA 0xF0DA 0xDB 0xF0DB 0xDC 0xF0DC 0xDD 0xF0DD 0xDE 0xF0DE 0xDF 0xF0DF 0xE0 0xF0E0 0xE1 0xF0E1 0xE2 0xF0E2 0xE3 0xF0E3 0xE4 0xF0E4 0xE5 0xF0E5 0xE6 0xF0E6 0xE7 0xF0E7 0xE8 0xF0E8 0xE9 0xF0E9 0xEA 0xF0EA 0xEB 0xF0EB 0xEC 0xF0EC 0xED 0xF0ED 0xEE 0xF0EE 0xEF 0xF0EF 0xF0 0xF0F0 0xF1 0xF0F1 0xF2 0xF0F2 0xF3 0xF0F3 0xF4 0xF0F4 0xF5 0xF0F5 0xF6 0xF0F6 0xF7 0xF0F7 0xF8 0xF0F8 0xF9 0xF0F9 0xFA 0xF0FA 0xFB 0xF0FB 0xFC 0xF0FC 0xFD 0xF0FD 0xFE 0xF0FE 0xFF 0xF0FFbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/FZXSuperLatin.txt000066400000000000000000000203041506470510200317610ustar00rootroot00000000000000# Name: FZX SuperLatin # Aliases: FZX_SuperLatin, x-fzx-superlatin # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00A3 # POUND SIGN 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x00A9 # COPYRIGHT SIGN 0x80 0x20AC # EURO SIGN 0x81 0x25CA # LOZENGE 0x82 0x201A # SINGLE LOW-9 QUOTATION MARK 0x83 0x0192 # LATIN SMALL LETTER F WITH HOOK 0x84 0x201E # DOUBLE LOW-9 QUOTATION MARK 0x85 0x2026 # HORIZONTAL ELLIPSIS 0x86 0x2020 # DAGGER 0x87 0x2021 # DOUBLE DAGGER 0x88 0x02C6 # MODIFIER LETTER CIRCUMFLEX ACCENT 0x89 0x2030 # PER MILLE SIGN 0x8A 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0x8B 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0x8C 0x0152 # LATIN CAPITAL LIGATURE OE 0x8D 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0x8E 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0x8F 0x0131 # LATIN SMALL LETTER DOTLESS I 0x90 0x2318 # PLACE OF INTEREST SIGN 0x91 0x2018 # LEFT SINGLE QUOTATION MARK 0x92 0x2019 # RIGHT SINGLE QUOTATION MARK 0x93 0x201C # LEFT DOUBLE QUOTATION MARK 0x94 0x201D # RIGHT DOUBLE QUOTATION MARK 0x95 0x2022 # BULLET 0x96 0x2013 # EN DASH 0x97 0x2014 # EM DASH 0x98 0x02DC # SMALL TILDE 0x99 0x2122 # TRADE MARK SIGN 0x9A 0x0161 # LATIN SMALL LETTER S WITH CARON 0x9B 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0x9C 0x0153 # LATIN SMALL LIGATURE OE 0x9D 0x0142 # LATIN SMALL LETTER L WITH STROKE 0x9E 0x017E # LATIN SMALL LETTER Z WITH CARON 0x9F 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESISbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885901.txt000066400000000000000000000234401506470510200304400ustar00rootroot00000000000000# Name: ISO-8859-1 # 8859-1.TXT # Date: 2015-12-02 20:19:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-1:1998 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-1:1998 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-1 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic) 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic) 0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German) 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic) 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic) 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885902.txt000066400000000000000000000240001506470510200304320ustar00rootroot00000000000000# Name: ISO-8859-2 # 8859-2.TXT # Date: 2015-12-02 21:34:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO 8859-2:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-2:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-2 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK 0xA2 0x02D8 # BREVE 0xA3 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x013D # LATIN CAPITAL LETTER L WITH CARON 0xA6 0x015A # LATIN CAPITAL LETTER S WITH ACUTE 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xAA 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA 0xAB 0x0164 # LATIN CAPITAL LETTER T WITH CARON 0xAC 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK 0xB2 0x02DB # OGONEK 0xB3 0x0142 # LATIN SMALL LETTER L WITH STROKE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x013E # LATIN SMALL LETTER L WITH CARON 0xB6 0x015B # LATIN SMALL LETTER S WITH ACUTE 0xB7 0x02C7 # CARON 0xB8 0x00B8 # CEDILLA 0xB9 0x0161 # LATIN SMALL LETTER S WITH CARON 0xBA 0x015F # LATIN SMALL LETTER S WITH CEDILLA 0xBB 0x0165 # LATIN SMALL LETTER T WITH CARON 0xBC 0x017A # LATIN SMALL LETTER Z WITH ACUTE 0xBD 0x02DD # DOUBLE ACUTE ACCENT 0xBE 0x017E # LATIN SMALL LETTER Z WITH CARON 0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE 0xC0 0x0154 # LATIN CAPITAL LETTER R WITH ACUTE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x0102 # LATIN CAPITAL LETTER A WITH BREVE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x0139 # LATIN CAPITAL LETTER L WITH ACUTE 0xC6 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x011A # LATIN CAPITAL LETTER E WITH CARON 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x010E # LATIN CAPITAL LETTER D WITH CARON 0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE 0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE 0xD2 0x0147 # LATIN CAPITAL LETTER N WITH CARON 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x0158 # LATIN CAPITAL LETTER R WITH CARON 0xD9 0x016E # LATIN CAPITAL LETTER U WITH RING ABOVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x0162 # LATIN CAPITAL LETTER T WITH CEDILLA 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x0155 # LATIN SMALL LETTER R WITH ACUTE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x0103 # LATIN SMALL LETTER A WITH BREVE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x013A # LATIN SMALL LETTER L WITH ACUTE 0xE6 0x0107 # LATIN SMALL LETTER C WITH ACUTE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x010D # LATIN SMALL LETTER C WITH CARON 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x011B # LATIN SMALL LETTER E WITH CARON 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x010F # LATIN SMALL LETTER D WITH CARON 0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE 0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE 0xF2 0x0148 # LATIN SMALL LETTER N WITH CARON 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x0159 # LATIN SMALL LETTER R WITH CARON 0xF9 0x016F # LATIN SMALL LETTER U WITH RING ABOVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x0163 # LATIN SMALL LETTER T WITH CEDILLA 0xFF 0x02D9 # DOT ABOVE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885903.txt000066400000000000000000000233021506470510200304370ustar00rootroot00000000000000# Name: ISO-8859-3 # 8859-3.TXT # Date: 2015-12-02 21:39:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-3:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-3:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-3 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0126 # LATIN CAPITAL LETTER H WITH STROKE 0xA2 0x02D8 # BREVE 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA6 0x0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE 0xAA 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA 0xAB 0x011E # LATIN CAPITAL LETTER G WITH BREVE 0xAC 0x0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX 0xAD 0x00AD # SOFT HYPHEN 0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x0127 # LATIN SMALL LETTER H WITH STROKE 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x0131 # LATIN SMALL LETTER DOTLESS I 0xBA 0x015F # LATIN SMALL LETTER S WITH CEDILLA 0xBB 0x011F # LATIN SMALL LETTER G WITH BREVE 0xBC 0x0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x010A # LATIN CAPITAL LETTER C WITH DOT ABOVE 0xC6 0x0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x016C # LATIN CAPITAL LETTER U WITH BREVE 0xDE 0x015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x010B # LATIN SMALL LETTER C WITH DOT ABOVE 0xE6 0x0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x0121 # LATIN SMALL LETTER G WITH DOT ABOVE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x011D # LATIN SMALL LETTER G WITH CIRCUMFLEX 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x016D # LATIN SMALL LETTER U WITH BREVE 0xFE 0x015D # LATIN SMALL LETTER S WITH CIRCUMFLEX 0xFF 0x02D9 # DOT ABOVE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885904.txt000066400000000000000000000237501506470510200304470ustar00rootroot00000000000000# Name: ISO-8859-4 # 8859-4.TXT # Date: 2015-12-02 21:41:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-4:1998 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-4:1998 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-4 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK 0xA2 0x0138 # LATIN SMALL LETTER KRA 0xA3 0x0156 # LATIN CAPITAL LETTER R WITH CEDILLA 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x0128 # LATIN CAPITAL LETTER I WITH TILDE 0xA6 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xAA 0x0112 # LATIN CAPITAL LETTER E WITH MACRON 0xAB 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA 0xAC 0x0166 # LATIN CAPITAL LETTER T WITH STROKE 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK 0xB2 0x02DB # OGONEK 0xB3 0x0157 # LATIN SMALL LETTER R WITH CEDILLA 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x0129 # LATIN SMALL LETTER I WITH TILDE 0xB6 0x013C # LATIN SMALL LETTER L WITH CEDILLA 0xB7 0x02C7 # CARON 0xB8 0x00B8 # CEDILLA 0xB9 0x0161 # LATIN SMALL LETTER S WITH CARON 0xBA 0x0113 # LATIN SMALL LETTER E WITH MACRON 0xBB 0x0123 # LATIN SMALL LETTER G WITH CEDILLA 0xBC 0x0167 # LATIN SMALL LETTER T WITH STROKE 0xBD 0x014A # LATIN CAPITAL LETTER ENG 0xBE 0x017E # LATIN SMALL LETTER Z WITH CARON 0xBF 0x014B # LATIN SMALL LETTER ENG 0xC0 0x0100 # LATIN CAPITAL LETTER A WITH MACRON 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x012E # LATIN CAPITAL LETTER I WITH OGONEK 0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x012A # LATIN CAPITAL LETTER I WITH MACRON 0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE 0xD1 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA 0xD2 0x014C # LATIN CAPITAL LETTER O WITH MACRON 0xD3 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x0168 # LATIN CAPITAL LETTER U WITH TILDE 0xDE 0x016A # LATIN CAPITAL LETTER U WITH MACRON 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x0101 # LATIN SMALL LETTER A WITH MACRON 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x012F # LATIN SMALL LETTER I WITH OGONEK 0xE8 0x010D # LATIN SMALL LETTER C WITH CARON 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x012B # LATIN SMALL LETTER I WITH MACRON 0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE 0xF1 0x0146 # LATIN SMALL LETTER N WITH CEDILLA 0xF2 0x014D # LATIN SMALL LETTER O WITH MACRON 0xF3 0x0137 # LATIN SMALL LETTER K WITH CEDILLA 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x0173 # LATIN SMALL LETTER U WITH OGONEK 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x0169 # LATIN SMALL LETTER U WITH TILDE 0xFE 0x016B # LATIN SMALL LETTER U WITH MACRON 0xFF 0x02D9 # DOT ABOVE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885905.txt000066400000000000000000000231731506470510200304470ustar00rootroot00000000000000# Name: ISO-8859-5 # 8859-5.TXT # Date: 2015-12-02 21:43:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO 8859-5:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-5:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-5 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0401 # CYRILLIC CAPITAL LETTER IO 0xA2 0x0402 # CYRILLIC CAPITAL LETTER DJE 0xA3 0x0403 # CYRILLIC CAPITAL LETTER GJE 0xA4 0x0404 # CYRILLIC CAPITAL LETTER UKRAINIAN IE 0xA5 0x0405 # CYRILLIC CAPITAL LETTER DZE 0xA6 0x0406 # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I 0xA7 0x0407 # CYRILLIC CAPITAL LETTER YI 0xA8 0x0408 # CYRILLIC CAPITAL LETTER JE 0xA9 0x0409 # CYRILLIC CAPITAL LETTER LJE 0xAA 0x040A # CYRILLIC CAPITAL LETTER NJE 0xAB 0x040B # CYRILLIC CAPITAL LETTER TSHE 0xAC 0x040C # CYRILLIC CAPITAL LETTER KJE 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x040E # CYRILLIC CAPITAL LETTER SHORT U 0xAF 0x040F # CYRILLIC CAPITAL LETTER DZHE 0xB0 0x0410 # CYRILLIC CAPITAL LETTER A 0xB1 0x0411 # CYRILLIC CAPITAL LETTER BE 0xB2 0x0412 # CYRILLIC CAPITAL LETTER VE 0xB3 0x0413 # CYRILLIC CAPITAL LETTER GHE 0xB4 0x0414 # CYRILLIC CAPITAL LETTER DE 0xB5 0x0415 # CYRILLIC CAPITAL LETTER IE 0xB6 0x0416 # CYRILLIC CAPITAL LETTER ZHE 0xB7 0x0417 # CYRILLIC CAPITAL LETTER ZE 0xB8 0x0418 # CYRILLIC CAPITAL LETTER I 0xB9 0x0419 # CYRILLIC CAPITAL LETTER SHORT I 0xBA 0x041A # CYRILLIC CAPITAL LETTER KA 0xBB 0x041B # CYRILLIC CAPITAL LETTER EL 0xBC 0x041C # CYRILLIC CAPITAL LETTER EM 0xBD 0x041D # CYRILLIC CAPITAL LETTER EN 0xBE 0x041E # CYRILLIC CAPITAL LETTER O 0xBF 0x041F # CYRILLIC CAPITAL LETTER PE 0xC0 0x0420 # CYRILLIC CAPITAL LETTER ER 0xC1 0x0421 # CYRILLIC CAPITAL LETTER ES 0xC2 0x0422 # CYRILLIC CAPITAL LETTER TE 0xC3 0x0423 # CYRILLIC CAPITAL LETTER U 0xC4 0x0424 # CYRILLIC CAPITAL LETTER EF 0xC5 0x0425 # CYRILLIC CAPITAL LETTER HA 0xC6 0x0426 # CYRILLIC CAPITAL LETTER TSE 0xC7 0x0427 # CYRILLIC CAPITAL LETTER CHE 0xC8 0x0428 # CYRILLIC CAPITAL LETTER SHA 0xC9 0x0429 # CYRILLIC CAPITAL LETTER SHCHA 0xCA 0x042A # CYRILLIC CAPITAL LETTER HARD SIGN 0xCB 0x042B # CYRILLIC CAPITAL LETTER YERU 0xCC 0x042C # CYRILLIC CAPITAL LETTER SOFT SIGN 0xCD 0x042D # CYRILLIC CAPITAL LETTER E 0xCE 0x042E # CYRILLIC CAPITAL LETTER YU 0xCF 0x042F # CYRILLIC CAPITAL LETTER YA 0xD0 0x0430 # CYRILLIC SMALL LETTER A 0xD1 0x0431 # CYRILLIC SMALL LETTER BE 0xD2 0x0432 # CYRILLIC SMALL LETTER VE 0xD3 0x0433 # CYRILLIC SMALL LETTER GHE 0xD4 0x0434 # CYRILLIC SMALL LETTER DE 0xD5 0x0435 # CYRILLIC SMALL LETTER IE 0xD6 0x0436 # CYRILLIC SMALL LETTER ZHE 0xD7 0x0437 # CYRILLIC SMALL LETTER ZE 0xD8 0x0438 # CYRILLIC SMALL LETTER I 0xD9 0x0439 # CYRILLIC SMALL LETTER SHORT I 0xDA 0x043A # CYRILLIC SMALL LETTER KA 0xDB 0x043B # CYRILLIC SMALL LETTER EL 0xDC 0x043C # CYRILLIC SMALL LETTER EM 0xDD 0x043D # CYRILLIC SMALL LETTER EN 0xDE 0x043E # CYRILLIC SMALL LETTER O 0xDF 0x043F # CYRILLIC SMALL LETTER PE 0xE0 0x0440 # CYRILLIC SMALL LETTER ER 0xE1 0x0441 # CYRILLIC SMALL LETTER ES 0xE2 0x0442 # CYRILLIC SMALL LETTER TE 0xE3 0x0443 # CYRILLIC SMALL LETTER U 0xE4 0x0444 # CYRILLIC SMALL LETTER EF 0xE5 0x0445 # CYRILLIC SMALL LETTER HA 0xE6 0x0446 # CYRILLIC SMALL LETTER TSE 0xE7 0x0447 # CYRILLIC SMALL LETTER CHE 0xE8 0x0448 # CYRILLIC SMALL LETTER SHA 0xE9 0x0449 # CYRILLIC SMALL LETTER SHCHA 0xEA 0x044A # CYRILLIC SMALL LETTER HARD SIGN 0xEB 0x044B # CYRILLIC SMALL LETTER YERU 0xEC 0x044C # CYRILLIC SMALL LETTER SOFT SIGN 0xED 0x044D # CYRILLIC SMALL LETTER E 0xEE 0x044E # CYRILLIC SMALL LETTER YU 0xEF 0x044F # CYRILLIC SMALL LETTER YA 0xF0 0x2116 # NUMERO SIGN 0xF1 0x0451 # CYRILLIC SMALL LETTER IO 0xF2 0x0452 # CYRILLIC SMALL LETTER DJE 0xF3 0x0453 # CYRILLIC SMALL LETTER GJE 0xF4 0x0454 # CYRILLIC SMALL LETTER UKRAINIAN IE 0xF5 0x0455 # CYRILLIC SMALL LETTER DZE 0xF6 0x0456 # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I 0xF7 0x0457 # CYRILLIC SMALL LETTER YI 0xF8 0x0458 # CYRILLIC SMALL LETTER JE 0xF9 0x0459 # CYRILLIC SMALL LETTER LJE 0xFA 0x045A # CYRILLIC SMALL LETTER NJE 0xFB 0x045B # CYRILLIC SMALL LETTER TSHE 0xFC 0x045C # CYRILLIC SMALL LETTER KJE 0xFD 0x00A7 # SECTION SIGN 0xFE 0x045E # CYRILLIC SMALL LETTER SHORT U 0xFF 0x045F # CYRILLIC SMALL LETTER DZHE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885906.txt000066400000000000000000000171001506470510200304410ustar00rootroot00000000000000# Name: ISO-8859-6 # 8859-6.TXT # Date: 2015-12-02 21:44:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO 8859-6:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-6:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-6 order. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead # of the Arabic digits (U+0660..U+0669). # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA4 0x00A4 # CURRENCY SIGN 0xAC 0x060C # ARABIC COMMA 0xAD 0x00AD # SOFT HYPHEN 0xBB 0x061B # ARABIC SEMICOLON 0xBF 0x061F # ARABIC QUESTION MARK 0xC1 0x0621 # ARABIC LETTER HAMZA 0xC2 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE 0xC3 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE 0xC4 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE 0xC5 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW 0xC6 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE 0xC7 0x0627 # ARABIC LETTER ALEF 0xC8 0x0628 # ARABIC LETTER BEH 0xC9 0x0629 # ARABIC LETTER TEH MARBUTA 0xCA 0x062A # ARABIC LETTER TEH 0xCB 0x062B # ARABIC LETTER THEH 0xCC 0x062C # ARABIC LETTER JEEM 0xCD 0x062D # ARABIC LETTER HAH 0xCE 0x062E # ARABIC LETTER KHAH 0xCF 0x062F # ARABIC LETTER DAL 0xD0 0x0630 # ARABIC LETTER THAL 0xD1 0x0631 # ARABIC LETTER REH 0xD2 0x0632 # ARABIC LETTER ZAIN 0xD3 0x0633 # ARABIC LETTER SEEN 0xD4 0x0634 # ARABIC LETTER SHEEN 0xD5 0x0635 # ARABIC LETTER SAD 0xD6 0x0636 # ARABIC LETTER DAD 0xD7 0x0637 # ARABIC LETTER TAH 0xD8 0x0638 # ARABIC LETTER ZAH 0xD9 0x0639 # ARABIC LETTER AIN 0xDA 0x063A # ARABIC LETTER GHAIN 0xE0 0x0640 # ARABIC TATWEEL 0xE1 0x0641 # ARABIC LETTER FEH 0xE2 0x0642 # ARABIC LETTER QAF 0xE3 0x0643 # ARABIC LETTER KAF 0xE4 0x0644 # ARABIC LETTER LAM 0xE5 0x0645 # ARABIC LETTER MEEM 0xE6 0x0646 # ARABIC LETTER NOON 0xE7 0x0647 # ARABIC LETTER HEH 0xE8 0x0648 # ARABIC LETTER WAW 0xE9 0x0649 # ARABIC LETTER ALEF MAKSURA 0xEA 0x064A # ARABIC LETTER YEH 0xEB 0x064B # ARABIC FATHATAN 0xEC 0x064C # ARABIC DAMMATAN 0xED 0x064D # ARABIC KASRATAN 0xEE 0x064E # ARABIC FATHA 0xEF 0x064F # ARABIC DAMMA 0xF0 0x0650 # ARABIC KASRA 0xF1 0x0651 # ARABIC SHADDA 0xF2 0x0652 # ARABIC SUKUN bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885907.txt000066400000000000000000000235321506470510200304500ustar00rootroot00000000000000# Name: ISO-8859-7 # 8859-7.TXT # Date: 2015-12-02 21:47:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO 8859-7:2003 to Unicode # Unicode version: 4.0 # Table version: 3.0 # Table format: Format A # Date: 2003-Nov-12 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO 8859-7:2003 characters map into Unicode. # # ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928, # and ECMA 118. ISO 8859-7:2003 adds two currency signs # and one other character not in the earlier standard. # # Format: Three tab-separated columns # Column #1 is the ISO 8859-7 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO 8859-7 order. # # Version history # 1.0 version updates 0.1 version by adding mappings for all # control characters. # Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7 # Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7 # # 2.0 version updates 1.0 version by adding mappings for the # three newly added characters 0xA4, 0xA5, 0xAA. # # 3.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x2018 # LEFT SINGLE QUOTATION MARK 0xA2 0x2019 # RIGHT SINGLE QUOTATION MARK 0xA3 0x00A3 # POUND SIGN 0xA4 0x20AC # EURO SIGN 0xA5 0x20AF # DRACHMA SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x037A # GREEK YPOGEGRAMMENI 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAF 0x2015 # HORIZONTAL BAR 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x0384 # GREEK TONOS 0xB5 0x0385 # GREEK DIALYTIKA TONOS 0xB6 0x0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS 0xB9 0x0389 # GREEK CAPITAL LETTER ETA WITH TONOS 0xBA 0x038A # GREEK CAPITAL LETTER IOTA WITH TONOS 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x038C # GREEK CAPITAL LETTER OMICRON WITH TONOS 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x038E # GREEK CAPITAL LETTER UPSILON WITH TONOS 0xBF 0x038F # GREEK CAPITAL LETTER OMEGA WITH TONOS 0xC0 0x0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS 0xC1 0x0391 # GREEK CAPITAL LETTER ALPHA 0xC2 0x0392 # GREEK CAPITAL LETTER BETA 0xC3 0x0393 # GREEK CAPITAL LETTER GAMMA 0xC4 0x0394 # GREEK CAPITAL LETTER DELTA 0xC5 0x0395 # GREEK CAPITAL LETTER EPSILON 0xC6 0x0396 # GREEK CAPITAL LETTER ZETA 0xC7 0x0397 # GREEK CAPITAL LETTER ETA 0xC8 0x0398 # GREEK CAPITAL LETTER THETA 0xC9 0x0399 # GREEK CAPITAL LETTER IOTA 0xCA 0x039A # GREEK CAPITAL LETTER KAPPA 0xCB 0x039B # GREEK CAPITAL LETTER LAMDA 0xCC 0x039C # GREEK CAPITAL LETTER MU 0xCD 0x039D # GREEK CAPITAL LETTER NU 0xCE 0x039E # GREEK CAPITAL LETTER XI 0xCF 0x039F # GREEK CAPITAL LETTER OMICRON 0xD0 0x03A0 # GREEK CAPITAL LETTER PI 0xD1 0x03A1 # GREEK CAPITAL LETTER RHO 0xD3 0x03A3 # GREEK CAPITAL LETTER SIGMA 0xD4 0x03A4 # GREEK CAPITAL LETTER TAU 0xD5 0x03A5 # GREEK CAPITAL LETTER UPSILON 0xD6 0x03A6 # GREEK CAPITAL LETTER PHI 0xD7 0x03A7 # GREEK CAPITAL LETTER CHI 0xD8 0x03A8 # GREEK CAPITAL LETTER PSI 0xD9 0x03A9 # GREEK CAPITAL LETTER OMEGA 0xDA 0x03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA 0xDB 0x03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA 0xDC 0x03AC # GREEK SMALL LETTER ALPHA WITH TONOS 0xDD 0x03AD # GREEK SMALL LETTER EPSILON WITH TONOS 0xDE 0x03AE # GREEK SMALL LETTER ETA WITH TONOS 0xDF 0x03AF # GREEK SMALL LETTER IOTA WITH TONOS 0xE0 0x03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS 0xE1 0x03B1 # GREEK SMALL LETTER ALPHA 0xE2 0x03B2 # GREEK SMALL LETTER BETA 0xE3 0x03B3 # GREEK SMALL LETTER GAMMA 0xE4 0x03B4 # GREEK SMALL LETTER DELTA 0xE5 0x03B5 # GREEK SMALL LETTER EPSILON 0xE6 0x03B6 # GREEK SMALL LETTER ZETA 0xE7 0x03B7 # GREEK SMALL LETTER ETA 0xE8 0x03B8 # GREEK SMALL LETTER THETA 0xE9 0x03B9 # GREEK SMALL LETTER IOTA 0xEA 0x03BA # GREEK SMALL LETTER KAPPA 0xEB 0x03BB # GREEK SMALL LETTER LAMDA 0xEC 0x03BC # GREEK SMALL LETTER MU 0xED 0x03BD # GREEK SMALL LETTER NU 0xEE 0x03BE # GREEK SMALL LETTER XI 0xEF 0x03BF # GREEK SMALL LETTER OMICRON 0xF0 0x03C0 # GREEK SMALL LETTER PI 0xF1 0x03C1 # GREEK SMALL LETTER RHO 0xF2 0x03C2 # GREEK SMALL LETTER FINAL SIGMA 0xF3 0x03C3 # GREEK SMALL LETTER SIGMA 0xF4 0x03C4 # GREEK SMALL LETTER TAU 0xF5 0x03C5 # GREEK SMALL LETTER UPSILON 0xF6 0x03C6 # GREEK SMALL LETTER PHI 0xF7 0x03C7 # GREEK SMALL LETTER CHI 0xF8 0x03C8 # GREEK SMALL LETTER PSI 0xF9 0x03C9 # GREEK SMALL LETTER OMEGA 0xFA 0x03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA 0xFB 0x03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA 0xFC 0x03CC # GREEK SMALL LETTER OMICRON WITH TONOS 0xFD 0x03CD # GREEK SMALL LETTER UPSILON WITH TONOS 0xFE 0x03CE # GREEK SMALL LETTER OMEGA WITH TONOS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885908.txt000066400000000000000000000174341506470510200304550ustar00rootroot00000000000000# Name: ISO-8859-8 # 8859-8.TXT # Date: 2015-12-02 21:50:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-8:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 2000-Jan-03 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-8:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-8 order. # # Version history # 1.0 version updates 0.1 version by adding mappings for all # control characters. # 1.1 version updates to the published 8859-8:1999, correcting # the mapping of 0xAF and adding mappings for LRM and RLM. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00D7 # MULTIPLICATION SIGN 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00F7 # DIVISION SIGN 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xDF 0x2017 # DOUBLE LOW LINE 0xE0 0x05D0 # HEBREW LETTER ALEF 0xE1 0x05D1 # HEBREW LETTER BET 0xE2 0x05D2 # HEBREW LETTER GIMEL 0xE3 0x05D3 # HEBREW LETTER DALET 0xE4 0x05D4 # HEBREW LETTER HE 0xE5 0x05D5 # HEBREW LETTER VAV 0xE6 0x05D6 # HEBREW LETTER ZAYIN 0xE7 0x05D7 # HEBREW LETTER HET 0xE8 0x05D8 # HEBREW LETTER TET 0xE9 0x05D9 # HEBREW LETTER YOD 0xEA 0x05DA # HEBREW LETTER FINAL KAF 0xEB 0x05DB # HEBREW LETTER KAF 0xEC 0x05DC # HEBREW LETTER LAMED 0xED 0x05DD # HEBREW LETTER FINAL MEM 0xEE 0x05DE # HEBREW LETTER MEM 0xEF 0x05DF # HEBREW LETTER FINAL NUN 0xF0 0x05E0 # HEBREW LETTER NUN 0xF1 0x05E1 # HEBREW LETTER SAMEKH 0xF2 0x05E2 # HEBREW LETTER AYIN 0xF3 0x05E3 # HEBREW LETTER FINAL PE 0xF4 0x05E4 # HEBREW LETTER PE 0xF5 0x05E5 # HEBREW LETTER FINAL TSADI 0xF6 0x05E6 # HEBREW LETTER TSADI 0xF7 0x05E7 # HEBREW LETTER QOF 0xF8 0x05E8 # HEBREW LETTER RESH 0xF9 0x05E9 # HEBREW LETTER SHIN 0xFA 0x05EA # HEBREW LETTER TAV 0xFD 0x200E # LEFT-TO-RIGHT MARK 0xFE 0x200F # RIGHT-TO-LEFT MARK bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885909.txt000066400000000000000000000235031506470510200304500ustar00rootroot00000000000000# Name: ISO-8859-9 # 8859-9.TXT # Date: 2015-12-02 21:51:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-9:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-9:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-9 order. # # ISO/IEC 8859-9 is also equivalent to ISO-IR-148. # # Version history # 1.0 version: updates 0.1 version by adding mappings for all # control characters. # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x011E # LATIN CAPITAL LETTER G WITH BREVE 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE 0xDE 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x011F # LATIN SMALL LETTER G WITH BREVE 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x0131 # LATIN SMALL LETTER DOTLESS I 0xFE 0x015F # LATIN SMALL LETTER S WITH CEDILLA 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885910.txt000066400000000000000000000243141506470510200304410ustar00rootroot00000000000000# Name: x-iso-8859-10 # Aliases: iso-8859-10, iso8859_10 # 8859-10.TXT # Date: 2015-12-02 21:53:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-10:1998 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 October 11 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-10:1998 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-10 order. # # Version history # 1.0 version new. # 1.1 corrected mistake in mapping of 0xA4 # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK 0xA2 0x0112 # LATIN CAPITAL LETTER E WITH MACRON 0xA3 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA 0xA4 0x012A # LATIN CAPITAL LETTER I WITH MACRON 0xA5 0x0128 # LATIN CAPITAL LETTER I WITH TILDE 0xA6 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA 0xA7 0x00A7 # SECTION SIGN 0xA8 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA 0xA9 0x0110 # LATIN CAPITAL LETTER D WITH STROKE 0xAA 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xAB 0x0166 # LATIN CAPITAL LETTER T WITH STROKE 0xAC 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x016A # LATIN CAPITAL LETTER U WITH MACRON 0xAF 0x014A # LATIN CAPITAL LETTER ENG 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK 0xB2 0x0113 # LATIN SMALL LETTER E WITH MACRON 0xB3 0x0123 # LATIN SMALL LETTER G WITH CEDILLA 0xB4 0x012B # LATIN SMALL LETTER I WITH MACRON 0xB5 0x0129 # LATIN SMALL LETTER I WITH TILDE 0xB6 0x0137 # LATIN SMALL LETTER K WITH CEDILLA 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x013C # LATIN SMALL LETTER L WITH CEDILLA 0xB9 0x0111 # LATIN SMALL LETTER D WITH STROKE 0xBA 0x0161 # LATIN SMALL LETTER S WITH CARON 0xBB 0x0167 # LATIN SMALL LETTER T WITH STROKE 0xBC 0x017E # LATIN SMALL LETTER Z WITH CARON 0xBD 0x2015 # HORIZONTAL BAR 0xBE 0x016B # LATIN SMALL LETTER U WITH MACRON 0xBF 0x014B # LATIN SMALL LETTER ENG 0xC0 0x0100 # LATIN CAPITAL LETTER A WITH MACRON 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x012E # LATIN CAPITAL LETTER I WITH OGONEK 0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic) 0xD1 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA 0xD2 0x014C # LATIN CAPITAL LETTER O WITH MACRON 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x0168 # LATIN CAPITAL LETTER U WITH TILDE 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic) 0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German) 0xE0 0x0101 # LATIN SMALL LETTER A WITH MACRON 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x012F # LATIN SMALL LETTER I WITH OGONEK 0xE8 0x010D # LATIN SMALL LETTER C WITH CARON 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic) 0xF1 0x0146 # LATIN SMALL LETTER N WITH CEDILLA 0xF2 0x014D # LATIN SMALL LETTER O WITH MACRON 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x0169 # LATIN SMALL LETTER U WITH TILDE 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x0173 # LATIN SMALL LETTER U WITH OGONEK 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic) 0xFF 0x0138 # LATIN SMALL LETTER KRA bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885911.txt000066400000000000000000000220431506470510200304370ustar00rootroot00000000000000# Name: x-iso-8859-11 # Aliases: iso-8859-11, iso8859_11 # 8859-11.TXT # Date: 2015-12-02 21:55:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-11:2001 to Unicode # Unicode version: 3.2 # Table version: 2.0 # Table format: Format A # Date: 2002 October 7 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-11:2001 characters map into Unicode. # # ISO/IEC 8859-11:2001 is equivalent to TIS 620-2533 (1990) with # the addition of 0xA0 NO-BREAK SPACE. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-11 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-11 order. # # Version history: # 2002 October 7 Created # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0E01 # THAI CHARACTER KO KAI 0xA2 0x0E02 # THAI CHARACTER KHO KHAI 0xA3 0x0E03 # THAI CHARACTER KHO KHUAT 0xA4 0x0E04 # THAI CHARACTER KHO KHWAI 0xA5 0x0E05 # THAI CHARACTER KHO KHON 0xA6 0x0E06 # THAI CHARACTER KHO RAKHANG 0xA7 0x0E07 # THAI CHARACTER NGO NGU 0xA8 0x0E08 # THAI CHARACTER CHO CHAN 0xA9 0x0E09 # THAI CHARACTER CHO CHING 0xAA 0x0E0A # THAI CHARACTER CHO CHANG 0xAB 0x0E0B # THAI CHARACTER SO SO 0xAC 0x0E0C # THAI CHARACTER CHO CHOE 0xAD 0x0E0D # THAI CHARACTER YO YING 0xAE 0x0E0E # THAI CHARACTER DO CHADA 0xAF 0x0E0F # THAI CHARACTER TO PATAK 0xB0 0x0E10 # THAI CHARACTER THO THAN 0xB1 0x0E11 # THAI CHARACTER THO NANGMONTHO 0xB2 0x0E12 # THAI CHARACTER THO PHUTHAO 0xB3 0x0E13 # THAI CHARACTER NO NEN 0xB4 0x0E14 # THAI CHARACTER DO DEK 0xB5 0x0E15 # THAI CHARACTER TO TAO 0xB6 0x0E16 # THAI CHARACTER THO THUNG 0xB7 0x0E17 # THAI CHARACTER THO THAHAN 0xB8 0x0E18 # THAI CHARACTER THO THONG 0xB9 0x0E19 # THAI CHARACTER NO NU 0xBA 0x0E1A # THAI CHARACTER BO BAIMAI 0xBB 0x0E1B # THAI CHARACTER PO PLA 0xBC 0x0E1C # THAI CHARACTER PHO PHUNG 0xBD 0x0E1D # THAI CHARACTER FO FA 0xBE 0x0E1E # THAI CHARACTER PHO PHAN 0xBF 0x0E1F # THAI CHARACTER FO FAN 0xC0 0x0E20 # THAI CHARACTER PHO SAMPHAO 0xC1 0x0E21 # THAI CHARACTER MO MA 0xC2 0x0E22 # THAI CHARACTER YO YAK 0xC3 0x0E23 # THAI CHARACTER RO RUA 0xC4 0x0E24 # THAI CHARACTER RU 0xC5 0x0E25 # THAI CHARACTER LO LING 0xC6 0x0E26 # THAI CHARACTER LU 0xC7 0x0E27 # THAI CHARACTER WO WAEN 0xC8 0x0E28 # THAI CHARACTER SO SALA 0xC9 0x0E29 # THAI CHARACTER SO RUSI 0xCA 0x0E2A # THAI CHARACTER SO SUA 0xCB 0x0E2B # THAI CHARACTER HO HIP 0xCC 0x0E2C # THAI CHARACTER LO CHULA 0xCD 0x0E2D # THAI CHARACTER O ANG 0xCE 0x0E2E # THAI CHARACTER HO NOKHUK 0xCF 0x0E2F # THAI CHARACTER PAIYANNOI 0xD0 0x0E30 # THAI CHARACTER SARA A 0xD1 0x0E31 # THAI CHARACTER MAI HAN-AKAT 0xD2 0x0E32 # THAI CHARACTER SARA AA 0xD3 0x0E33 # THAI CHARACTER SARA AM 0xD4 0x0E34 # THAI CHARACTER SARA I 0xD5 0x0E35 # THAI CHARACTER SARA II 0xD6 0x0E36 # THAI CHARACTER SARA UE 0xD7 0x0E37 # THAI CHARACTER SARA UEE 0xD8 0x0E38 # THAI CHARACTER SARA U 0xD9 0x0E39 # THAI CHARACTER SARA UU 0xDA 0x0E3A # THAI CHARACTER PHINTHU 0xDF 0x0E3F # THAI CURRENCY SYMBOL BAHT 0xE0 0x0E40 # THAI CHARACTER SARA E 0xE1 0x0E41 # THAI CHARACTER SARA AE 0xE2 0x0E42 # THAI CHARACTER SARA O 0xE3 0x0E43 # THAI CHARACTER SARA AI MAIMUAN 0xE4 0x0E44 # THAI CHARACTER SARA AI MAIMALAI 0xE5 0x0E45 # THAI CHARACTER LAKKHANGYAO 0xE6 0x0E46 # THAI CHARACTER MAIYAMOK 0xE7 0x0E47 # THAI CHARACTER MAITAIKHU 0xE8 0x0E48 # THAI CHARACTER MAI EK 0xE9 0x0E49 # THAI CHARACTER MAI THO 0xEA 0x0E4A # THAI CHARACTER MAI TRI 0xEB 0x0E4B # THAI CHARACTER MAI CHATTAWA 0xEC 0x0E4C # THAI CHARACTER THANTHAKHAT 0xED 0x0E4D # THAI CHARACTER NIKHAHIT 0xEE 0x0E4E # THAI CHARACTER YAMAKKAN 0xEF 0x0E4F # THAI CHARACTER FONGMAN 0xF0 0x0E50 # THAI DIGIT ZERO 0xF1 0x0E51 # THAI DIGIT ONE 0xF2 0x0E52 # THAI DIGIT TWO 0xF3 0x0E53 # THAI DIGIT THREE 0xF4 0x0E54 # THAI DIGIT FOUR 0xF5 0x0E55 # THAI DIGIT FIVE 0xF6 0x0E56 # THAI DIGIT SIX 0xF7 0x0E57 # THAI DIGIT SEVEN 0xF8 0x0E58 # THAI DIGIT EIGHT 0xF9 0x0E59 # THAI DIGIT NINE 0xFA 0x0E5A # THAI CHARACTER ANGKHANKHU 0xFB 0x0E5B # THAI CHARACTER KHOMUT bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885913.txt000066400000000000000000000235001506470510200304400ustar00rootroot00000000000000# Name: ISO-8859-13 # 8859-13.TXT # Date: 2015-12-02 22:03:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-13:1998 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-13:1998 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-13 order. # # Version history # 1.0 version: created # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x201D # RIGHT DOUBLE QUOTATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x201E # DOUBLE LOW-9 QUOTATION MARK 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x0156 # LATIN CAPITAL LETTER R WITH CEDILLA 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00C6 # LATIN CAPITAL LETTER AE 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x201C # LEFT DOUBLE QUOTATION MARK 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x0157 # LATIN SMALL LETTER R WITH CEDILLA 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00E6 # LATIN SMALL LETTER AE 0xC0 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK 0xC1 0x012E # LATIN CAPITAL LETTER I WITH OGONEK 0xC2 0x0100 # LATIN CAPITAL LETTER A WITH MACRON 0xC3 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK 0xC7 0x0112 # LATIN CAPITAL LETTER E WITH MACRON 0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE 0xCB 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE 0xCC 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA 0xCD 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA 0xCE 0x012A # LATIN CAPITAL LETTER I WITH MACRON 0xCF 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA 0xD0 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE 0xD2 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x014C # LATIN CAPITAL LETTER O WITH MACRON 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK 0xD9 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0xDA 0x015A # LATIN CAPITAL LETTER S WITH ACUTE 0xDB 0x016A # LATIN CAPITAL LETTER U WITH MACRON 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE 0xDE 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German) 0xE0 0x0105 # LATIN SMALL LETTER A WITH OGONEK 0xE1 0x012F # LATIN SMALL LETTER I WITH OGONEK 0xE2 0x0101 # LATIN SMALL LETTER A WITH MACRON 0xE3 0x0107 # LATIN SMALL LETTER C WITH ACUTE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x0119 # LATIN SMALL LETTER E WITH OGONEK 0xE7 0x0113 # LATIN SMALL LETTER E WITH MACRON 0xE8 0x010D # LATIN SMALL LETTER C WITH CARON 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x017A # LATIN SMALL LETTER Z WITH ACUTE 0xEB 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE 0xEC 0x0123 # LATIN SMALL LETTER G WITH CEDILLA 0xED 0x0137 # LATIN SMALL LETTER K WITH CEDILLA 0xEE 0x012B # LATIN SMALL LETTER I WITH MACRON 0xEF 0x013C # LATIN SMALL LETTER L WITH CEDILLA 0xF0 0x0161 # LATIN SMALL LETTER S WITH CARON 0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE 0xF2 0x0146 # LATIN SMALL LETTER N WITH CEDILLA 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x014D # LATIN SMALL LETTER O WITH MACRON 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x0173 # LATIN SMALL LETTER U WITH OGONEK 0xF9 0x0142 # LATIN SMALL LETTER L WITH STROKE 0xFA 0x015B # LATIN SMALL LETTER S WITH ACUTE 0xFB 0x016B # LATIN SMALL LETTER U WITH MACRON 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE 0xFE 0x017E # LATIN SMALL LETTER Z WITH CARON 0xFF 0x2019 # RIGHT SINGLE QUOTATION MARK bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885914.txt000066400000000000000000000244261506470510200304510ustar00rootroot00000000000000# Name: x-iso-8859-14 # Aliases: iso-8859-14, iso8859_14 # 8859-14.TXT # Date: 2015-12-02 22:05:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-14:1998 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Markus Kuhn # Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-14:1998 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-14 order. # # Version history # 1.0 version: created # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x1E02 # LATIN CAPITAL LETTER B WITH DOT ABOVE 0xA2 0x1E03 # LATIN SMALL LETTER B WITH DOT ABOVE 0xA3 0x00A3 # POUND SIGN 0xA4 0x010A # LATIN CAPITAL LETTER C WITH DOT ABOVE 0xA5 0x010B # LATIN SMALL LETTER C WITH DOT ABOVE 0xA6 0x1E0A # LATIN CAPITAL LETTER D WITH DOT ABOVE 0xA7 0x00A7 # SECTION SIGN 0xA8 0x1E80 # LATIN CAPITAL LETTER W WITH GRAVE 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x1E82 # LATIN CAPITAL LETTER W WITH ACUTE 0xAB 0x1E0B # LATIN SMALL LETTER D WITH DOT ABOVE 0xAC 0x1EF2 # LATIN CAPITAL LETTER Y WITH GRAVE 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xB0 0x1E1E # LATIN CAPITAL LETTER F WITH DOT ABOVE 0xB1 0x1E1F # LATIN SMALL LETTER F WITH DOT ABOVE 0xB2 0x0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE 0xB3 0x0121 # LATIN SMALL LETTER G WITH DOT ABOVE 0xB4 0x1E40 # LATIN CAPITAL LETTER M WITH DOT ABOVE 0xB5 0x1E41 # LATIN SMALL LETTER M WITH DOT ABOVE 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x1E56 # LATIN CAPITAL LETTER P WITH DOT ABOVE 0xB8 0x1E81 # LATIN SMALL LETTER W WITH GRAVE 0xB9 0x1E57 # LATIN SMALL LETTER P WITH DOT ABOVE 0xBA 0x1E83 # LATIN SMALL LETTER W WITH ACUTE 0xBB 0x1E60 # LATIN CAPITAL LETTER S WITH DOT ABOVE 0xBC 0x1EF3 # LATIN SMALL LETTER Y WITH GRAVE 0xBD 0x1E84 # LATIN CAPITAL LETTER W WITH DIAERESIS 0xBE 0x1E85 # LATIN SMALL LETTER W WITH DIAERESIS 0xBF 0x1E61 # LATIN SMALL LETTER S WITH DOT ABOVE 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x1E6A # LATIN CAPITAL LETTER T WITH DOT ABOVE 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x1E6B # LATIN SMALL LETTER T WITH DOT ABOVE 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885915.txt000066400000000000000000000235151506470510200304500ustar00rootroot00000000000000# Name: ISO-8859-15 # 8859-15.TXT # Date: 2015-12-02 22:06:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-15:1999 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 1999 July 27 (header updated: 2015 December 02) # Authors: Markus Kuhn # Ken Whistler # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-15:1999 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-15 order. # # Version history # # Version history # 1.0 version: created # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x20AC # EURO SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xA7 0x00A7 # SECTION SIGN 0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x0152 # LATIN CAPITAL LIGATURE OE 0xBD 0x0153 # LATIN SMALL LIGATURE OE 0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/ISO885916.txt000066400000000000000000000242541506470510200304520ustar00rootroot00000000000000# Name: ISO-8859-16 # 8859-16.TXT # Date: 2015-12-02 22:08:00 GMT [KW] # © 2015 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # ## Name: ISO/IEC 8859-16:2001 to Unicode # Unicode version: 3.0 # Table version: 2.0 # Table format: Format A # Date: 2001 July 26 (header updated: 2015 December 02) # Authors: Markus Kuhn # # Copyright (c) 1999-2001 Unicode, Inc. All Rights reserved. # # General notes: # # This table contains the data the Unicode Consortium has on how # ISO/IEC 8859-16:2001 characters map into Unicode. # # Format: Three tab-separated columns # Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX) # Column #2 is the Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # # The entries are in ISO/IEC 8859-16 order. # # Version history # 1.0 version: created # 2.0 version: updates to copyright notice and terms of use; no # changes to character mappings # # Updated versions of this file may be found in: # http://www.unicode.org/Public/MAPPINGS/ # # Any comments or problems, contact us at: # http://www.unicode.org/reporting.html # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x0080 # 0x81 0x0081 # 0x82 0x0082 # 0x83 0x0083 # 0x84 0x0084 # 0x85 0x0085 # 0x86 0x0086 # 0x87 0x0087 # 0x88 0x0088 # 0x89 0x0089 # 0x8A 0x008A # 0x8B 0x008B # 0x8C 0x008C # 0x8D 0x008D # 0x8E 0x008E # 0x8F 0x008F # 0x90 0x0090 # 0x91 0x0091 # 0x92 0x0092 # 0x93 0x0093 # 0x94 0x0094 # 0x95 0x0095 # 0x96 0x0096 # 0x97 0x0097 # 0x98 0x0098 # 0x99 0x0099 # 0x9A 0x009A # 0x9B 0x009B # 0x9C 0x009C # 0x9D 0x009D # 0x9E 0x009E # 0x9F 0x009F # 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK 0xA2 0x0105 # LATIN SMALL LETTER A WITH OGONEK 0xA3 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0xA4 0x20AC # EURO SIGN 0xA5 0x201E # DOUBLE LOW-9 QUOTATION MARK 0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xA7 0x00A7 # SECTION SIGN 0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x0218 # LATIN CAPITAL LETTER S WITH COMMA BELOW 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x017A # LATIN SMALL LETTER Z WITH ACUTE 0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xB3 0x0142 # LATIN SMALL LETTER L WITH STROKE 0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xB5 0x201D # RIGHT DOUBLE QUOTATION MARK 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON 0xB9 0x010D # LATIN SMALL LETTER C WITH CARON 0xBA 0x0219 # LATIN SMALL LETTER S WITH COMMA BELOW 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x0152 # LATIN CAPITAL LIGATURE OE 0xBD 0x0153 # LATIN SMALL LIGATURE OE 0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x0102 # LATIN CAPITAL LETTER A WITH BREVE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE 0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x015A # LATIN CAPITAL LETTER S WITH ACUTE 0xD8 0x0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK 0xDE 0x021A # LATIN CAPITAL LETTER T WITH COMMA BELOW 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x0103 # LATIN SMALL LETTER A WITH BREVE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x0107 # LATIN SMALL LETTER C WITH ACUTE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE 0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x015B # LATIN SMALL LETTER S WITH ACUTE 0xF8 0x0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x0119 # LATIN SMALL LETTER E WITH OGONEK 0xFE 0x021B # LATIN SMALL LETTER T WITH COMMA BELOW 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuper437.txt000066400000000000000000000231641506470510200310740ustar00rootroot00000000000000# # Name: Kreative Super437 # Aliases: Kreative_Super437, X-Super437, X-KK-Super437, X-Kreative-Super437 # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2018 January 17 # Authors: Rebecca Bettencourt # # Copyright (c) 2018 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 # NULL 0x01 0x02CB # MODIFIER LETTER GRAVE ACCENT 0x02 0x02DD # DOUBLE ACUTE ACCENT 0x03 0x02D9 # DOT ABOVE 0x04 0x02DA # RING ABOVE 0x05 0x02C7 # CARON 0x06 0x02D8 # BREVE 0x07 0x02DB # OGONEK 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0xFB01 # LATIN SMALL LIGATURE FI 0x0F 0xFB02 # LATIN SMALL LIGATURE FL 0x10 0xF8FF # Apple logo 0x11 0x2020 # DAGGER 0x12 0x2021 # DOUBLE DAGGER 0x13 0x02C6 # MODIFIER LETTER CIRCUMFLEX ACCENT 0x14 0x02DC # SMALL TILDE 0x15 0x00A8 # DIAERESIS 0x16 0x00B4 # ACUTE ACCENT 0x17 0x00B8 # CEDILLA 0x18 0x201A # SINGLE LOW-9 QUOTATION MARK 0x19 0x201E # DOUBLE LOW-9 QUOTATION MARK 0x1A 0x2026 # HORIZONTAL ELLIPSIS 0x1B 0x001B # ESCAPE 0x1C 0x2018 # LEFT SINGLE QUOTATION MARK 0x1D 0x2019 # RIGHT SINGLE QUOTATION MARK 0x1E 0x201C # LEFT DOUBLE QUOTATION MARK 0x1F 0x201D # RIGHT DOUBLE QUOTATION MARK 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0x81 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0x82 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x83 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0x84 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0x85 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x86 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0x87 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x88 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0x89 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0x8A 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0x8B 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0x8C 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0x8D 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0x8E 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0x8F 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0x90 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0x91 0x00E6 # LATIN SMALL LETTER AE 0x92 0x00C6 # LATIN CAPITAL LETTER AE 0x93 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0x94 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x95 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0x96 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0x97 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0x98 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS 0x99 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x9A 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0x9B 0x00A2 # CENT SIGN 0x9C 0x00A3 # POUND SIGN 0x9D 0x00A5 # YEN SIGN 0x9E 0x00A4 # CURRENCY SIGN 0x9F 0x0192 # LATIN SMALL LETTER F WITH HOOK 0xA0 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xA1 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xA2 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xA3 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xA4 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xA5 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xA6 0x00AA # FEMININE ORDINAL INDICATOR 0xA7 0x00BA # MASCULINE ORDINAL INDICATOR 0xA8 0x00BF # INVERTED QUESTION MARK 0xA9 0x00AD # SOFT HYPHEN 0xAA 0x00AC # NOT SIGN 0xAB 0x00BD # VULGAR FRACTION ONE HALF 0xAC 0x00BC # VULGAR FRACTION ONE QUARTER 0xAD 0x00A1 # INVERTED EXCLAMATION MARK 0xAE 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAF 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xB0 0x0161 # LATIN SMALL LETTER S WITH CARON 0xB1 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xB2 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0xB3 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xB4 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xB5 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xB6 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xB7 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xB8 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xB9 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xBA 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xBB 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xBC 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xBD 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xBE 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xBF 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xC0 0x0142 # LATIN SMALL LETTER L WITH STROKE 0xC1 0x0152 # LATIN CAPITAL LIGATURE OE 0xC2 0x0153 # LATIN SMALL LIGATURE OE 0xC3 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xC4 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xC5 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xC6 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xC7 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xC8 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xC9 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xCA 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xCB 0x00F0 # LATIN SMALL LETTER ETH 0xCC 0x00D0 # LATIN CAPITAL LETTER ETH 0xCD 0x00DE # LATIN CAPITAL LETTER THORN 0xCE 0x00FE # LATIN SMALL LETTER THORN 0xCF 0x0131 # LATIN SMALL LETTER DOTLESS I 0xD0 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xD1 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xD2 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD3 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xD4 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xD5 0x017E # LATIN SMALL LETTER Z WITH CARON 0xD6 0x00A9 # COPYRIGHT SIGN 0xD7 0x00AE # REGISTERED SIGN 0xD8 0x2122 # TRADE MARK SIGN 0xD9 0x2013 # EN DASH 0xDA 0x2014 # EM DASH 0xDB 0x2030 # PER MILLE SIGN 0xDC 0x00BE # VULGAR FRACTION THREE QUARTERS 0xDD 0x00A6 # BROKEN BAR 0xDE 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0xDF 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0xE0 0x2318 # PLACE OF INTEREST SIGN 0xE1 0x00DF # LATIN SMALL LETTER SHARP S 0xE2 0x220F # N-ARY PRODUCT 0xE3 0x03C0 # GREEK SMALL LETTER PI 0xE4 0x2211 # N-ARY SUMMATION 0xE5 0x00A7 # SECTION SIGN 0xE6 0x00B5 # MICRO SIGN 0xE7 0x00D7 # MULTIPLICATION SIGN 0xE8 0x25CA # LOZENGE 0xE9 0x2206 # INCREMENT 0xEA 0x03A9 # GREEK CAPITAL LETTER OMEGA 0xEB 0x2202 # PARTIAL DIFFERENTIAL 0xEC 0x221E # INFINITY 0xED 0x00B6 # PILCROW SIGN 0xEE 0x20AC # EURO SIGN 0xEF 0x00AF # MACRON 0xF0 0x2260 # NOT EQUAL TO 0xF1 0x00B1 # PLUS-MINUS SIGN 0xF2 0x2265 # GREATER-THAN OR EQUAL TO 0xF3 0x2264 # LESS-THAN OR EQUAL TO 0xF4 0x222B # INTEGRAL 0xF5 0x2044 # FRACTION SLASH 0xF6 0x00F7 # DIVISION SIGN 0xF7 0x2248 # ALMOST EQUAL TO 0xF8 0x00B0 # DEGREE SIGN 0xF9 0x2022 # BULLET 0xFA 0x00B7 # MIDDLE DOT 0xFB 0x221A # SQUARE ROOT 0xFC 0x00B9 # SUPERSCRIPT ONE 0xFD 0x00B2 # SUPERSCRIPT TWO 0xFE 0x00B3 # SUPERSCRIPT THREE 0xFF 0x00A0 # NO-BREAK SPACE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuper437C0.txt000066400000000000000000000230751506470510200312600ustar00rootroot00000000000000# # Name: Kreative Super437 C0 # Aliases: Kreative_Super437_C0, X-Super437-C0, X-KK-Super437-C0, X-Kreative-Super437-C0 # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2018 January 17 # Authors: Rebecca Bettencourt # # Copyright (c) 2018 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 # NULL 0x01 0x0001 # START OF HEADING 0x02 0x0002 # START OF TEXT 0x03 0x0003 # END OF TEXT 0x04 0x0004 # END OF TRANSMISSION 0x05 0x0005 # ENQUIRY 0x06 0x0006 # ACKNOWLEDGE 0x07 0x0007 # BELL 0x08 0x0008 # BACKSPACE 0x09 0x0009 # HORIZONTAL TABULATION 0x0A 0x000A # LINE FEED 0x0B 0x000B # VERTICAL TABULATION 0x0C 0x000C # FORM FEED 0x0D 0x000D # CARRIAGE RETURN 0x0E 0x000E # SHIFT OUT 0x0F 0x000F # SHIFT IN 0x10 0x0010 # DATA LINK ESCAPE 0x11 0x0011 # DEVICE CONTROL ONE 0x12 0x0012 # DEVICE CONTROL TWO 0x13 0x0013 # DEVICE CONTROL THREE 0x14 0x0014 # DEVICE CONTROL FOUR 0x15 0x0015 # NEGATIVE ACKNOWLEDGE 0x16 0x0016 # SYNCHRONOUS IDLE 0x17 0x0017 # END OF TRANSMISSION BLOCK 0x18 0x0018 # CANCEL 0x19 0x0019 # END OF MEDIUM 0x1A 0x001A # SUBSTITUTE 0x1B 0x001B # ESCAPE 0x1C 0x001C # FILE SEPARATOR 0x1D 0x001D # GROUP SEPARATOR 0x1E 0x001E # RECORD SEPARATOR 0x1F 0x001F # UNIT SEPARATOR 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0x81 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0x82 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x83 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0x84 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0x85 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x86 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0x87 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x88 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0x89 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0x8A 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0x8B 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0x8C 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0x8D 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0x8E 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0x8F 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0x90 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0x91 0x00E6 # LATIN SMALL LETTER AE 0x92 0x00C6 # LATIN CAPITAL LETTER AE 0x93 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0x94 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x95 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0x96 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0x97 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0x98 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS 0x99 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x9A 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0x9B 0x00A2 # CENT SIGN 0x9C 0x00A3 # POUND SIGN 0x9D 0x00A5 # YEN SIGN 0x9E 0x00A4 # CURRENCY SIGN 0x9F 0x0192 # LATIN SMALL LETTER F WITH HOOK 0xA0 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xA1 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xA2 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xA3 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xA4 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xA5 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xA6 0x00AA # FEMININE ORDINAL INDICATOR 0xA7 0x00BA # MASCULINE ORDINAL INDICATOR 0xA8 0x00BF # INVERTED QUESTION MARK 0xA9 0x00AD # SOFT HYPHEN 0xAA 0x00AC # NOT SIGN 0xAB 0x00BD # VULGAR FRACTION ONE HALF 0xAC 0x00BC # VULGAR FRACTION ONE QUARTER 0xAD 0x00A1 # INVERTED EXCLAMATION MARK 0xAE 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAF 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xB0 0x0161 # LATIN SMALL LETTER S WITH CARON 0xB1 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xB2 0x0141 # LATIN CAPITAL LETTER L WITH STROKE 0xB3 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xB4 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xB5 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xB6 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xB7 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xB8 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xB9 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xBA 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xBB 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xBC 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xBD 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xBE 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xBF 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xC0 0x0142 # LATIN SMALL LETTER L WITH STROKE 0xC1 0x0152 # LATIN CAPITAL LIGATURE OE 0xC2 0x0153 # LATIN SMALL LIGATURE OE 0xC3 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xC4 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xC5 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xC6 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xC7 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xC8 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS 0xC9 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xCA 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xCB 0x00F0 # LATIN SMALL LETTER ETH 0xCC 0x00D0 # LATIN CAPITAL LETTER ETH 0xCD 0x00DE # LATIN CAPITAL LETTER THORN 0xCE 0x00FE # LATIN SMALL LETTER THORN 0xCF 0x0131 # LATIN SMALL LETTER DOTLESS I 0xD0 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xD1 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xD2 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD3 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xD4 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xD5 0x017E # LATIN SMALL LETTER Z WITH CARON 0xD6 0x00A9 # COPYRIGHT SIGN 0xD7 0x00AE # REGISTERED SIGN 0xD8 0x2122 # TRADE MARK SIGN 0xD9 0x2013 # EN DASH 0xDA 0x2014 # EM DASH 0xDB 0x2030 # PER MILLE SIGN 0xDC 0x00BE # VULGAR FRACTION THREE QUARTERS 0xDD 0x00A6 # BROKEN BAR 0xDE 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0xDF 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0xE0 0x2318 # PLACE OF INTEREST SIGN 0xE1 0x00DF # LATIN SMALL LETTER SHARP S 0xE2 0x220F # N-ARY PRODUCT 0xE3 0x03C0 # GREEK SMALL LETTER PI 0xE4 0x2211 # N-ARY SUMMATION 0xE5 0x00A7 # SECTION SIGN 0xE6 0x00B5 # MICRO SIGN 0xE7 0x00D7 # MULTIPLICATION SIGN 0xE8 0x25CA # LOZENGE 0xE9 0x2206 # INCREMENT 0xEA 0x03A9 # GREEK CAPITAL LETTER OMEGA 0xEB 0x2202 # PARTIAL DIFFERENTIAL 0xEC 0x221E # INFINITY 0xED 0x00B6 # PILCROW SIGN 0xEE 0x20AC # EURO SIGN 0xEF 0x00AF # MACRON 0xF0 0x2260 # NOT EQUAL TO 0xF1 0x00B1 # PLUS-MINUS SIGN 0xF2 0x2265 # GREATER-THAN OR EQUAL TO 0xF3 0x2264 # LESS-THAN OR EQUAL TO 0xF4 0x222B # INTEGRAL 0xF5 0x2044 # FRACTION SLASH 0xF6 0x00F7 # DIVISION SIGN 0xF7 0x2248 # ALMOST EQUAL TO 0xF8 0x00B0 # DEGREE SIGN 0xF9 0x2022 # BULLET 0xFA 0x00B7 # MIDDLE DOT 0xFB 0x221A # SQUARE ROOT 0xFC 0x00B9 # SUPERSCRIPT ONE 0xFD 0x00B2 # SUPERSCRIPT TWO 0xFE 0x00B3 # SUPERSCRIPT THREE 0xFF 0x00A0 # NO-BREAK SPACE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuperLatin.txt000077500000000000000000000071601506470510200316270ustar00rootroot00000000000000# # Name: Kreative SuperLatin # Aliases: Kreative_SuperLatin, X-SuperLatin, X-KK-SuperLatin, X-Kreative-SuperLatin # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2012 July 30 # Authors: Rebecca Bettencourt # # Copyright (c) 2012 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 0x01 0x02CB 0x02 0x02DD 0x03 0x02D9 0x04 0x02DA 0x05 0x02C7 0x06 0x02D8 0x07 0x02DB 0x08 0x0008 0x09 0x0009 0x0A 0x000A 0x0B 0x000B 0x0C 0x000C 0x0D 0x000D 0x0E 0xFB01 0x0F 0xFB02 0x10 0xF8FF 0x11 0x2044 0x12 0x221A 0x13 0x2211 0x14 0x220F 0x15 0x222B 0x16 0x2206 0x17 0x03A9 0x18 0x03C0 0x19 0x2202 0x1A 0x221E 0x1B 0x001B 0x1C 0x2264 0x1D 0x2260 0x1E 0x2265 0x1F 0x2248 0x20 0x0020 0x21 0x0021 0x22 0x0022 0x23 0x0023 0x24 0x0024 0x25 0x0025 0x26 0x0026 0x27 0x0027 0x28 0x0028 0x29 0x0029 0x2A 0x002A 0x2B 0x002B 0x2C 0x002C 0x2D 0x002D 0x2E 0x002E 0x2F 0x002F 0x30 0x0030 0x31 0x0031 0x32 0x0032 0x33 0x0033 0x34 0x0034 0x35 0x0035 0x36 0x0036 0x37 0x0037 0x38 0x0038 0x39 0x0039 0x3A 0x003A 0x3B 0x003B 0x3C 0x003C 0x3D 0x003D 0x3E 0x003E 0x3F 0x003F 0x40 0x0040 0x41 0x0041 0x42 0x0042 0x43 0x0043 0x44 0x0044 0x45 0x0045 0x46 0x0046 0x47 0x0047 0x48 0x0048 0x49 0x0049 0x4A 0x004A 0x4B 0x004B 0x4C 0x004C 0x4D 0x004D 0x4E 0x004E 0x4F 0x004F 0x50 0x0050 0x51 0x0051 0x52 0x0052 0x53 0x0053 0x54 0x0054 0x55 0x0055 0x56 0x0056 0x57 0x0057 0x58 0x0058 0x59 0x0059 0x5A 0x005A 0x5B 0x005B 0x5C 0x005C 0x5D 0x005D 0x5E 0x005E 0x5F 0x005F 0x60 0x0060 0x61 0x0061 0x62 0x0062 0x63 0x0063 0x64 0x0064 0x65 0x0065 0x66 0x0066 0x67 0x0067 0x68 0x0068 0x69 0x0069 0x6A 0x006A 0x6B 0x006B 0x6C 0x006C 0x6D 0x006D 0x6E 0x006E 0x6F 0x006F 0x70 0x0070 0x71 0x0071 0x72 0x0072 0x73 0x0073 0x74 0x0074 0x75 0x0075 0x76 0x0076 0x77 0x0077 0x78 0x0078 0x79 0x0079 0x7A 0x007A 0x7B 0x007B 0x7C 0x007C 0x7D 0x007D 0x7E 0x007E 0x7F 0x007F 0x80 0x20AC 0x81 0x25CA 0x82 0x201A 0x83 0x0192 0x84 0x201E 0x85 0x2026 0x86 0x2020 0x87 0x2021 0x88 0x02C6 0x89 0x2030 0x8A 0x0160 0x8B 0x2039 0x8C 0x0152 0x8D 0x0141 0x8E 0x017D 0x8F 0x0131 0x90 0x2318 0x91 0x2018 0x92 0x2019 0x93 0x201C 0x94 0x201D 0x95 0x2022 0x96 0x2013 0x97 0x2014 0x98 0x02DC 0x99 0x2122 0x9A 0x0161 0x9B 0x203A 0x9C 0x0153 0x9D 0x0142 0x9E 0x017E 0x9F 0x0178 0xA0 0x00A0 0xA1 0x00A1 0xA2 0x00A2 0xA3 0x00A3 0xA4 0x00A4 0xA5 0x00A5 0xA6 0x00A6 0xA7 0x00A7 0xA8 0x00A8 0xA9 0x00A9 0xAA 0x00AA 0xAB 0x00AB 0xAC 0x00AC 0xAD 0x00AD 0xAE 0x00AE 0xAF 0x00AF 0xB0 0x00B0 0xB1 0x00B1 0xB2 0x00B2 0xB3 0x00B3 0xB4 0x00B4 0xB5 0x00B5 0xB6 0x00B6 0xB7 0x00B7 0xB8 0x00B8 0xB9 0x00B9 0xBA 0x00BA 0xBB 0x00BB 0xBC 0x00BC 0xBD 0x00BD 0xBE 0x00BE 0xBF 0x00BF 0xC0 0x00C0 0xC1 0x00C1 0xC2 0x00C2 0xC3 0x00C3 0xC4 0x00C4 0xC5 0x00C5 0xC6 0x00C6 0xC7 0x00C7 0xC8 0x00C8 0xC9 0x00C9 0xCA 0x00CA 0xCB 0x00CB 0xCC 0x00CC 0xCD 0x00CD 0xCE 0x00CE 0xCF 0x00CF 0xD0 0x00D0 0xD1 0x00D1 0xD2 0x00D2 0xD3 0x00D3 0xD4 0x00D4 0xD5 0x00D5 0xD6 0x00D6 0xD7 0x00D7 0xD8 0x00D8 0xD9 0x00D9 0xDA 0x00DA 0xDB 0x00DB 0xDC 0x00DC 0xDD 0x00DD 0xDE 0x00DE 0xDF 0x00DF 0xE0 0x00E0 0xE1 0x00E1 0xE2 0x00E2 0xE3 0x00E3 0xE4 0x00E4 0xE5 0x00E5 0xE6 0x00E6 0xE7 0x00E7 0xE8 0x00E8 0xE9 0x00E9 0xEA 0x00EA 0xEB 0x00EB 0xEC 0x00EC 0xED 0x00ED 0xEE 0x00EE 0xEF 0x00EF 0xF0 0x00F0 0xF1 0x00F1 0xF2 0x00F2 0xF3 0x00F3 0xF4 0x00F4 0xF5 0x00F5 0xF6 0x00F6 0xF7 0x00F7 0xF8 0x00F8 0xF9 0x00F9 0xFA 0x00FA 0xFB 0x00FB 0xFC 0x00FC 0xFD 0x00FD 0xFE 0x00FE 0xFF 0x00FF bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuperLatinC0.txt000077500000000000000000000072031506470510200320100ustar00rootroot00000000000000# # Name: Kreative SuperLatin C0 # Aliases: Kreative_SuperLatin_C0, X-SuperLatin-C0, X-KK-SuperLatin-C0, X-Kreative-SuperLatin-C0 # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2014 July 4 # Authors: Rebecca Bettencourt # # Copyright (c) 2012-2014 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 0x01 0x0001 0x02 0x0002 0x03 0x0003 0x04 0x0004 0x05 0x0005 0x06 0x0006 0x07 0x0007 0x08 0x0008 0x09 0x0009 0x0A 0x000A 0x0B 0x000B 0x0C 0x000C 0x0D 0x000D 0x0E 0x000E 0x0F 0x000F 0x10 0x0010 0x11 0x0011 0x12 0x0012 0x13 0x0013 0x14 0x0014 0x15 0x0015 0x16 0x0016 0x17 0x0017 0x18 0x0018 0x19 0x0019 0x1A 0x001A 0x1B 0x001B 0x1C 0x001C 0x1D 0x001D 0x1E 0x001E 0x1F 0x001F 0x20 0x0020 0x21 0x0021 0x22 0x0022 0x23 0x0023 0x24 0x0024 0x25 0x0025 0x26 0x0026 0x27 0x0027 0x28 0x0028 0x29 0x0029 0x2A 0x002A 0x2B 0x002B 0x2C 0x002C 0x2D 0x002D 0x2E 0x002E 0x2F 0x002F 0x30 0x0030 0x31 0x0031 0x32 0x0032 0x33 0x0033 0x34 0x0034 0x35 0x0035 0x36 0x0036 0x37 0x0037 0x38 0x0038 0x39 0x0039 0x3A 0x003A 0x3B 0x003B 0x3C 0x003C 0x3D 0x003D 0x3E 0x003E 0x3F 0x003F 0x40 0x0040 0x41 0x0041 0x42 0x0042 0x43 0x0043 0x44 0x0044 0x45 0x0045 0x46 0x0046 0x47 0x0047 0x48 0x0048 0x49 0x0049 0x4A 0x004A 0x4B 0x004B 0x4C 0x004C 0x4D 0x004D 0x4E 0x004E 0x4F 0x004F 0x50 0x0050 0x51 0x0051 0x52 0x0052 0x53 0x0053 0x54 0x0054 0x55 0x0055 0x56 0x0056 0x57 0x0057 0x58 0x0058 0x59 0x0059 0x5A 0x005A 0x5B 0x005B 0x5C 0x005C 0x5D 0x005D 0x5E 0x005E 0x5F 0x005F 0x60 0x0060 0x61 0x0061 0x62 0x0062 0x63 0x0063 0x64 0x0064 0x65 0x0065 0x66 0x0066 0x67 0x0067 0x68 0x0068 0x69 0x0069 0x6A 0x006A 0x6B 0x006B 0x6C 0x006C 0x6D 0x006D 0x6E 0x006E 0x6F 0x006F 0x70 0x0070 0x71 0x0071 0x72 0x0072 0x73 0x0073 0x74 0x0074 0x75 0x0075 0x76 0x0076 0x77 0x0077 0x78 0x0078 0x79 0x0079 0x7A 0x007A 0x7B 0x007B 0x7C 0x007C 0x7D 0x007D 0x7E 0x007E 0x7F 0x007F 0x80 0x20AC 0x81 0x25CA 0x82 0x201A 0x83 0x0192 0x84 0x201E 0x85 0x2026 0x86 0x2020 0x87 0x2021 0x88 0x02C6 0x89 0x2030 0x8A 0x0160 0x8B 0x2039 0x8C 0x0152 0x8D 0x0141 0x8E 0x017D 0x8F 0x0131 0x90 0x2318 0x91 0x2018 0x92 0x2019 0x93 0x201C 0x94 0x201D 0x95 0x2022 0x96 0x2013 0x97 0x2014 0x98 0x02DC 0x99 0x2122 0x9A 0x0161 0x9B 0x203A 0x9C 0x0153 0x9D 0x0142 0x9E 0x017E 0x9F 0x0178 0xA0 0x00A0 0xA1 0x00A1 0xA2 0x00A2 0xA3 0x00A3 0xA4 0x00A4 0xA5 0x00A5 0xA6 0x00A6 0xA7 0x00A7 0xA8 0x00A8 0xA9 0x00A9 0xAA 0x00AA 0xAB 0x00AB 0xAC 0x00AC 0xAD 0x00AD 0xAE 0x00AE 0xAF 0x00AF 0xB0 0x00B0 0xB1 0x00B1 0xB2 0x00B2 0xB3 0x00B3 0xB4 0x00B4 0xB5 0x00B5 0xB6 0x00B6 0xB7 0x00B7 0xB8 0x00B8 0xB9 0x00B9 0xBA 0x00BA 0xBB 0x00BB 0xBC 0x00BC 0xBD 0x00BD 0xBE 0x00BE 0xBF 0x00BF 0xC0 0x00C0 0xC1 0x00C1 0xC2 0x00C2 0xC3 0x00C3 0xC4 0x00C4 0xC5 0x00C5 0xC6 0x00C6 0xC7 0x00C7 0xC8 0x00C8 0xC9 0x00C9 0xCA 0x00CA 0xCB 0x00CB 0xCC 0x00CC 0xCD 0x00CD 0xCE 0x00CE 0xCF 0x00CF 0xD0 0x00D0 0xD1 0x00D1 0xD2 0x00D2 0xD3 0x00D3 0xD4 0x00D4 0xD5 0x00D5 0xD6 0x00D6 0xD7 0x00D7 0xD8 0x00D8 0xD9 0x00D9 0xDA 0x00DA 0xDB 0x00DB 0xDC 0x00DC 0xDD 0x00DD 0xDE 0x00DE 0xDF 0x00DF 0xE0 0x00E0 0xE1 0x00E1 0xE2 0x00E2 0xE3 0x00E3 0xE4 0x00E4 0xE5 0x00E5 0xE6 0x00E6 0xE7 0x00E7 0xE8 0x00E8 0xE9 0x00E9 0xEA 0x00EA 0xEB 0x00EB 0xEC 0x00EC 0xED 0x00ED 0xEE 0x00EE 0xEF 0x00EF 0xF0 0x00F0 0xF1 0x00F1 0xF2 0x00F2 0xF3 0x00F3 0xF4 0x00F4 0xF5 0x00F5 0xF6 0x00F6 0xF7 0x00F7 0xF8 0x00F8 0xF9 0x00F9 0xFA 0x00FA 0xFB 0x00FB 0xFC 0x00FC 0xFD 0x00FD 0xFE 0x00FE 0xFF 0x00FF bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuperRoman.txt000077500000000000000000000071601506470510200316340ustar00rootroot00000000000000# # Name: Kreative SuperRoman # Aliases: Kreative_SuperRoman, X-SuperRoman, X-KK-SuperRoman, X-Kreative-SuperRoman # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2012 July 30 # Authors: Rebecca Bettencourt # # Copyright (c) 2012 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 0x01 0x00B9 0x02 0x00B2 0x03 0x00B3 0x04 0x00BC 0x05 0x00BD 0x06 0x00BE 0x07 0x00D7 0x08 0x0008 0x09 0x0009 0x0A 0x000A 0x0B 0x000B 0x0C 0x000C 0x0D 0x000D 0x0E 0x02CB 0x0F 0x00AD 0x10 0x2318 0x11 0x0141 0x12 0x0160 0x13 0x00DD 0x14 0x017D 0x15 0x0142 0x16 0x0161 0x17 0x00FD 0x18 0x017E 0x19 0x00A4 0x1A 0x00A6 0x1B 0x001B 0x1C 0x00D0 0x1D 0x00F0 0x1E 0x00DE 0x1F 0x00FE 0x20 0x0020 0x21 0x0021 0x22 0x0022 0x23 0x0023 0x24 0x0024 0x25 0x0025 0x26 0x0026 0x27 0x0027 0x28 0x0028 0x29 0x0029 0x2A 0x002A 0x2B 0x002B 0x2C 0x002C 0x2D 0x002D 0x2E 0x002E 0x2F 0x002F 0x30 0x0030 0x31 0x0031 0x32 0x0032 0x33 0x0033 0x34 0x0034 0x35 0x0035 0x36 0x0036 0x37 0x0037 0x38 0x0038 0x39 0x0039 0x3A 0x003A 0x3B 0x003B 0x3C 0x003C 0x3D 0x003D 0x3E 0x003E 0x3F 0x003F 0x40 0x0040 0x41 0x0041 0x42 0x0042 0x43 0x0043 0x44 0x0044 0x45 0x0045 0x46 0x0046 0x47 0x0047 0x48 0x0048 0x49 0x0049 0x4A 0x004A 0x4B 0x004B 0x4C 0x004C 0x4D 0x004D 0x4E 0x004E 0x4F 0x004F 0x50 0x0050 0x51 0x0051 0x52 0x0052 0x53 0x0053 0x54 0x0054 0x55 0x0055 0x56 0x0056 0x57 0x0057 0x58 0x0058 0x59 0x0059 0x5A 0x005A 0x5B 0x005B 0x5C 0x005C 0x5D 0x005D 0x5E 0x005E 0x5F 0x005F 0x60 0x0060 0x61 0x0061 0x62 0x0062 0x63 0x0063 0x64 0x0064 0x65 0x0065 0x66 0x0066 0x67 0x0067 0x68 0x0068 0x69 0x0069 0x6A 0x006A 0x6B 0x006B 0x6C 0x006C 0x6D 0x006D 0x6E 0x006E 0x6F 0x006F 0x70 0x0070 0x71 0x0071 0x72 0x0072 0x73 0x0073 0x74 0x0074 0x75 0x0075 0x76 0x0076 0x77 0x0077 0x78 0x0078 0x79 0x0079 0x7A 0x007A 0x7B 0x007B 0x7C 0x007C 0x7D 0x007D 0x7E 0x007E 0x7F 0x007F 0x80 0x00C4 0x81 0x00C5 0x82 0x00C7 0x83 0x00C9 0x84 0x00D1 0x85 0x00D6 0x86 0x00DC 0x87 0x00E1 0x88 0x00E0 0x89 0x00E2 0x8A 0x00E4 0x8B 0x00E3 0x8C 0x00E5 0x8D 0x00E7 0x8E 0x00E9 0x8F 0x00E8 0x90 0x00EA 0x91 0x00EB 0x92 0x00ED 0x93 0x00EC 0x94 0x00EE 0x95 0x00EF 0x96 0x00F1 0x97 0x00F3 0x98 0x00F2 0x99 0x00F4 0x9A 0x00F6 0x9B 0x00F5 0x9C 0x00FA 0x9D 0x00F9 0x9E 0x00FB 0x9F 0x00FC 0xA0 0x2020 0xA1 0x00B0 0xA2 0x00A2 0xA3 0x00A3 0xA4 0x00A7 0xA5 0x2022 0xA6 0x00B6 0xA7 0x00DF 0xA8 0x00AE 0xA9 0x00A9 0xAA 0x2122 0xAB 0x00B4 0xAC 0x00A8 0xAD 0x2260 0xAE 0x00C6 0xAF 0x00D8 0xB0 0x221E 0xB1 0x00B1 0xB2 0x2264 0xB3 0x2265 0xB4 0x00A5 0xB5 0x00B5 0xB6 0x2202 0xB7 0x2211 0xB8 0x220F 0xB9 0x03C0 0xBA 0x222B 0xBB 0x00AA 0xBC 0x00BA 0xBD 0x03A9 0xBE 0x00E6 0xBF 0x00F8 0xC0 0x00BF 0xC1 0x00A1 0xC2 0x00AC 0xC3 0x221A 0xC4 0x0192 0xC5 0x2248 0xC6 0x2206 0xC7 0x00AB 0xC8 0x00BB 0xC9 0x2026 0xCA 0x00A0 0xCB 0x00C0 0xCC 0x00C3 0xCD 0x00D5 0xCE 0x0152 0xCF 0x0153 0xD0 0x2013 0xD1 0x2014 0xD2 0x201C 0xD3 0x201D 0xD4 0x2018 0xD5 0x2019 0xD6 0x00F7 0xD7 0x25CA 0xD8 0x00FF 0xD9 0x0178 0xDA 0x2044 0xDB 0x20AC 0xDC 0x2039 0xDD 0x203A 0xDE 0xFB01 0xDF 0xFB02 0xE0 0x2021 0xE1 0x00B7 0xE2 0x201A 0xE3 0x201E 0xE4 0x2030 0xE5 0x00C2 0xE6 0x00CA 0xE7 0x00C1 0xE8 0x00CB 0xE9 0x00C8 0xEA 0x00CD 0xEB 0x00CE 0xEC 0x00CF 0xED 0x00CC 0xEE 0x00D3 0xEF 0x00D4 0xF0 0xF8FF 0xF1 0x00D2 0xF2 0x00DA 0xF3 0x00DB 0xF4 0x00D9 0xF5 0x0131 0xF6 0x02C6 0xF7 0x02DC 0xF8 0x00AF 0xF9 0x02D8 0xFA 0x02D9 0xFB 0x02DA 0xFC 0x00B8 0xFD 0x02DD 0xFE 0x02DB 0xFF 0x02C7 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/KKSuperRomanC0.txt000077500000000000000000000072031506470510200320150ustar00rootroot00000000000000# # Name: Kreative SuperRoman C0 # Aliases: Kreative_SuperRoman_C0, X-SuperRoman-C0, X-KK-SuperRoman-C0, X-Kreative-SuperRoman-C0 # Unicode Version: 6.0 # Table Version: 1.0 # Table Format: Format A # Date: 2014 July 4 # Authors: Rebecca Bettencourt # # Copyright (c) 2012-2014 Kreative Software. All Rights Reserved. # # This file is provided as-is by Kreative Software. # No claims are made as to fitness for any particular purpose. # No warranties of any kind are expressed or implied. # The recipient agrees to determine applicability of information provided. # 0x00 0x0000 0x01 0x0001 0x02 0x0002 0x03 0x0003 0x04 0x0004 0x05 0x0005 0x06 0x0006 0x07 0x0007 0x08 0x0008 0x09 0x0009 0x0A 0x000A 0x0B 0x000B 0x0C 0x000C 0x0D 0x000D 0x0E 0x000E 0x0F 0x000F 0x10 0x0010 0x11 0x0011 0x12 0x0012 0x13 0x0013 0x14 0x0014 0x15 0x0015 0x16 0x0016 0x17 0x0017 0x18 0x0018 0x19 0x0019 0x1A 0x001A 0x1B 0x001B 0x1C 0x001C 0x1D 0x001D 0x1E 0x001E 0x1F 0x001F 0x20 0x0020 0x21 0x0021 0x22 0x0022 0x23 0x0023 0x24 0x0024 0x25 0x0025 0x26 0x0026 0x27 0x0027 0x28 0x0028 0x29 0x0029 0x2A 0x002A 0x2B 0x002B 0x2C 0x002C 0x2D 0x002D 0x2E 0x002E 0x2F 0x002F 0x30 0x0030 0x31 0x0031 0x32 0x0032 0x33 0x0033 0x34 0x0034 0x35 0x0035 0x36 0x0036 0x37 0x0037 0x38 0x0038 0x39 0x0039 0x3A 0x003A 0x3B 0x003B 0x3C 0x003C 0x3D 0x003D 0x3E 0x003E 0x3F 0x003F 0x40 0x0040 0x41 0x0041 0x42 0x0042 0x43 0x0043 0x44 0x0044 0x45 0x0045 0x46 0x0046 0x47 0x0047 0x48 0x0048 0x49 0x0049 0x4A 0x004A 0x4B 0x004B 0x4C 0x004C 0x4D 0x004D 0x4E 0x004E 0x4F 0x004F 0x50 0x0050 0x51 0x0051 0x52 0x0052 0x53 0x0053 0x54 0x0054 0x55 0x0055 0x56 0x0056 0x57 0x0057 0x58 0x0058 0x59 0x0059 0x5A 0x005A 0x5B 0x005B 0x5C 0x005C 0x5D 0x005D 0x5E 0x005E 0x5F 0x005F 0x60 0x0060 0x61 0x0061 0x62 0x0062 0x63 0x0063 0x64 0x0064 0x65 0x0065 0x66 0x0066 0x67 0x0067 0x68 0x0068 0x69 0x0069 0x6A 0x006A 0x6B 0x006B 0x6C 0x006C 0x6D 0x006D 0x6E 0x006E 0x6F 0x006F 0x70 0x0070 0x71 0x0071 0x72 0x0072 0x73 0x0073 0x74 0x0074 0x75 0x0075 0x76 0x0076 0x77 0x0077 0x78 0x0078 0x79 0x0079 0x7A 0x007A 0x7B 0x007B 0x7C 0x007C 0x7D 0x007D 0x7E 0x007E 0x7F 0x007F 0x80 0x00C4 0x81 0x00C5 0x82 0x00C7 0x83 0x00C9 0x84 0x00D1 0x85 0x00D6 0x86 0x00DC 0x87 0x00E1 0x88 0x00E0 0x89 0x00E2 0x8A 0x00E4 0x8B 0x00E3 0x8C 0x00E5 0x8D 0x00E7 0x8E 0x00E9 0x8F 0x00E8 0x90 0x00EA 0x91 0x00EB 0x92 0x00ED 0x93 0x00EC 0x94 0x00EE 0x95 0x00EF 0x96 0x00F1 0x97 0x00F3 0x98 0x00F2 0x99 0x00F4 0x9A 0x00F6 0x9B 0x00F5 0x9C 0x00FA 0x9D 0x00F9 0x9E 0x00FB 0x9F 0x00FC 0xA0 0x2020 0xA1 0x00B0 0xA2 0x00A2 0xA3 0x00A3 0xA4 0x00A7 0xA5 0x2022 0xA6 0x00B6 0xA7 0x00DF 0xA8 0x00AE 0xA9 0x00A9 0xAA 0x2122 0xAB 0x00B4 0xAC 0x00A8 0xAD 0x2260 0xAE 0x00C6 0xAF 0x00D8 0xB0 0x221E 0xB1 0x00B1 0xB2 0x2264 0xB3 0x2265 0xB4 0x00A5 0xB5 0x00B5 0xB6 0x2202 0xB7 0x2211 0xB8 0x220F 0xB9 0x03C0 0xBA 0x222B 0xBB 0x00AA 0xBC 0x00BA 0xBD 0x03A9 0xBE 0x00E6 0xBF 0x00F8 0xC0 0x00BF 0xC1 0x00A1 0xC2 0x00AC 0xC3 0x221A 0xC4 0x0192 0xC5 0x2248 0xC6 0x2206 0xC7 0x00AB 0xC8 0x00BB 0xC9 0x2026 0xCA 0x00A0 0xCB 0x00C0 0xCC 0x00C3 0xCD 0x00D5 0xCE 0x0152 0xCF 0x0153 0xD0 0x2013 0xD1 0x2014 0xD2 0x201C 0xD3 0x201D 0xD4 0x2018 0xD5 0x2019 0xD6 0x00F7 0xD7 0x25CA 0xD8 0x00FF 0xD9 0x0178 0xDA 0x2044 0xDB 0x20AC 0xDC 0x2039 0xDD 0x203A 0xDE 0xFB01 0xDF 0xFB02 0xE0 0x2021 0xE1 0x00B7 0xE2 0x201A 0xE3 0x201E 0xE4 0x2030 0xE5 0x00C2 0xE6 0x00CA 0xE7 0x00C1 0xE8 0x00CB 0xE9 0x00C8 0xEA 0x00CD 0xEB 0x00CE 0xEC 0x00CF 0xED 0x00CC 0xEE 0x00D3 0xEF 0x00D4 0xF0 0xF8FF 0xF1 0x00D2 0xF2 0x00DA 0xF3 0x00DB 0xF4 0x00D9 0xF5 0x0131 0xF6 0x02C6 0xF7 0x02DC 0xF8 0x00AF 0xF9 0x02D8 0xFA 0x02D9 0xFB 0x02DA 0xFC 0x00B8 0xFD 0x02DD 0xFE 0x02DB 0xFF 0x02C7 bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.da.txt000066400000000000000000000103031506470510200315630ustar00rootroot00000000000000# Name: MouseDesk (da) # Aliases: x-apple2-mousedesk-da 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00C6 # LATIN CAPITAL LETTER AE 0x5C 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0x5D 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00E6 # LATIN SMALL LETTER AE 0x7C 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0x7D 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.de.txt000066400000000000000000000103671506470510200316010ustar00rootroot00000000000000# Name: MouseDesk (de) # Aliases: x-apple2-mousedesk-de 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x00A7 # SECTION SIGN 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0x5C 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x5D 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0x7C 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x7D 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0x7E 0x00DF # LATIN SMALL LETTER SHARP S 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.en.txt000066400000000000000000000101631506470510200316050ustar00rootroot00000000000000# Name: MouseDesk (en) # Aliases: x-apple2-mousedesk-en 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.epo.txt000066400000000000000000000105121506470510200317640ustar00rootroot00000000000000# Name: MouseDesk (epo) # Aliases: x-apple2-mousedesk-epo 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x016C # LATIN CAPITAL LETTER U WITH BREVE 0x58 0x015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX 0x59 0x0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x011D # LATIN SMALL LETTER G WITH CIRCUMFLEX 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x016D # LATIN SMALL LETTER U WITH BREVE 0x78 0x015D # LATIN SMALL LETTER S WITH CIRCUMFLEX 0x79 0x0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.es.txt000066400000000000000000000103361506470510200316140ustar00rootroot00000000000000# Name: MouseDesk (es) # Aliases: x-apple2-mousedesk-es 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0x11 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x12 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0x13 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0x14 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x00A3 # POUND SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x00A7 # SECTION SIGN 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00A1 # INVERTED EXCLAMATION MARK 0x5C 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0x5D 0x00BF # INVERTED QUESTION MARK 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00B0 # DEGREE SIGN 0x7C 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0x7D 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.fr.txt000066400000000000000000000102651506470510200316150ustar00rootroot00000000000000# Name: MouseDesk (fr) # Aliases: x-apple2-mousedesk-fr 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x00A3 # POUND SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00B0 # DEGREE SIGN 0x5C 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x5D 0x00A7 # SECTION SIGN 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x7C 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0x7D 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0x7E 0x00A8 # DIAERESIS 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.it.txt000066400000000000000000000103361506470510200316210ustar00rootroot00000000000000# Name: MouseDesk (it) # Aliases: x-apple2-mousedesk-it 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x00A3 # POUND SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x00A7 # SECTION SIGN 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00B0 # DEGREE SIGN 0x5C 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x5D 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x7C 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0x7D 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0x7E 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.nl.txt000066400000000000000000000101741506470510200316160ustar00rootroot00000000000000# Name: MouseDesk (nl) # Aliases: x-apple2-mousedesk-nl 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.pt.txt000066400000000000000000000105261506470510200316310ustar00rootroot00000000000000# Name: MouseDesk (pt) # Aliases: x-apple2-mousedesk-pt 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0x5C 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0x5D 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x60 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0x7C 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0x7D 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0x7E 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.qmk.txt000066400000000000000000000103351506470510200317740ustar00rootroot00000000000000# Name: MouseDesk (qmk) # Aliases: x-apple2-mousedesk-qmk 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x5C 0xF700 # LATIN CAPITAL LETTER K WITH TILDE 0x5D 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x7C 0xF701 # LATIN SMALL LETTER K WITH TILDE 0x7D 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.sv.txt000066400000000000000000000103451506470510200316350ustar00rootroot00000000000000# Name: MouseDesk (sv) # Aliases: x-apple2-mousedesk-sv 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0x5C 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x5D 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0x7C 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x7D 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/MouseDesk.txt000066400000000000000000000101531506470510200312030ustar00rootroot00000000000000# Name: MouseDesk # Aliases: x-apple2-mousedesk 0x00 0x0000 # NULL 0x01 0x1FBB9 # LEFT HALF FOLDER 0x02 0x1FBBA # RIGHT HALF FOLDER 0x03 0xFFC3C # empty document, left half 0x04 0xFFC3D # empty document, right half 0x05 0xFFC3E # hard disk, left half 0x06 0xFFC3F # hard disk, right half 0x07 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x08 0x2190 # LEFTWARDS ARROW 0x09 0xFFCC4 # rectangle, left half 0x0A 0x2193 # DOWNWARDS ARROW 0x0B 0x2191 # UPWARDS ARROW 0x0C 0xFFCC5 # rectangle, right half 0x0D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x0E 0x00A9 # COPYRIGHT SIGN 0x0F 0x00AE # REGISTERED SIGN 0x10 0xFFC28 # trademark sign, left half 0x11 0xFFC29 # trademark sign, right half 0x12 0x00A3 # POUND SIGN 0x13 0x03C0 # GREEK SMALL LETTER PI 0x14 0x00F7 # DIVISION SIGN 0x15 0x2192 # RIGHTWARDS ARROW 0x16 0x00B0 # DEGREE SIGN 0x17 0x25C7 # WHITE DIAMOND 0x18 0x1FBBB # VOIDED GREEK CROSS 0x19 0x2592 # MEDIUM SHADE 0x1A 0x1FB90 # INVERSE MEDIUM SHADE 0x1B 0x25C6 # BLACK DIAMOND 0x1C 0x1FBB1 # INVERSE CHECK MARK 0x1D 0x2713 # CHECK MARK 0x1E 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x1F 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MATASCII.txt000066400000000000000000000177401506470510200307240ustar00rootroot00000000000000# Name: U8/M ATASCII # Aliases: U8-M_ATASCII, x-u8m-atascii # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x2665 # BLACK HEART SUIT 0x81 0x251C # BOX DRAWINGS LIGHT VERTICAL AND RIGHT 0x82 0x23B9 # RIGHT VERTICAL BOX LINE 0x83 0x2518 # BOX DRAWINGS LIGHT UP AND LEFT 0x84 0x2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT 0x85 0x2510 # BOX DRAWINGS LIGHT DOWN AND LEFT 0x86 0x2571 # BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT 0x87 0x2572 # BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT 0x88 0x25E2 # BLACK LOWER RIGHT TRIANGLE 0x89 0x2597 # QUADRANT LOWER RIGHT 0x8A 0x25E3 # BLACK LOWER LEFT TRIANGLE 0x8B 0x259D # QUADRANT UPPER RIGHT 0x8C 0x2598 # QUADRANT UPPER LEFT 0x8D 0x23BA # HORIZONTAL SCAN LINE-1 0x8E 0x23BD # HORIZONTAL SCAN LINE-9 0x8F 0x2596 # QUADRANT LOWER LEFT 0x90 0x2663 # BLACK CLUB SUIT 0x91 0x250C # BOX DRAWINGS LIGHT DOWN AND RIGHT 0x92 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x93 0x253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL 0x94 0x2022 # BULLET 0x95 0x2584 # LOWER HALF BLOCK 0x96 0x23B8 # LEFT VERTICAL BOX LINE 0x97 0x252C # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL 0x98 0x2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL 0x99 0x258C # LEFT HALF BLOCK 0x9A 0x2514 # BOX DRAWINGS LIGHT UP AND RIGHT 0x9B 0x241B # SYMBOL FOR ESCAPE 0x9C 0x2191 # UPWARDS ARROW 0x9D 0x2193 # DOWNWARDS ARROW 0x9E 0x2190 # LEFTWARDS ARROW 0x9F 0x2192 # RIGHTWARDS ARROW 0xA0 0x2666 # BLACK DIAMOND SUIT 0xA1 0x0061 # LATIN SMALL LETTER A 0xA2 0x0062 # LATIN SMALL LETTER B 0xA3 0x0063 # LATIN SMALL LETTER C 0xA4 0x0064 # LATIN SMALL LETTER D 0xA5 0x0065 # LATIN SMALL LETTER E 0xA6 0x0066 # LATIN SMALL LETTER F 0xA7 0x0067 # LATIN SMALL LETTER G 0xA8 0x0068 # LATIN SMALL LETTER H 0xA9 0x0069 # LATIN SMALL LETTER I 0xAA 0x006A # LATIN SMALL LETTER J 0xAB 0x006B # LATIN SMALL LETTER K 0xAC 0x006C # LATIN SMALL LETTER L 0xAD 0x006D # LATIN SMALL LETTER M 0xAE 0x006E # LATIN SMALL LETTER N 0xAF 0x006F # LATIN SMALL LETTER O 0xB0 0x0070 # LATIN SMALL LETTER P 0xB1 0x0071 # LATIN SMALL LETTER Q 0xB2 0x0072 # LATIN SMALL LETTER R 0xB3 0x0073 # LATIN SMALL LETTER S 0xB4 0x0074 # LATIN SMALL LETTER T 0xB5 0x0075 # LATIN SMALL LETTER U 0xB6 0x0076 # LATIN SMALL LETTER V 0xB7 0x0077 # LATIN SMALL LETTER W 0xB8 0x0078 # LATIN SMALL LETTER X 0xB9 0x0079 # LATIN SMALL LETTER Y 0xBA 0x007A # LATIN SMALL LETTER Z 0xBB 0x2660 # BLACK SPADE SUIT 0xBC 0x007C # VERTICAL LINE 0xBD 0x1F8B0 # ARROW POINTING UPWARDS THEN NORTH WEST 0xBE 0x25C0 # BLACK LEFT-POINTING TRIANGLE 0xBF 0x25B6 # BLACK RIGHT-POINTING TRIANGLE 0xC0 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xC1 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xC2 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xC3 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xC4 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xC5 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xC6 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xC7 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xC8 0x00A3 # POUND SIGN 0xC9 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xCA 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xCB 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xCC 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xCD 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xCE 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xCF 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xD0 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xD1 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xD2 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xD3 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xD4 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xD5 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xD6 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xD7 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xD8 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xD9 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xDA 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xDB 0x241B # SYMBOL FOR ESCAPE 0xDC 0x2191 # UPWARDS ARROW 0xDD 0x2193 # DOWNWARDS ARROW 0xDE 0x2190 # LEFTWARDS ARROW 0xDF 0x2192 # RIGHTWARDS ARROW 0xE0 0x00A1 # INVERTED EXCLAMATION MARK 0xE1 0x0061 # LATIN SMALL LETTER A 0xE2 0x0062 # LATIN SMALL LETTER B 0xE3 0x0063 # LATIN SMALL LETTER C 0xE4 0x0064 # LATIN SMALL LETTER D 0xE5 0x0065 # LATIN SMALL LETTER E 0xE6 0x0066 # LATIN SMALL LETTER F 0xE7 0x0067 # LATIN SMALL LETTER G 0xE8 0x0068 # LATIN SMALL LETTER H 0xE9 0x0069 # LATIN SMALL LETTER I 0xEA 0x006A # LATIN SMALL LETTER J 0xEB 0x006B # LATIN SMALL LETTER K 0xEC 0x006C # LATIN SMALL LETTER L 0xED 0x006D # LATIN SMALL LETTER M 0xEE 0x006E # LATIN SMALL LETTER N 0xEF 0x006F # LATIN SMALL LETTER O 0xF0 0x0070 # LATIN SMALL LETTER P 0xF1 0x0071 # LATIN SMALL LETTER Q 0xF2 0x0072 # LATIN SMALL LETTER R 0xF3 0x0073 # LATIN SMALL LETTER S 0xF4 0x0074 # LATIN SMALL LETTER T 0xF5 0x0075 # LATIN SMALL LETTER U 0xF6 0x0076 # LATIN SMALL LETTER V 0xF7 0x0077 # LATIN SMALL LETTER W 0xF8 0x0078 # LATIN SMALL LETTER X 0xF9 0x0079 # LATIN SMALL LETTER Y 0xFA 0x007A # LATIN SMALL LETTER Z 0xFB 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xFC 0x007C # VERTICAL LINE 0xFD 0x1F8B0 # ARROW POINTING UPWARDS THEN NORTH WEST 0xFE 0x25C0 # BLACK LEFT-POINTING TRIANGLE 0xFF 0x25B6 # BLACK RIGHT-POINTING TRIANGLEbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MAppleII.txt000066400000000000000000000164551506470510200311340ustar00rootroot00000000000000# Name: U8/M Apple II # Aliases: U8-M_Apple_II, x-u8m-apple2 # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0xF813 # Apple logo, filled (closed Apple, solid Apple) 0x81 0xF812 # Apple logo, outline (open Apple, hollow Apple) 0x82 0x1FBB0 # ARROWHEAD-SHAPED POINTER 0x83 0x231B # HOURGLASS 0x84 0x2713 # CHECK MARK 0x85 0x1FBB1 # INVERSE CHECK MARK 0x86 0x1FBB4 # INVERSE DOWNWARDS ARROW WITH TIP LEFTWARDS 0x87 0x1FB81 # HORIZONTAL ONE EIGHTH BLOCK-1358 0x88 0x2190 # LEFTWARDS ARROW 0x89 0x2026 # HORIZONTAL ELLIPSIS 0x8A 0x2193 # DOWNWARDS ARROW 0x8B 0x2191 # UPWARDS ARROW 0x8C 0x2594 # UPPER ONE EIGHTH BLOCK 0x8D 0x21B2 # DOWNWARDS ARROW WITH TIP LEFTWARDS 0x8E 0x2589 # LEFT SEVEN EIGHTHS BLOCK 0x8F 0x1FBB5 # LEFTWARDS ARROW AND UPPER AND LOWER ONE EIGHTH BLOCK 0x90 0x1FBB6 # RIGHTWARDS ARROW AND UPPER AND LOWER ONE EIGHTH BLOCK 0x91 0x1FBB7 # DOWNWARDS ARROW AND RIGHT ONE EIGHTH BLOCK 0x92 0x1FBB8 # UPWARDS ARROW AND RIGHT ONE EIGHTH BLOCK 0x93 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x94 0x1FB7C # LEFT AND LOWER ONE EIGHTH BLOCK 0x95 0x2192 # RIGHTWARDS ARROW 0x96 0x2592 # MEDIUM SHADE 0x97 0x1FB90 # INVERSE MEDIUM SHADE 0x98 0x1FBB9 # LEFT HALF FOLDER 0x99 0x1FBBA # RIGHT HALF FOLDER 0x9A 0x2595 # RIGHT ONE EIGHTH BLOCK 0x9B 0x25C6 # BLACK DIAMOND 0x9C 0x1FB80 # UPPER AND LOWER ONE EIGHTH BLOCK 0x9D 0x1FBBB # VOIDED GREEK CROSS 0x9E 0x1FBBC # RIGHT OPEN SQUARED DOT 0x9F 0x258F # LEFT ONE EIGHTH BLOCK 0xA0 0x0020 # SPACE 0xA1 0x0021 # EXCLAMATION MARK 0xA2 0x0022 # QUOTATION MARK 0xA3 0x0023 # NUMBER SIGN 0xA4 0x0024 # DOLLAR SIGN 0xA5 0x0025 # PERCENT SIGN 0xA6 0x0026 # AMPERSAND 0xA7 0x0027 # APOSTROPHE 0xA8 0x0028 # LEFT PARENTHESIS 0xA9 0x0029 # RIGHT PARENTHESIS 0xAA 0x002A # ASTERISK 0xAB 0x002B # PLUS SIGN 0xAC 0x002C # COMMA 0xAD 0x002D # HYPHEN-MINUS 0xAE 0x002E # FULL STOP 0xAF 0x002F # SOLIDUS 0xB0 0x0030 # DIGIT ZERO 0xB1 0x0031 # DIGIT ONE 0xB2 0x0032 # DIGIT TWO 0xB3 0x0033 # DIGIT THREE 0xB4 0x0034 # DIGIT FOUR 0xB5 0x0035 # DIGIT FIVE 0xB6 0x0036 # DIGIT SIX 0xB7 0x0037 # DIGIT SEVEN 0xB8 0x0038 # DIGIT EIGHT 0xB9 0x0039 # DIGIT NINE 0xBA 0x003A # COLON 0xBB 0x003B # SEMICOLON 0xBC 0x003C # LESS-THAN SIGN 0xBD 0x003D # EQUALS SIGN 0xBE 0x003E # GREATER-THAN SIGN 0xBF 0x003F # QUESTION MARK 0xC0 0x0040 # COMMERCIAL AT 0xC1 0x0041 # LATIN CAPITAL LETTER A 0xC2 0x0042 # LATIN CAPITAL LETTER B 0xC3 0x0043 # LATIN CAPITAL LETTER C 0xC4 0x0044 # LATIN CAPITAL LETTER D 0xC5 0x0045 # LATIN CAPITAL LETTER E 0xC6 0x0046 # LATIN CAPITAL LETTER F 0xC7 0x0047 # LATIN CAPITAL LETTER G 0xC8 0x0048 # LATIN CAPITAL LETTER H 0xC9 0x0049 # LATIN CAPITAL LETTER I 0xCA 0x004A # LATIN CAPITAL LETTER J 0xCB 0x004B # LATIN CAPITAL LETTER K 0xCC 0x004C # LATIN CAPITAL LETTER L 0xCD 0x004D # LATIN CAPITAL LETTER M 0xCE 0x004E # LATIN CAPITAL LETTER N 0xCF 0x004F # LATIN CAPITAL LETTER O 0xD0 0x0050 # LATIN CAPITAL LETTER P 0xD1 0x0051 # LATIN CAPITAL LETTER Q 0xD2 0x0052 # LATIN CAPITAL LETTER R 0xD3 0x0053 # LATIN CAPITAL LETTER S 0xD4 0x0054 # LATIN CAPITAL LETTER T 0xD5 0x0055 # LATIN CAPITAL LETTER U 0xD6 0x0056 # LATIN CAPITAL LETTER V 0xD7 0x0057 # LATIN CAPITAL LETTER W 0xD8 0x0058 # LATIN CAPITAL LETTER X 0xD9 0x0059 # LATIN CAPITAL LETTER Y 0xDA 0x005A # LATIN CAPITAL LETTER Z 0xDB 0x005B # LEFT SQUARE BRACKET 0xDC 0x005C # REVERSE SOLIDUS 0xDD 0x005D # RIGHT SQUARE BRACKET 0xDE 0x005E # CIRCUMFLEX ACCENT 0xDF 0x005F # LOW LINE 0xE0 0x0060 # GRAVE ACCENT 0xE1 0x0061 # LATIN SMALL LETTER A 0xE2 0x0062 # LATIN SMALL LETTER B 0xE3 0x0063 # LATIN SMALL LETTER C 0xE4 0x0064 # LATIN SMALL LETTER D 0xE5 0x0065 # LATIN SMALL LETTER E 0xE6 0x0066 # LATIN SMALL LETTER F 0xE7 0x0067 # LATIN SMALL LETTER G 0xE8 0x0068 # LATIN SMALL LETTER H 0xE9 0x0069 # LATIN SMALL LETTER I 0xEA 0x006A # LATIN SMALL LETTER J 0xEB 0x006B # LATIN SMALL LETTER K 0xEC 0x006C # LATIN SMALL LETTER L 0xED 0x006D # LATIN SMALL LETTER M 0xEE 0x006E # LATIN SMALL LETTER N 0xEF 0x006F # LATIN SMALL LETTER O 0xF0 0x0070 # LATIN SMALL LETTER P 0xF1 0x0071 # LATIN SMALL LETTER Q 0xF2 0x0072 # LATIN SMALL LETTER R 0xF3 0x0073 # LATIN SMALL LETTER S 0xF4 0x0074 # LATIN SMALL LETTER T 0xF5 0x0075 # LATIN SMALL LETTER U 0xF6 0x0076 # LATIN SMALL LETTER V 0xF7 0x0077 # LATIN SMALL LETTER W 0xF8 0x0078 # LATIN SMALL LETTER X 0xF9 0x0079 # LATIN SMALL LETTER Y 0xFA 0x007A # LATIN SMALL LETTER Z 0xFB 0x007B # LEFT CURLY BRACKET 0xFC 0x007C # VERTICAL LINE 0xFD 0x007D # RIGHT CURLY BRACKET 0xFE 0x007E # TILDE 0xFF 0x007F # DELETEbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MAtariST.txt000066400000000000000000000224061506470510200311510ustar00rootroot00000000000000# Name: U8/M Atari ST # Aliases: U8-M_Atari_ST, x-u8m-atarist 0x00 0x0000 # NULL 0x01 0x21E7 # UPWARDS WHITE ARROW 0x02 0x21E9 # DOWNWARDS WHITE ARROW 0x03 0x21E8 # RIGHTWARDS WHITE ARROW 0x04 0x21E6 # LEFTWARDS WHITE ARROW 0x05 0x1FBBD # NEGATIVE DIAGONAL CROSS 0x06 0x1FBBE # NEGATIVE DIAGONAL MIDDLE RIGHT TO LOWER CENTRE 0x07 0x1FBBF # NEGATIVE DIAGONAL DIAMOND 0x08 0x2713 # CHECK MARK 0x09 0x1F552 # CLOCK FACE THREE OCLOCK 0x0A 0x1F514 # BELL 0x0B 0x266A # EIGHTH NOTE 0x0C 0x240C # SYMBOL FOR FORM FEED 0x0D 0x240D # SYMBOL FOR CARRIAGE RETURN 0x0E 0xF82A # Atari logo, left half 0x0F 0xF82B # Atari logo, right half 0x10 0x1FBF0 # SEGMENTED DIGIT ZERO 0x11 0x1FBF1 # SEGMENTED DIGIT ONE 0x12 0x1FBF2 # SEGMENTED DIGIT TWO 0x13 0x1FBF3 # SEGMENTED DIGIT THREE 0x14 0x1FBF4 # SEGMENTED DIGIT FOUR 0x15 0x1FBF5 # SEGMENTED DIGIT FIVE 0x16 0x1FBF6 # SEGMENTED DIGIT SIX 0x17 0x1FBF7 # SEGMENTED DIGIT SEVEN 0x18 0x1FBF8 # SEGMENTED DIGIT EIGHT 0x19 0x1FBF9 # SEGMENTED DIGIT NINE 0x1A 0x0259 # LATIN SMALL LETTER SCHWA 0x1B 0x241B # SYMBOL FOR ESCAPE 0x1C 0xF82C # Image of J.R. "Bob" Dobbs, upper left quarter 0x1D 0xF82D # Image of J.R. "Bob" Dobbs, upper right quarter 0x1E 0xF82E # Image of J.R. "Bob" Dobbs, lower left quarter 0x1F 0xF82F # Image of J.R. "Bob" Dobbs, lower right quarter 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x2302 # HOUSE 0x80 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0x81 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0x82 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x83 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0x84 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0x85 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x86 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0x87 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0x88 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0x89 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0x8A 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0x8B 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0x8C 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0x8D 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0x8E 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0x8F 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0x90 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0x91 0x00E6 # LATIN SMALL LIGATURE AE 0x92 0x00C6 # LATIN CAPITAL LIGATURE AE 0x93 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0x94 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0x95 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0x96 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0x97 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0x98 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS 0x99 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0x9A 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0x9B 0x00A2 # CENT SIGN 0x9C 0x00A3 # POUND SIGN 0x9D 0x00A5 # YEN SIGN 0x9E 0x00DF # LATIN SMALL LETTER SHARP S 0x9F 0x0192 # LATIN SMALL LETTER F WITH HOOK 0xA0 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xA1 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xA2 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xA3 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xA4 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xA5 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xA6 0x00AA # FEMININE ORDINAL INDICATOR 0xA7 0x00BA # MASCULINE ORDINAL INDICATOR 0xA8 0x00BF # INVERTED QUESTION MARK 0xA9 0x2310 # REVERSED NOT SIGN 0xAA 0x00AC # NOT SIGN 0xAB 0x00BD # VULGAR FRACTION ONE HALF 0xAC 0x00BC # VULGAR FRACTION ONE QUARTER 0xAD 0x00A1 # INVERTED EXCLAMATION MARK 0xAE 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAF 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xB0 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xB1 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xB2 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xB3 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xB4 0x0153 # LATIN SMALL LIGATURE OE 0xB5 0x0152 # LATIN CAPITAL LIGATURE OE 0xB6 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xB7 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xB8 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xB9 0x00A8 # DIAERESIS 0xBA 0x00B4 # ACUTE ACCENT 0xBB 0x2020 # DAGGER 0xBC 0x00B6 # PILCROW SIGN 0xBD 0x00A9 # COPYRIGHT SIGN 0xBE 0x00AE # REGISTERED SIGN 0xBF 0x2122 # TRADE MARK SIGN 0xC0 0x0133 # LATIN SMALL LIGATURE IJ 0xC1 0x0132 # LATIN CAPITAL LIGATURE IJ 0xC2 0x05D0 # HEBREW LETTER ALEF 0xC3 0x05D1 # HEBREW LETTER BET 0xC4 0x05D2 # HEBREW LETTER GIMEL 0xC5 0x05D3 # HEBREW LETTER DALET 0xC6 0x05D4 # HEBREW LETTER HE 0xC7 0x05D5 # HEBREW LETTER VAV 0xC8 0x05D6 # HEBREW LETTER ZAYIN 0xC9 0x05D7 # HEBREW LETTER HET 0xCA 0x05D8 # HEBREW LETTER TET 0xCB 0x05D9 # HEBREW LETTER YOD 0xCC 0x05DB # HEBREW LETTER KAF 0xCD 0x05DC # HEBREW LETTER LAMED 0xCE 0x05DE # HEBREW LETTER MEM 0xCF 0x05E0 # HEBREW LETTER NUN 0xD0 0x05E1 # HEBREW LETTER SAMEKH 0xD1 0x05E2 # HEBREW LETTER AYIN 0xD2 0x05E4 # HEBREW LETTER PE 0xD3 0x05E6 # HEBREW LETTER TSADI 0xD4 0x05E7 # HEBREW LETTER QOF 0xD5 0x05E8 # HEBREW LETTER RESH 0xD6 0x05E9 # HEBREW LETTER SHIN 0xD7 0x05EA # HEBREW LETTER TAV 0xD8 0x05DF # HEBREW LETTER FINAL NUN 0xD9 0x05DA # HEBREW LETTER FINAL KAF 0xDA 0x05DD # HEBREW LETTER FINAL MEM 0xDB 0x05E3 # HEBREW LETTER FINAL PE 0xDC 0x05E5 # HEBREW LETTER FINAL TSADI 0xDD 0x00A7 # SECTION SIGN 0xDE 0x2227 # LOGICAL AND 0xDF 0x221E # INFINITY 0xE0 0x03B1 # GREEK SMALL LETTER ALPHA 0xE1 0x03B2 # GREEK SMALL LETTER BETA 0xE2 0x0393 # GREEK CAPITAL LETTER GAMMA 0xE3 0x03C0 # GREEK SMALL LETTER PI 0xE4 0x03A3 # GREEK CAPITAL LETTER SIGMA 0xE5 0x03C3 # GREEK SMALL LETTER SIGMA 0xE6 0x00B5 # MICRO SIGN 0xE7 0x03C4 # GREEK SMALL LETTER TAU 0xE8 0x03A6 # GREEK CAPITAL LETTER PHI 0xE9 0x0398 # GREEK CAPITAL LETTER THETA 0xEA 0x03A9 # GREEK CAPITAL LETTER OMEGA 0xEB 0x03B4 # GREEK SMALL LETTER DELTA 0xEC 0x222E # CONTOUR INTEGRAL 0xED 0x03D5 # GREEK PHI SYMBOL 0xEE 0x2208 # ELEMENT OF 0xEF 0x2229 # INTERSECTION 0xF0 0x2261 # IDENTICAL TO 0xF1 0x00B1 # PLUS-MINUS SIGN 0xF2 0x2265 # GREATER-THAN OR EQUAL TO 0xF3 0x2264 # LESS-THAN OR EQUAL TO 0xF4 0x2320 # TOP HALF INTEGRAL 0xF5 0x2321 # BOTTOM HALF INTEGRAL 0xF6 0x00F7 # DIVISION SIGN 0xF7 0x2248 # ALMOST EQUAL TO 0xF8 0x00B0 # DEGREE SIGN 0xF9 0x2219 # BULLET OPERATOR 0xFA 0x00B7 # MIDDLE DOT 0xFB 0x221A # SQUARE ROOT 0xFC 0x207F # SUPERSCRIPT LATIN SMALL LETTER N 0xFD 0x00B2 # SUPERSCRIPT TWO 0xFE 0x00B3 # SUPERSCRIPT THREE 0xFF 0x00AF # MACRONbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MPETSCII.txt000066400000000000000000000207351506470510200307450ustar00rootroot00000000000000# Name: U8/M PETSCII # Aliases: U8-M_PETSCII, x-u8m-petscii # Include: C0, C1 # Merges both primary and alternate PETSCII character sets into # a single character set with minimal changes in character codes. # # Primary $00 - $1F -> U8/M 0x00 - 0x1F (control codes) # Primary $20 - $3F -> U8/M 0x20 - 0x3F # Primary $40 - $5F -> U8/M 0x40 - 0x5F # Primary $60 - $7F -> U8/M 0x60 - 0x7F # Primary $80 - $9F -> U8/M 0x80 - 0x9F (control codes) # Primary $A0 - $BF -> U8/M 0xA0 - 0xBF # Primary $C0 - $DF -> U8/M 0x60 - 0x7F # Primary $E0 - $FF -> U8/M 0xA0 - 0xBF # # Altern. $00 - $1F -> U8/M 0x00 - 0x1F (control codes) # Altern. $20 - $3F -> U8/M 0x20 - 0x3F # Altern. $40 - $5F -> U8/M 0xC0 - 0xDF except $5E -> 0x5E and $5F -> 0x5F # Altern. $60 - $7F -> U8/M 0xE0 - 0xFF # Altern. $80 - $9F -> U8/M 0x80 - 0x9F (control codes) # Altern. $A0 - $BF -> U8/M 0xA0 - 0xBF except $A9 -> 0xDE and $BA -> 0xDF # Altern. $C0 - $DF -> U8/M 0xE0 - 0xFF # Altern. $E0 - $FF -> U8/M 0xA0 - 0xBF except $E9 -> 0xDE and $FA -> 0xDF # Primary $20 - $3F # Alternate $20 - $3F 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK # Primary $40 - $5F 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x00A3 # POUND SIGN 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x2191 # UPWARDS ARROW 0x5F 0x2190 # LEFTWARDS ARROW # Primary $60 - $7F and $C0 - $DF 0x60 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0x61 0x2660 # BLACK SPADE SUIT 0x62 0x1FB72 # VERTICAL ONE EIGHTH BLOCK-4 0x63 0x1FB78 # HORIZONTAL ONE EIGHTH BLOCK-4 0x64 0x1FB77 # HORIZONTAL ONE EIGHTH BLOCK-3 0x65 0x1FB76 # HORIZONTAL ONE EIGHTH BLOCK-2 0x66 0x1FB7A # HORIZONTAL ONE EIGHTH BLOCK-6 0x67 0x1FB71 # VERTICAL ONE EIGHTH BLOCK-3 0x68 0x1FB74 # VERTICAL ONE EIGHTH BLOCK-6 0x69 0x256E # BOX DRAWINGS LIGHT ARC DOWN AND LEFT 0x6A 0x2570 # BOX DRAWINGS LIGHT ARC UP AND RIGHT 0x6B 0x256F # BOX DRAWINGS LIGHT ARC UP AND LEFT 0x6C 0x1FB7C # LEFT AND LOWER ONE EIGHTH BLOCK 0x6D 0x2572 # BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT 0x6E 0x2571 # BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT 0x6F 0x1FB7D # LEFT AND UPPER ONE EIGHTH BLOCK 0x70 0x1FB7E # RIGHT AND UPPER ONE EIGHTH BLOCK 0x71 0x2022 # BULLET (or 0x25CF BLACK CIRCLE) 0x72 0x1FB7B # HORIZONTAL ONE EIGHTH BLOCK-7 0x73 0x2665 # BLACK HEART SUIT 0x74 0x1FB70 # VERTICAL ONE EIGHTH BLOCK-2 0x75 0x256D # BOX DRAWINGS LIGHT ARC DOWN AND RIGHT 0x76 0x2573 # BOX DRAWINGS LIGHT DIAGONAL CROSS 0x77 0x25CB # WHITE CIRCLE (or 0x25E6 WHITE BULLET) 0x78 0x2663 # BLACK CLUB SUIT 0x79 0x1FB75 # VERTICAL ONE EIGHTH BLOCK-7 0x7A 0x2666 # BLACK DIAMOND SUIT 0x7B 0x253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL 0x7C 0x1FB8C # LEFT HALF MEDIUM SHADE 0x7D 0x2502 # BOX DRAWINGS LIGHT VERTICAL 0x7E 0x03C0 # GREEK SMALL LETTER PI 0x7F 0x25E5 # BLACK UPPER RIGHT TRIANGLE # Primary $A0 - $BF and $E0 - $FF # Alternate $A0 - $BF and $E0 - $FF # (except $A9/$E9 and $BA/$FA which are mapped to 0xDE and 0xDF) 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x258C # LEFT HALF BLOCK 0xA2 0x2584 # LOWER HALF BLOCK 0xA3 0x2594 # UPPER ONE EIGHTH BLOCK 0xA4 0x2581 # LOWER ONE EIGHTH BLOCK 0xA5 0x258F # LEFT ONE EIGHTH BLOCK 0xA6 0x2592 # MEDIUM SHADE 0xA7 0x2595 # RIGHT ONE EIGHTH BLOCK 0xA8 0x1FB8F # LOWER HALF MEDIUM SHADE # This is only primary $A9/$E9; alternate $A9/$E9 is 0xDE instead. 0xA9 0x25E4 # BLACK UPPER LEFT TRIANGLE 0xAA 0x1FB87 # RIGHT ONE QUARTER BLOCK 0xAB 0x251C # BOX DRAWINGS LIGHT VERTICAL AND RIGHT 0xAC 0x2597 # QUADRANT LOWER RIGHT 0xAD 0x2514 # BOX DRAWINGS LIGHT UP AND RIGHT 0xAE 0x2510 # BOX DRAWINGS LIGHT DOWN AND LEFT 0xAF 0x2582 # LOWER ONE QUARTER BLOCK 0xB0 0x250C # BOX DRAWINGS LIGHT DOWN AND RIGHT 0xB1 0x2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL 0xB2 0x252C # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL 0xB3 0x2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT 0xB4 0x258E # LEFT ONE QUARTER BLOCK 0xB5 0x258D # LEFT THREE EIGHTHS BLOCK 0xB6 0x1FB88 # RIGHT THREE EIGHTHS BLOCK 0xB7 0x1FB82 # UPPER ONE QUARTER BLOCK 0xB8 0x1FB83 # UPPER THREE EIGHTHS BLOCK 0xB9 0x2583 # LOWER THREE EIGHTHS BLOCK # This is only primary $BA/$FA; alternate $BA/$FA is 0xDF instead. 0xBA 0x1FB7F # RIGHT AND LOWER ONE EIGHTH BLOCK 0xBB 0x2596 # QUADRANT LOWER LEFT 0xBC 0x259D # QUADRANT UPPER RIGHT 0xBD 0x2518 # BOX DRAWINGS LIGHT UP AND LEFT 0xBE 0x2598 # QUADRANT UPPER LEFT 0xBF 0x259A # QUADRANT UPPER LEFT AND LOWER RIGHT # Alternate $40 - $5F # (except $5E and $5F which are mapped to 0x5E and 0x5F) 0xC0 0x0040 # COMMERCIAL AT 0xC1 0x0061 # LATIN SMALL LETTER A 0xC2 0x0062 # LATIN SMALL LETTER B 0xC3 0x0063 # LATIN SMALL LETTER C 0xC4 0x0064 # LATIN SMALL LETTER D 0xC5 0x0065 # LATIN SMALL LETTER E 0xC6 0x0066 # LATIN SMALL LETTER F 0xC7 0x0067 # LATIN SMALL LETTER G 0xC8 0x0068 # LATIN SMALL LETTER H 0xC9 0x0069 # LATIN SMALL LETTER I 0xCA 0x006A # LATIN SMALL LETTER J 0xCB 0x006B # LATIN SMALL LETTER K 0xCC 0x006C # LATIN SMALL LETTER L 0xCD 0x006D # LATIN SMALL LETTER M 0xCE 0x006E # LATIN SMALL LETTER N 0xCF 0x006F # LATIN SMALL LETTER O 0xD0 0x0070 # LATIN SMALL LETTER P 0xD1 0x0071 # LATIN SMALL LETTER Q 0xD2 0x0072 # LATIN SMALL LETTER R 0xD3 0x0073 # LATIN SMALL LETTER S 0xD4 0x0074 # LATIN SMALL LETTER T 0xD5 0x0075 # LATIN SMALL LETTER U 0xD6 0x0076 # LATIN SMALL LETTER V 0xD7 0x0077 # LATIN SMALL LETTER W 0xD8 0x0078 # LATIN SMALL LETTER X 0xD9 0x0079 # LATIN SMALL LETTER Y 0xDA 0x007A # LATIN SMALL LETTER Z 0xDB 0x005B # LEFT SQUARE BRACKET 0xDC 0x00A3 # POUND SIGN 0xDD 0x005D # RIGHT SQUARE BRACKET # This is actually alternate $A9; alternate $5E is 0x5E instead. 0xDE 0x1FB99 # UPPER RIGHT TO LOWER LEFT FILL # This is actually alternate $BA; alternate $5F is 0x5F instead. 0xDF 0x2713 # CHECK MARK # Alternate $60 - $7F and $C0 - $DF 0xE0 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL 0xE1 0x0041 # LATIN CAPITAL LETTER A 0xE2 0x0042 # LATIN CAPITAL LETTER B 0xE3 0x0043 # LATIN CAPITAL LETTER C 0xE4 0x0044 # LATIN CAPITAL LETTER D 0xE5 0x0045 # LATIN CAPITAL LETTER E 0xE6 0x0046 # LATIN CAPITAL LETTER F 0xE7 0x0047 # LATIN CAPITAL LETTER G 0xE8 0x0048 # LATIN CAPITAL LETTER H 0xE9 0x0049 # LATIN CAPITAL LETTER I 0xEA 0x004A # LATIN CAPITAL LETTER J 0xEB 0x004B # LATIN CAPITAL LETTER K 0xEC 0x004C # LATIN CAPITAL LETTER L 0xED 0x004D # LATIN CAPITAL LETTER M 0xEE 0x004E # LATIN CAPITAL LETTER N 0xEF 0x004F # LATIN CAPITAL LETTER O 0xF0 0x0050 # LATIN CAPITAL LETTER P 0xF1 0x0051 # LATIN CAPITAL LETTER Q 0xF2 0x0052 # LATIN CAPITAL LETTER R 0xF3 0x0053 # LATIN CAPITAL LETTER S 0xF4 0x0054 # LATIN CAPITAL LETTER T 0xF5 0x0055 # LATIN CAPITAL LETTER U 0xF6 0x0056 # LATIN CAPITAL LETTER V 0xF7 0x0057 # LATIN CAPITAL LETTER W 0xF8 0x0058 # LATIN CAPITAL LETTER X 0xF9 0x0059 # LATIN CAPITAL LETTER Y 0xFA 0x005A # LATIN CAPITAL LETTER Z 0xFB 0x253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL 0xFC 0x1FB8C # LEFT HALF MEDIUM SHADE 0xFD 0x2502 # BOX DRAWINGS LIGHT VERTICAL 0xFE 0x1FB96 # INVERSE CHECKER BOARD FILL 0xFF 0x1FB98 # UPPER LEFT TO LOWER RIGHT FILLbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MRISCOS.txt000066400000000000000000000202461506470510200306440ustar00rootroot00000000000000# Name: U8/M RISC OS # Aliases: U8-M_RISC_OS, x-u8m-riscos # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x20AC # EURO SIGN 0x81 0x0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX 0x82 0x0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX 0x83 0x25F0 # WHITE SQUARE WITH UPPER LEFT QUADRANT 0x84 0x1FBC0 # WHITE HEAVY SALTIRE WITH ROUNDED CORNERS 0x85 0x0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX 0x86 0x0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX 0x87 0x0087 # 0x88 0x21E6 # LEFTWARDS WHITE ARROW 0x89 0x21E8 # RIGHTWARDS WHITE ARROW 0x8A 0x21E9 # DOWNWARDS WHITE ARROW 0x8B 0x21E7 # UPWARDS WHITE ARROW 0x8C 0x2026 # HORIZONTAL ELLIPSIS 0x8D 0x2122 # TRADE MARK SIGN 0x8E 0x2030 # PER MILLE SIGN 0x8F 0x2022 # BULLET 0x90 0x2018 # LEFT SINGLE QUOTATION MARK 0x91 0x2019 # RIGHT SINGLE QUOTATION MARK 0x92 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0x93 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0x94 0x201C # LEFT DOUBLE QUOTATION MARK 0x95 0x201D # RIGHT DOUBLE QUOTATION MARK 0x96 0x201E # DOUBLE LOW-9 QUOTATION MARK 0x97 0x2013 # EN DASH 0x98 0x2014 # EM DASH 0x99 0x2212 # MINUS SIGN 0x9A 0x0152 # LATIN CAPITAL LIGATURE OE 0x9B 0x0153 # LATIN SMALL LIGATURE OE 0x9C 0x2020 # DAGGER 0x9D 0x2021 # DOUBLE DAGGER 0x9E 0xFB01 # LATIN SMALL LIGATURE FI 0x9F 0xFB02 # LATIN SMALL LIGATURE FL 0xA0 0x00A0 # NO-BREAK SPACE 0xA1 0x00A1 # INVERTED EXCLAMATION MARK 0xA2 0x00A2 # CENT SIGN 0xA3 0x00A3 # POUND SIGN 0xA4 0x00A4 # CURRENCY SIGN 0xA5 0x00A5 # YEN SIGN 0xA6 0x00A6 # BROKEN BAR 0xA7 0x00A7 # SECTION SIGN 0xA8 0x00A8 # DIAERESIS 0xA9 0x00A9 # COPYRIGHT SIGN 0xAA 0x00AA # FEMININE ORDINAL INDICATOR 0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0xAC 0x00AC # NOT SIGN 0xAD 0x00AD # SOFT HYPHEN 0xAE 0x00AE # REGISTERED SIGN 0xAF 0x00AF # MACRON 0xB0 0x00B0 # DEGREE SIGN 0xB1 0x00B1 # PLUS-MINUS SIGN 0xB2 0x00B2 # SUPERSCRIPT TWO 0xB3 0x00B3 # SUPERSCRIPT THREE 0xB4 0x00B4 # ACUTE ACCENT 0xB5 0x00B5 # MICRO SIGN 0xB6 0x00B6 # PILCROW SIGN 0xB7 0x00B7 # MIDDLE DOT 0xB8 0x00B8 # CEDILLA 0xB9 0x00B9 # SUPERSCRIPT ONE 0xBA 0x00BA # MASCULINE ORDINAL INDICATOR 0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0xBC 0x00BC # VULGAR FRACTION ONE QUARTER 0xBD 0x00BD # VULGAR FRACTION ONE HALF 0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS 0xBF 0x00BF # INVERTED QUESTION MARK 0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS 0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE 0xC6 0x00C6 # LATIN CAPITAL LETTER AE 0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE 0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS 0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE 0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS 0xD0 0x00D0 # LATIN CAPITAL LETTER ETH 0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE 0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS 0xD7 0x00D7 # MULTIPLICATION SIGN 0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE 0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE 0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xDE 0x00DE # LATIN CAPITAL LETTER THORN 0xDF 0x00DF # LATIN SMALL LETTER SHARP S 0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS 0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE 0xE6 0x00E6 # LATIN SMALL LETTER AE 0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE 0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS 0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE 0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX 0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS 0xF0 0x00F0 # LATIN SMALL LETTER ETH 0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE 0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS 0xF7 0x00F7 # DIVISION SIGN 0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE 0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE 0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX 0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xFE 0x00FE # LATIN SMALL LETTER THORN 0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESISbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/mappings/U8MSpectrum.txt000066400000000000000000000203211506470510200314360ustar00rootroot00000000000000# Name: U8/M Spectrum # Aliases: U8-M_Spectrum, x-u8m-spectrum # Include: C0 0x20 0x0020 # SPACE 0x21 0x0021 # EXCLAMATION MARK 0x22 0x0022 # QUOTATION MARK 0x23 0x0023 # NUMBER SIGN 0x24 0x0024 # DOLLAR SIGN 0x25 0x0025 # PERCENT SIGN 0x26 0x0026 # AMPERSAND 0x27 0x0027 # APOSTROPHE 0x28 0x0028 # LEFT PARENTHESIS 0x29 0x0029 # RIGHT PARENTHESIS 0x2A 0x002A # ASTERISK 0x2B 0x002B # PLUS SIGN 0x2C 0x002C # COMMA 0x2D 0x002D # HYPHEN-MINUS 0x2E 0x002E # FULL STOP 0x2F 0x002F # SOLIDUS 0x30 0x0030 # DIGIT ZERO 0x31 0x0031 # DIGIT ONE 0x32 0x0032 # DIGIT TWO 0x33 0x0033 # DIGIT THREE 0x34 0x0034 # DIGIT FOUR 0x35 0x0035 # DIGIT FIVE 0x36 0x0036 # DIGIT SIX 0x37 0x0037 # DIGIT SEVEN 0x38 0x0038 # DIGIT EIGHT 0x39 0x0039 # DIGIT NINE 0x3A 0x003A # COLON 0x3B 0x003B # SEMICOLON 0x3C 0x003C # LESS-THAN SIGN 0x3D 0x003D # EQUALS SIGN 0x3E 0x003E # GREATER-THAN SIGN 0x3F 0x003F # QUESTION MARK 0x40 0x0040 # COMMERCIAL AT 0x41 0x0041 # LATIN CAPITAL LETTER A 0x42 0x0042 # LATIN CAPITAL LETTER B 0x43 0x0043 # LATIN CAPITAL LETTER C 0x44 0x0044 # LATIN CAPITAL LETTER D 0x45 0x0045 # LATIN CAPITAL LETTER E 0x46 0x0046 # LATIN CAPITAL LETTER F 0x47 0x0047 # LATIN CAPITAL LETTER G 0x48 0x0048 # LATIN CAPITAL LETTER H 0x49 0x0049 # LATIN CAPITAL LETTER I 0x4A 0x004A # LATIN CAPITAL LETTER J 0x4B 0x004B # LATIN CAPITAL LETTER K 0x4C 0x004C # LATIN CAPITAL LETTER L 0x4D 0x004D # LATIN CAPITAL LETTER M 0x4E 0x004E # LATIN CAPITAL LETTER N 0x4F 0x004F # LATIN CAPITAL LETTER O 0x50 0x0050 # LATIN CAPITAL LETTER P 0x51 0x0051 # LATIN CAPITAL LETTER Q 0x52 0x0052 # LATIN CAPITAL LETTER R 0x53 0x0053 # LATIN CAPITAL LETTER S 0x54 0x0054 # LATIN CAPITAL LETTER T 0x55 0x0055 # LATIN CAPITAL LETTER U 0x56 0x0056 # LATIN CAPITAL LETTER V 0x57 0x0057 # LATIN CAPITAL LETTER W 0x58 0x0058 # LATIN CAPITAL LETTER X 0x59 0x0059 # LATIN CAPITAL LETTER Y 0x5A 0x005A # LATIN CAPITAL LETTER Z 0x5B 0x005B # LEFT SQUARE BRACKET 0x5C 0x005C # REVERSE SOLIDUS 0x5D 0x005D # RIGHT SQUARE BRACKET 0x5E 0x005E # CIRCUMFLEX ACCENT 0x5F 0x005F # LOW LINE 0x60 0x0060 # GRAVE ACCENT 0x61 0x0061 # LATIN SMALL LETTER A 0x62 0x0062 # LATIN SMALL LETTER B 0x63 0x0063 # LATIN SMALL LETTER C 0x64 0x0064 # LATIN SMALL LETTER D 0x65 0x0065 # LATIN SMALL LETTER E 0x66 0x0066 # LATIN SMALL LETTER F 0x67 0x0067 # LATIN SMALL LETTER G 0x68 0x0068 # LATIN SMALL LETTER H 0x69 0x0069 # LATIN SMALL LETTER I 0x6A 0x006A # LATIN SMALL LETTER J 0x6B 0x006B # LATIN SMALL LETTER K 0x6C 0x006C # LATIN SMALL LETTER L 0x6D 0x006D # LATIN SMALL LETTER M 0x6E 0x006E # LATIN SMALL LETTER N 0x6F 0x006F # LATIN SMALL LETTER O 0x70 0x0070 # LATIN SMALL LETTER P 0x71 0x0071 # LATIN SMALL LETTER Q 0x72 0x0072 # LATIN SMALL LETTER R 0x73 0x0073 # LATIN SMALL LETTER S 0x74 0x0074 # LATIN SMALL LETTER T 0x75 0x0075 # LATIN SMALL LETTER U 0x76 0x0076 # LATIN SMALL LETTER V 0x77 0x0077 # LATIN SMALL LETTER W 0x78 0x0078 # LATIN SMALL LETTER X 0x79 0x0079 # LATIN SMALL LETTER Y 0x7A 0x007A # LATIN SMALL LETTER Z 0x7B 0x007B # LEFT CURLY BRACKET 0x7C 0x007C # VERTICAL LINE 0x7D 0x007D # RIGHT CURLY BRACKET 0x7E 0x007E # TILDE 0x7F 0x007F # DELETE 0x80 0x00A0 # NO-BREAK SPACE 0x81 0x259D # QUADRANT UPPER RIGHT 0x82 0x2598 # QUADRANT UPPER LEFT 0x83 0x2580 # UPPER HALF BLOCK 0x84 0x2597 # QUADRANT LOWER RIGHT 0x85 0x2590 # RIGHT HALF BLOCK 0x86 0x259A # QUADRANT UPPER LEFT AND LOWER RIGHT 0x87 0x259C # QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT 0x88 0x2596 # QUADRANT LOWER LEFT 0x89 0x259E # QUADRANT UPPER RIGHT AND LOWER LEFT 0x8A 0x258C # LEFT HALF BLOCK 0x8B 0x259B # QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT 0x8C 0x2584 # LOWER HALF BLOCK 0x8D 0x259F # QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT 0x8E 0x2599 # QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT 0x8F 0x2588 # FULL BLOCK 0x90 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE 0x91 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE 0x92 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE 0x93 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE 0x94 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE 0x95 0x00E1 # LATIN SMALL LETTER A WITH ACUTE 0x96 0x00E9 # LATIN SMALL LETTER E WITH ACUTE 0x97 0x00ED # LATIN SMALL LETTER I WITH ACUTE 0x98 0x00F3 # LATIN SMALL LETTER O WITH ACUTE 0x99 0x00FA # LATIN SMALL LETTER U WITH ACUTE 0x9A 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE 0x9B 0x00E0 # LATIN SMALL LETTER A WITH GRAVE 0x9C 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0x9D 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0x9E 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX 0x9F 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX 0xA0 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX 0xA1 0x00E3 # LATIN SMALL LETTER A WITH TILDE 0xA2 0x00F5 # LATIN SMALL LETTER O WITH TILDE 0xA3 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA 0xA4 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA 0xA5 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xA6 0x00F1 # LATIN SMALL LETTER N WITH TILDE 0xA7 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE 0xA8 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE 0xA9 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE 0xAA 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS 0xAB 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS 0xAC 0x011B # LATIN SMALL LETTER E WITH CARON 0xAD 0x011A # LATIN CAPITAL LETTER E WITH CARON 0xAE 0x0161 # LATIN SMALL LETTER S WITH CARON 0xAF 0x0160 # LATIN CAPITAL LETTER S WITH CARON 0xB0 0x010D # LATIN SMALL LETTER C WITH CARON 0xB1 0x010C # LATIN CAPITAL LETTER C WITH CARON 0xB2 0x0159 # LATIN SMALL LETTER R WITH CARON 0xB3 0x0158 # LATIN CAPITAL LETTER R WITH CARON 0xB4 0x017E # LATIN SMALL LETTER Z WITH CARON 0xB5 0x017D # LATIN CAPITAL LETTER Z WITH CARON 0xB6 0x00FD # LATIN SMALL LETTER Y WITH ACUTE 0xB7 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE 0xB8 0x010F # LATIN SMALL LETTER D WITH CARON 0xB9 0x010E # LATIN CAPITAL LETTER D WITH CARON 0xBA 0x0148 # LATIN SMALL LETTER N WITH CARON 0xBB 0x0147 # LATIN CAPITAL LETTER N WITH CARON 0xBC 0x0165 # LATIN SMALL LETTER T WITH CARON 0xBD 0x0164 # LATIN CAPITAL LETTER T WITH CARON 0xBE 0x016F # LATIN SMALL LETTER U WITH RING ABOVE 0xBF 0x016E # LATIN CAPITAL LETTER U WITH RING ABOVE 0xC0 0x0040 # COMMERCIAL AT 0xC1 0x0041 # LATIN CAPITAL LETTER A 0xC2 0x0042 # LATIN CAPITAL LETTER B 0xC3 0x0043 # LATIN CAPITAL LETTER C 0xC4 0x0044 # LATIN CAPITAL LETTER D 0xC5 0x0045 # LATIN CAPITAL LETTER E 0xC6 0x0046 # LATIN CAPITAL LETTER F 0xC7 0x0047 # LATIN CAPITAL LETTER G 0xC8 0x0048 # LATIN CAPITAL LETTER H 0xC9 0x0049 # LATIN CAPITAL LETTER I 0xCA 0x004A # LATIN CAPITAL LETTER J 0xCB 0x004B # LATIN CAPITAL LETTER K 0xCC 0x004C # LATIN CAPITAL LETTER L 0xCD 0x004D # LATIN CAPITAL LETTER M 0xCE 0x004E # LATIN CAPITAL LETTER N 0xCF 0x004F # LATIN CAPITAL LETTER O 0xD0 0x0050 # LATIN CAPITAL LETTER P 0xD1 0x0051 # LATIN CAPITAL LETTER Q 0xD2 0x0052 # LATIN CAPITAL LETTER R 0xD3 0x0053 # LATIN CAPITAL LETTER S 0xD4 0x0054 # LATIN CAPITAL LETTER T 0xD5 0x0055 # LATIN CAPITAL LETTER U 0xD6 0x0056 # LATIN CAPITAL LETTER V 0xD7 0x0057 # LATIN CAPITAL LETTER W 0xD8 0x0058 # LATIN CAPITAL LETTER X 0xD9 0x0059 # LATIN CAPITAL LETTER Y 0xDA 0x005A # LATIN CAPITAL LETTER Z 0xDB 0x2592 # MEDIUM SHADE 0xDC 0x1FB8F # LOWER HALF MEDIUM SHADE 0xDD 0x1FB8E # UPPER HALF MEDIUM SHADE 0xDE 0x2191 # UPWARDS ARROW 0xDF 0x005F # LOW LINE 0xE0 0x00A3 # POUND SIGN 0xE1 0x0061 # LATIN SMALL LETTER A 0xE2 0x0062 # LATIN SMALL LETTER B 0xE3 0x0063 # LATIN SMALL LETTER C 0xE4 0x0064 # LATIN SMALL LETTER D 0xE5 0x0065 # LATIN SMALL LETTER E 0xE6 0x0066 # LATIN SMALL LETTER F 0xE7 0x0067 # LATIN SMALL LETTER G 0xE8 0x0068 # LATIN SMALL LETTER H 0xE9 0x0069 # LATIN SMALL LETTER I 0xEA 0x006A # LATIN SMALL LETTER J 0xEB 0x006B # LATIN SMALL LETTER K 0xEC 0x006C # LATIN SMALL LETTER L 0xED 0x006D # LATIN SMALL LETTER M 0xEE 0x006E # LATIN SMALL LETTER N 0xEF 0x006F # LATIN SMALL LETTER O 0xF0 0x0070 # LATIN SMALL LETTER P 0xF1 0x0071 # LATIN SMALL LETTER Q 0xF2 0x0072 # LATIN SMALL LETTER R 0xF3 0x0073 # LATIN SMALL LETTER S 0xF4 0x0074 # LATIN SMALL LETTER T 0xF5 0x0075 # LATIN SMALL LETTER U 0xF6 0x0076 # LATIN SMALL LETTER V 0xF7 0x0077 # LATIN SMALL LETTER W 0xF8 0x0078 # LATIN SMALL LETTER X 0xF9 0x0079 # LATIN SMALL LETTER Y 0xFA 0x007A # LATIN SMALL LETTER Z 0xFB 0x1FB90 # INVERSE MEDIUM SHADE 0xFC 0x1FB91 # UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE 0xFD 0x1FB92 # UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK 0xFE 0x007E # TILDE 0xFF 0x00A9 # COPYRIGHT SIGNbitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/000077500000000000000000000000001506470510200262135ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/DfontToc.java000066400000000000000000000015761506470510200306070ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.IOException; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; import com.kreative.unicode.ttflib.DfontResourceType; public class DfontToc { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { DfontFile dfont = new DfontFile(new File(arg)); System.out.println("\tType\tID\tLength\tName"); for (DfontResourceType t : dfont.getResourceTypes()) { for (DfontResource r : t.getResources()) { String name = r.getName(); if (name == null) name = ""; System.out.println( "\t" + t.getTypeString() + "\t" + r.getId() + "\t" + r.getData().length + "\t" + name ); } } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/DfontUnpack.java000066400000000000000000000017361506470510200313010ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import com.kreative.unicode.ttflib.DfontFile; import com.kreative.unicode.ttflib.DfontResource; import com.kreative.unicode.ttflib.DfontResourceType; public class DfontUnpack { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { File file = new File(arg); DfontFile dfont = new DfontFile(file); DfontResourceType sfnt = dfont.getResourceType("sfnt"); if (sfnt != null) { for (DfontResource r : sfnt.getResources()) { String newName = file.getName() + "." + r.getId() + ".ttf"; System.out.println("\t" + newName); File newFile = new File(file.getParentFile(), newName); FileOutputStream out = new FileOutputStream(newFile); out.write(r.getData()); out.close(); } } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/PuaaLookup.java000066400000000000000000000121731506470510200311420ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.awt.Font; import java.awt.font.OpenType; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.kreative.unicode.ttflib.FindOpenType; import com.kreative.unicode.ttflib.PuaaEntry; import com.kreative.unicode.ttflib.PuaaTable; import com.kreative.unicode.ttflib.TtfFile; public class PuaaLookup { public static void main(String[] args) { try { System.setProperty("apple.awt.UIElement", "true"); } catch (Exception e) {} if (args.length == 0) { printHelp(); return; } PuaaTable table = null; List properties = new ArrayList(); List codePoints = new ArrayList(); boolean parsingOptions = true; int argi = 0; while (argi < args.length) { String arg = args[argi++]; if (parsingOptions && arg.startsWith("-")) { if (arg.equals("--")) { parsingOptions = false; } else if (arg.equals("-f") && argi < args.length) { PuaaTable t = readFromFont(args[argi++]); if (t != null) table = t; } else if (arg.equals("-i") && argi < args.length) { PuaaTable t = readFromFile(args[argi++]); if (t != null) table = t; } else if (arg.equals("-p") && argi < args.length) { properties.add(args[argi++]); } else if (arg.equals("-c") && argi < args.length) { codePoints.add(parseCP(args[argi++])); } else if (arg.equals("--help")) { printHelp(); } else { System.out.println("Unknown option: " + arg); } } else { codePoints.add(parseCP(arg)); } } if (table == null) return; printChars(table, properties, codePoints); } private static PuaaTable readFromFont(String arg) { try { Font font = new Font(arg, 0, 1); OpenType ot = FindOpenType.forFont(font); if (ot != null) { byte[] d = ot.getFontTable("PUAA"); if (d != null) return new PuaaTable(d); System.out.println("Error: Table not found."); return null; } System.out.println("Error: Not an OpenType font."); return null; } catch (Exception e) { System.out.println("Error: " + e); return null; } } private static PuaaTable readFromFile(String arg) { try { File file = new File(arg); TtfFile ttf = new TtfFile(file); PuaaTable t = ttf.getTableAs(PuaaTable.class, "PUAA"); if (t != null) return t; System.out.println("Error: Table not found."); return null; } catch (Exception e) { System.out.println("Error: " + e); return null; } } private static void printChars(PuaaTable t, List p, List c) { if (c == null || c.isEmpty()) { printProps(t, p); return; } int nameWidth = 0; for (String prop : t.getProperties()) { if (prop.length() > nameWidth) nameWidth = prop.length(); } nameWidth += 4; Map> tables = new HashMap>(); for (String prop : t.getProperties()) tables.put(prop, t.getPropertyMap(prop)); for (int cp : c) { System.out.println("U+" + toHexString(cp) + ":"); for (String prop : t.getProperties()) { if (p.isEmpty() || p.contains(prop)) { if (tables.get(prop).containsKey(cp)) { StringBuffer sb = new StringBuffer(" "); sb.append(prop); sb.append(":"); while (sb.length() < nameWidth) sb.append(" "); sb.append(tables.get(prop).get(cp)); System.out.println(sb.toString()); } } } } } private static void printProps(PuaaTable t, List p) { if (p == null || p.isEmpty()) { printTOC(t); return; } for (String prop : t.getProperties()) { if (p.contains(prop)) { System.out.println(prop + ":"); for (PuaaEntry e : t.getPropertyRuns(prop)) { StringBuffer sb = new StringBuffer(" "); sb.append(toHexString(e.getFirstCodePoint())); if (e.getFirstCodePoint() != e.getLastCodePoint()) { sb.append(".."); sb.append(toHexString(e.getLastCodePoint())); } sb.append(":"); while (sb.length() < 18) sb.append(" "); sb.append(e.getPropertyString(e.getFirstCodePoint())); System.out.println(sb.toString()); } } } } private static void printTOC(PuaaTable t) { System.out.println("Properties:"); for (String prop : t.getProperties()) { System.out.println(" " + prop); } } private static String toHexString(int v) { String s = Integer.toHexString(v).toUpperCase(); if (s.length() < 4) s = ("0000" + s).substring(s.length()); return s; } private static int parseCP(String s) { s = s.replaceAll("[Uu][+]|[0][Xx]|\\s+", ""); return Integer.parseInt(s, 16); } private static void printHelp() { System.out.println(); System.out.println("PuaaLookup - Look up Unicode Character Database properties in TrueType files."); System.out.println(); System.out.println(" -f Specify source TrueType font name."); System.out.println(" -i Specify source TrueType file."); System.out.println(" -p Specify properties to look up."); System.out.println(" -c Specify code points to look up."); System.out.println(" -- Process remaining arguments as code points."); System.out.println(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtcName.java000066400000000000000000000016301506470510200304110ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.IOException; import java.util.List; import com.kreative.unicode.ttflib.NameTable; import com.kreative.unicode.ttflib.TtcFile; import com.kreative.unicode.ttflib.TtcFont; public class TtcName { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { TtcFile ttc = new TtcFile(new File(arg)); List fonts = ttc.getFonts(); for (int i = 0; i < fonts.size(); i++) { System.out.println("\tFont #" + i); NameTable names = fonts.get(i).getTableAs(NameTable.class, "name"); if (names != null) { for (int j = 0; j < 256; j++) { String name = names.getName(j); if (name != null) { System.out.println("\t\t" + j + "\t" + name); } } } } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtcToc.java000066400000000000000000000015531506470510200302620ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.IOException; import java.util.List; import com.kreative.unicode.ttflib.TtcFile; import com.kreative.unicode.ttflib.TtcFont; import com.kreative.unicode.ttflib.TtfTable; public class TtcToc { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { TtcFile ttc = new TtcFile(new File(arg)); List fonts = ttc.getFonts(); for (int i = 0; i < fonts.size(); i++) { System.out.println("\tFont #" + i); System.out.println("\t\tTag\tOffset\tLength"); for (TtfTable t : fonts.get(i).getTables()) { System.out.println( "\t\t" + t.getTagString() + "\t" + t.getOffset() + "\t" + t.getLength() ); } } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtcUnpack.java000066400000000000000000000036241506470510200307570ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.kreative.unicode.ttflib.TtcFile; import com.kreative.unicode.ttflib.TtcFont; import com.kreative.unicode.ttflib.TtfTable; public class TtcUnpack { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { File file = new File(arg); TtcFile ttc = new TtcFile(file); List fonts = ttc.getFonts(); for (int i = 0; i < fonts.size(); i++) { TtcFont font = fonts.get(i); List tables = font.getTables(); List offsets = new ArrayList(); int offset = 12 + 16 * tables.size(); for (TtfTable table : tables) { offsets.add(offset); offset += table.getLength() + 3; offset &= ~3; } String newName = file.getName() + "." + i + ".ttf"; System.out.println("\t" + newName); File newFile = new File(file.getParentFile(), newName); FileOutputStream fos = new FileOutputStream(newFile); DataOutputStream out = new DataOutputStream(fos); out.writeInt(font.getScaler()); out.writeShort(font.getCount()); out.writeShort(font.getSearchRange()); out.writeShort(font.getEntrySelector()); out.writeShort(font.getRangeShift()); for (int j = 0; j < tables.size(); j++) { out.writeInt(tables.get(j).getTag()); out.writeInt(tables.get(j).getChecksum()); out.writeInt(offsets.get(j)); out.writeInt(tables.get(j).getLength()); } for (TtfTable table : tables) { out.write(table.getData()); int p = table.getLength() & 3; if (p > 0) while (p < 4) { out.write(0); p++; } } out.close(); fos.close(); } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtfName.java000066400000000000000000000012731506470510200304170ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.IOException; import com.kreative.unicode.ttflib.NameTable; import com.kreative.unicode.ttflib.TtfFile; public class TtfName { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { TtfFile ttf = new TtfFile(new File(arg)); NameTable names = ttf.getTableAs(NameTable.class, "name"); if (names != null) { for (int i = 0; i < 256; i++) { String name = names.getName(i); if (name != null) { System.out.println("\t" + i + "\t" + name); } } } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtfToc.java000066400000000000000000000012151506470510200302600ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.IOException; import com.kreative.unicode.ttflib.TtfFile; import com.kreative.unicode.ttflib.TtfTable; public class TtfToc { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { TtfFile ttf = new TtfFile(new File(arg)); System.out.println("\tTag\tOffset\tLength"); for (TtfTable t : ttf.getTables()) { System.out.println( "\t" + t.getTagString() + "\t" + t.getOffset() + "\t" + t.getLength() ); } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttfbin/TtfUnpack.java000066400000000000000000000015621506470510200307610ustar00rootroot00000000000000package com.kreative.unicode.ttfbin; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import com.kreative.unicode.ttflib.TtfFile; import com.kreative.unicode.ttflib.TtfTable; public class TtfUnpack { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); try { File file = new File(arg); TtfFile ttf = new TtfFile(file); for (TtfTable t : ttf.getTables()) { String newTag = t.getTagString().replaceAll("[^A-Za-z0-9]", "_"); String newName = file.getName() + "." + newTag + ".bin"; System.out.println("\t" + newName); File newFile = new File(file.getParentFile(), newName); FileOutputStream out = new FileOutputStream(newFile); out.write(t.getData()); out.close(); } } catch (IOException e) { System.out.println("\tERROR: " + e); } } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/000077500000000000000000000000001506470510200262115ustar00rootroot00000000000000bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/DfontFile.java000066400000000000000000000174701506470510200307370ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class DfontFile { private int dataOffset; private int mapOffset; private int attributes; private int typesOffset; private int namesOffset; private final List rwTypes = new ArrayList(); private final Map rwByType = new TreeMap(); private final Map rwByTypeString = new TreeMap(); private final List roTypes = Collections.unmodifiableList(rwTypes); private final Map roByType = Collections.unmodifiableMap(rwByType); private final Map roByTypeString = Collections.unmodifiableMap(rwByTypeString); public DfontFile() {} public DfontFile(File file) throws IOException { read(file); } public DfontFile(InputStream in) throws IOException { read(in); } public DfontFile(byte[] data) throws IOException { read(data); } private void read(File file) throws IOException { InputStream in = new FileInputStream(file); read(in); in.close(); } private void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); read(out.toByteArray()); } private void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bin); readHead(in); readBody(in); in.close(); bin.close(); } private void readHead(DataInputStream in) throws IOException { this.dataOffset = in.readInt(); this.mapOffset = in.readInt(); in.reset(); in.skipBytes(this.mapOffset + 22); this.attributes = in.readShort(); this.typesOffset = in.readShort(); this.namesOffset = in.readShort(); } private void readBody(DataInputStream in) throws IOException { // Read type entries in.reset(); in.skipBytes(mapOffset + typesOffset); int count = (in.readShort() + 1) & 0xFFFF; for (int i = 0; i < count; i++) { int type = in.readInt(); String typeString = DfontResourceType.toString(type); DfontResourceType t = new DfontResourceType(type, typeString); t.readHead(in); rwTypes.add(t); rwByType.put(type, t); rwByTypeString.put(typeString, t); } // Read resources for (DfontResourceType t : rwTypes) { t.readBody(in, dataOffset, mapOffset, typesOffset, namesOffset); } } public int getAttributes() { return attributes; } public List getResourceTypes() { return roTypes; } public Set getResourceTypeIds() { return roByType.keySet(); } public Set getResourceTypeStrings() { return roByTypeString.keySet(); } public DfontResourceType getResourceType(int type) { return roByType.get(type); } public DfontResourceType getResourceType(String type) { return roByTypeString.get(type); } public DfontResource getResource(int type, int id) { DfontResourceType t = getResourceType(type); return (t != null) ? t.getResource(id) : null; } public DfontResource getResource(int type, String name) { DfontResourceType t = getResourceType(type); return (t != null) ? t.getResource(name) : null; } public DfontResource getResource(String type, int id) { DfontResourceType t = getResourceType(type); return (t != null) ? t.getResource(id) : null; } public DfontResource getResource(String type, String name) { DfontResourceType t = getResourceType(type); return (t != null) ? t.getResource(name) : null; } public boolean addResource(DfontResource r) { if (r == null) return false; DfontResourceType t = getResourceType(r.getType()); if (t == null) { t = new DfontResourceType(r.getType(), r.getTypeString()); rwTypes.add(t); rwByType.put(r.getType(), t); rwByTypeString.put(r.getTypeString(), t); } return t.addResource(r); } public boolean removeResource(DfontResource r) { DfontResourceType t = getResourceType(r.getType()); boolean ret = (t != null) ? t.removeResource(r) : false; checkType(t); return ret; } public DfontResource removeResource(int type, int id) { DfontResourceType t = getResourceType(type); DfontResource ret = (t != null) ? t.removeResource(id) : null; checkType(t); return ret; } public DfontResource removeResource(int type, String name) { DfontResourceType t = getResourceType(type); DfontResource ret = (t != null) ? t.removeResource(name) : null; checkType(t); return ret; } public DfontResource removeResource(String type, int id) { DfontResourceType t = getResourceType(type); DfontResource ret = (t != null) ? t.removeResource(id) : null; checkType(t); return ret; } public DfontResource removeResource(String type, String name) { DfontResourceType t = getResourceType(type); DfontResource ret = (t != null) ? t.removeResource(name) : null; checkType(t); return ret; } private void checkType(DfontResourceType t) { if (t != null && t.getResources().isEmpty()) { rwTypes.remove(t); rwByType.values().remove(t); rwByTypeString.values().remove(t); } } public byte[] write() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); write(out); return out.toByteArray(); } public void write(File file) throws IOException { OutputStream out = new FileOutputStream(file); write(out); out.close(); } public void write(OutputStream out) throws IOException { writeImpl(new DataOutputStream(out)); } private void writeImpl(DataOutputStream out) throws IOException { ByteArrayOutputStream dataArr = new ByteArrayOutputStream(); ByteArrayOutputStream nameArr = new ByteArrayOutputStream(); ByteArrayOutputStream listArr = new ByteArrayOutputStream(); ByteArrayOutputStream typeArr = new ByteArrayOutputStream(); DataOutputStream dataOut = new DataOutputStream(dataArr); DataOutputStream nameOut = new DataOutputStream(nameArr); DataOutputStream listOut = new DataOutputStream(listArr); DataOutputStream typeOut = new DataOutputStream(typeArr); int dataPtr = 0; int namePtr = 0; int listPtr = roTypes.size() * 8 + 2; typeOut.writeShort(roTypes.size() - 1); for (DfontResourceType t : roTypes) { dataPtr = t.writeData(dataOut, dataPtr); namePtr = t.writeName(nameOut, namePtr); listPtr = t.writeList(listOut, listPtr); t.writeHead(typeOut); } out.writeInt(256); // resource data offset out.writeInt(dataPtr + 256); // resource map offset out.writeInt(dataPtr); // resource data size out.writeInt(namePtr + listPtr + 28); // resource map size out.write(new byte[240]); // empty space out.write(dataArr.toByteArray()); // resource data out.writeInt(256); // resource data offset out.writeInt(dataPtr + 256); // resource map offset out.writeInt(dataPtr); // resource data size out.writeInt(namePtr + listPtr + 28); // resource map size out.writeInt(0); // next resource map out.writeShort(0); // file ref out.writeShort(attributes); // attributes out.writeShort(28); // offset from map to type list out.writeShort(listPtr + 28); // offset from map to name list out.write(typeArr.toByteArray()); // type list out.write(listArr.toByteArray()); // resource list out.write(nameArr.toByteArray()); // name list } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/DfontResource.java000066400000000000000000000076631506470510200316520ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class DfontResource { public static final int ATTRIBUTE_COMPRESSED = 0x01; public static final int ATTRIBUTE_CHANGED = 0x02; public static final int ATTRIBUTE_PRELOAD = 0x04; public static final int ATTRIBUTE_PROTECTED = 0x08; public static final int ATTRIBUTE_LOCKED = 0x10; public static final int ATTRIBUTE_PURGEABLE = 0x20; public static final int ATTRIBUTE_SYSHEAP = 0x40; public static final int ATTRIBUTE_RESERVED = 0x80; public static final int OWNER_TYPE_DRVR = -8; public static final int OWNER_TYPE_WDEF = -7; public static final int OWNER_TYPE_MDEF = -6; public static final int OWNER_TYPE_CDEF = -5; public static final int OWNER_TYPE_PDEF = -4; public static final int OWNER_TYPE_PACK = -3; public static final int OWNER_TYPE_RSV1 = -2; public static final int OWNER_TYPE_RSV2 = -1; public static int ownedId(int ownerType, int ownerId, int subId) { return (ownerType << 11) | ((ownerId & 0x3F) << 5) | (subId & 0x1F); } private final int type; private final String typeString; private int id; private int attributes; private int nameOffset; private int dataOffset; private String name; private byte[] data; public DfontResource(String type, int id, int attr, String name, byte[] data, int off, int len) { this(DfontResourceType.toInteger(type), id, attr, name, data, off, len); } public DfontResource(int type, int id, int attr, String name, byte[] data, int off, int len) { this(type, DfontResourceType.toString(type)); this.id = id; this.attributes = attr; this.name = name; this.setData(data, off, len); } DfontResource(int type, String typeString) { this.type = type; this.typeString = typeString; } void readHead(DataInputStream in) throws IOException { this.id = in.readShort(); this.nameOffset = in.readShort(); int tmp = in.readInt(); this.attributes = tmp >> 24; this.dataOffset = tmp & 0xFFFFFF; in.readInt(); } void readBody(DataInputStream in, int dataOffset, int mapOffset, int namesOffset) throws IOException { // Read name if (this.nameOffset < 0) { this.name = null; } else { in.reset(); in.skipBytes(mapOffset + namesOffset + this.nameOffset); int l = in.readUnsignedByte(); byte[] d = new byte[l]; in.readFully(d); this.name = new String(d, "MacRoman"); } // Read data in.reset(); in.skipBytes(dataOffset + this.dataOffset); int l = in.readInt(); if (l < 0) l = 0; byte[] d = new byte[l]; in.readFully(d); this.data = d; } public int getType() { return type; } public String getTypeString() { return typeString; } public int getId() { return id; } public int getOwnerType() { return id >> 11; } public int getOwnerId() { return (id >> 5) & 0x3F; } public int getSubId() { return id & 0x1F; } public int getAttributes() { return attributes; } public String getName() { return name; } public byte[] getData() { return data; } public void setData(byte[] data, int offset, int length) { this.data = new byte[length]; for (int i = 0; i < length; i++) { this.data[i] = data[offset]; offset++; } } int writeData(DataOutputStream out, int ptr) throws IOException { byte[] d = this.data; int len = (d.length < 0xFFFFFF) ? d.length : 0xFFFFFF; out.writeInt(len); out.write(d, 0, len); this.dataOffset = ptr; return ptr + 4 + len; } int writeName(DataOutputStream out, int ptr) throws IOException { if (this.name == null) { this.nameOffset = -1; return ptr; } byte[] d = this.name.getBytes("MacRoman"); int len = (d.length < 0xFF) ? d.length : 0xFF; out.writeByte(len); out.write(d, 0, len); this.nameOffset = ptr; return ptr + 1 + len; } void writeHead(DataOutputStream out) throws IOException { out.writeShort(this.id); out.writeShort(this.nameOffset); out.writeInt((this.attributes << 24) | this.dataOffset); out.writeInt(0); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/DfontResourceType.java000066400000000000000000000102561506470510200325040ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class DfontResourceType { public static int toInteger(String type) { try { byte[] d = ((type == null) ? " " : (type + " ")).getBytes("MacRoman"); return ((d[0]&0xFF) << 24) | ((d[1]&0xFF) << 16) | ((d[2]&0xFF) << 8) | (d[3]&0xFF); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e); } } public static String toString(int type) { try { byte[] d = { (byte)(type >> 24), (byte)(type >> 16), (byte)(type >> 8), (byte)type }; return new String(d, "MacRoman"); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e); } } private final int type; private final String typeString; private int count; private int offset; private final List rwResources = new ArrayList(); private final Map rwById = new TreeMap(); private final Map rwByName = new TreeMap(); private final List roResources = Collections.unmodifiableList(rwResources); private final Map roById = Collections.unmodifiableMap(rwById); private final Map roByName = Collections.unmodifiableMap(rwByName); DfontResourceType(int type, String typeString) { this.type = type; this.typeString = typeString; } void readHead(DataInputStream in) throws IOException { this.count = (in.readShort() + 1) & 0xFFFF; this.offset = in.readShort(); } void readBody(DataInputStream in, int dataOffset, int mapOffset, int typesOffset, int namesOffset) throws IOException { // Read resource entries in.reset(); in.skipBytes(mapOffset + typesOffset + offset); for (int i = 0; i < count; i++) { DfontResource r = new DfontResource(type, typeString); r.readHead(in); rwResources.add(r); rwById.put(r.getId(), r); } // Read resource names and data for (DfontResource r : rwResources) { r.readBody(in, dataOffset, mapOffset, namesOffset); if (r.getName() != null) rwByName.put(r.getName(), r); } } public int getType() { return type; } public String getTypeString() { return typeString; } public List getResources() { return roResources; } public Set getResourceIds() { return roById.keySet(); } public Set getResourceNames() { return roByName.keySet(); } public DfontResource getResource(int id) { return roById.get(id); } public DfontResource getResource(String name) { return roByName.get(name); } boolean addResource(DfontResource r) { if (r == null) return false; if (r.getType() != this.type) return false; if (getResource(r.getId()) != null) return false; rwResources.add(r); rwById.put(r.getId(), r); if (r.getName() != null) rwByName.put(r.getName(), r); return true; } boolean removeResource(DfontResource r) { boolean a = rwResources.remove(r); boolean b = rwById.values().remove(r); boolean c = rwByName.values().remove(r); return a || b || c; } DfontResource removeResource(int id) { DfontResource r = getResource(id); return removeResource(r) ? r : null; } DfontResource removeResource(String name) { DfontResource r = getResource(name); return removeResource(r) ? r : null; } int writeData(DataOutputStream out, int ptr) throws IOException { for (DfontResource r : roResources) { ptr = r.writeData(out, ptr); } return ptr; } int writeName(DataOutputStream out, int ptr) throws IOException { for (DfontResource r : roResources) { ptr = r.writeName(out, ptr); } return ptr; } int writeList(DataOutputStream out, int ptr) throws IOException { for (DfontResource r : roResources) { r.writeHead(out); } this.offset = ptr; return roResources.size() * 12 + ptr; } void writeHead(DataOutputStream out) throws IOException { out.writeInt(this.type); out.writeShort(this.roResources.size() - 1); out.writeShort(this.offset); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/FindOpenType.java000066400000000000000000000073301506470510200314230ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.awt.Font; import java.awt.font.OpenType; import java.lang.reflect.Method; public class FindOpenType { static { try { Method getModule = Class.class.getMethod("getModule"); Object javaDesktop = getModule.invoke(Font.class); Object allUnnamed = getModule.invoke(FindOpenType.class); Class module = Class.forName("java.lang.Module"); Method addOpens = module.getMethod("addOpens", String.class, module); addOpens.invoke(javaDesktop, "java.awt", allUnnamed); addOpens.invoke(javaDesktop, "sun.font", allUnnamed); } catch (Exception e) { // Be gay. Do crimes. } } public static OpenType forTtf(TtfBase ttf) { if (ttf == null) return null; return new TtfOpenType(ttf); } public static OpenType forFont(Font font) { if (font == null) return null; if (font instanceof OpenType) return (OpenType)font; OpenType ot; if ((ot = forFont2D(Font_getFont2D(font))) != null) return ot; if ((ot = forFont2D(FontUtilities_getFont2D(font))) != null) return ot; if ((ot = forFont2D(FontAccess_getFont2D(font))) != null) return ot; if ((ot = forFont2D(FontManager_findFont2D(font))) != null) return ot; return null; } private static Object Font_getFont2D(final Font font) { try { Method m = Font.class.getDeclaredMethod("getFont2D"); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(font); } catch (Exception e) { return null; } } private static Object FontUtilities_getFont2D(Font font) { try { Class cls = Class.forName("sun.font.FontUtilities"); Method m = cls.getDeclaredMethod("getFont2D", Font.class); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(null, font); } catch (Exception e) { return null; } } private static Object FontAccess_getFont2D(Font font) { try { Class cls = Class.forName("sun.font.FontAccess"); Method m = cls.getDeclaredMethod("getFont2D", Font.class); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(FontAccess_getFontAccess(), font); } catch (Exception e) { return null; } } private static Object FontAccess_getFontAccess() { try { Class cls = Class.forName("sun.font.FontAccess"); Method m = cls.getDeclaredMethod("getFontAccess"); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(null); } catch (Exception e) { return null; } } private static Object FontManager_findFont2D(Font font) { try { Class cls = Class.forName("sun.font.FontManager"); Method m = cls.getDeclaredMethod("findFont2D", String.class, int.class, int.class); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(FontManagerFactory_getInstance(), font.getName(), font.getStyle(), 0); } catch (Exception e) { return null; } } private static Object FontManagerFactory_getInstance() { try { Class cls = Class.forName("sun.font.FontManagerFactory"); Method m = cls.getDeclaredMethod("getInstance"); if (!m.isAccessible()) m.setAccessible(true); return m.invoke(null); } catch (Exception e) { return null; } } private static OpenType forFont2D(Object obj) { if (obj == null) return null; if (obj instanceof OpenType) return (OpenType)obj; OpenType ot; if ((ot = forRef("sun.font.Font2D", "getTableBytes", obj)) != null) return ot; if ((ot = forRef("sun.font.TrueTypeFont", "getTableBytes", obj)) != null) return ot; return null; } private static OpenType forRef(String className, String methodName, Object obj) { try { Class cls = Class.forName(className); Method m = cls.getDeclaredMethod(methodName, int.class); if (!m.isAccessible()) m.setAccessible(true); return new RefOpenType(m, cls.cast(obj)); } catch (Exception e) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/NameEntry.java000066400000000000000000000034271506470510200307640ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.IOException; public class NameEntry { private int platformId; private int encodingId; private int languageId; private int nameId; private int length; private int offset; private byte[] data; private String name; NameEntry() {} void readHead(DataInputStream in) throws IOException { this.platformId = in.readUnsignedShort(); this.encodingId = in.readUnsignedShort(); this.languageId = in.readUnsignedShort(); this.nameId = in.readUnsignedShort(); this.length = in.readUnsignedShort(); this.offset = in.readUnsignedShort(); } void readBody(DataInputStream in, int stringOffset) throws IOException { in.reset(); in.skipBytes(stringOffset + this.offset); byte[] d = new byte[this.length]; in.readFully(d); this.data = d; if (this.platformId == 0 || this.platformId == 2 || this.platformId == 10) { this.name = new String(d, "UTF-16BE"); } else if (this.platformId == 3 && (this.encodingId == 1 || this.encodingId == 10)) { this.name = new String(d, "UTF-16BE"); } else if (this.platformId == 1 && this.encodingId == 0) { this.name = new String(d, "MacRoman"); } else { this.name = null; } } public int getPlatformId() { return platformId; } public int getEncodingId() { return encodingId; } public int getLanguageId() { return languageId; } public int getNameId() { return nameId; } public byte[] getData() { return data; } public String getName() { return name; } public boolean isEnglish() { switch (platformId) { case 0: return true; case 1: return encodingId == 0 && languageId == 0; case 2: return true; case 3: return (encodingId == 1 || encodingId == 10) && languageId == 1033; case 10: return true; default: return false; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/NameTable.java000066400000000000000000000033301506470510200307030ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class NameTable { private List names; public NameTable(InputStream in) throws IOException { read(in); } public NameTable(byte[] data) throws IOException { read(data); } private void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); read(out.toByteArray()); } private void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bin); readData(in); in.close(); bin.close(); } private void readData(DataInputStream in) throws IOException { this.names = new ArrayList(); in.readUnsignedShort(); int count = in.readUnsignedShort(); int stringOffset = in.readUnsignedShort(); for (int i = 0; i < count; i++) { NameEntry e = new NameEntry(); e.readHead(in); this.names.add(e); } for (NameEntry e : this.names) { e.readBody(in, stringOffset); } this.names = Collections.unmodifiableList(this.names); } public List getNames() { return names; } public String getName(int nameId) { String name = null; for (NameEntry e : names) { if (e.isEnglish() && e.getNameId() == nameId) { if (name == null || e.getName().length() < name.length()) { name = e.getName(); } } } return name; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/PuaaEntry.java000066400000000000000000000115341506470510200307700ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.IOException; public class PuaaEntry { private int entryType; private int firstCodePoint; private int lastCodePoint; private int entryData; private Object value; PuaaEntry() {} void readHead(DataInputStream in) throws IOException { this.entryType = in.readUnsignedByte(); int plane = in.readUnsignedByte() << 16; this.firstCodePoint = in.readUnsignedShort() | plane; this.lastCodePoint = in.readUnsignedShort() | plane; this.entryData = in.readInt(); } void readBody(DataInputStream in, int to) throws IOException { switch (this.entryType) { case 1: this.value = readString(in, to, this.entryData); break; case 2: int[] sd = readIntArray(in, to, this.entryData); int sn = sd.length; String[] sv = new String[sn]; for (int i = 0; i < sn; i++) sv[i] = readString(in, to, sd[i]); this.value = sv; break; case 3: this.value = (this.entryData != 0); break; case 4: case 5: this.value = this.entryData; break; case 6: case 7: this.value = readIntArray(in, to, this.entryData); break; case 8: int[] cd = readIntArray(in, to, this.entryData); int cn = cd.length - 1; int[] cs = new int[cn]; for (int i = 0; i < cn; i++) cs[i] = cd[i]; String cc = readString(in, to, cd[cn]); this.value = new CaseMapping(cs, cc); break; case 9: int[] nd = readIntArray(in, to, this.entryData); String n0 = readString(in, to, nd[0]); String n1 = readString(in, to, nd[1]); this.value = new NameAlias(n0, n1); break; default: this.value = null; break; } } void setData(int cp, String value) { this.entryType = 1; this.firstCodePoint = cp; this.lastCodePoint = cp; this.entryData = 0; this.value = value; } boolean extendData(int cp, String value) { if ((this.lastCodePoint + 1) != cp) return false; if (this.value == null && value != null) return false; if (this.value != null && !this.value.equals(value)) return false; this.lastCodePoint++; return true; } public int getFirstCodePoint() { return firstCodePoint; } public int getLastCodePoint() { return lastCodePoint; } public boolean contains(int cp) { return cp >= firstCodePoint && cp <= lastCodePoint; } public Object getPropertyValue(int cp) { if (value == null) return null; switch (entryType) { case 2: return ((String[])value)[cp - firstCodePoint]; case 6: return ((int[])value)[cp - firstCodePoint]; default: return value; } } public String getPropertyString(int cp) { if (value == null) return null; switch (entryType) { case 2: return ((String[])value)[cp - firstCodePoint]; case 3: return ((Boolean)value) ? "Y" : "N"; case 5: return toHexString((Integer)value); case 6: return toHexString(((int[])value)[cp - firstCodePoint]); case 7: return toHexString((int[])value); default: return value.toString(); } } static String readString(DataInputStream in, int to, int ed) throws IOException { if (ed > 0) { in.reset(); in.skipBytes(to + ed); int l = in.readUnsignedByte(); byte[] d = new byte[l]; in.readFully(d); return new String(d, "UTF-8"); } if (ed < 0) { StringBuffer sb = new StringBuffer(); char ch0 = (char)((ed >> 24) & 0x7F); if (ch0 != 0) sb.append(ch0); char ch1 = (char)((ed >> 16) & 0x7F); if (ch1 != 0) sb.append(ch1); char ch2 = (char)((ed >> 8) & 0x7F); if (ch2 != 0) sb.append(ch2); char ch3 = (char)((ed >> 0) & 0x7F); if (ch3 != 0) sb.append(ch3); return sb.toString(); } return null; } static int[] readIntArray(DataInputStream in, int to, int ed) throws IOException { if (ed > 0) { in.reset(); in.skipBytes(to + ed); int l = in.readUnsignedShort(); int[] d = new int[l]; for (int i = 0; i < l; i++) d[i] = in.readInt(); return d; } return null; } static String toHexString(int v) { String s = Integer.toHexString(v).toUpperCase(); if (s.length() < 4) s = ("0000" + s).substring(s.length()); return s; } static String toHexString(int[] v) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < v.length; i++) { if (i > 0) sb.append(" "); sb.append(toHexString(v[i])); } return sb.toString(); } public static final class CaseMapping { public final int[] codePoints; public final String condition; public CaseMapping(int[] codePoints, String condition) { this.codePoints = codePoints; this.condition = condition; } @Override public String toString() { String s = toHexString(codePoints); if (condition == null) return s; return s + "; " + condition; } } public static final class NameAlias { public final String alias; public final String type; public NameAlias(String alias, String type) { this.alias = alias; this.type = type; } @Override public String toString() { return alias + ";" + type; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/PuaaTable.java000066400000000000000000000077671506470510200307330ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; public class PuaaTable { private SortedMap> entries; public PuaaTable(InputStream in) throws IOException { read(in); } public PuaaTable(byte[] data) throws IOException { read(data); } private void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); read(out.toByteArray()); } private void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bin); readData(in); in.close(); bin.close(); } private void readData(DataInputStream in) throws IOException { this.entries = new TreeMap>(); in.readUnsignedShort(); int count = in.readUnsignedShort(); int[] pno = new int[count]; int[] sho = new int[count]; for (int i = 0; i < count; i++) { pno[i] = in.readInt(); sho[i] = in.readInt(); } for (int i = 0; i < count; i++) { String prop = PuaaEntry.readString(in, 0, pno[i]); List list = readEntryList(in, 0, sho[i]); this.entries.put(prop, list); } this.entries = Collections.unmodifiableSortedMap(this.entries); } public Set getProperties() { return entries.keySet(); } public List getPropertyEntries(String prop) { return entries.get(prop); } public Map getPropertyMap(String prop) { return mapFromEntries(entries.get(prop)); } public SortedMap getPropertySortedMap(String prop) { return sortedMapFromEntries(entries.get(prop)); } public List getPropertyRuns(String prop) { return runsFromEntries(entries.get(prop)); } static List readEntryList(DataInputStream in, int to, int sho) throws IOException { if (sho > 0) { in.reset(); in.skipBytes(to + sho); int l = in.readUnsignedShort(); PuaaEntry[] d = new PuaaEntry[l]; for (int i = 0; i < l; i++) d[i] = new PuaaEntry(); for (int i = 0; i < l; i++) d[i].readHead(in); for (int i = 0; i < l; i++) d[i].readBody(in, to); return Collections.unmodifiableList(Arrays.asList(d)); } return null; } static Map mapFromEntries(List entries) { if (entries == null) return null; Map m = new HashMap(); putEntriesIntoMap(entries, m); return Collections.unmodifiableMap(m); } static SortedMap sortedMapFromEntries(List entries) { if (entries == null) return null; SortedMap m = new TreeMap(); putEntriesIntoMap(entries, m); return Collections.unmodifiableSortedMap(m); } static void putEntriesIntoMap(List entries, Map map) { for (PuaaEntry entry : entries) { int fcp = entry.getFirstCodePoint(); int lcp = entry.getLastCodePoint(); for (int cp = fcp; cp <= lcp; cp++) { String ov = map.get(cp); String nv = entry.getPropertyString(cp); map.put(cp, (ov == null) ? nv : (ov + nv)); } } } static List runsFromEntries(List entries) { if (entries == null) return null; SortedMap m = sortedMapFromEntries(entries); List runs = new ArrayList(); PuaaEntry run = null; for (Map.Entry e : m.entrySet()) { if (run == null || !run.extendData(e.getKey(), e.getValue())) { run = new PuaaEntry(); run.setData(e.getKey(), e.getValue()); runs.add(run); } } return Collections.unmodifiableList(runs); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/RefOpenType.java000066400000000000000000000034011506470510200312520ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.awt.font.OpenType; import java.lang.reflect.Method; public class RefOpenType implements OpenType { private final Method getTableBytes; private final Object instance; public RefOpenType(Method getTableBytes, Object instance) { this.getTableBytes = getTableBytes; this.instance = instance; } @Override public byte[] getFontTable(int tag) { try { return (byte[])getTableBytes.invoke(instance, tag); } catch (Exception e) { return null; } } @Override public byte[] getFontTable(String tag) { return getFontTable(tagInt(tag)); } @Override public byte[] getFontTable(int tag, int offset, int length) { byte[] data = getFontTable(tag); return (data != null) ? copy(data, offset, length) : null; } @Override public byte[] getFontTable(String tag, int offset, int length) { return getFontTable(tagInt(tag), offset, length); } @Override public int getFontTableSize(int tag) { byte[] data = getFontTable(tag); return (data != null) ? data.length : 0; } @Override public int getFontTableSize(String tag) { return getFontTableSize(tagInt(tag)); } @Override public int getVersion() { return 0; } private static int tagInt(String s) { char[] ch = s.toCharArray(); int tag = 0; tag |= (int)((ch.length > 0) ? ((ch[0] < 0x80) ? ch[0] : '?') : ' ') << 24; tag |= (int)((ch.length > 1) ? ((ch[1] < 0x80) ? ch[1] : '?') : ' ') << 16; tag |= (int)((ch.length > 2) ? ((ch[2] < 0x80) ? ch[2] : '?') : ' ') << 8; tag |= (int)((ch.length > 3) ? ((ch[3] < 0x80) ? ch[3] : '?') : ' ') << 0; return tag; } private static byte[] copy(byte[] src, int offset, int length) { byte[] dst = new byte[length]; for (int i = 0; i < length; i++) dst[i] = src[offset++]; return dst; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtcFile.java000066400000000000000000000033351506470510200304120ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class TtcFile { private List fonts; public TtcFile(File file) throws IOException { read(file); } public TtcFile(InputStream in) throws IOException { read(in); } public TtcFile(byte[] data) throws IOException { read(data); } private void read(File file) throws IOException { InputStream in = new FileInputStream(file); read(in); in.close(); } private void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); read(out.toByteArray()); } private void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bin); read(in, new HashMap()); in.close(); bin.close(); } private void read(DataInputStream in, Map dataCache) throws IOException { this.fonts = new ArrayList(); in.readInt(); in.readInt(); int count = in.readInt(); for (int i = 0; i < count; i++) { TtcFont f = new TtcFont(); f.readHead(in); this.fonts.add(f); } for (TtcFont f : this.fonts) { f.readBody(in, dataCache); } this.fonts = Collections.unmodifiableList(this.fonts); } public List getFonts() { return fonts; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtcFont.java000066400000000000000000000007031506470510200304350ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.IOException; import java.util.Map; public class TtcFont extends TtfBase { private int offset; TtcFont() {} void readHead(DataInputStream in) throws IOException { this.offset = in.readInt(); } void readBody(DataInputStream in, Map dataCache) throws IOException { in.reset(); in.skipBytes(this.offset); super.read(in, dataCache); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtfBase.java000066400000000000000000000045661506470510200304170ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public abstract class TtfBase { private int scaler; private int count; private int searchRange; private int entrySelector; private int rangeShift; private List tables; private Map byTag; private Map byTagString; TtfBase() {} void read(DataInputStream in, Map dataCache) throws IOException { this.tables = new ArrayList(); this.byTag = new TreeMap(); this.byTagString = new TreeMap(); this.scaler = in.readInt(); this.count = in.readShort(); this.searchRange = in.readShort(); this.entrySelector = in.readShort(); this.rangeShift = in.readShort(); for (int i = 0; i < this.count; i++) { TtfTable t = new TtfTable(); t.readHead(in); this.tables.add(t); this.byTag.put(t.getTag(), t); this.byTagString.put(t.getTagString(), t); } for (TtfTable t : this.tables) { t.readBody(in, dataCache); } this.tables = Collections.unmodifiableList(this.tables); this.byTag = Collections.unmodifiableMap(this.byTag); this.byTagString = Collections.unmodifiableMap(this.byTagString); } public int getScaler() { return scaler; } public int getCount() { return count; } public int getSearchRange() { return searchRange; } public int getEntrySelector() { return entrySelector; } public int getRangeShift() { return rangeShift; } public List getTables() { return tables; } public Set getTags() { return byTag.keySet(); } public Set getTagStrings() { return byTagString.keySet(); } public TtfTable getTable(int tag) { return byTag.get(tag); } public TtfTable getTable(String tag) { return byTagString.get(tag); } public T getTableAs(Class cls, int tag) { TtfTable t = getTable(tag); if (t == null) return null; try { return cls.getConstructor(byte[].class).newInstance(t.getData()); } catch (Exception e) { return null; } } public T getTableAs(Class cls, String tag) { TtfTable t = getTable(tag); if (t == null) return null; try { return cls.getConstructor(byte[].class).newInstance(t.getData()); } catch (Exception e) { return null; } } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtfFile.java000066400000000000000000000021761506470510200304170ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; public class TtfFile extends TtfBase { public TtfFile(File file) throws IOException { read(file); } public TtfFile(InputStream in) throws IOException { read(in); } public TtfFile(byte[] data) throws IOException { read(data); } private void read(File file) throws IOException { InputStream in = new FileInputStream(file); read(in); in.close(); } private void read(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[65536]; int read; while ((read = in.read(buf)) >= 0) out.write(buf, 0, read); out.close(); read(out.toByteArray()); } private void read(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bin); super.read(in, new HashMap()); in.close(); bin.close(); } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtfOpenType.java000066400000000000000000000025121506470510200312750ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.awt.font.OpenType; public class TtfOpenType implements OpenType { private final TtfBase ttf; public TtfOpenType(TtfBase ttf) { this.ttf = ttf; } @Override public byte[] getFontTable(int tag) { TtfTable t = ttf.getTable(tag); return (t != null) ? t.getData() : null; } @Override public byte[] getFontTable(String tag) { TtfTable t = ttf.getTable(tag); return (t != null) ? t.getData() : null; } @Override public byte[] getFontTable(int tag, int offset, int length) { TtfTable t = ttf.getTable(tag); return (t != null) ? copy(t.getData(), offset, length) : null; } @Override public byte[] getFontTable(String tag, int offset, int length) { TtfTable t = ttf.getTable(tag); return (t != null) ? copy(t.getData(), offset, length) : null; } @Override public int getFontTableSize(int tag) { TtfTable t = ttf.getTable(tag); return (t != null) ? t.getData().length : 0; } @Override public int getFontTableSize(String tag) { TtfTable t = ttf.getTable(tag); return (t != null) ? t.getData().length : 0; } @Override public int getVersion() { return ttf.getScaler(); } private static byte[] copy(byte[] src, int offset, int length) { byte[] dst = new byte[length]; for (int i = 0; i < length; i++) dst[i] = src[offset++]; return dst; } } bitsnpicas-2.1.1+ds/main/java/BitsNPicas/src/com/kreative/unicode/ttflib/TtfTable.java000066400000000000000000000026321506470510200305640ustar00rootroot00000000000000package com.kreative.unicode.ttflib; import java.io.DataInputStream; import java.io.IOException; import java.util.Map; public class TtfTable { private int tag; private String tagString; private int checksum; private int offset; private int length; private byte[] data; TtfTable() {} void readHead(DataInputStream in) throws IOException { this.tag = in.readInt(); byte[] d = { (byte)(this.tag >> 24), (byte)(this.tag >> 16), (byte)(this.tag >> 8), (byte)(this.tag >> 0), }; this.tagString = new String(d, "US-ASCII"); this.checksum = in.readInt(); this.offset = in.readInt(); this.length = in.readInt(); } void readBody(DataInputStream in, Map dataCache) throws IOException { if (dataCache != null) { long key = (((long)this.offset) << 32) | ((long)this.length); if (dataCache.containsKey(key)) { this.data = dataCache.get(key); return; } } in.reset(); in.skipBytes(this.offset); byte[] d = new byte[this.length]; in.readFully(d); this.data = d; if (dataCache != null) { long key = (((long)this.offset) << 32) | ((long)this.length); dataCache.put(key, d); } } public int getTag() { return tag; } public String getTagString() { return tagString; } public int getChecksum() { return checksum; } public int getOffset() { return offset; } public int getLength() { return length; } public byte[] getData() { return data; } }