1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.platform;
16
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.lang.reflect.InvocationTargetException;
20
21 import org.apache.commons.lang3.reflect.ConstructorUtils;
22 import org.htmlunit.platform.canvas.rendering.AwtRenderingBackend;
23 import org.htmlunit.platform.canvas.rendering.NoOpRenderingBackend;
24 import org.htmlunit.platform.canvas.rendering.RenderingBackend;
25 import org.htmlunit.platform.font.AwtFontUtil;
26 import org.htmlunit.platform.font.FontUtil;
27 import org.htmlunit.platform.font.NoOpFontUtil;
28 import org.htmlunit.platform.image.ImageData;
29 import org.htmlunit.platform.image.NoOpImageData;
30
31 /**
32 * Singleton to handle JDK specific stuff.
33 * This is required to support at least the differences with android.
34 *
35 * @author Ronald Brill
36 * @author Sven Strickroth
37 */
38 public final class Platform {
39
40 // private static final Log LOG = LogFactory.getLog(Platform.class);
41
42 private static FontUtil FontUtil_;
43
44 /**
45 * Creates a rendering backend for an image with the specified dimensions.
46 *
47 * @param imageWidth the width of the image
48 * @param imageHeight the height of the image
49 * @return a new {@link RenderingBackend} instance, or a
50 * {@link NoOpRenderingBackend} if the
51 * {@link AwtRenderingBackend} cannot be created
52 */
53 public static RenderingBackend getRenderingBackend(final int imageWidth, final int imageHeight) {
54 // for Android
55 try {
56 final Class<?> backendClass = Class.forName(
57 "org.htmlunit.platform.canvas.rendering.AwtRenderingBackend");
58 return (RenderingBackend) ConstructorUtils.invokeConstructor(backendClass, imageWidth, imageHeight);
59 }
60 catch (final Throwable e) {
61 return new NoOpRenderingBackend(imageWidth, imageHeight);
62 }
63 }
64
65 /**
66 * Returns the shared font utility instance.
67 *
68 * @return the shared {@link FontUtil} instance, or a
69 * {@link NoOpFontUtil} if the {@link AwtFontUtil} cannot be created
70 */
71 public static FontUtil getFontUtil() {
72 // for Android
73 if (FontUtil_ != null) {
74 return FontUtil_;
75 }
76
77 try {
78 final Class<?> backendClass = Class.forName("org.htmlunit.platform.font.AwtFontUtil");
79 FontUtil_ = (FontUtil) ConstructorUtils.invokeConstructor(backendClass);
80 return FontUtil_;
81 }
82 catch (final Throwable e) {
83 FontUtil_ = new NoOpFontUtil();
84 return FontUtil_;
85 }
86 }
87
88 /**
89 * Creates an {@link ImageData} instance by reading image data from the specified input stream.
90 *
91 * @param inputStream the {@link InputStream} to read from
92 * @return a new {@link ImageData} instance created from the specified input stream,
93 * or a {@link NoOpImageData} if image processing is unavailable
94 * @throws IOException if an I/O error occurs while reading the image data
95 */
96 public static ImageData buildImageData(final InputStream inputStream) throws IOException {
97 try {
98 final Class<?> backendClass = Class.forName(
99 "org.htmlunit.platform.image.ImageIOImageData");
100 return (ImageData) ConstructorUtils.invokeConstructor(backendClass, inputStream);
101 }
102 catch (final InvocationTargetException ex) {
103 final Throwable targetEx = ex.getTargetException();
104 if (targetEx instanceof IOException exception) {
105 throw exception;
106 }
107
108 return new NoOpImageData();
109 }
110 catch (final RuntimeException ex) {
111 throw ex;
112 }
113 catch (final Throwable ex) {
114 return new NoOpImageData();
115 }
116 }
117
118 private Platform() {
119 // util class
120 }
121 }