From: gotty Date: Sat, 25 Jan 2020 00:21:58 +0000 (+0300) Subject: [LIB-9] merge to graphics: Set of entities for PGN parsing and formatting X-Git-Url: https://git.hedgecode.org/?p=chesshog.git;a=commitdiff_plain;h=d5a05f57515051443a33089f93577cf51099cf4b;hp=5d271f23371d6a435a0435f000370f4d9b8c621a [LIB-9] merge to graphics: Set of entities for PGN parsing and formatting --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2e28d95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +.project +.classpath +.settings/ +.svn/ +target/ +bin/ +out/ +*.ipr +*.iml +.idea +.java-version diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..c2fdf49 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,7 @@ +CHANGELOG Hedgecode ChessHog +============================ + +v.0.1 [2020-XX-XX] +------------------ +- Initial release of the project +- ... diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0954fe0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,193 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +*************************************************************************** + + Copyright (c) 2018-2020 Hedgecode. All rights reserved. + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..b5b2dad --- /dev/null +++ b/NOTICE @@ -0,0 +1,6 @@ + +Hedgecode ChessHog +Copyright (c) 2018-2020 Hedgecode. All rights reserved. + +This product includes software developed at +Hedgecode (https://hedgecode.org/). diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b96133 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +## Hedgecode ChessHog + +### Description + +Hedgecode ChessHog is a chess project that includes modules with different functionality, such as: + +* own internal format for the presentation of chess games and positions, which makes + it possible to use this project as API library for various chess Java applications; +* ability to work with various formats of chess games and diagrams (e.g. PGN, FEN), + including the functionality of generating chess positions in ASCII format, + as well as Wikipedia format; +* provide full functionality for working with UCI (Universal Chess Interface) protocol, + which allows both connecting external UCI engines and developing your own + using API of UCI module with a set of necessary interfaces described in it; +* building chess diagrams in the form of images with a diverse set of chess pieces; +* ability to record chess games and positions in the form of a QR code, + as well as recognition of this chess QR code. + +### Links + +Below are links to the project description pages: +- [ENG](https://lib.hedgecode.org/chesshog/) +- [RUS](https://lib.hedgecode.org/chesshog/ru/) + +Copyright © 2018–2020 [Hedgecode](https://hedgecode.org/). diff --git a/chesshog-core/pom.xml b/chesshog-core/pom.xml index d1dda9e..f200eef 100644 --- a/chesshog-core/pom.xml +++ b/chesshog-core/pom.xml @@ -1,7 +1,7 @@ + + + 4.0.0 + + + org.hedgecode.chess + chesshog + 0.1-SNAPSHOT + + + chesshog-graphics + 0.1-SNAPSHOT + jar + + Hedgecode ChessHog Graphics + + Hedgecode ChessHog Graphics Module. + + + + 1.11 + + + + + org.hedgecode.chess + chesshog-core + ${chessHogVersion} + + + org.hedgecode.chess + chesshog-format + ${chessHogVersion} + + + org.apache.xmlgraphics + batik-transcoder + ${transcoderVersion} + + + + \ No newline at end of file diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java new file mode 100644 index 0000000..0d3681f --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +import java.awt.image.BufferedImage; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import org.hedgecode.chess.img.fs.FileSystemDetector; +import org.hedgecode.chess.img.fs.FileSystemContractor; + +/** + * Abstract common image loader with type state of saved resources. + * + * @author Dmitry Samoshin aka gotty + */ +public abstract class AbstractImageLoader implements ImageLoader { + + private static final String IMAGES_DIR = + ImageConstants.RESOURCE_ROOT_DIR.concat(ImageConstants.RESOURCE_IMAGES_DIR); + + private static final int DEF_IMAGE_SIZE = 100; + + private Type loadType; + + private URI imageResourceUri; + + public AbstractImageLoader() { + loadType = Type.STATELESS; + try { + if (FileSystemDetector.detectJar(getImageResourceUri())) { + loadType = Type.STATEFUL; + } + } catch (ImageException ignored) { + } + } + + protected abstract void clear(); + + @Override + public Type loadType() { + return loadType; + } + + protected void setLoadType(Type loadType) { + if (Type.STATELESS.equals(loadType)) { + clear(); + } + this.loadType = loadType; + } + + protected URI getImageResourceUri() throws ImageException { + if (imageResourceUri == null) { + try { + imageResourceUri = getClass().getResource(IMAGES_DIR).toURI(); + } catch (URISyntaxException e) { + throw new ImageException("image.unable.access.resource"); + } + } + return imageResourceUri; + } + + protected Map loadImages(String imagesPath, ImageFilter filter) + throws ImageException + { + return loadImages(imagesPath, filter, DEF_IMAGE_SIZE); + } + + protected Map loadImages(String imagesPath, ImageFilter filter, int size) + throws ImageException + { + Map images = new HashMap<>(); + try (FileSystemContractor fsc = FileSystemDetector.detect(getImageResourceUri())) { + try (DirectoryStream ds = + Files.newDirectoryStream( + fsc.getPath(imagesPath), filter + ) + ) { + ImageFormatShaper formatShaper = ImageFormatShaper.getInstance(); + for (Path file : ds) { + String fileName = file.getFileName().toString(); + String baseName = FilenameUtils.getBaseName(fileName).toLowerCase(); + String imageFormat = FilenameUtils.getExtension(fileName).toLowerCase(); + images.put( + baseName, + formatShaper.shape( + imageFormat, + fsc.getResourceAsStream(file), + size + ) + ); + } + } + } catch (Exception e) { + throw new ImageException("image.unable.access.resource", e.getMessage()); + } + return images; + } + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java new file mode 100644 index 0000000..6d62d86 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +import java.awt.image.RenderedImage; + +import org.hedgecode.chess.position.Position; + +/** + * Storage class for chess diagrams. + * + * @author Dmitry Samoshin aka gotty + */ +public class Diagram { + + private Position position; + private RenderedImage image; + + Diagram(Position position, RenderedImage image) { + this.position = position; + this.image = image; + } + + public Position getPosition() { + return position; + } + + public RenderedImage getImage() { + return image; + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java similarity index 85% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java index c059361..341b452 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018. Developed by Hedgecode. + * Copyright (c) 2018-2019. Developed by Hedgecode. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package org.hedgecode.chess.img; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; -import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.util.Map; @@ -36,7 +35,7 @@ import org.hedgecode.chess.position.Positions; import org.hedgecode.chess.position.Square; /** - * + * Builder for chess diagrams. * * @author Dmitry Samoshin aka gotty */ @@ -53,12 +52,7 @@ public class DiagramBuilder implements ImageBuilder { } @Override - public String build(Position position) { - return ""; // todo - } - - @Override - public RenderedImage build(Position position, String boardType, String pieceType) + public Diagram build(Position position, String boardType, String pieceType) throws ImageException { Map squares = position.getSquares(); @@ -67,22 +61,22 @@ public class DiagramBuilder implements ImageBuilder { PieceSet pieces = pieceSetLoader.load(pieceType); if (board == null || pieces == null) { - throw new ImageException("Couldn't find image resources!"); // todo: locale + throw new ImageException("image.unable.find.resource"); } int squareSize = board.squareSize(); - BufferedImage diagram = board.render(); - Graphics diagramGraphics = diagram.getGraphics(); + BufferedImage image = board.getBoard(); + Graphics imageGraphics = image.getGraphics(); for (int y = 0; y < Square.getSize(); ++y) { for (int x = 0; x < Square.getSize(); ++x) { Square square = Square.getSquare(x, Square.getSize() - (y + 1)); ColorPiece colorPiece = squares.get(square); if (colorPiece != null) { - diagramGraphics.drawImage( + imageGraphics.drawImage( pieces.get(colorPiece).getScaledInstance( squareSize, squareSize, Image.SCALE_SMOOTH - ), + ), // todo: scale in other place x * squareSize, y * squareSize, null @@ -90,7 +84,9 @@ public class DiagramBuilder implements ImageBuilder { } } } - return diagram; + return new Diagram( + position, image + ); } public static ImageBuilder getInstance() { @@ -101,7 +97,9 @@ public class DiagramBuilder implements ImageBuilder { public static void main(String[] args) throws IOException, ImageException { ImageIO.write( - DiagramBuilder.getInstance().build(Positions.INITIAL.getPosition(), "test", "shade"), + DiagramBuilder.getInstance().build( + Positions.INITIAL.getPosition(), "test", "chess24" + ).getImage(), ImageFormat.PNG.name(), new File("chessboard" + "." + ImageFormat.PNG.getExt()) ); diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java new file mode 100644 index 0000000..f4f4719 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +/** + * Utilities for path, file name and extension manipulation. + * + * @author Dmitry Samoshin aka gotty + */ +public final class FilenameUtils { + + private static final String EMPTY_STRING = ""; + + private static final char EXTENSION_SEPARATOR = '.'; + + private static final char UNIX_SEPARATOR = '/'; + private static final char WINDOWS_SEPARATOR = '\\'; + + private static final String PATH_COLON = ":"; + + private static final String JAR_SEPARATOR = ".jar!"; + + private static final String OS = System.getProperty("os.name").toLowerCase(); + + private static final String WIN_OS_TEMPLATE = "win"; + + public static String getName(final String fileName) { + if (fileName == null) { + return null; + } + final int endPathIndex = Math.max( + fileName.lastIndexOf(UNIX_SEPARATOR), + fileName.lastIndexOf(WINDOWS_SEPARATOR) + ); + return fileName.substring(endPathIndex + 1); + } + + public static String getBaseName(final String fileName) { + return removeExtension( + getName(fileName) + ); + } + + public static String getExtension(final String fileName) { + if (fileName == null) { + return null; + } + final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR); + return extensionPos < 0 + ? EMPTY_STRING + : fileName.substring(extensionPos + 1); + } + + public static String getFullPath(final String parentDir, final String... childDirs) { + StringBuilder sb = new StringBuilder(); + sb.append(parentDir); + if (childDirs.length > 0) { + for (String childDir : childDirs) { + sb.append(isWindows() ? WINDOWS_SEPARATOR : UNIX_SEPARATOR).append(childDir); + } + } + return sb.toString(); + } + + public static String fixPath(final String path) { + if (isWindows()) { + return path.startsWith(String.valueOf(UNIX_SEPARATOR)) + && path.contains(PATH_COLON) + ? path.substring(1) + : path; + } + return path; + } + + public static String getPathFromJar(final String jarPath) { + final int jarEndPos = jarPath.lastIndexOf(JAR_SEPARATOR); + return jarEndPos < 0 + ? EMPTY_STRING + : jarPath.substring(jarEndPos + JAR_SEPARATOR.length()); + } + + private static String removeExtension(final String fileName) { + if (fileName == null) { + return null; + } + final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR); + return extensionPos < 0 + ? fileName + : fileName.substring(0, extensionPos); + } + + private static boolean isWindows() { + return (OS.contains(WIN_OS_TEMPLATE)); + } + + private FilenameUtils() { + throw new AssertionError( + "No org.hedgecode.chess.img.FilenameUtils instances!" + ); + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageException.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageBuilder.java similarity index 73% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageException.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageBuilder.java index 4a24b80..304e923 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageException.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageBuilder.java @@ -16,21 +16,15 @@ package org.hedgecode.chess.img; +import org.hedgecode.chess.position.Position; + /** - * Image working Exception. + * Common image builder interface. * * @author Dmitry Samoshin aka gotty */ -public class ImageException extends Exception { - - private String message; - - public ImageException(String message) { - this.message = message; - } +public interface ImageBuilder { - public String getMessage() { - return message; - } + Diagram build(Position position, String boardType, String pieceType) throws ImageException; } diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageConstants.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageConstants.java similarity index 89% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageConstants.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageConstants.java index eb85f1a..d197d47 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageConstants.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageConstants.java @@ -31,6 +31,9 @@ public final class ImageConstants { public static final String DARK_SQUARE_FILENAME = "dark"; public static final String LIGHT_SQUARE_FILENAME = "light"; + public static final String BOARD_FILENAME = "board"; + + public static final String LOCALE_BUNDLE_FILE = "org.hedgecode.chess.img.LocalStrings"; private ImageConstants() { throw new AssertionError( diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java new file mode 100644 index 0000000..2a177ae --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +import java.util.ResourceBundle; + +/** + * Image load/build Exception. + * + * @author Dmitry Samoshin aka gotty + */ +public class ImageException extends Exception { + + private static final ResourceBundle LOCALE_BUNDLE = + ResourceBundle.getBundle(ImageConstants.LOCALE_BUNDLE_FILE); + + private String localeKey; + private String message; + + public ImageException(String localeKey) { + this.localeKey = localeKey; + this.message = null; + } + + public ImageException(String localeKey, String message) { + this.localeKey = localeKey; + this.message = message; + } + + public String getLocaleKey() { + return localeKey; + } + + public String getMessage() { + StringBuilder sb = new StringBuilder(); + sb.append(LOCALE_BUNDLE.getString(localeKey)); + if (message != null) + sb.append(": [").append(message).append("]"); + return sb.toString(); + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFilter.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFilter.java similarity index 65% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFilter.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFilter.java index 27c238e..37a2e0e 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFilter.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFilter.java @@ -16,15 +16,18 @@ package org.hedgecode.chess.img; -import java.io.File; -import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; /** - * + * Filter for images by name and extention. * * @author Dmitry Samoshin aka gotty + * @see DirectoryStream.Filter */ -public class ImageFilter implements FilenameFilter { +public class ImageFilter implements DirectoryStream.Filter { private static final String[] IMAGES_EXTS = ImageFormat.getAllExts(); @@ -39,13 +42,17 @@ public class ImageFilter implements FilenameFilter { } @Override - public boolean accept(File dir, String name) { - return isImageName(name) && isImageExt(name); + public boolean accept(Path file) throws IOException { + if (Files.isDirectory(file)) { + return false; + } + String filename = file.getFileName().toString(); + return acceptExt(filename) && acceptName(filename); } - private boolean isImageName(String name) { + private boolean acceptName(String filename) { if (names != null) { - name = name.substring(0, name.lastIndexOf('.')); + String name = FilenameUtils.getBaseName(filename); for (String imageName : names) { if (imageName.equalsIgnoreCase(name)) return true; @@ -55,8 +62,8 @@ public class ImageFilter implements FilenameFilter { return true; } - private boolean isImageExt(String ext) { - ext = ext.substring(ext.lastIndexOf('.') + 1); + private boolean acceptExt(String filename) { + String ext = FilenameUtils.getExtension(filename); for (String imageExt : IMAGES_EXTS) { if (imageExt.equalsIgnoreCase(ext)) return true; diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFormat.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormat.java similarity index 72% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFormat.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormat.java index e5122fd..238a7b4 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFormat.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018. Developed by Hedgecode. + * Copyright (c) 2018-2019. Developed by Hedgecode. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,41 +23,54 @@ import java.util.List; import javax.imageio.ImageIO; /** - * Supported image formats for reading/writing. + * Supported image formats for reading/writing, indicated by type. * * @author Dmitry Samoshin aka gotty */ public enum ImageFormat { - PNG ( new String[]{"png"} ), - GIF ( new String[]{"gif"} ), - JPG ( new String[]{"jpg", "jpeg"} ), - SVG ( new String[]{"svg"} ), // todo - BMP ( new String[]{"bmp", "wbmp"} ); + PNG ( Type.BITMAP, new String[]{"png"} ), + GIF ( Type.BITMAP, new String[]{"gif"} ), + JPG ( Type.BITMAP, new String[]{"jpg", "jpeg"} ), + BMP ( Type.BITMAP, new String[]{"bmp", "wbmp"} ), + SVG ( Type.VECTOR, new String[]{"svg"} ); - private String[] fortmatExts; + enum Type { + + BITMAP, + VECTOR + + } + + private Type formatType; + private String[] formatExts; private boolean isRead; private boolean isWrite; private static String[] allAvailableExts; - ImageFormat(String[] exts) { - fortmatExts = exts; + ImageFormat(Type type, String[] exts) { + formatType = type; + formatExts = exts; isRead = isExist( - ImageIO.getReaderFormatNames(), fortmatExts + ImageIO.getReaderFormatNames(), formatExts ); isWrite = isExist( - ImageIO.getWriterFormatNames(), fortmatExts + ImageIO.getWriterFormatNames(), formatExts ); } + public Type getType() { + return formatType; + } + public String getExt() { - return fortmatExts[0]; + return formatExts[0]; } public String[] getExts() { - return fortmatExts; + return formatExts; } public boolean isRead() { @@ -99,15 +112,4 @@ public enum ImageFormat { return false; } - -/* - public static void main(String[] args) { - ImageFormat imageFormat = JPG; - System.out.println("Supported format: " + imageFormat); - imageFormat = findFormat("jpeg"); - imageFormat = findFormat("svg"); - imageFormat = findFormat("jpeeg"); - } -*/ - } \ No newline at end of file diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java new file mode 100644 index 0000000..5c1aea2 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormatShaper.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +import java.awt.image.BufferedImage; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.hedgecode.chess.img.bitmap.BitmapImageShaper; +import org.hedgecode.chess.img.vector.VectorImageShaper; + +import static org.hedgecode.chess.img.ImageFormat.Type; + +/** + * Shaper for images, indicated by type format. + * + * @author Dmitry Samoshin aka gotty + */ +public final class ImageFormatShaper { + + private static ImageFormatShaper _instance = new ImageFormatShaper(); + + private Map imageShapers = new HashMap<>(); + + private ImageFormatShaper() { + imageShapers.put( + Type.BITMAP, + BitmapImageShaper.create() + ); + imageShapers.put( + Type.VECTOR, + VectorImageShaper.create() + ); + } + + public BufferedImage shape(String imageFormat, InputStream imageStream, int size) + throws ImageException + { + ImageFormat format = ImageFormat.findFormat(imageFormat); + if (format != null) { + ImageShaper imageShaper = imageShapers.get( + format.getType() + ); + return imageShaper.shape(imageStream, size); + } else { + throw new ImageException("image.unknown.image.format", imageFormat); + } + } + + public static ImageFormatShaper getInstance() { + return _instance; + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageLoader.java similarity index 96% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageLoader.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageLoader.java index 1eee4c2..9267a05 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/ImageLoader.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageLoader.java @@ -17,7 +17,7 @@ package org.hedgecode.chess.img; /** - * + * Common image loader interface. * * @author Dmitry Samoshin aka gotty */ diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java new file mode 100644 index 0000000..36f3e40 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageShaper.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.InputStream; +import java.net.URL; + +/** + * Common image shaper interface. + * + * @author Dmitry Samoshin aka gotty + */ +public interface ImageShaper { + + BufferedImage shape(InputStream imageStream, int size) throws ImageException; + + BufferedImage shape(URL imageUrl, int size) throws ImageException; + + BufferedImage shape(File imageFile, int size) throws ImageException; + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java new file mode 100644 index 0000000..10a8e33 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/bitmap/BitmapImageShaper.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.bitmap; + +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.imageio.ImageIO; + +import org.hedgecode.chess.img.ImageException; +import org.hedgecode.chess.img.ImageShaper; + +/** + * Shaper for bitmap images. + * + * @author Dmitry Samoshin aka gotty + */ +public class BitmapImageShaper implements ImageShaper { + + private BitmapImageShaper() { + } + + @Override + public BufferedImage shape(InputStream imageStream, int size) throws ImageException { + try { + return scaledImage( + ImageIO.read(imageStream), + size + ); + } catch (IOException e) { + throw new ImageException("image.unable.load.bitmap", e.getMessage()); + } + } + + @Override + public BufferedImage shape(URL imageUrl, int size) throws ImageException { + try { + return scaledImage( + ImageIO.read(imageUrl), + size + ); + } catch (IOException e) { + throw new ImageException("image.unable.load.bitmap", e.getMessage()); + } + } + + @Override + public BufferedImage shape(File imageFile, int size) throws ImageException { + try { + return scaledImage( + ImageIO.read(imageFile), + size + ); + } catch (IOException e) { + throw new ImageException("image.unable.load.bitmap", e.getMessage()); + } + } + + private BufferedImage scaledImage(BufferedImage image, int size) { + if (image.getWidth() == size && image.getHeight() == size) { + return image; + } + BufferedImage scaledImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + Graphics graphics = scaledImage.createGraphics(); + graphics.drawImage( + image.getScaledInstance(size, size, BufferedImage.SCALE_SMOOTH), + 0, 0, null + ); + graphics.dispose(); + return scaledImage; + } + + public static ImageShaper create() { + return new BitmapImageShaper(); + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/board/Board.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/Board.java similarity index 78% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/board/Board.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/Board.java index f251e13..ab4371f 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/board/Board.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/Board.java @@ -22,22 +22,29 @@ import java.awt.image.BufferedImage; import org.hedgecode.chess.position.Square; /** - * + * Storage class for chess board images. * * @author Dmitry Samoshin aka gotty */ public class Board { + private BufferedImage board; private SquarePair squares; + private int squareSize; - Board(SquarePair squares) { + private Board(SquarePair squares) { this.squares = squares; int width = Math.max(squares.getDark().getWidth(), squares.getLight().getWidth()); int height = Math.max(squares.getDark().getHeight(), squares.getLight().getHeight()); this.squareSize = Math.max(width, height); } + private Board(BufferedImage board) { + this.board = board; + this.squareSize = Math.max(board.getWidth(), board.getHeight()) / Square.getSize(); + } + public int squareSize() { return squareSize; } @@ -46,7 +53,14 @@ public class Board { return squareSize * Square.getSize(); } - public BufferedImage render() { + public BufferedImage getBoard() { + if (board == null && squares != null) { + board = renderBoard(); + } + return board; + } + + private BufferedImage renderBoard() { BufferedImage board = new BufferedImage( squareSize * Square.getSize(), squareSize * Square.getSize(), @@ -68,6 +82,10 @@ public class Board { return board; } + public static Board create(BufferedImage board) { + return new Board(board); + } + public static Board create(SquarePair squares) { return new Board(squares); } diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java new file mode 100644 index 0000000..e171418 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.board; + +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; + +import org.hedgecode.chess.img.AbstractImageLoader; +import org.hedgecode.chess.img.FilenameUtils; +import org.hedgecode.chess.img.ImageConstants; +import org.hedgecode.chess.img.ImageException; +import org.hedgecode.chess.img.ImageFilter; + +/** + * Loader for chess board's set of images. + * + * @author Dmitry Samoshin aka gotty + */ +public class BoardLoader extends AbstractImageLoader { + + private static final String SQUARES_DIR = ImageConstants.RESOURCE_SQUARES_DIR; + + private static final String SQUARE_DARK = ImageConstants.DARK_SQUARE_FILENAME; + private static final String SQUARE_LIGHT = ImageConstants.LIGHT_SQUARE_FILENAME; + + private static final String BOARD = ImageConstants.BOARD_FILENAME; + + private static final String[] BOARD_SQUARE_NAMES = { BOARD, SQUARE_DARK, SQUARE_LIGHT }; + + private Map squareSetMap = new HashMap<>(); + + @Override + public Board load(String name) throws ImageException { + Board board; + if (Type.STATELESS.equals(loadType()) || !squareSetMap.containsKey(name)) { + String boardPath = FilenameUtils.getFullPath(SQUARES_DIR, name); + board = loadBoard(boardPath); + if (Type.STATEFUL.equals(loadType())) { + squareSetMap.put(name, board); + } + } else { + board = squareSetMap.get(name); + } + return board; + } + + @Override + public void unload(String name) { + if (Type.STATEFUL.equals(loadType()) && squareSetMap.containsKey(name)) { + squareSetMap.remove(name); + } + } + + @Override + protected void clear() { + squareSetMap.clear(); + } + + private Board loadBoard(String boardPath) throws ImageException { + Map images = + loadImages( + boardPath, + new ImageFilter(BOARD_SQUARE_NAMES) + ); + BufferedImage board = images.get(BOARD); + SquarePair squarePair = SquarePair.create( + images.get(SQUARE_DARK), images.get(SQUARE_LIGHT) + ); + if (board == null && !squarePair.isFilled()) { + throw new ImageException("image.incomplete.board.set", boardPath); + } + return board != null + ? Board.create(board) + : Board.create(squarePair); + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/board/SquarePair.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/SquarePair.java similarity index 86% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/board/SquarePair.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/SquarePair.java index 836d273..5fcdd66 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/board/SquarePair.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/SquarePair.java @@ -20,7 +20,7 @@ import java.awt.image.BufferedImage; import java.util.Objects; /** - * + * Storage class for set of images of chess board squares. * * @author Dmitry Samoshin aka gotty */ @@ -29,7 +29,7 @@ public class SquarePair { private final T dark; private final T light; - SquarePair(T dark, T light) { + private SquarePair(T dark, T light) { this.dark = dark; this.light = light; } @@ -42,6 +42,13 @@ public class SquarePair { return light; } + public boolean isFilled() { + if (this.dark == null || this.light == null) { + return false; + } + return true; + } + @Override public boolean equals(Object o) { if (!(o instanceof SquarePair)) { diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java new file mode 100644 index 0000000..ef9fd93 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.fs; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; + +import org.hedgecode.chess.img.FilenameUtils; + +/** + * Default FileSystem contractor. + * + * @author Dmitry Samoshin aka gotty + */ +public class DefFileSystemContractor implements FileSystemContractor { + + private FileSystem fileSystem; + private String rootPath; + + DefFileSystemContractor(URI uri) { + fileSystem = FileSystems.getDefault(); + rootPath = FilenameUtils.fixPath(uri.getPath()); + } + + @Override + public FileSystem getFileSystem() { + return fileSystem; + } + + @Override + public Path getPath(String path) { + return fileSystem.getPath(rootPath, path); + } + + @Override + public InputStream getResourceAsStream(Path file) throws IOException { + return new FileInputStream(file.toString()); + } + + @Override + public void close() throws Exception { + // do nothing + } + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java new file mode 100644 index 0000000..32f4244 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.fs; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileSystem; +import java.nio.file.Path; + +/** + * Common FileSystem contractor interface. + * + * @author Dmitry Samoshin aka gotty + * @see FileSystem + */ +public interface FileSystemContractor extends AutoCloseable { + + FileSystem getFileSystem(); + + Path getPath(String path); + + InputStream getResourceAsStream(Path file) throws IOException; + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java new file mode 100644 index 0000000..66cd6e5 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.fs; + +import java.io.IOException; +import java.net.URI; + +/** + * FileSystem Detector. + * + * @author Dmitry Samoshin aka gotty + */ +public final class FileSystemDetector { + + private static final String JAR_SCHEME_NAME = "jar"; + + public static FileSystemContractor detect(URI uri) throws IOException { + if (JAR_SCHEME_NAME.equals(uri.getScheme())) { + return new JarFileSystemContractor(uri); + } else { + return new DefFileSystemContractor(uri); + } + } + + public static boolean detectJar(URI uri) { + return JAR_SCHEME_NAME.equals(uri.getScheme()); + } + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java new file mode 100644 index 0000000..a57dfbb --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.fs; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.Collections; + +import org.hedgecode.chess.img.FilenameUtils; + +/** + * FileSystem contractor for jar-files. + * + * @author Dmitry Samoshin aka gotty + */ +public class JarFileSystemContractor implements FileSystemContractor { + + private FileSystem fileSystem; + private String rootPath; + + JarFileSystemContractor(URI uri) throws IOException { + fileSystem = FileSystems.newFileSystem( + uri, Collections.emptyMap() + ); + rootPath = FilenameUtils.getPathFromJar(uri.toString()); + } + + @Override + public FileSystem getFileSystem() { + return fileSystem; + } + + @Override + public Path getPath(String path) { + return fileSystem.getPath(rootPath, path); + } + + @Override + public InputStream getResourceAsStream(Path file) throws IOException { + return getClass().getResourceAsStream(file.toString()); + } + + @Override + public void close() throws Exception { + fileSystem.close(); + } + +} diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java similarity index 96% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java index 342ba1a..58faf41 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java @@ -27,7 +27,7 @@ import org.hedgecode.chess.position.ColorPiece; import org.hedgecode.chess.position.Piece; /** - * + * Storage class for set of images of chess pieces. * * @author Dmitry Samoshin aka gotty */ @@ -37,7 +37,7 @@ public class PieceSet { private static String[] allPieceNames; - PieceSet() { + private PieceSet() { } public void add(String name, BufferedImage image) { @@ -65,7 +65,7 @@ public class PieceSet { return pieceSetMap.get(colorPiece); } - public boolean isFull() { + public boolean isFilled() { for (ColorPiece colorPiece : ColorPiece.values()) { if (!pieceSetMap.containsKey(colorPiece) || (pieceSetMap.get(colorPiece) == null)) { diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java similarity index 59% rename from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java rename to chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java index f069ba9..8b0e7c8 100644 --- a/chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java @@ -16,26 +16,24 @@ package org.hedgecode.chess.img.piece; -import java.io.File; -import java.io.IOException; +import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; -import javax.imageio.ImageIO; - import org.hedgecode.chess.img.AbstractImageLoader; +import org.hedgecode.chess.img.FilenameUtils; import org.hedgecode.chess.img.ImageConstants; import org.hedgecode.chess.img.ImageException; import org.hedgecode.chess.img.ImageFilter; /** - * + * Loader for chess piece's set of images. * * @author Dmitry Samoshin aka gotty */ public class PieceSetLoader extends AbstractImageLoader { - private static final File PIECES_PATH = new File(IMAGES_PATH, ImageConstants.RESOURCE_PIECES_DIR); + private static final String PIECES_DIR = ImageConstants.RESOURCE_PIECES_DIR; private static final String[] PIECES_NAMES = PieceSet.getAllPieceNames(); @@ -43,13 +41,11 @@ public class PieceSetLoader extends AbstractImageLoader { @Override public PieceSet load(String name) throws ImageException { - PieceSet pieceSet = null; + PieceSet pieceSet; if (Type.STATELESS.equals(loadType()) || !pieceSetMap.containsKey(name)) { - File piecePath = new File(PIECES_PATH, name); - if (piecePath.exists() && piecePath.isDirectory()) { - pieceSet = loadPieces(piecePath); - } - if (Type.STATEFUL.equals(loadType()) && pieceSet != null) { + String piecePath = FilenameUtils.getFullPath(PIECES_DIR, name); + pieceSet = loadPieces(piecePath); + if (Type.STATEFUL.equals(loadType())) { pieceSetMap.put(name, pieceSet); } } else { @@ -70,25 +66,23 @@ public class PieceSetLoader extends AbstractImageLoader { pieceSetMap.clear(); } - private PieceSet loadPieces(File piecePath) throws ImageException { + private PieceSet loadPieces(String piecePath) throws ImageException { PieceSet pieceSet = PieceSet.create(); - File[] images = piecePath.listFiles(new ImageFilter(PIECES_NAMES)); - if (images != null) { - for (File image : images) { - if (image.isFile()) { - String filename = image.getName(); - try { - pieceSet.add( - filename.substring(0, filename.lastIndexOf('.')), - ImageIO.read(image) - ); - } catch (IOException e) { - throw new ImageException(e.getMessage()); // todo: locale - } - } - } + Map images = + loadImages( + piecePath, + new ImageFilter(PIECES_NAMES) + ); + for (String name : PIECES_NAMES) { + pieceSet.add( + name, + images.get(name) + ); + } + if (!pieceSet.isFilled()) { + throw new ImageException("image.incomplete.piece.set", piecePath); } - return pieceSet.isFull() ? pieceSet : null; + return pieceSet; } } diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java new file mode 100644 index 0000000..deeb890 --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/SquareImageTranscoder.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.vector; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import org.apache.batik.transcoder.TranscoderException; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.image.ImageTranscoder; + +import org.hedgecode.chess.img.ImageFormat; + +/** + * Transcoder for vector square images to {@link BufferedImage}. + * + * @author Dmitry Samoshin aka gotty + * @see ImageTranscoder + */ +public class SquareImageTranscoder extends ImageTranscoder { + + private final int type; + private BufferedImage image; + + SquareImageTranscoder(int type) { + this.type = type; + } + + SquareImageTranscoder(int type, int size) { + this.type = type; + addTranscodingHint(ImageTranscoder.KEY_WIDTH, (float) size); + addTranscodingHint(ImageTranscoder.KEY_HEIGHT, (float) size); + + } + + @Override + protected void setImageSize(float width, float height) { + if (width > 0 && height > 0) { + super.setImageSize(width, height); + } + } + + @Override + public BufferedImage createImage(int width, int height) { + return new BufferedImage(width, height, type); + } + + @Override + public void writeImage(BufferedImage image, TranscoderOutput to) throws TranscoderException { + this.image = image; + } + + public BufferedImage transcode(InputStream inputStream) throws TranscoderException { + transcode( + new TranscoderInput(inputStream), + null + ); + return getImage(); + } + + public BufferedImage getImage() { + return image; + } + + + public static void main(String[] args) throws TranscoderException, IOException { + SquareImageTranscoder imageTranscoder = + new SquareImageTranscoder(BufferedImage.TYPE_INT_ARGB); // , 250 + ImageIO.write( + imageTranscoder.transcode( + ClassLoader.getSystemResourceAsStream("images/pieces/spatial/bb.svg") + ), + ImageFormat.PNG.name(), + new File("bishop" + "." + ImageFormat.PNG.getExt()) + ); + } + +} diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java new file mode 100644 index 0000000..bd11dcf --- /dev/null +++ b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/vector/VectorImageShaper.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019. Developed by Hedgecode. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hedgecode.chess.img.vector; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.apache.batik.transcoder.TranscoderException; + +import org.hedgecode.chess.img.ImageException; +import org.hedgecode.chess.img.ImageShaper; + +/** + * Shaper for vector images. + * + * @author Dmitry Samoshin aka gotty + */ +public class VectorImageShaper implements ImageShaper { + + private VectorImageShaper() { + } + + @Override + public BufferedImage shape(InputStream imageStream, int size) throws ImageException { + SquareImageTranscoder imageTranscoder = + new SquareImageTranscoder(BufferedImage.TYPE_INT_ARGB, size); + try { + return imageTranscoder.transcode(imageStream); + } catch (TranscoderException e) { + throw new ImageException("image.unable.load.vector", e.getMessage()); + } + } + + @Override + public BufferedImage shape(URL imageUrl, int size) throws ImageException { + try { + return shape( + imageUrl.openStream(), + size + ); + } catch (IOException e) { + throw new ImageException("image.unable.load.vector", e.getMessage()); + } + } + + @Override + public BufferedImage shape(File imageFile, int size) throws ImageException { + try { + return shape( + new FileInputStream(imageFile), + size + ); + } catch (FileNotFoundException e) { + throw new ImageException("image.unable.load.vector", e.getMessage()); + } + } + + public static ImageShaper create() { + return new VectorImageShaper(); + } + +} diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties new file mode 100644 index 0000000..75bd45e --- /dev/null +++ b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties @@ -0,0 +1,24 @@ +# Copyright (c) 2018-2019. Developed by Hedgecode. +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Default localized string information +# Localized for Locale en_US + +image.unable.access.resource=Unable to access resources of graphic module +image.unable.find.resource=Unable to find image resources +image.unable.load.bitmap=Unable to load bitmap image +image.unable.load.vector=Unable to load vector image +image.unknown.image.format=Unknown image format +image.incomplete.board.set=Incomplete board set for load +image.incomplete.piece.set=Incomplete piece set for load diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties new file mode 100644 index 0000000..8def590 --- /dev/null +++ b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2019. Developed by Hedgecode. +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Localized for Locale ru_RU + +image.unable.access.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F \u043A \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043C \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u043E\u0433\u043E \u043C\u043E\u0434\u0443\u043B\u044F +image.unable.find.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044B +image.unable.load.bitmap=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0440\u0430\u0441\u0442\u0440\u043E\u0432\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 +image.unable.load.vector=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0432\u0435\u043A\u0442\u043E\u0440\u043D\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 +image.unknown.image.format=\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F +image.incomplete.board.set=\u041D\u0435\u043F\u043E\u043B\u043D\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0448\u0430\u0445\u043C\u0430\u0442\u043D\u043E\u0439 \u0434\u043E\u0441\u043A\u0438 +image.incomplete.piece.set=\u041D\u0435\u043F\u043E\u043B\u043D\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0448\u0430\u0445\u043C\u0430\u0442\u043D\u044B\u0445 \u0444\u0438\u0433\u0443\u0440 diff --git a/chesshog-hedgefish/pom.xml b/chesshog-hedgefish/pom.xml index ef93be5..4ad6b23 100644 --- a/chesshog-hedgefish/pom.xml +++ b/chesshog-hedgefish/pom.xml @@ -1,7 +1,7 @@