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