1 /* 2 * Copyright (C) 2019 The Android Open Source Project 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 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.framebufferizer.utils; 18 19 import com.android.framebufferizer.NativeRenderer; 20 import java.awt.geom.AffineTransform; 21 import java.awt.image.BufferedImage; 22 import java.awt.image.DataBufferInt; 23 import java.awt.image.RenderedImage; 24 import java.util.Iterator; 25 import java.util.Map; 26 import java.util.Set; 27 import java.awt.image.ColorModel; 28 import java.awt.image.DirectColorModel; 29 import java.awt.image.Raster; 30 import java.awt.image.WritableRaster; 31 import javax.swing.*; 32 import java.awt.*; 33 import java.awt.event.*; 34 35 public class FrameBufferBuffer extends JPanel implements ComponentListener, MouseMotionListener, 36 MouseListener { 37 public class MagnifiedView extends JPanel implements ComponentListener { 38 private BufferedImage mImage; 39 MagnifiedView()40 protected MagnifiedView() { 41 addComponentListener(this); 42 } 43 44 @Override componentResized(ComponentEvent e)45 public void componentResized(ComponentEvent e) { 46 synchronized (this) { 47 mImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB_PRE); 48 } 49 } 50 51 @Override componentMoved(ComponentEvent e)52 public void componentMoved(ComponentEvent e) { 53 54 } 55 56 @Override componentShown(ComponentEvent e)57 public void componentShown(ComponentEvent e) { 58 59 } 60 61 @Override componentHidden(ComponentEvent e)62 public void componentHidden(ComponentEvent e) { 63 64 } 65 d()66 public int d() { 67 return getWidth() / 5; 68 } 69 draw(RenderedImage image)70 public void draw(RenderedImage image) { 71 if (mImage == null) 72 return; 73 Graphics2D gc = mImage.createGraphics(); 74 gc.drawRenderedImage(image, AffineTransform.getScaleInstance(5.0, 5.0)); 75 repaint(); 76 } 77 78 @Override paint(Graphics g)79 public void paint(Graphics g) { 80 synchronized (this) { 81 g.drawImage(mImage, 0, 0, null); 82 } 83 } 84 85 } 86 87 public static enum EVENT_RESULT{ 88 NONE(0), CONFIRM(1) ,CANCEL(2); 89 private int id; 90 EVENT_RESULT(int id)91 EVENT_RESULT(int id){ 92 this.id = id; 93 } 94 getValue()95 public int getValue(){ 96 return id; 97 } 98 } 99 100 public class ConfigSelector extends JPanel implements ActionListener { 101 private final String languages[]; 102 103 { 104 languages = NativeRenderer.getLanguageIdList(); 105 } 106 107 private final String layouts[] = NativeRenderer.getAvailableLayouts(); 108 private JComboBox<String> deviceSelector = new JComboBox(DeviceInfoDB.Device.values()); 109 private JCheckBox magnifiedCheckbox = new JCheckBox("Magnified"); 110 private JCheckBox invertedCheckbox = new JCheckBox("Inverted"); 111 112 private JComboBox<String> localeSelector = new JComboBox(languages); 113 private JTextField confirmationMessage = new JTextField(); 114 115 private JComboBox<String> layoutSelector = new JComboBox(layouts); 116 ConfigSelector()117 protected ConfigSelector() { 118 System.err.println("ConfigSelector"); 119 this.setLayout(new GridBagLayout()); 120 121 GridBagConstraints c = null; 122 123 c = new GridBagConstraints(); 124 c.gridx = 0; 125 c.gridy = 0; 126 this.add(new JLabel("Select Device:"), c); 127 128 deviceSelector.addActionListener(this); 129 c = new GridBagConstraints(); 130 c.gridx = 1; 131 c.gridy = 0; 132 c.fill = GridBagConstraints.HORIZONTAL; 133 c.gridwidth = 2; 134 this.add(deviceSelector, c); 135 136 c = new GridBagConstraints(); 137 c.gridx = 0; 138 c.gridy = 1; 139 this.add(new JLabel("Select Locale:"), c); 140 141 localeSelector.addActionListener(this); 142 c = new GridBagConstraints(); 143 c.gridx = 1; 144 c.gridy = 1; 145 c.gridwidth = 2; 146 c.fill = GridBagConstraints.HORIZONTAL; 147 this.add(localeSelector, c); 148 149 c = new GridBagConstraints(); 150 c.gridx = 0; 151 c.gridy = 2; 152 this.add(new JLabel("Select Layout:"), c); 153 154 layoutSelector.addActionListener(this); 155 c = new GridBagConstraints(); 156 c.gridx = 1; 157 c.gridy = 2; 158 c.gridwidth = 2; 159 c.fill = GridBagConstraints.HORIZONTAL; 160 this.add(layoutSelector, c); 161 162 c = new GridBagConstraints(); 163 c.gridx = 0; 164 c.gridy = 3; 165 this.add(new JLabel("UIOptions:"), c); 166 167 magnifiedCheckbox.addActionListener(this); 168 c = new GridBagConstraints(); 169 c.gridx = 1; 170 c.gridy = 3; 171 this.add(magnifiedCheckbox, c); 172 173 invertedCheckbox.addActionListener(this); 174 c = new GridBagConstraints(); 175 c.gridx = 2; 176 c.gridy = 3; 177 this.add(invertedCheckbox, c); 178 179 c = new GridBagConstraints(); 180 c.gridx = 0; 181 c.gridy = 4; 182 this.add(new JLabel("Confirmation message:"), c); 183 184 confirmationMessage.setText( 185 "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"); 186 confirmationMessage.addActionListener(this); 187 c = new GridBagConstraints(); 188 c.gridx = 1; 189 c.gridy = 4; 190 c.fill = GridBagConstraints.BOTH; 191 c.gridwidth = 2; 192 this.add(confirmationMessage, c); 193 } 194 setConfiguration()195 public void setConfiguration() { 196 Config config = Config.getInstance(); 197 config.setValue(Config.KEY_DEVICE, currentDevice()); 198 config.setValue(Config.KEY_LOCALE, getConfigSelector().currentLocale()); 199 config.setValue(Config.KEY_MAGNIFIED, getConfigSelector().magnified()); 200 config.setValue(Config.KEY_INVERTED, getConfigSelector().inverted()); 201 config.setValue(Config.KEY_MESSAGE, getConfigSelector().confirmationMessage()); 202 config.setValue(Config.KEY_LAYOUT, getConfigSelector().currentLayout()); 203 } 204 actionPerformed(ActionEvent e)205 public void actionPerformed(ActionEvent e) { 206 setConfiguration(); 207 FrameBufferBuffer.this.renderNativeBuffer(); 208 } 209 currentDevice()210 public DeviceInfoDB.Device currentDevice() { 211 return (DeviceInfoDB.Device) deviceSelector.getSelectedItem(); 212 } 213 currentLocale()214 public String currentLocale() { 215 return (String) localeSelector.getSelectedItem(); 216 } 217 currentLayout()218 public String currentLayout() { 219 return (String) layoutSelector.getSelectedItem(); 220 } 221 magnified()222 public boolean magnified() { 223 return magnifiedCheckbox.isSelected(); 224 } 225 inverted()226 public boolean inverted() { 227 return invertedCheckbox.isSelected(); 228 } 229 confirmationMessage()230 public String confirmationMessage() { 231 return confirmationMessage.getText(); 232 } 233 } 234 235 private BufferedImage mImage; 236 private DataBufferInt mBuffer; 237 private MagnifiedView mMagnifiedView; 238 private ConfigSelector mConfigSelector; 239 private JFrame mFrame; 240 private double mScale; 241 getMagnifiedView()242 public MagnifiedView getMagnifiedView() { 243 if (mMagnifiedView == null) { 244 mMagnifiedView = new MagnifiedView(); 245 } 246 return mMagnifiedView; 247 } 248 getConfigSelector()249 public ConfigSelector getConfigSelector() { 250 if (mConfigSelector == null) { 251 mConfigSelector = new ConfigSelector(); 252 } 253 return mConfigSelector; 254 } 255 256 @Override mouseReleased(MouseEvent e)257 public void mouseReleased(MouseEvent e) { 258 if (e.MOUSE_RELEASED == MouseEvent.MOUSE_RELEASED) { 259 double x = e.getPoint().x / mScale; 260 double y = e.getPoint().y / mScale; 261 int value = NativeRenderer.onEvent((int)x, (int)y, MouseEvent.MOUSE_RELEASED); 262 if(value == EVENT_RESULT.CONFIRM.getValue()){ 263 JOptionPane.showMessageDialog((Component) e.getSource(), "Confirm clicked."); 264 } else if (value == EVENT_RESULT.CANCEL.getValue()){ 265 JOptionPane.showMessageDialog((Component) e.getSource(), "Cancel clicked."); 266 } 267 } 268 } 269 270 @Override mouseClicked(MouseEvent e)271 public void mouseClicked(MouseEvent e){ 272 } 273 274 @Override mousePressed(MouseEvent e)275 public void mousePressed(MouseEvent e){ 276 } 277 278 @Override mouseEntered(MouseEvent e)279 public void mouseEntered(MouseEvent e){ 280 } 281 282 @Override mouseExited(MouseEvent e)283 public void mouseExited(MouseEvent e){ 284 } 285 286 @Override mouseDragged(MouseEvent e)287 public void mouseDragged(MouseEvent e) { 288 289 } 290 291 @Override mouseMoved(MouseEvent e)292 public void mouseMoved(MouseEvent e) { 293 if (mMagnifiedView != null) { 294 final int rMask = 0xff; 295 final int gMask = 0xff00; 296 final int bMask = 0xff0000; 297 final int bpp = 24; 298 int d = mMagnifiedView.d(); 299 int x = e.getX() - d / 2; 300 if (x + d > mImage.getWidth()) { 301 x = mImage.getWidth() - d; 302 } 303 if (x < 0) { 304 x = 0; 305 } 306 int y = e.getY() - d / 2; 307 if (y + d > mImage.getHeight()) { 308 y = mImage.getHeight() - d; 309 } 310 if (y < 0) { 311 y = 0; 312 } 313 if (mImage.getWidth() < d) { 314 d = mImage.getWidth(); 315 } 316 if (mImage.getHeight() < d) { 317 d = mImage.getHeight(); 318 } 319 mMagnifiedView.draw(mImage.getSubimage(x, y, d, d)); 320 } 321 } 322 setDefaultValues()323 public void setDefaultValues() { 324 Map<String, Object> configMap = Config.getInstance().getConfiguration(); 325 if (configMap != null) { 326 Set set = configMap.entrySet(); 327 Iterator iterator = set.iterator(); 328 while (iterator.hasNext()) { 329 Map.Entry<String, Object> element = (Map.Entry) iterator.next(); 330 switch (element.getKey()) { 331 case Config.KEY_DEVICE: 332 getConfigSelector().deviceSelector 333 .setSelectedItem((DeviceInfoDB.Device.valueOf(((String) element.getValue())))); 334 break; 335 case Config.KEY_LOCALE: 336 getConfigSelector().localeSelector.setSelectedItem((String) element.getValue()); 337 break; 338 case Config.KEY_MAGNIFIED: 339 getConfigSelector().magnifiedCheckbox.setSelected((Boolean) element.getValue()); 340 break; 341 case Config.KEY_INVERTED: 342 getConfigSelector().invertedCheckbox.setSelected((Boolean) element.getValue()); 343 break; 344 case Config.KEY_MESSAGE: 345 getConfigSelector().confirmationMessage.setText((String) element.getValue()); 346 break; 347 case Config.KEY_LAYOUT: 348 getConfigSelector().layoutSelector.setSelectedItem((String) element.getValue()); 349 break; 350 } 351 } 352 } 353 } 354 FrameBufferBuffer()355 public FrameBufferBuffer() { 356 setSize(412, 900); 357 setPreferredSize(new Dimension(412, 900)); 358 setDefaultValues(); 359 renderNativeBuffer(); 360 addComponentListener(this); 361 addMouseMotionListener(this); 362 addMouseListener(this); 363 } 364 365 @Override componentResized(ComponentEvent e)366 public void componentResized(ComponentEvent e) { 367 renderNativeBuffer(); 368 repaint(); 369 } 370 371 @Override componentMoved(ComponentEvent e)372 public void componentMoved(ComponentEvent e) { 373 374 } 375 376 @Override componentShown(ComponentEvent e)377 public void componentShown(ComponentEvent e) { 378 379 } 380 381 @Override componentHidden(ComponentEvent e)382 public void componentHidden(ComponentEvent e) { 383 384 } 385 386 @Override paint(Graphics g)387 public void paint(Graphics g) { 388 synchronized (this) { 389 g.drawImage(mImage, 0, 0, null); 390 } 391 } 392 setFrame(JFrame frame)393 public void setFrame(JFrame frame) { 394 mFrame = frame; 395 } 396 renderNativeBuffer()397 public void renderNativeBuffer() { 398 final int LAYOUT_EXAMPLE_ERROR = -2; 399 final int FRAME_BUFFER_ERROR = -1; 400 DeviceInfo deviceInfo = DeviceInfoDB.getDeviceInfo(getConfigSelector().currentDevice()); 401 boolean magnified = getConfigSelector().magnified(); 402 boolean inverted = getConfigSelector().inverted(); 403 404 int w = deviceInfo.getWidthPx(); 405 int h = deviceInfo.getHeightPx(); 406 final int linestride = w; 407 final int rMask = 0xff; 408 final int gMask = 0xff00; 409 final int bMask = 0xff0000; 410 final int bpp = 24; 411 int error = 0; 412 synchronized (this) { 413 mBuffer = new DataBufferInt(h * linestride); 414 WritableRaster raster = Raster.createPackedRaster(mBuffer, w, h, linestride, 415 new int[] { rMask, gMask, bMask }, null); 416 ColorModel colorModel = new DirectColorModel(bpp, rMask, gMask, bMask); 417 BufferedImage image = new BufferedImage(colorModel, raster, true, null); 418 NativeRenderer.setDeviceInfo(deviceInfo, magnified, inverted, getConfigSelector().currentLayout()); 419 NativeRenderer.setLanguage(getConfigSelector().currentLocale()); 420 NativeRenderer.setConfimationMessage(getConfigSelector().confirmationMessage()); 421 error = NativeRenderer.renderBuffer(0, 0, w, h, linestride, mBuffer.getData()); 422 if(error == FRAME_BUFFER_ERROR){ 423 System.out.println("Error framebuffer not initilized " + error); 424 } else if(error == LAYOUT_EXAMPLE_ERROR){ 425 System.out.println("Error layout example not initilized " + error); 426 } else if (error != 0) { 427 System.out.println("Error rendering native buffer " + error); 428 } 429 430 mImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB_PRE); 431 Graphics2D gc = mImage.createGraphics(); 432 if (w / (double) h > getWidth() / (double) getHeight()) { 433 mScale = (double) getWidth() / (double) w; 434 } else { 435 mScale = (double) getHeight() / (double) h; 436 } 437 gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 438 gc.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 439 gc.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 440 gc.drawRenderedImage(image, AffineTransform.getScaleInstance(mScale, mScale)); 441 } 442 repaint(); 443 } 444 } 445