Changeset 659


Ignore:
Timestamp:
01/07/14 15:26:22 (10 years ago)
Author:
ngw8
Message:

Improvements WebParser conversions of wrapped text - links and other formatting now maintained. Fixed inability to have negative letter spacing, doesn't seem to have broken anything. Changed text line spacing to be a float.

Location:
trunk/src/org/expeditee
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/io/Conversion.java

    r562 r659  
    669669
    670670                // floats can also be returned immediately
    671                 if (output instanceof Float && (Float) output >= 0)
     671                if (output instanceof Float) // && (Float) output >= 0) // Removed checking if >0, as some floats (e.g. letter spacing) can be negative
    672672                        return "" + output;
    673673
  • trunk/src/org/expeditee/io/DefaultFrameReader.java

    r656 r659  
    115115                       
    116116                        _ItemTags.put('f', Text.class.getMethod("setFont", pFont));
    117                         _ItemTags.put('t', Text.class.getMethod("setSpacing", pInt));
     117                        _ItemTags.put('t', Text.class.getMethod("setSpacing", pFloat));
    118118                        _ItemTags.put('T', Text.class.getMethod("appendLine", pString));
    119119                        _ItemTags.put('a', Text.class.getMethod("setWordSpacing", pInt));
    120                         _ItemTags.put('b', Text.class.getMethod("setLetterSpacing", pInt));
    121                         _ItemTags.put('m', Text.class.getMethod("setInitialSpacing", pInt));
     120                        _ItemTags.put('b', Text.class.getMethod("setLetterSpacing", pFloat));
     121                        _ItemTags.put('m', Text.class.getMethod("setInitialSpacing", pFloat));
    122122                        _ItemTags.put('w', Text.class.getMethod("setWidth", pIntO));
    123123                        _ItemTags.put('k', Text.class.getMethod("setJustification", pJustification));
  • trunk/src/org/expeditee/io/ExpReader.java

    r584 r659  
    199199                } catch (Exception e) {
    200200                        System.out.println("Error running tag method: " + tag);
    201                         // e.printStackTrace();
     201                        e.printStackTrace();
    202202                }
    203203        }
  • trunk/src/org/expeditee/io/WebParser.java

    r644 r659  
    134134                                                frame.setBackgroundColor(rgbStringToColor((String) JavaFX.JSObjectCall.invoke(JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { doc }), "getPropertyValue",
    135135                                                                new Object[] { "background-color" })));
    136 
    137                                                 // Following 2 functions taken from jQuery (Apache 2 License)
    138                                         /*      JavaFX.WebEngineExecuteScript
    139                                                                 .invoke(webEngine,
    140                                                                                 "function getText ( elem ) { var i, node, nodeType = elem.nodeType, ret = ''; if ( nodeType ) { if ( nodeType === 1 || nodeType === 9 ) { if ( typeof elem.textContent === 'string' ) { return elem.textContent; } else if ( typeof elem.innerText === 'string' ) { return elem.innerText.replace( rReturn, '' ); } else { for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } } else { for ( i = 0; (node = elem[i]); i++ ) { if ( node.nodeType !== 8 ) { ret += getText( node ); } } } return ret; };");
    141                                                 JavaFX.WebEngineExecuteScript
    142                                                                 .invoke(webEngine,
    143                                                                                 "function myText(elem) { var i, node, nodeType = elem.nodeType, ret = ''; if (nodeType) { if (nodeType === 1 || nodeType === 9 || nodeType === 11) { if (typeof elem.textContent === 'string') { return elem.textContent; } else if (typeof elem.innerText === 'string') { return elem.innerText.replace(rReturn, ''); } else { for (elem = elem.firstChild; elem; elem = elem.nextSibling) { ret += getText(elem); } } } else if (nodeType === 3 || nodeType === 4) { return elem.nodeValue; } } else { for (i = 0; (node = elem[i]); i++) { if (node.nodeType !== 8) { ret += getText(node); } } } return ret; }");
    144                
    145                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine,
    146                                                                 "var ps = document.getElementsByTagName('p');"
    147                                                                 + "for(var i = 0; i < ps.length; i++) {"
    148                                                                         + "ps[i].innerHTML = myText(ps[i]);"
    149                                                                         + "var span = document.createElement('replacement');"
    150                                                                         + "span.textContent = ps[i].textContent;"
    151                                                                         + " ps[i].innerHTML = span.outerHTML;"
    152                                                                 + "}" );
    153                                         */
    154136                                               
     137                                                // Functions to be used later in JavaScript
    155138                                                JavaFX.WebEngineExecuteScript
    156139                                                                .invoke(webEngine,
     
    171154                                                                                + "             span = document.createElement('wordSpan');"
    172155                                                                                + "             span.textContent = text + ' ';"
    173                                                                                 + "             para.appendChild(span);"
     156                                                                                + "             textNode.parentElement.insertBefore(span, textNode);"
    174157                                                                                + "             if (prevSpan !== null && span.getBoundingClientRect().top > prevSpan.getBoundingClientRect().top) {"
    175158                                                                                + "                     span.textContent = '\\n' + span.textContent;"
    176                                                                                 + "                     if (prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
     159                                                                                + "                     if ( prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
    177160                                                                                + "                             prevPrevSpan.textContent = prevPrevSpan.textContent + prevSpan.textContent;"
    178                                                                                 + "                             para.removeChild(prevSpan);"
     161                                                                                + "                             textNode.parentElement.removeChild(prevSpan);"
    179162                                                                                + "                     } else {"
    180163                                                                                + "                             prevPrevSpan = prevSpan;"
    181164                                                                                + "                     }"
    182165                                                                                + "                     prevSpan = span;"
     166                                                                                + "             } else if ( prevSpan !== null) {"
     167                                                                                + "                     prevSpan.textContent = prevSpan.textContent + span.textContent;"
     168                                                                                + "                     textNode.parentElement.removeChild(span);"
    183169                                                                                + "             } else {"
    184                                                                                 + "                     prevSpan.textContent = prevSpan.textContent + span.textContent;"
    185                                                                                 + "                     para.removeChild(span);"
     170                                                                                + "                     prevSpan = span;"
    186171                                                                                + "             }"
    187172                                                                                + "}"   
    188173                                                );
    189174                                       
     175                                                // Getting an array of HTML elements from the page that will be checked for 'content' (i.e. will be modified to be
     176                                                // properly wrapped in Expeditee)
    190177                                                Object contentElements = JavaFX.WebEngineExecuteScript.invoke(webEngine, "document.querySelectorAll('p,li');");
    191178                                                int contentElementsLength = (Integer) JavaFX.JSObjectGetMember.invoke(contentElements, "length");
    192179
    193180                                                for (int i = 0; i < contentElementsLength; i++) {
    194                                                         Element currentNode = (Element) JavaFX.JSObjectGetSlot.invoke(contentElements, i);
    195 
    196                                                         JavaFX.JSObjectSetMember.invoke(window, "para", currentNode);
    197181                                                       
     182                                                        // Getting the current HTML element, then making it accessable in JavaScript
     183                                                        Element currentElement = (Element) JavaFX.JSObjectGetSlot.invoke(contentElements, i);
     184                                                        JavaFX.JSObjectSetMember.invoke(window, "para", currentElement);
     185
    198186                                                        if ((boolean) (JavaFX.WebEngineExecuteScript.invoke(webEngine, "isContent(para)"))) {
    199187                                                               
    200                                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
    201                                                                                 + "var span = document.createElement('wordSpan');"
    202                                                                                 + "var prevSpan = span;"
    203                                                                                 + "var prevPrevSpan = null;"
    204                                                                                 );
     188                                                                JavaFX.WebEngineExecuteScript.invoke(webEngine, "para.style.wordBreak = 'normal';");
     189
     190                                                                // Creating a TreeWalker that is used to loop over all the TextNodes within the current paragraph
     191                                                                JavaFX.WebEngineExecuteScript.invoke(webEngine, "var walker = document.createTreeWalker(para, NodeFilter.SHOW_TEXT, null, false);");
     192
     193                                                                Node textNode;
    205194                                                               
    206                                                                 Object paraWords = JavaFX.WebEngineExecuteScript.invoke(webEngine, "para.textContent.split(/\\s+/);");
    207                                                                 int paraWordsLength = (Integer) JavaFX.JSObjectGetMember.invoke(paraWords, "length");
    208195                                                               
    209                                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
    210                                                                                 + "para.innerHTML = '';"
    211                                                                                 + "para.style.wordBreak = 'normal';"
    212                                                                                 );
    213                                                                
    214                                                                 for (int j = 0; j < paraWordsLength; j++) {
    215                                                                         Object currentWord = JavaFX.JSObjectGetSlot.invoke(paraWords, j);
    216                                                                         JavaFX.JSObjectCall.invoke(window, "addToSpan", new Object[] { currentWord });
     196
     197                                                                // Looping through all the text nodes in the current paragraph
     198                                                                while ((textNode = (Node) JavaFX.WebEngineExecuteScript.invoke(webEngine, "walker.nextNode()")) != null) {
     199                                                                        // Making the current node accesable in JavaScript
     200                                                                        JavaFX.JSObjectSetMember.invoke(window, "textNode", textNode);
     201                                                                       
     202                                                                        JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     203                                                                                        + "var span = null;"
     204                                                                                        + "var prevSpan = null;"
     205                                                                                        + "var prevPrevSpan = null;"
     206                                                                                        );
     207
     208                                                                        // Splitting the text node's content into individual words
     209                                                                        Object words = JavaFX.WebEngineExecuteScript.invoke(webEngine, "textNode.textContent.split(/\\s+/);");
     210                                                                        int wordsLength = (Integer) JavaFX.JSObjectGetMember.invoke(words, "length");
     211                                                                       
     212                                                                        // Clearing all text from the current text node (but not removing it, as it is needed as a reference
     213                                                                        // point for adding back the words)
     214                                                                        JavaFX.WebEngineExecuteScript.invoke(webEngine, "textNode.textContent = '';");
     215                                                                       
     216                                                                        // Adding each word back to the page
     217                                                                        for (int j = 0; j < wordsLength; j++) {
     218                                                                                Object currentWord = JavaFX.JSObjectGetSlot.invoke(words, j);
     219                                                                                JavaFX.JSObjectCall.invoke(window, "addToSpan", new Object[] { currentWord });
     220                                                                        }
     221                                                                       
     222                                                                        JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     223                                                                                        + "                     if (prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
     224                                                                                        + "                             prevPrevSpan.textContent = prevPrevSpan.textContent + prevSpan.textContent;"
     225                                                                                        + "                             textNode.parentElement.removeChild(prevSpan);"
     226                                                                                        + "                     }"
     227                                                                                        );
    217228                                                                }
    218                                                                
    219                                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
    220                                                                                 + "                     if (prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
    221                                                                                 + "                             prevPrevSpan.textContent = prevPrevSpan.textContent + prevSpan.textContent;"
    222                                                                                 + "                             para.removeChild(prevSpan);"
    223                                                                                 + "                     }"
    224                                                                                 );
    225229                                                        }
    226230                                                }
     
    232236                                                                        + "var walk = document.createTreeWalker(rootNode, NodeFilter.SHOW_ALL);"
    233237                                                                        + "while(node=walk.nextNode()) {"
    234                                                                                 + " textNodes.push(node);" + "}"
     238                                                                                + " textNodes.push(node);"
     239                                                                        + "}"
    235240                                                                        + "return textNodes;"
    236                                                                         + "}; "
     241                                                                + "}; "
    237242                                                                + "getTextNodes(document.body)");
    238243
     
    243248
    244249                                                        if (currentNode.getNodeType() == Node.TEXT_NODE || currentNode.getNodeType() == Node.ELEMENT_NODE) {
    245 
    246                                                                 System.out.println(i + "/" + nodesLength + " : " + currentNode);
    247250                                                               
    248251                                                                Object style;
     
    267270                                                                                + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageYOffset").toString());
    268271
    269                                                                 float width = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "width").toString());
     272                                                                float width = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "width").toString()) + 5;
    270273                                                                float height = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "height").toString());
    271274
     
    299302                                                                                // Returns "normal" or a value in pixels (e.g. "10px")
    300303                                                                                String letterSpacing = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "letter-spacing" });
     304
     305                                                                                // Returns a value in pixels (e.g. "10px")
     306                                                                                String lineHeight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "line-height" });
    301307
    302308                                                                                String textTransform = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-transform" });
     
    334340                                                                                        weightInt = Integer.parseInt(weight);
    335341                                                                                } catch (NumberFormatException nfe) {
    336                                                                                         weightInt = 0;
     342                                                                                        // Use default value as set above
    337343                                                                                }
    338344
     
    346352                                                                                }
    347353
    348                                                                                 int letterSpacingInt = 0;
     354                                                                                float fontSizeFloat = 12;
    349355
    350356                                                                                try {
    351                                                                                         letterSpacingInt = (int) (Integer.parseInt(letterSpacing.substring(0, letterSpacing.length() - 2)) / Float.valueOf(fontSize));
     357                                                                                        fontSizeFloat = Float.valueOf(fontSize);
    352358                                                                                } catch (NumberFormatException nfe) {
    353                                                                                         letterSpacingInt = 0;
     359                                                                                        // Use default value as set above
     360                                                                                }
     361
     362                                                                                float letterSpacingFloat = -0.008f;
     363
     364                                                                                try {
     365                                                                                        letterSpacingFloat = (Integer.parseInt(letterSpacing.substring(0, letterSpacing.length() - 2)) / (fontSizeFloat));
     366                                                                                } catch (NumberFormatException nfe) {
     367                                                                                        // Use default value as set above
     368                                                                                }
     369
     370                                                                                float lineSpacingInt = -1;
     371                                                                               
     372                                                                                try {
     373                                                                                        lineSpacingInt = ((Float.parseFloat(lineHeight.substring(0, lineHeight.length() - 2)) - (fontSizeFloat * 1.22f)));
     374                                                                                } catch (NumberFormatException nfe) {
     375                                                                                        // Use default value as set above
    354376                                                                                }
    355377
     
    368390                                                                                t.setBackgroundColor(rgbStringToColor(bgColor));
    369391                                                                                t.setFont(font);
    370                                                                                 t.setSize(Float.valueOf(fontSize));
     392                                                                                t.setSize(fontSizeFloat);
    371393                                                                                t.setFontStyle(fontStyleComplete);
    372                                                                                 t.setLetterSpacing(letterSpacingInt);
     394                                                                                t.setLetterSpacing(letterSpacingFloat);
     395
     396                                                                                t.setSpacing(lineSpacingInt);
    373397
    374398                                                                                if (align.equals("left")) {
  • trunk/src/org/expeditee/items/Text.java

    r655 r659  
    3939import org.expeditee.gui.FreeItems;
    4040import org.expeditee.math.ExpediteeJEP;
     41import org.expeditee.settings.UserSettings;
    4142import org.expeditee.settings.experimental.ExperimentalFeatures;
    4243import org.nfunk.jep.Node;
     
    112113        private Justification _justification = Justification.left;
    113114
    114         private int _spacing = -1;
     115        private float _spacing = -1;
    115116
    116117        private int _word_spacing = -1;
    117118
    118         private int _initial_spacing = -1;
    119 
    120         private int _letter_spacing = -1;
     119        private float _initial_spacing = 0;
     120
     121        private float _letter_spacing = 0;
    121122
    122123        // used during ranging out
     
    11921193         *            The number of pixels to allow between each line
    11931194         */
    1194         public void setSpacing(int spacing) {
     1195        public void setSpacing(float spacing) {
    11951196                _spacing = spacing;
    11961197                updatePolygon();
     
    12021203         * @return The spacing (inter-line) in pixels of this Text.
    12031204         */
    1204         public int getSpacing() {
     1205        public float getSpacing() {
    12051206                return _spacing;
    12061207        }
     
    12281229         *            Additional spacing to add between letters. See {@link java.awt.font.TextAttribute#TRACKING}
    12291230         */
    1230         public void setLetterSpacing(int spacing) {
     1231        public void setLetterSpacing(float spacing) {
    12311232                _letter_spacing = spacing;
    12321233                HashMap<TextAttribute, Object> attr = new HashMap<TextAttribute, Object>();
    12331234                attr.put(TextAttribute.TRACKING, spacing);
    1234                 this._font = this._font.deriveFont(attr);
     1235               
     1236                if (this._font == null) {
     1237                        this._font = Font.decode(DEFAULT_FONT);
     1238                }
     1239
     1240                this.setFont(this._font.deriveFont(attr));
    12351241        }
    12361242
     
    12381244         * @return The spacing (proportional to the font size) between letters. See {@link java.awt.font.TextAttribute#TRACKING}
    12391245         */
    1240         public int getLetterSpacing() {
     1246        public float getLetterSpacing() {
    12411247                return _letter_spacing;
    12421248        }
    12431249
    1244         public void setInitialSpacing(int spacing) {
     1250        public void setInitialSpacing(float spacing) {
    12451251                _initial_spacing = spacing;
    12461252        }
    12471253
    1248         public int getInitialSpacing() {
     1254        public float getInitialSpacing() {
    12491255                return _initial_spacing;
    12501256        }
Note: See TracChangeset for help on using the changeset viewer.