| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f775d44 commit 0eb5ba5
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,8 +22,23 @@ | |||
| 22 | 22 | ||
| 23 | 23 | package processing.core; | |
| 24 | 24 | ||
| 25 | + import java.awt.Image; | ||
| 26 | + import java.awt.color.ColorSpace; | ||
| 27 | + import java.awt.image.BufferedImage; | ||
| 28 | + import java.io.IOException; | ||
| 29 | + import java.nio.charset.Charset; | ||
| 30 | + import java.nio.file.Files; | ||
| 31 | + import java.nio.file.Paths; | ||
| 25 | 32 | import java.util.HashMap; | |
| 26 | 33 | import java.util.Map; | |
| 34 | + import java.util.Base64.Decoder; | ||
| 35 | + import java.util.logging.Level; | ||
| 36 | + import java.util.logging.Logger; | ||
| 37 | + import java.nio.charset.StandardCharsets; | ||
| 38 | + import javax.swing.ImageIcon; | ||
| 39 | + import javax.xml.bind.DatatypeConverter; | ||
| 40 | + | ||
| 41 | + | ||
| 27 | 42 | ||
| 28 | 43 | import processing.core.PApplet; | |
| 29 | 44 | ||
@@ -106,6 +121,7 @@ public class PShape implements PConstants { | |||
| 106 | 121 | ||
| 107 | 122 | /** Texture or image data associated with this shape. */ | |
| 108 | 123 | protected PImage image; | |
| 124 | + protected String imagePath = null; | ||
| 109 | 125 | ||
| 110 | 126 | public static final String OUTSIDE_BEGIN_END_ERROR = | |
| 111 | 127 | "%1$s can only be called between beginShape() and endShape()"; | |
@@ -1645,6 +1661,10 @@ protected void drawPrimitive(PGraphics g) { | |||
| 1645 | 1661 | params[6], params[7]); | |
| 1646 | 1662 | ||
| 1647 | 1663 | } else if (kind == RECT) { | |
| 1664 | + | ||
| 1665 | + if (imagePath != null){ | ||
| 1666 | + loadImage(g); | ||
| 1667 | + } | ||
| 1648 | 1668 | if (image != null) { | |
| 1649 | 1669 | int oldMode = g.imageMode; | |
| 1650 | 1670 | g.imageMode(CORNER); | |
@@ -1879,6 +1899,63 @@ protected void drawPath(PGraphics g) { | |||
| 1879 | 1899 | g.endShape(close ? CLOSE : OPEN); | |
| 1880 | 1900 | } | |
| 1881 | 1901 | ||
| 1902 | + private void loadImage(PGraphics g){ | ||
| 1903 | + | ||
| 1904 | + if(this.imagePath.startsWith("data:image")){ | ||
| 1905 | + loadBase64Image(); | ||
| 1906 | + } | ||
| 1907 | + | ||
| 1908 | + if(this.imagePath.startsWith("file://")){ | ||
| 1909 | + loadFileSystemImage(g); | ||
| 1910 | + } | ||
| 1911 | + this.imagePath = null; | ||
| 1912 | + } | ||
| 1913 | + | ||
| 1914 | + private void loadFileSystemImage(PGraphics g){ | ||
| 1915 | + imagePath = imagePath.substring(7); | ||
| 1916 | + PImage loadedImage = g.parent.loadImage(imagePath); | ||
| 1917 | + if(loadedImage == null){ | ||
| 1918 | + System.err.println("Error loading image file: " + imagePath); | ||
| 1919 | + }else{ | ||
| 1920 | + setTexture(loadedImage); | ||
| 1921 | + } | ||
| 1922 | + } | ||
| 1923 | + | ||
| 1924 | + private void loadBase64Image(){ | ||
| 1925 | + String[] parts = this.imagePath.split(";base64,"); | ||
| 1926 | + String extension = parts[0].substring(11); | ||
| 1927 | + String encodedData = parts[1]; | ||
| 1928 | + | ||
| 1929 | + byte[] decodedBytes = DatatypeConverter.parseBase64Binary(encodedData); | ||
| 1930 | + | ||
| 1931 | + if(decodedBytes == null){ | ||
| 1932 | + System.err.println("Decode Error on image: " + imagePath.substring(0, 20)); | ||
| 1933 | + return; | ||
| 1934 | + } | ||
| 1935 | + | ||
| 1936 | + Image awtImage = new ImageIcon(decodedBytes).getImage(); | ||
| 1937 | + | ||
| 1938 | + if (awtImage instanceof BufferedImage) { | ||
| 1939 | + BufferedImage buffImage = (BufferedImage) awtImage; | ||
| 1940 | + int space = buffImage.getColorModel().getColorSpace().getType(); | ||
| 1941 | + if (space == ColorSpace.TYPE_CMYK) { | ||
| 1942 | + return; | ||
| 1943 | + } | ||
| 1944 | + } | ||
| 1945 | + | ||
| 1946 | + PImage loadedImage = new PImage(awtImage); | ||
| 1947 | + if (loadedImage.width == -1) { | ||
| 1948 | + // error... | ||
| 1949 | + } | ||
| 1950 | + | ||
| 1951 | + // if it's a .gif image, test to see if it has transparency | ||
| 1952 | + if (extension.equals("gif") || extension.equals("png") || | ||
| 1953 | + extension.equals("unknown")) { | ||
| 1954 | + loadedImage.checkAlpha(); | ||
| 1955 | + } | ||
| 1956 | + | ||
| 1957 | + setTexture(loadedImage); | ||
| 1958 | + } | ||
| 1882 | 1959 | ||
| 1883 | 1960 | // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |
| 1884 | 1961 | ||
@@ -2387,14 +2464,14 @@ public void setFill(boolean fill) { | |||
| 2387 | 2464 | /** | |
| 2388 | 2465 | * ( begin auto-generated from PShape_setFill.xml ) | |
| 2389 | 2466 | * | |
| 2390 | - * The <b>setFill()</b> method defines the fill color of a <b>PShape</b>. | ||
| 2391 | - * This method is used after shapes are created or when a shape is defined explicitly | ||
| 2392 | - * (e.g. <b>createShape(RECT, 20, 20, 80, 80)</b>) as shown in the above example. | ||
| 2393 | - * When a shape is created with <b>beginShape()</b> and <b>endShape()</b>, its | ||
| 2394 | - * attributes may be changed with <b>fill()</b> and <b>stroke()</b> within | ||
| 2395 | - * <b>beginShape()</b> and <b>endShape()</b>. However, after the shape is | ||
| 2396 | - * created, only the <b>setFill()</b> method can define a new fill value for | ||
| 2397 | - * the <b>PShape</b>. | ||
| 2467 | + * The <b>setFill()</b> method defines the fill color of a <b>PShape</b>. | ||
| 2468 | + * This method is used after shapes are created or when a shape is defined explicitly | ||
| 2469 | + * (e.g. <b>createShape(RECT, 20, 20, 80, 80)</b>) as shown in the above example. | ||
| 2470 | + * When a shape is created with <b>beginShape()</b> and <b>endShape()</b>, its | ||
| 2471 | + * attributes may be changed with <b>fill()</b> and <b>stroke()</b> within | ||
| 2472 | + * <b>beginShape()</b> and <b>endShape()</b>. However, after the shape is | ||
| 2473 | + * created, only the <b>setFill()</b> method can define a new fill value for | ||
| 2474 | + * the <b>PShape</b>. | ||
| 2398 | 2475 | * | |
| 2399 | 2476 | * ( end auto-generated ) | |
| 2400 | 2477 | * | |
@@ -2543,14 +2620,14 @@ public void setStroke(boolean stroke) { | |||
| 2543 | 2620 | /** | |
| 2544 | 2621 | * ( begin auto-generated from PShape_setStroke.xml ) | |
| 2545 | 2622 | * | |
| 2546 | - * The <b>setStroke()</b> method defines the outline color of a <b>PShape</b>. | ||
| 2547 | - * This method is used after shapes are created or when a shape is defined | ||
| 2548 | - * explicitly (e.g. <b>createShape(RECT, 20, 20, 80, 80)</b>) as shown in | ||
| 2549 | - * the above example. When a shape is created with <b>beginShape()</b> and | ||
| 2550 | - * <b>endShape()</b>, its attributes may be changed with <b>fill()</b> and | ||
| 2551 | - * <b>stroke()</b> within <b>beginShape()</b> and <b>endShape()</b>. | ||
| 2552 | - * However, after the shape is created, only the <b>setStroke()</b> method | ||
| 2553 | - * can define a new stroke value for the <b>PShape</b>. | ||
| 2623 | + * The <b>setStroke()</b> method defines the outline color of a <b>PShape</b>. | ||
| 2624 | + * This method is used after shapes are created or when a shape is defined | ||
| 2625 | + * explicitly (e.g. <b>createShape(RECT, 20, 20, 80, 80)</b>) as shown in | ||
| 2626 | + * the above example. When a shape is created with <b>beginShape()</b> and | ||
| 2627 | + * <b>endShape()</b>, its attributes may be changed with <b>fill()</b> and | ||
| 2628 | + * <b>stroke()</b> within <b>beginShape()</b> and <b>endShape()</b>. | ||
| 2629 | + * However, after the shape is created, only the <b>setStroke()</b> method | ||
| 2630 | + * can define a new stroke value for the <b>PShape</b>. | ||
| 2554 | 2631 | * | |
| 2555 | 2632 | * ( end auto-generated ) | |
| 2556 | 2633 | * | |
@@ -3442,4 +3519,4 @@ protected void colorCalcARGB(int argb, float alpha) { | |||
| 3442 | 3519 | calcAlpha = (calcAi != 255); | |
| 3443 | 3520 | } | |
| 3444 | 3521 | ||
| 3445 | - } | ||
| 3522 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,9 @@ | |||
| 24 | 24 | ||
| 25 | 25 | package processing.core; | |
| 26 | 26 | ||
| 27 | + import static java.awt.Font.BOLD; | ||
| 28 | + import static java.awt.Font.ITALIC; | ||
| 29 | + import static java.awt.Font.PLAIN; | ||
| 27 | 30 | import processing.data.*; | |
| 28 | 31 | ||
| 29 | 32 | // TODO replace these with PMatrix2D | |
@@ -329,6 +332,10 @@ protected PShape parseChild(XML elem) { | |||
| 329 | 332 | } else if (name.equals("rect")) { | |
| 330 | 333 | shape = createShape(this, elem, true); | |
| 331 | 334 | shape.parseRect(); | |
| 335 | + | ||
| 336 | + } else if (name.equals("image")) { | ||
| 337 | + shape = createShape(this, elem, true); | ||
| 338 | + shape.parseImage(); | ||
| 332 | 339 | ||
| 333 | 340 | } else if (name.equals("polygon")) { | |
| 334 | 341 | shape = createShape(this, elem, true); | |
@@ -358,8 +365,10 @@ protected PShape parseChild(XML elem) { | |||
| 358 | 365 | // return new FontGlyph(this, elem); | |
| 359 | 366 | ||
| 360 | 367 | } else if (name.equals("text")) { // || name.equals("font")) { | |
| 361 | - PGraphics.showWarning("Text and fonts in SVG files are " + | ||
| 362 | - "not currently supported, convert text to outlines instead."); | ||
| 368 | + return new Text(this, elem); | ||
| 369 | + | ||
| 370 | + } else if (name.equals("tspan")) { | ||
| 371 | + return new LineOfText(this, elem); | ||
| 363 | 372 | ||
| 364 | 373 | } else if (name.equals("filter")) { | |
| 365 | 374 | PGraphics.showWarning("Filters are not supported."); | |
@@ -439,8 +448,23 @@ protected void parseRect() { | |||
| 439 | 448 | getFloatWithUnit(element, "height", svgHeight) | |
| 440 | 449 | }; | |
| 441 | 450 | } | |
| 451 | + | ||
| 452 | + | ||
| 453 | + protected void parseImage() { | ||
| 454 | + kind = RECT; | ||
| 455 | + textureMode = NORMAL; | ||
| 442 | 456 | ||
| 457 | + family = PRIMITIVE; | ||
| 458 | + params = new float[] { | ||
| 459 | + getFloatWithUnit(element, "x", svgWidth), | ||
| 460 | + getFloatWithUnit(element, "y", svgHeight), | ||
| 461 | + getFloatWithUnit(element, "width", svgWidth), | ||
| 462 | + getFloatWithUnit(element, "height", svgHeight) | ||
| 463 | + }; | ||
| 443 | 464 | ||
| 465 | + this.imagePath = element.getString("xlink:href"); | ||
| 466 | + } | ||
| 467 | + | ||
| 444 | 468 | /** | |
| 445 | 469 | * Parse a polyline or polygon from an SVG file. | |
| 446 | 470 | * Syntax defined at http://www.w3.org/TR/SVG/shapes.html#PointsBNF | |
@@ -1557,8 +1581,179 @@ public RadialGradient(PShapeSVG parent, XML properties) { | |||
| 1557 | 1581 | ||
| 1558 | 1582 | ||
| 1559 | 1583 | // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |
| 1584 | + | ||
| 1585 | + public static float TEXT_QUALITY = 1; | ||
| 1586 | + protected PFont parseFont(XML properties) { | ||
| 1587 | + | ||
| 1588 | + // FontFace fontFace = new FontFace(this, properties); | ||
| 1589 | + String fontFamily = null; | ||
| 1590 | + float size = 10; | ||
| 1591 | + int weight = PLAIN; // 0 | ||
| 1592 | + int italic = 0; | ||
| 1593 | + | ||
| 1594 | + if (properties.hasAttribute("style")) { | ||
| 1595 | + String styleText = properties.getString("style"); | ||
| 1596 | + String[] styleTokens = PApplet.splitTokens(styleText, ";"); | ||
| 1597 | + | ||
| 1598 | + //PApplet.println(styleTokens); | ||
| 1599 | + for (int i = 0; i < styleTokens.length; i++) { | ||
| 1600 | + | ||
| 1601 | + String[] tokens = PApplet.splitTokens(styleTokens[i], ":"); | ||
| 1602 | + //PApplet.println(tokens); | ||
| 1603 | + | ||
| 1604 | + tokens[0] = PApplet.trim(tokens[0]); | ||
| 1605 | + | ||
| 1606 | + if (tokens[0].equals("font-style")) { | ||
| 1607 | + // PApplet.println("font-style: " + tokens[1]); | ||
| 1608 | + if (tokens[1].contains("italic")) { | ||
| 1609 | + italic = ITALIC; | ||
| 1610 | + } | ||
| 1611 | + } else if (tokens[0].equals("font-variant")) { | ||
| 1612 | + // PApplet.println("font-variant: " + tokens[1]); | ||
| 1613 | + // setFillOpacity(tokens[1]); | ||
| 1614 | + | ||
| 1615 | + } else if (tokens[0].equals("font-weight")) { | ||
| 1616 | + // PApplet.println("font-weight: " + tokens[1]); | ||
| 1617 | + | ||
| 1618 | + if (tokens[1].contains("bold")) { | ||
| 1619 | + weight = BOLD; | ||
| 1620 | + // PApplet.println("Bold weight ! "); | ||
| 1621 | + } | ||
| 1622 | + | ||
| 1623 | + | ||
| 1624 | + } else if (tokens[0].equals("font-stretch")) { | ||
| 1625 | + // not supported. | ||
| 1626 | + | ||
| 1627 | + } else if (tokens[0].equals("font-size")) { | ||
| 1628 | + // PApplet.println("font-size: " + tokens[1]); | ||
| 1629 | + size = Float.parseFloat(tokens[1].split("px")[0]); | ||
| 1630 | + // PApplet.println("font-size-parsed: " + size); | ||
| 1631 | + } else if (tokens[0].equals("line-height")) { | ||
| 1632 | + // not supported | ||
| 1633 | + | ||
| 1634 | + } else if (tokens[0].equals("font-family")) { | ||
| 1635 | + // PApplet.println("Font-family: " + tokens[1]); | ||
| 1636 | + fontFamily = tokens[1]; | ||
| 1637 | + | ||
| 1638 | + } else if (tokens[0].equals("text-align")) { | ||
| 1639 | + // not supported | ||
| 1640 | + | ||
| 1641 | + } else if (tokens[0].equals("letter-spacing")) { | ||
| 1642 | + // not supported | ||
| 1643 | + | ||
| 1644 | + } else if (tokens[0].equals("word-spacing")) { | ||
| 1645 | + // not supported | ||
| 1646 | + | ||
| 1647 | + } else if (tokens[0].equals("writing-mode")) { | ||
| 1648 | + // not supported | ||
| 1649 | + | ||
| 1650 | + } else if (tokens[0].equals("text-anchor")) { | ||
| 1651 | + // not supported | ||
| 1652 | + | ||
| 1653 | + } else { | ||
| 1654 | + // Other attributes are not yet implemented | ||
| 1655 | + } | ||
| 1656 | + } | ||
| 1657 | + } | ||
| 1658 | + if (fontFamily == null) { | ||
| 1659 | + return null; | ||
| 1660 | + } | ||
| 1661 | + size = size * TEXT_QUALITY; | ||
| 1662 | + | ||
| 1663 | + return createFont(fontFamily, weight | italic, size, true); | ||
| 1664 | + } | ||
| 1665 | + | ||
| 1666 | + protected PFont createFont(String name, int weight, float size, boolean smooth) { | ||
| 1667 | + | ||
| 1668 | + // System.out.println("Try to create a font of " + name + " family, " + weight); | ||
| 1669 | + java.awt.Font baseFont = new java.awt.Font(name, weight, (int) size); // PFont.findFont(name);ç | ||
| 1670 | + | ||
| 1671 | + // System.out.println("Resulting family : " + baseFont.getFamily() + " " + baseFont.getStyle()); | ||
| 1672 | + PFont outputPFont = new PFont(baseFont.deriveFont(size), smooth, null); | ||
| 1673 | + | ||
| 1674 | + // System.out.println("Resulting PFont family : " + outputPFont.getName()); | ||
| 1675 | + return outputPFont; | ||
| 1676 | + } | ||
| 1677 | + | ||
| 1678 | + public static class Text extends PShapeSVG { | ||
| 1679 | + | ||
| 1680 | + protected PFont font; | ||
| 1681 | + | ||
| 1682 | + public Text(PShapeSVG parent, XML properties) { | ||
| 1683 | + super(parent, properties, true); | ||
| 1684 | + | ||
| 1685 | + // get location | ||
| 1686 | + float x = Float.parseFloat(properties.getString("x")); | ||
| 1687 | + float y = Float.parseFloat(properties.getString("y")); | ||
| 1688 | + | ||
| 1689 | + if (matrix == null) { | ||
| 1690 | + matrix = new PMatrix2D(); | ||
| 1691 | + } | ||
| 1692 | + matrix.translate(x, y); | ||
| 1693 | + | ||
| 1694 | + family = GROUP; | ||
| 1695 | + | ||
| 1696 | + font = parseFont(properties); | ||
| 1560 | 1697 | ||
| 1698 | + } | ||
| 1699 | + | ||
| 1700 | + // @Override | ||
| 1701 | + // public void drawImpl(PGraphics g){ | ||
| 1702 | + // } | ||
| 1703 | + } | ||
| 1704 | + | ||
| 1705 | + public static class LineOfText extends PShapeSVG { | ||
| 1561 | 1706 | ||
| 1707 | + String textToDisplay; | ||
| 1708 | + PFont font; | ||
| 1709 | + | ||
| 1710 | + public LineOfText(PShapeSVG parent, XML properties) { | ||
| 1711 | + | ||
| 1712 | + // TODO: child should ideally be parsed too... | ||
| 1713 | + // for inline content. | ||
| 1714 | + super(parent, properties, false); | ||
| 1715 | + | ||
| 1716 | + // // get location | ||
| 1717 | + float x = Float.parseFloat(properties.getString("x")); | ||
| 1718 | + float y = Float.parseFloat(properties.getString("y")); | ||
| 1719 | + | ||
| 1720 | + float parentX = Float.parseFloat(parent.element.getString("x")); | ||
| 1721 | + float parentY = Float.parseFloat(parent.element.getString("y")); | ||
| 1722 | + | ||
| 1723 | + if (matrix == null) matrix = new PMatrix2D(); | ||
| 1724 | + matrix.translate(x - parentX, (y - parentY) / 2f); | ||
| 1725 | + | ||
| 1726 | + // get the first properties | ||
| 1727 | + parseColors(properties); | ||
| 1728 | + font = parseFont(properties); | ||
| 1729 | + | ||
| 1730 | + // It is a line.. | ||
| 1731 | + boolean isALine = properties.getString("role") == "line"; | ||
| 1732 | + // NO inline content yet. | ||
| 1733 | + if (this.childCount > 0) { | ||
| 1734 | + } | ||
| 1735 | + | ||
| 1736 | + String text = properties.getContent(); | ||
| 1737 | + textToDisplay = text; | ||
| 1738 | + } | ||
| 1739 | + | ||
| 1740 | + @Override | ||
| 1741 | + public void drawImpl(PGraphics g) { | ||
| 1742 | + if (font == null) { | ||
| 1743 | + font = ((Text) parent).font; | ||
| 1744 | + if (font == null) { | ||
| 1745 | + return; | ||
| 1746 | + } | ||
| 1747 | + } | ||
| 1748 | + | ||
| 1749 | + pre(g); | ||
| 1750 | + g.textFont(font, font.size / TEXT_QUALITY); | ||
| 1751 | + g.text(textToDisplay, 0, 0); | ||
| 1752 | + post(g); | ||
| 1753 | + } | ||
| 1754 | + | ||
| 1755 | + } | ||
| 1756 | + | ||
| 1562 | 1757 | public static class Font extends PShapeSVG { | |
| 1563 | 1758 | public FontFace face; | |
| 1564 | 1759 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments