View Javadoc
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 }