1 /* 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.webkit.graphics; 27 28 import com.sun.javafx.logging.PlatformLogger; 29 30 import java.lang.annotation.Native; 31 import java.nio.ByteBuffer; 32 import java.nio.ByteOrder; 33 34 public final class GraphicsDecoder { 35 @Native public final static int FILLRECT_FFFFI = 0; 36 @Native public final static int SETFILLCOLOR = 1; 37 @Native public final static int SETSTROKESTYLE = 2; 38 @Native public final static int SETSTROKECOLOR = 3; 39 @Native public final static int SETSTROKEWIDTH = 4; 40 @Native public final static int DRAWPOLYGON = 6; 41 @Native public final static int DRAWLINE = 7; 42 @Native public final static int DRAWIMAGE = 8; 43 @Native public final static int DRAWICON = 9; 44 @Native public final static int DRAWPATTERN = 10; 45 @Native public final static int TRANSLATE = 11; 46 @Native public final static int SAVESTATE = 12; 47 @Native public final static int RESTORESTATE = 13; 48 @Native public final static int CLIP_PATH = 14; 49 @Native public final static int SETCLIP_IIII = 15; 50 @Native public final static int DRAWRECT = 16; 51 @Native public final static int SETCOMPOSITE = 17; 52 @Native public final static int STROKEARC = 18; 53 @Native public final static int DRAWELLIPSE = 19; 54 @Native public final static int DRAWFOCUSRING = 20; 55 @Native public final static int SETALPHA = 21; 56 @Native public final static int BEGINTRANSPARENCYLAYER = 22; 57 @Native public final static int ENDTRANSPARENCYLAYER = 23; 58 @Native public final static int STROKE_PATH = 24; 59 @Native public final static int FILL_PATH = 25; 60 @Native public final static int GETIMAGE = 26; 61 @Native public final static int SCALE = 27; 62 @Native public final static int SETSHADOW = 28; 63 @Native public final static int DRAWSTRING = 29; 64 @Native public final static int DRAWSTRING_FAST = 31; 65 @Native public final static int DRAWWIDGET = 33; 66 @Native public final static int DRAWSCROLLBAR = 34; 67 @Native public final static int CLEARRECT_FFFF = 36; 68 @Native public final static int STROKERECT_FFFFF = 37; 69 @Native public final static int RENDERMEDIAPLAYER = 38; 70 @Native public final static int CONCATTRANSFORM_FFFFFF = 39; 71 @Native public final static int COPYREGION = 40; 72 @Native public final static int DECODERQ = 41; 73 @Native public final static int SET_TRANSFORM = 42; 74 @Native public final static int ROTATE = 43; 75 @Native public final static int RENDERMEDIACONTROL = 44; 76 @Native public final static int RENDERMEDIA_TIMETRACK = 45; 77 @Native public final static int RENDERMEDIA_VOLUMETRACK = 46; 78 @Native public final static int FILLRECT_FFFF = 47; 79 @Native public final static int FILL_ROUNDED_RECT = 48; 80 @Native public final static int SET_FILL_GRADIENT = 49; 81 @Native public final static int SET_STROKE_GRADIENT = 50; 82 @Native public final static int SET_LINE_DASH = 51; 83 @Native public final static int SET_LINE_CAP = 52; 84 @Native public final static int SET_LINE_JOIN = 53; 85 @Native public final static int SET_MITER_LIMIT = 54; 86 @Native public final static int SET_TEXT_MODE = 55; 87 88 private final static PlatformLogger log = 89 PlatformLogger.getLogger(GraphicsDecoder.class.getName()); 90 91 static void decode(WCGraphicsManager gm, WCGraphicsContext gc, BufferData bdata) { 92 if (gc == null) { 93 return; 94 } 95 ByteBuffer buf = bdata.getBuffer(); 96 buf.order(ByteOrder.nativeOrder()); 97 while (buf.remaining() > 0) { 98 int op = buf.getInt(); 99 switch(op) { 100 case FILLRECT_FFFF: 101 gc.fillRect( 102 buf.getFloat(), 103 buf.getFloat(), 104 buf.getFloat(), 105 buf.getFloat(), 106 null); 107 break; 108 case FILLRECT_FFFFI: 109 gc.fillRect( 110 buf.getFloat(), 111 buf.getFloat(), 112 buf.getFloat(), 113 buf.getFloat(), 114 buf.getInt()); 115 break; 116 case FILL_ROUNDED_RECT: 117 gc.fillRoundedRect( 118 // base rectangle 119 buf.getFloat(), buf.getFloat(), buf.getFloat(), buf.getFloat(), 120 // top corners w/h 121 buf.getFloat(), buf.getFloat(), buf.getFloat(), buf.getFloat(), 122 // bottom corners w/h 123 buf.getFloat(), buf.getFloat(), buf.getFloat(), buf.getFloat(), 124 buf.getInt()); 125 break; 126 case CLEARRECT_FFFF: 127 gc.clearRect( 128 buf.getFloat(), 129 buf.getFloat(), 130 buf.getFloat(), 131 buf.getFloat()); 132 break; 133 case STROKERECT_FFFFF: 134 gc.strokeRect( 135 buf.getFloat(), 136 buf.getFloat(), 137 buf.getFloat(), 138 buf.getFloat(), 139 buf.getFloat()); 140 break; 141 case SETFILLCOLOR: 142 gc.setFillColor(buf.getInt()); 143 break; 144 case SET_TEXT_MODE: 145 gc.setTextMode(getBoolean(buf), getBoolean(buf), getBoolean(buf)); 146 break; 147 case SETSTROKESTYLE: 148 gc.setStrokeStyle(buf.getInt()); 149 break; 150 case SETSTROKECOLOR: 151 gc.setStrokeColor(buf.getInt()); 152 break; 153 case SETSTROKEWIDTH: 154 gc.setStrokeWidth(buf.getFloat()); 155 break; 156 case SET_FILL_GRADIENT: 157 gc.setFillGradient(getGradient(gc, buf)); 158 break; 159 case SET_STROKE_GRADIENT: 160 gc.setStrokeGradient(getGradient(gc, buf)); 161 break; 162 case SET_LINE_DASH: 163 gc.setLineDash(buf.getFloat(), getFloatArray(buf)); 164 break; 165 case SET_LINE_CAP: 166 gc.setLineCap(buf.getInt()); 167 break; 168 case SET_LINE_JOIN: 169 gc.setLineJoin(buf.getInt()); 170 break; 171 case SET_MITER_LIMIT: 172 gc.setMiterLimit(buf.getFloat()); 173 break; 174 case DRAWPOLYGON: 175 gc.drawPolygon(getPath(gm, buf), buf.getInt() == -1); 176 break; 177 case DRAWLINE: 178 gc.drawLine( 179 buf.getInt(), 180 buf.getInt(), 181 buf.getInt(), 182 buf.getInt()); 183 break; 184 case DRAWIMAGE: 185 drawImage(gc, 186 gm.getRef(buf.getInt()), 187 //dest React 188 buf.getFloat(), 189 buf.getFloat(), 190 buf.getFloat(), 191 buf.getFloat(), 192 //src Rect 193 buf.getFloat(), 194 buf.getFloat(), 195 buf.getFloat(), 196 buf.getFloat()); 197 break; 198 case DRAWICON: 199 gc.drawIcon((WCIcon)gm.getRef(buf.getInt()), 200 buf.getInt(), 201 buf.getInt()); 202 break; 203 case DRAWPATTERN: 204 drawPattern(gc, 205 gm.getRef(buf.getInt()), 206 getRectangle(buf), 207 (WCTransform)gm.getRef(buf.getInt()), 208 getPoint(buf), 209 getRectangle(buf)); 210 break; 211 case TRANSLATE: 212 gc.translate(buf.getFloat(), buf.getFloat()); 213 break; 214 case SCALE: 215 gc.scale(buf.getFloat(), buf.getFloat()); 216 break; 217 case SAVESTATE: 218 gc.saveState(); 219 break; 220 case RESTORESTATE: 221 gc.restoreState(); 222 break; 223 case CLIP_PATH: 224 gc.setClip( 225 getPath(gm, buf), 226 buf.getInt()>0); 227 break; 228 case SETCLIP_IIII: 229 gc.setClip( 230 buf.getInt(), 231 buf.getInt(), 232 buf.getInt(), 233 buf.getInt()); 234 break; 235 case DRAWRECT: 236 gc.drawRect( 237 buf.getInt(), 238 buf.getInt(), 239 buf.getInt(), 240 buf.getInt()); 241 break; 242 case SETCOMPOSITE: 243 gc.setComposite(buf.getInt()); 244 break; 245 case STROKEARC: 246 gc.strokeArc( 247 buf.getInt(), 248 buf.getInt(), 249 buf.getInt(), 250 buf.getInt(), 251 buf.getInt(), 252 buf.getInt()); 253 break; 254 case DRAWELLIPSE: 255 gc.drawEllipse( 256 buf.getInt(), 257 buf.getInt(), 258 buf.getInt(), 259 buf.getInt()); 260 break; 261 case DRAWFOCUSRING: 262 gc.drawFocusRing( 263 buf.getInt(), 264 buf.getInt(), 265 buf.getInt(), 266 buf.getInt(), 267 buf.getInt()); 268 break; 269 case SETALPHA: 270 gc.setAlpha(buf.getFloat()); 271 break; 272 case BEGINTRANSPARENCYLAYER: 273 gc.beginTransparencyLayer(buf.getFloat()); 274 break; 275 case ENDTRANSPARENCYLAYER: 276 gc.endTransparencyLayer(); 277 break; 278 case STROKE_PATH: 279 gc.strokePath(getPath(gm, buf)); 280 break; 281 case FILL_PATH: 282 gc.fillPath(getPath(gm, buf)); 283 break; 284 case SETSHADOW: 285 gc.setShadow( 286 buf.getFloat(), 287 buf.getFloat(), 288 buf.getFloat(), 289 buf.getInt()); 290 break; 291 case DRAWSTRING: 292 gc.drawString( 293 (WCFont) gm.getRef(buf.getInt()), 294 bdata.getString(buf.getInt()), 295 (buf.getInt() == -1), // rtl flag 296 buf.getInt(), buf.getInt(), // from and to positions 297 buf.getFloat(), buf.getFloat());// (x,y) position 298 break; 299 case DRAWSTRING_FAST: 300 gc.drawString( 301 (WCFont) gm.getRef(buf.getInt()), 302 bdata.getIntArray(buf.getInt()), //glyphs 303 bdata.getFloatArray(buf.getInt()), //offsets 304 buf.getFloat(), 305 buf.getFloat()); 306 break; 307 case DRAWWIDGET: 308 gc.drawWidget((RenderTheme)(gm.getRef(buf.getInt())), 309 gm.getRef(buf.getInt()), buf.getInt(), buf.getInt()); 310 break; 311 case DRAWSCROLLBAR: 312 gc.drawScrollbar((ScrollBarTheme)(gm.getRef(buf.getInt())), 313 gm.getRef(buf.getInt()), buf.getInt(), buf.getInt(), 314 buf.getInt(), buf.getInt()); 315 break; 316 case RENDERMEDIAPLAYER: 317 WCMediaPlayer mp = (WCMediaPlayer)gm.getRef(buf.getInt()); 318 mp.render(gc, 319 buf.getInt(), // x 320 buf.getInt(), // y 321 buf.getInt(), // width 322 buf.getInt()); // height 323 break; 324 case CONCATTRANSFORM_FFFFFF: 325 gc.concatTransform(new WCTransform( 326 buf.getFloat(), buf.getFloat(), buf.getFloat(), 327 buf.getFloat(), buf.getFloat(), buf.getFloat())); 328 break; 329 case SET_TRANSFORM: 330 gc.setTransform(new WCTransform( 331 buf.getFloat(), buf.getFloat(), buf.getFloat(), 332 buf.getFloat(), buf.getFloat(), buf.getFloat())); 333 break; 334 case COPYREGION: 335 WCPageBackBuffer buffer = (WCPageBackBuffer)gm.getRef(buf.getInt()); 336 buffer.copyArea(buf.getInt(), buf.getInt(), buf.getInt(), buf.getInt(), 337 buf.getInt(), buf.getInt()); 338 break; 339 case DECODERQ: 340 WCRenderQueue _rq = (WCRenderQueue)gm.getRef(buf.getInt()); 341 _rq.decode(gc.getFontSmoothingType()); 342 break; 343 case ROTATE: 344 gc.rotate(buf.getFloat()); 345 break; 346 case RENDERMEDIACONTROL: 347 RenderMediaControls.paintControl(gc, 348 buf.getInt(), // control type 349 buf.getInt(), // x 350 buf.getInt(), // y 351 buf.getInt(), // width 352 buf.getInt()); // height 353 break; 354 case RENDERMEDIA_TIMETRACK: { 355 int n = buf.getInt(); // number of timeRange pairs 356 float[] buffered = new float[n*2]; 357 buf.asFloatBuffer().get(buffered); 358 buf.position(buf.position() + n*4 *2); 359 RenderMediaControls.paintTimeSliderTrack(gc, 360 buf.getFloat(), // duration 361 buf.getFloat(), // currentTime 362 buffered, // buffered() timeRanges 363 buf.getInt(), // x 364 buf.getInt(), // y 365 buf.getInt(), // width 366 buf.getInt()); // height 367 break; 368 } 369 case RENDERMEDIA_VOLUMETRACK: 370 RenderMediaControls.paintVolumeTrack(gc, 371 buf.getFloat(), // curVolume 372 buf.getInt() != 0, // muted 373 buf.getInt(), // x 374 buf.getInt(), // y 375 buf.getInt(), // width 376 buf.getInt()); // height 377 break; 378 default: 379 log.fine("ERROR. Unknown primitive found"); 380 break; 381 } 382 } 383 } 384 385 386 private static void drawPattern( 387 WCGraphicsContext gc, 388 Object imgFrame, 389 WCRectangle srcRect, 390 WCTransform patternTransform, 391 WCPoint phase, 392 WCRectangle destRect) 393 { 394 WCImage img = WCImage.getImage(imgFrame); 395 if (img != null) { 396 // RT-10059: drawImage() may have to create the texture 397 // lazily, and may fail with an OutOfMemory error 398 // if the texture is too large. This is a legitimate 399 // situation that should be handled gracefully. It should 400 // not cause us to quit painting other page components. 401 try { 402 gc.drawPattern( 403 img, 404 srcRect, 405 patternTransform, 406 phase, 407 destRect); 408 } catch (OutOfMemoryError error) { 409 error.printStackTrace(); 410 } 411 } 412 } 413 414 private static void drawImage( 415 WCGraphicsContext gc, 416 Object imgFrame, 417 float dstx, float dsty, float dstw, float dsth, 418 float srcx, float srcy, float srcw, float srch) 419 { 420 WCImage img = WCImage.getImage(imgFrame); 421 if (img != null) { 422 // RT-10059: drawImage() may have to create the texture 423 // lazily, and may fail with an OutOfMemory error 424 // if the texture is too large. This is a legitimate 425 // situation that should be handled gracefully. It should 426 // not cause us to quit painting other page components. 427 try { 428 gc.drawImage( 429 img, 430 dstx, dsty, dstw, dsth, 431 srcx, srcy, srcw, srch); 432 } catch (OutOfMemoryError error) { 433 error.printStackTrace(); 434 } 435 } 436 } 437 438 private static boolean getBoolean(ByteBuffer buf) { 439 return 0 != buf.getInt(); 440 } 441 442 private static float[] getFloatArray(ByteBuffer buf) { 443 float[] array = new float[buf.getInt()]; 444 for (int i = 0; i < array.length; i++) { 445 array[i] = buf.getFloat(); 446 } 447 return array; 448 } 449 450 private static WCPath getPath(WCGraphicsManager gm, ByteBuffer buf) { 451 WCPath path = (WCPath) gm.getRef(buf.getInt()); 452 path.setWindingRule(buf.getInt()); 453 return path; 454 } 455 456 private static WCPoint getPoint(ByteBuffer buf) { 457 return new WCPoint(buf.getFloat(), 458 buf.getFloat()); 459 } 460 461 private static WCRectangle getRectangle(ByteBuffer buf) { 462 return new WCRectangle(buf.getFloat(), 463 buf.getFloat(), 464 buf.getFloat(), 465 buf.getFloat()); 466 } 467 468 private static WCGradient getGradient(WCGraphicsContext gc, ByteBuffer buf) { 469 WCPoint p1 = getPoint(buf); 470 WCPoint p2 = getPoint(buf); 471 WCGradient gradient = getBoolean(buf) 472 ? gc.createRadialGradient(p1, buf.getFloat(), p2, buf.getFloat()) 473 : gc.createLinearGradient(p1, p2); 474 475 boolean proportional = getBoolean(buf); 476 int spreadMethod = buf.getInt(); 477 if (gradient != null) { 478 gradient.setProportional(proportional); 479 gradient.setSpreadMethod(spreadMethod); 480 } 481 int count = buf.getInt(); 482 for (int i = 0; i < count; i++) { 483 int color = buf.getInt(); 484 float offset = buf.getFloat(); 485 if (gradient != null) { 486 gradient.addStop(color, offset); 487 } 488 } 489 return gradient; 490 } 491 }