Changeset 701
- Timestamp:
- 01/16/14 10:27:29 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/io/WebParser.java
r695 r701 6 6 import java.io.File; 7 7 import java.io.IOException; 8 import java.lang.reflect.InvocationTargetException; 8 9 import java.net.HttpURLConnection; 9 10 import java.net.MalformedURLException; … … 23 24 import org.expeditee.items.Text; 24 25 import org.expeditee.reflection.JavaFX; 26 import org.w3c.dom.Element; 25 27 import org.w3c.dom.Node; 26 28 import org.w3c.dom.html.HTMLBodyElement; … … 221 223 222 224 // Will never reach 100% here, as the processing is not quite finished - progress is set to 100% at the end of 223 // the loop below225 // the addPageToFrame loop below 224 226 progressBar.set((100 * (j)) / nodesLength); 225 227 } … … 240 242 + "}" 241 243 ); 242 243 // Creating a TreeWalker that is used to loop over all the nodes within the document 244 JavaFX.WebEngineExecuteScript.invoke(webEngine, "var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ALL);"); 245 246 Node currentNode; 247 248 // Looping through all the nodes in the document 249 while ((currentNode = (Node) JavaFX.WebEngineExecuteScript.invoke(webEngine, "walker.nextNode()")) != null) { 250 251 if (currentNode.getNodeType() == Node.TEXT_NODE || currentNode.getNodeType() == Node.ELEMENT_NODE) { 252 253 Object style; 254 Object bounds; 255 256 if (currentNode.getNodeType() == Node.TEXT_NODE) { 257 // CSS style for the element 258 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode.getParentNode() }); 259 260 // Getting a rectangle that represents the area and position of the element 261 bounds = JavaFX.JSObjectCall.invoke(currentNode.getParentNode(), "getBoundingClientRect", new Object[] {}); 262 } else { 263 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode }); 264 265 bounds = JavaFX.JSObjectCall.invoke(currentNode, "getBoundingClientRect", new Object[] {}); 266 } 267 268 // Bounding rectangle position is relative to the current view, so scroll position must be added to x/y 269 // TODO: This doesn't check if an element or any of its parent elements have position:fixed set - the only 270 // way to check seems to be to walking through the element's parents until the document root is reached 271 float x = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "left").toString()) 272 + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageXOffset").toString()); 273 float y = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "top").toString()) 274 + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageYOffset").toString()); 275 276 float width = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "width").toString()); 277 float height = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "height").toString()); 278 279 // Checking if the element is actually visible on the page 280 if (WebParser.elementVisible(x, y, width, height, style)) { 281 282 // Filtering the node type, starting with text nodes 283 if (currentNode.getNodeType() == Node.TEXT_NODE) { 284 String fontSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-size" })); 285 286 // Trimming off the units (always px) from the font size 287 fontSize = fontSize.substring(0, fontSize.length() - 2); 288 289 // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)" 290 String color = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "color" }); 291 292 // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)" 293 String bgColor = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-color" }); 294 295 String align = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-align" }); 296 297 // Returns comma-separated list of typefaces 298 String typeface = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-family" }); 299 300 String[] typefaces = typeface.split(", |,"); 301 302 String weight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-weight" }); 303 304 String fontStyle = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-style" }); 305 306 // Returns "normal" or a value in pixels (e.g. "10px") 307 String letterSpacing = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "letter-spacing" }); 308 309 // Returns a value in pixels (e.g. "10px") 310 String lineHeight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "line-height" }); 311 312 String textTransform = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-transform" }); 313 314 String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode.getParentNode(), "href"); 315 316 Boolean fontFound = false; 317 Font font = new Font(null); 318 319 // Looping through all font-families listed in the element's CSS until one that is installed is 320 // found, or the end of the list is reached, in which case the default font is used 321 for (int j = 0; j < typefaces.length && !fontFound; j++) { 322 if (typefaces[j].toLowerCase().equals("sans-serif")) { 323 typefaces[j] = "Arial Unicode MS"; 324 } else if (typefaces[j].toLowerCase().equals("serif")) { 325 typefaces[j] = "Times New Roman"; 326 } else if ((typefaces[j].toLowerCase().equals("arial"))) { 327 // Have to use Arial Unicode, otherwise unicode characters display incorrectly 328 typefaces[j] = "Arial Unicode MS"; 329 } 330 331 // Regex will remove any inverted commas surrounding multi-word typeface names 332 font = new Font(typefaces[j].replaceAll("^'|'$", ""), Font.PLAIN, 12); 333 334 // If the font isn't found, Java just uses Font.DIALOG, so this check checks whether the font was found 335 if (!(font.getFamily().toLowerCase().equals(Font.DIALOG.toLowerCase()))) { 336 fontFound = true; 337 } 338 } 339 340 if (font.getFamily().toLowerCase().equals(Font.DIALOG.toLowerCase())) { 341 font = new Font("Times New Roman", Font.PLAIN, 12); 342 } 343 344 String fontStyleComplete = ""; 345 346 int weightInt = 0; 347 348 try { 349 weightInt = Integer.parseInt(weight); 350 } catch (NumberFormatException nfe) { 351 // Use default value as set above 352 } 353 354 // checking if font is bold - i.e. 'bold', 'bolder' or weight over 500 355 if (weight.toLowerCase().startsWith("bold") || weightInt > 500) { 356 fontStyleComplete = fontStyleComplete.concat("bold"); 357 } 358 359 if (fontStyle.toLowerCase().equals("italic") || fontStyle.toLowerCase().equals("oblique")) { 360 fontStyleComplete = fontStyleComplete.concat("italic"); 361 } 362 363 float fontSizeFloat = 12; 364 365 try { 366 fontSizeFloat = Float.valueOf(fontSize); 367 } catch (NumberFormatException nfe) { 368 // Use default value as set above 369 } 370 371 float letterSpacingFloat = -0.008f; 372 373 try { 374 letterSpacingFloat = (Integer.parseInt(letterSpacing.substring(0, letterSpacing.length() - 2)) / (fontSizeFloat)); 375 } catch (NumberFormatException nfe) { 376 // Use default value as set above 377 } 378 379 float lineHeightInt = -1; 380 381 try { 382 lineHeightInt = (Float.parseFloat(lineHeight.substring(0, lineHeight.length() - 2))); 383 } catch (NumberFormatException nfe) { 384 // Use default value as set above 385 } 386 387 Text t; 388 389 String textContent = currentNode.getTextContent().replaceAll("[^\\S\\n]+", " "); 390 textContent = textContent.replaceAll("^(\\s)(\\n|\\r)", ""); 391 392 if (textTransform.equals("uppercase")) { 393 textContent = textContent.toUpperCase(); 394 } else if (textTransform.equals("lowercase")) { 395 textContent = textContent.toUpperCase(); 396 } 397 398 t = frame.addText(Math.round(x), Math.round(y), textContent, null); 399 400 t.setColor(rgbStringToColor(color)); 401 t.setBackgroundColor(rgbStringToColor(bgColor)); 402 t.setFont(font); 403 t.setSize(fontSizeFloat); 404 t.setFontStyle(fontStyleComplete); 405 t.setLetterSpacing(letterSpacingFloat); 406 407 // Removing any spacing between lines allowing t.getLineHeight() to be used to get the actual height 408 // of just the characters (i.e. distance from ascenders to descenders) 409 t.setSpacing(0); 410 411 t.setSpacing(lineHeightInt - t.getLineHeight()); 412 413 if (align.equals("left")) { 414 t.setJustification(Justification.left); 415 } else if (align.equals("right")) { 416 t.setJustification(Justification.right); 417 } else if (align.equals("center")) { 418 t.setJustification(Justification.center); 419 } else if (align.equals("justify")) { 420 t.setJustification(Justification.full); 421 } 422 423 // Font size is added to the item width to give a little breathing room 424 t.setWidth(Math.round(width + (t.getSize()))); 425 426 if (!linkUrl.equals("undefined")) { 427 t.setAction("gotourl " + linkUrl); 428 t.setActionMark(false); 429 } 430 431 } else if (currentNode.getNodeType() == Node.ELEMENT_NODE) { 432 433 // background image, returns in format "url(protocol://absolute/path/to/img.extension)" for images, 434 // may also return gradients, data, etc. (not handled yet). Only need to add bg image on 435 // 'ELEMENT_NODE' (and not 'TEXT_NODE' otherwise there would be double-ups 436 String bgImage = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-image" }); 437 438 String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode, "href"); 439 440 if (bgImage.startsWith("url(")) { 441 442 bgImage = bgImage.substring(4, bgImage.length() - 1); 443 444 String bgSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-size" })).toLowerCase(); 445 String bgRepeat = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-repeat" })).toLowerCase(); 446 447 // Returns "[x]px [y]px", "[x]% [y]%", "[x]px [y]%" or "[x]% [y]px" 448 String bgPosition = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-position" })).toLowerCase(); 449 450 String[] bgOffsetCoords = bgPosition.split(" "); 451 452 int bgOffsetX = 0, bgOffsetY = 0; 453 454 float originXPercent = 0, originYPercent = 0; 455 456 int cropStartX, cropStartY, cropEndX, cropEndY; 457 458 // Converting the x and y offset values to integers (and from % to px if needed) 459 if (bgOffsetCoords[0].endsWith("%")) { 460 bgOffsetX = (int) ((Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 1)) / 100.0) * width); 461 originXPercent = (Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 1))) / 100f; 462 } else if (bgOffsetCoords[0].endsWith("px")) { 463 bgOffsetX = (int) (Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 2))); 464 } 465 466 if (bgOffsetCoords[1].endsWith("%")) { 467 bgOffsetY = (int) ((Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 1)) / 100.0) * height); 468 originYPercent = (Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 1))) / 100f; 469 } else if (bgOffsetCoords[1].endsWith("px")) { 470 bgOffsetY = (int) (Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 2))); 471 } 472 473 // Converting from an offset to crop coords 474 cropStartX = -1 * bgOffsetX; 475 cropEndX = (int) (cropStartX + width); 476 477 cropStartY = -1 * bgOffsetY; 478 cropEndY = (int) (cropStartY + height); 479 480 int bgWidth = -1; 481 482 if (bgSize.equals("cover")) { 483 bgWidth = (int) width; 484 } else if (bgSize.equals("contain")) { 485 // TODO: actually compute the appropriate width 486 bgWidth = (int) width; 487 } else if (bgSize.equals("auto")) { 488 bgWidth = -1; 489 } else { 490 bgSize = bgSize.split(" ")[0]; 491 492 if (bgSize.endsWith("%")) { 493 bgWidth = (int) ((Integer.parseInt(bgSize.replaceAll("\\D", "")) / 100.0) * width); 494 } else if (bgSize.endsWith("px")) { 495 bgWidth = Integer.parseInt(bgSize.replaceAll("\\D", "")); 496 } 497 } 498 499 try { 500 WebParser.addImageFromUrl(bgImage, linkUrl, frame, x, y, bgWidth, cropStartX, cropStartY, cropEndX, cropEndY, bgRepeat, originXPercent, originYPercent); 501 } catch (MalformedURLException mue) { 502 // probably a 'data:' url, not supported yet 503 mue.printStackTrace(); 504 } 505 } 506 507 String imgSrc; 508 509 if (currentNode.getNodeName().toLowerCase().equals("img") && (imgSrc = JavaFX.JSObjectGetMember.invoke(currentNode, "src").toString()) != null) { 510 try { 511 WebParser.addImageFromUrl(imgSrc, linkUrl, frame, x, y, (int) width, null, null, null, null, null, 0, 0); 512 } catch (MalformedURLException mue) { 513 // probably a 'data:' url, not supported yet 514 mue.printStackTrace(); 515 } 516 } 517 } 518 } 519 } 520 } 521 244 245 WebParser.addPageToFrame(doc, null, window, webEngine, frame); 246 522 247 progressBar.set(100); 523 248 … … 542 267 */ 543 268 private static Color rgbStringToColor(String rgbString) { 269 270 if (rgbString == null) { 271 return null; 272 } 273 544 274 // Splitting the string into 'rgb' and 'x, x, x' 545 275 String[] tmpStrings = rgbString.split("\\(|\\)"); … … 561 291 } else { 562 292 return null; 293 } 294 } 295 296 /** 297 * @param rootElement 298 * Element that will be converted (including all sub-elements) 299 * @param backgroundColor 300 * String to be used as the background color of this element when added. In the format "rgb(x,x,x)" or "rgba(x,x,x,x)" 301 * @param window 302 * 'window' from Javascript 303 * @param webEngine 304 * Web engine that the page is loaded in 305 * @param frame 306 * Expeditee frame to add the converted page to 307 * @throws IllegalArgumentException 308 * @throws IllegalAccessException 309 */ 310 private static void addPageToFrame(Node rootElement, Color parentBgColor, Object window, Object webEngine, Frame frame) throws InvocationTargetException, IllegalAccessException, 311 IllegalArgumentException { 312 313 Node currentNode = rootElement; 314 315 Color bgColor = null; 316 317 if (currentNode.getNodeType() == Node.TEXT_NODE || currentNode.getNodeType() == Node.ELEMENT_NODE) { 318 319 Object style; 320 Object bounds; 321 322 if (currentNode.getNodeType() == Node.TEXT_NODE) { 323 // CSS style for the element 324 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode.getParentNode() }); 325 326 // Getting a rectangle that represents the area and position of the element 327 bounds = JavaFX.JSObjectCall.invoke(currentNode.getParentNode(), "getBoundingClientRect", new Object[] {}); 328 } else { 329 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode }); 330 331 bounds = JavaFX.JSObjectCall.invoke(currentNode, "getBoundingClientRect", new Object[] {}); 332 } 333 334 // Bounding rectangle position is relative to the current view, so scroll position must be added to x/y 335 // TODO: This doesn't check if an element or any of its parent elements have position:fixed set - the only 336 // way to check seems to be to walking through the element's parents until the document root is reached 337 float x = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "left").toString()) 338 + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageXOffset").toString()); 339 float y = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "top").toString()) 340 + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageYOffset").toString()); 341 342 float width = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "width").toString()); 343 float height = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "height").toString()); 344 345 // Have to get the bg color even if the element isn't visible, so it can be cascaded down to child elements 346 // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)" 347 String bgColorString = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-color" }); 348 349 bgColor = rgbStringToColor(bgColorString); 350 351 bgColor = (bgColor != null ? bgColor : parentBgColor); 352 353 354 // Checking if the element is actually visible on the page 355 if (WebParser.elementVisible(x, y, width, height, style)) { 356 357 // Filtering the node type, starting with text nodes 358 if (currentNode.getNodeType() == Node.TEXT_NODE) { 359 String fontSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-size" })); 360 361 // Trimming off the units (always px) from the font size 362 fontSize = fontSize.substring(0, fontSize.length() - 2); 363 364 // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)" 365 String color = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "color" }); 366 367 String align = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-align" }); 368 369 // Returns comma-separated list of typefaces 370 String typeface = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-family" }); 371 372 String[] typefaces = typeface.split(", |,"); 373 374 String weight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-weight" }); 375 376 String fontStyle = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-style" }); 377 378 // Returns "normal" or a value in pixels (e.g. "10px") 379 String letterSpacing = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "letter-spacing" }); 380 381 // Returns a value in pixels (e.g. "10px") 382 String lineHeight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "line-height" }); 383 384 String textTransform = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-transform" }); 385 386 String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode.getParentNode(), "href"); 387 388 Boolean fontFound = false; 389 Font font = new Font(null); 390 391 // Looping through all font-families listed in the element's CSS until one that is installed is 392 // found, or the end of the list is reached, in which case the default font is used 393 for (int j = 0; j < typefaces.length && !fontFound; j++) { 394 if (typefaces[j].toLowerCase().equals("sans-serif")) { 395 typefaces[j] = "Arial Unicode MS"; 396 } else if (typefaces[j].toLowerCase().equals("serif")) { 397 typefaces[j] = "Times New Roman"; 398 } else if ((typefaces[j].toLowerCase().equals("arial"))) { 399 // Have to use Arial Unicode, otherwise unicode characters display incorrectly 400 typefaces[j] = "Arial Unicode MS"; 401 } 402 403 // Regex will remove any inverted commas surrounding multi-word typeface names 404 font = new Font(typefaces[j].replaceAll("^'|'$", ""), Font.PLAIN, 12); 405 406 // If the font isn't found, Java just uses Font.DIALOG, so this check checks whether the font was found 407 if (!(font.getFamily().toLowerCase().equals(Font.DIALOG.toLowerCase()))) { 408 fontFound = true; 409 } 410 } 411 412 if (font.getFamily().toLowerCase().equals(Font.DIALOG.toLowerCase())) { 413 font = new Font("Times New Roman", Font.PLAIN, 12); 414 } 415 416 String fontStyleComplete = ""; 417 418 int weightInt = 0; 419 420 try { 421 weightInt = Integer.parseInt(weight); 422 } catch (NumberFormatException nfe) { 423 // Use default value as set above 424 } 425 426 // checking if font is bold - i.e. 'bold', 'bolder' or weight over 500 427 if (weight.toLowerCase().startsWith("bold") || weightInt > 500) { 428 fontStyleComplete = fontStyleComplete.concat("bold"); 429 } 430 431 if (fontStyle.toLowerCase().equals("italic") || fontStyle.toLowerCase().equals("oblique")) { 432 fontStyleComplete = fontStyleComplete.concat("italic"); 433 } 434 435 float fontSizeFloat = 12; 436 437 try { 438 fontSizeFloat = Float.valueOf(fontSize); 439 } catch (NumberFormatException nfe) { 440 // Use default value as set above 441 } 442 443 float letterSpacingFloat = -0.008f; 444 445 try { 446 letterSpacingFloat = (Integer.parseInt(letterSpacing.substring(0, letterSpacing.length() - 2)) / (fontSizeFloat)); 447 } catch (NumberFormatException nfe) { 448 // Use default value as set above 449 } 450 451 float lineHeightInt = -1; 452 453 try { 454 lineHeightInt = (Float.parseFloat(lineHeight.substring(0, lineHeight.length() - 2))); 455 } catch (NumberFormatException nfe) { 456 // Use default value as set above 457 } 458 459 Text t; 460 461 String textContent = currentNode.getTextContent().replaceAll("[^\\S\\n]+", " "); 462 textContent = textContent.replaceAll("^(\\s)(\\n|\\r)", ""); 463 464 if (textTransform.equals("uppercase")) { 465 textContent = textContent.toUpperCase(); 466 } else if (textTransform.equals("lowercase")) { 467 textContent = textContent.toUpperCase(); 468 } 469 470 t = frame.addText(Math.round(x), Math.round(y), textContent, null); 471 472 t.setColor(rgbStringToColor(color)); 473 t.setBackgroundColor(bgColor); 474 t.setFont(font); 475 t.setSize(fontSizeFloat); 476 t.setFontStyle(fontStyleComplete); 477 t.setLetterSpacing(letterSpacingFloat); 478 479 // Removing any spacing between lines allowing t.getLineHeight() to be used to get the actual height 480 // of just the characters (i.e. distance from ascenders to descenders) 481 t.setSpacing(0); 482 483 t.setSpacing(lineHeightInt - t.getLineHeight()); 484 485 if (align.equals("left")) { 486 t.setJustification(Justification.left); 487 } else if (align.equals("right")) { 488 t.setJustification(Justification.right); 489 } else if (align.equals("center")) { 490 t.setJustification(Justification.center); 491 } else if (align.equals("justify")) { 492 t.setJustification(Justification.full); 493 } 494 495 // Font size is added to the item width to give a little breathing room 496 t.setWidth(Math.round(width + (t.getSize()))); 497 498 if (!linkUrl.equals("undefined")) { 499 t.setAction("gotourl " + linkUrl); 500 t.setActionMark(false); 501 } 502 503 } else if (currentNode.getNodeType() == Node.ELEMENT_NODE) { 504 505 // background image, returns in format "url(protocol://absolute/path/to/img.extension)" for images, 506 // may also return gradients, data, etc. (not handled yet). Only need to add bg image on 507 // 'ELEMENT_NODE' (and not 'TEXT_NODE' otherwise there would be double-ups 508 String bgImage = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-image" }); 509 510 String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode, "href"); 511 512 if (bgImage.startsWith("url(")) { 513 514 bgImage = bgImage.substring(4, bgImage.length() - 1); 515 516 String bgSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-size" })).toLowerCase(); 517 String bgRepeat = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-repeat" })).toLowerCase(); 518 519 // Returns "[x]px [y]px", "[x]% [y]%", "[x]px [y]%" or "[x]% [y]px" 520 String bgPosition = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-position" })).toLowerCase(); 521 522 String[] bgOffsetCoords = bgPosition.split(" "); 523 524 int bgOffsetX = 0, bgOffsetY = 0; 525 526 float originXPercent = 0, originYPercent = 0; 527 528 int cropStartX, cropStartY, cropEndX, cropEndY; 529 530 // Converting the x and y offset values to integers (and from % to px if needed) 531 if (bgOffsetCoords[0].endsWith("%")) { 532 bgOffsetX = (int) ((Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 1)) / 100.0) * width); 533 originXPercent = (Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 1))) / 100f; 534 } else if (bgOffsetCoords[0].endsWith("px")) { 535 bgOffsetX = (int) (Integer.valueOf(bgOffsetCoords[0].substring(0, bgOffsetCoords[0].length() - 2))); 536 } 537 538 if (bgOffsetCoords[1].endsWith("%")) { 539 bgOffsetY = (int) ((Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 1)) / 100.0) * height); 540 originYPercent = (Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 1))) / 100f; 541 } else if (bgOffsetCoords[1].endsWith("px")) { 542 bgOffsetY = (int) (Integer.valueOf(bgOffsetCoords[1].substring(0, bgOffsetCoords[1].length() - 2))); 543 } 544 545 // Converting from an offset to crop coords 546 cropStartX = -1 * bgOffsetX; 547 cropEndX = (int) (cropStartX + width); 548 549 cropStartY = -1 * bgOffsetY; 550 cropEndY = (int) (cropStartY + height); 551 552 int bgWidth = -1; 553 554 if (bgSize.equals("cover")) { 555 bgWidth = (int) width; 556 } else if (bgSize.equals("contain")) { 557 // TODO: actually compute the appropriate width 558 bgWidth = (int) width; 559 } else if (bgSize.equals("auto")) { 560 bgWidth = -1; 561 } else { 562 bgSize = bgSize.split(" ")[0]; 563 564 if (bgSize.endsWith("%")) { 565 bgWidth = (int) ((Integer.parseInt(bgSize.replaceAll("\\D", "")) / 100.0) * width); 566 } else if (bgSize.endsWith("px")) { 567 bgWidth = Integer.parseInt(bgSize.replaceAll("\\D", "")); 568 } 569 } 570 571 try { 572 WebParser.addImageFromUrl(bgImage, linkUrl, frame, x, y, bgWidth, cropStartX, cropStartY, cropEndX, cropEndY, bgRepeat, originXPercent, originYPercent); 573 } catch (MalformedURLException mue) { 574 // probably a 'data:' url, not supported yet 575 mue.printStackTrace(); 576 } catch (IOException e) { 577 // TODO Auto-generated catch block 578 e.printStackTrace(); 579 } 580 } 581 582 String imgSrc; 583 584 if (currentNode.getNodeName().toLowerCase().equals("img") && (imgSrc = JavaFX.JSObjectGetMember.invoke(currentNode, "src").toString()) != null) { 585 try { 586 WebParser.addImageFromUrl(imgSrc, linkUrl, frame, x, y, (int) width, null, null, null, null, null, 0, 0); 587 } catch (MalformedURLException mue) { 588 // probably a 'data:' url, not supported yet 589 mue.printStackTrace(); 590 } catch (IOException e) { 591 // TODO Auto-generated catch block 592 e.printStackTrace(); 593 } 594 } 595 } 596 } 597 598 Node childNode = currentNode.getFirstChild(); 599 600 while (childNode != null) { 601 addPageToFrame(childNode, bgColor, window, webEngine, frame); 602 childNode = childNode.getNextSibling(); 603 } 563 604 } 564 605 }
Note:
See TracChangeset
for help on using the changeset viewer.