Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git
M build.gradle
5959
  implementation 'org.jsoup:jsoup:1.13.1'
6060
  implementation 'org.xhtmlrenderer:flying-saucer-core:9.1.20'
61
  implementation 'org.xhtmlrenderer:flying-saucer-swt:9.1.20'
6162
6263
  // R
...
7879
  implementation 'org.apache.xmlgraphics:batik-util:1.13'
7980
  implementation 'org.apache.xmlgraphics:batik-xml:1.13'
80
81
  implementation 'org.apache.bsf:bsf-api:3.1'
8281
8382
  // Misc.
...
9089
9190
  // Create cross-platform überjar.
92
  //
9391
  // Including these runtime dependencies breaks creating cross-platform binaries.
9492
  fx.each { fxitem ->
M src/main/java/com/scrivenvar/preview/CustomImageResourceLoader.java
3838
import java.nio.file.Paths;
3939
40
import static com.scrivenvar.preview.SVGRasterizer.PLACEHOLDER_IMAGE;
40
import static com.scrivenvar.preview.SVGRasterizer.BROKEN_IMAGE_PLACEHOLDER;
4141
import static org.xhtmlrenderer.swing.AWTFSImage.createImage;
4242
...
5050
   */
5151
  private static final FSImage FS_PLACEHOLDER_IMAGE =
52
      createImage( PLACEHOLDER_IMAGE );
52
      createImage( BROKEN_IMAGE_PLACEHOLDER );
5353
5454
  private final IntegerProperty mMaxWidthProperty = new SimpleIntegerProperty();
M src/main/java/com/scrivenvar/preview/HTMLPreviewPane.java
4444
import org.xhtmlrenderer.simple.extend.XhtmlNamespaceHandler;
4545
import org.xhtmlrenderer.swing.SwingReplacedElementFactory;
46
import org.xhtmlrenderer.util.Configuration;
4647
4748
import javax.swing.*;
...
140141
141142
    mSwingNode.setContent( mScrollPane );
143
    mSwingNode.setCache( true );
142144
143145
    mHtmlRenderer.addDocumentListener( mDocumentHandler );
M src/main/java/com/scrivenvar/preview/SVGRasterizer.java
3636
import org.apache.batik.transcoder.TranscoderOutput;
3737
import org.apache.batik.transcoder.image.ImageTranscoder;
38
import org.w3c.dom.svg.SVGDocument;
38
import org.apache.batik.util.XMLResourceDescriptor;
39
import org.w3c.dom.Document;
3940
4041
import java.awt.*;
4142
import java.awt.image.BufferedImage;
4243
import java.io.IOException;
44
import java.io.StringReader;
4345
import java.net.URL;
4446
import java.util.Map;
4547
46
import static java.awt.Color.RED;
4748
import static java.awt.Color.WHITE;
4849
import static java.awt.RenderingHints.*;
...
7980
  );
8081
81
  public final static BufferedImage PLACEHOLDER_IMAGE;
82
  public final static Image BROKEN_IMAGE_PLACEHOLDER;
8283
8384
  static {
85
    // A FontAwesome camera icon, cleft asunder.
86
    // @formatter:off
87
    final String BROKEN_IMAGE_SVG = "<svg xmlns='http://www.w3.org/2000/svg' " +
88
        "viewBox='0 0 150 150' width='150pt' height='150pt' " +
89
        "fill='#454545'><path d='m41.738281 87.738281c2.480469 11.433594 12" +
90
        ".464844 19.8125 24.15625 20.269531zm0 0'/><path d='m32.328125 76" +
91
        ".152344-2.25 1.800781 1.824219 1.527344c.089844-1.125.230468-2.230469" +
92
        ".425781-3.328125zm0 0'/><path d='m60.953125 7.5-18.90625 1.65625c-5" +
93
        ".835937.511719-10.746094 4.585938-12.308594 10.222656l-2.75 9" +
94
        ".917969-25.683593 2.246094c-7.734376.675781-13.460938 7.5-12.785157 15" +
95
        ".234375l7.355469 84.054687c.675781 7.734375 7.5 13.457031 15.234375 12" +
96
        ".78125l88.042969-7.703125-23.417969-19.648437c-1.867187.480469-3" +
97
        ".777344.855469-5.757813 1.027343-19.324218 1.691407-36.398437-12" +
98
        ".636718-38.089843-31.957031-.171875-1.980469-.136719-3.929687.015625-5" +
99
        ".851562l-1.824219-1.527344 2.25-1.800781c2.703125-15.277344 15" +
100
        ".339844-27.492188 31.519531-28.90625 1.570313-.140625 3.121094-.132813" +
101
        " 4.65625-.066406l7-5.605469zm0 0'/><path d='m58.210938 87.628906 22" +
102
        ".296874 22.300782c1.070313.132812 2.148438.226562 3.253907.226562 14" +
103
        ".210937 0 25.78125-11.570312 25.78125-25.78125 0-14.207031-11" +
104
        ".570313-25.78125-25.78125-25.78125-14.207031 0-25.78125 11.574219-25" +
105
        ".78125 25.78125 0 1.105469.09375 2.1875.230469 3.253906zm0 0'/><path " +
106
        "d='m90.203125 6.382812 8.410156 36.082032-7.867187 4.304687c16.9375 3" +
107
        ".773438 28.917968 19.589844 27.363281 37.339844-1.515625 17.339844-15" +
108
        ".433594 30.621094-32.238281 31.945313l19.652344 23.421874 33.367187 2" +
109
        ".917969c7.734375.675781 14.558594-5.050781 15.234375-12.785156l7" +
110
        ".351562-84.050781c.679688-7.734375-5.046874-14.558594-12.78125-15" +
111
        ".234375l-25.683593-2.246094-2.78125-9.921875c-1.5625-5.632812-6" +
112
        ".472657-9.710938-12.308594-10.222656zm0 0'/></svg>";
113
    // @formatter:on
114
115
    // The width and height cannot be embedded in the SVG above because the
116
    // path element values are relative to the viewBox dimensions.
84117
    final int w = 150;
85118
    final int h = 150;
86
    final var image = new BufferedImage( w, h, TYPE_INT_RGB );
87
    final var graphics = (Graphics2D) image.getGraphics();
88
    graphics.setRenderingHints( RENDERING_HINTS );
119
    Image image;
89120
90
    graphics.setColor( new Color( 204, 204, 204 ) );
91
    graphics.fillRect( 0, 0, w, h );
92
    graphics.setColor( new Color( 255, 204, 204 ) );
93
    graphics.setStroke( new BasicStroke( 4 ) );
94
    graphics.drawOval( w / 4, h / 4, w / 2, h / 2 );
95
    graphics.drawLine( w / 4 + (int) (w / 4 / Math.PI),
96
                       h / 4 + (int) (w / 4 / Math.PI),
97
                       w / 2 + w / 4 - (int) (w / 4 / Math.PI),
98
                       h / 2 + h / 4 - (int) (w / 4 / Math.PI) );
99
    PLACEHOLDER_IMAGE = image;
121
    try( final StringReader reader = new StringReader( BROKEN_IMAGE_SVG ) ) {
122
      final String parser = XMLResourceDescriptor.getXMLParserClassName();
123
      final SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( parser );
124
      final Document document = factory.createDocument( "", reader );
125
126
      image = rasterize( document, w );
127
    } catch( final Exception e ) {
128
      image = new BufferedImage( w, h, TYPE_INT_RGB );
129
      final var graphics = (Graphics2D) image.getGraphics();
130
      graphics.setRenderingHints( RENDERING_HINTS );
131
132
      // Fall back to a (\) symbol.
133
      graphics.setColor( new Color( 204, 204, 204 ) );
134
      graphics.fillRect( 0, 0, w, h );
135
      graphics.setColor( new Color( 255, 204, 204 ) );
136
      graphics.setStroke( new BasicStroke( 4 ) );
137
      graphics.drawOval( w / 4, h / 4, w / 2, h / 2 );
138
      graphics.drawLine( w / 4 + (int) (w / 4 / Math.PI),
139
                         h / 4 + (int) (w / 4 / Math.PI),
140
                         w / 2 + w / 4 - (int) (w / 4 / Math.PI),
141
                         h / 2 + h / 4 - (int) (w / 4 / Math.PI) );
142
    }
143
144
    BROKEN_IMAGE_PLACEHOLDER = image;
100145
  }
101146
...
145190
    } catch( final Exception e ) {
146191
      NOTIFIER.notify( e );
147
      return PLACEHOLDER_IMAGE;
192
      return BROKEN_IMAGE_PLACEHOLDER;
148193
    }
149194
  }
...
164209
      throws IOException, TranscoderException {
165210
    return rasterize(
166
        (SVGDocument) mFactory.createDocument( url.toString() ), width );
211
        mFactory.createDocument( url.toString() ), width );
167212
  }
168213
169214
  public static Image rasterize(
170
      final SVGDocument svg, final int width ) throws TranscoderException {
215
      final Document svg, final int width ) throws TranscoderException {
171216
    final var transcoder = new BufferedImageTranscoder();
172217
    final var input = new TranscoderInput( svg );
M src/main/resources/com/scrivenvar/preview/webview.css
1
/* RESET
2
=============================================================================*/
3
html, body, div, span, applet, object, iframe,
4
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
5
a, abbr, acronym, address, big, cite, code,
6
del, dfn, em, img, ins, kbd, q, s, samp,
7
small, strike, strong, sub, sup, tt, var,
8
b, u, i, center,
9
dl, dt, dd, ol, ul, li,
10
fieldset, form, label, legend,
11
table, caption, tbody, tfoot, thead, tr, th, td,
12
article, aside, canvas, details, embed,
13
figure, figcaption, footer, header, hgroup,
14
menu, nav, output, ruby, section, summary,
15
time, mark, audio, video {
16
	margin: 0;
17
	padding: 0;
18
	border: 0;
19
	font-size: 100%;
20
	font: inherit;
21
	vertical-align: baseline;
22
}
23
ol, ul {
24
	list-style: none;
25
}
26
blockquote, q {
27
	quotes: none;
28
}
29
blockquote:before, blockquote:after,
30
q:before, q:after {
31
	content: "";
32
	content: none;
33
}
34
table {
35
	border-collapse: collapse;
36
	border-spacing: 0;
37
}
1
/* RESET ***/
2
html{box-sizing:border-box;font-size:12pt}body,h1,h2,h3,h4,h5,h6,ol,p,ul{margin:0;padding:0}img{max-width:100%;height:auto}table{table-collapse:collapse;table-spacing:0;border-spacing:0}
383
39
/* BODY
40
=============================================================================*/
4
/* BODY ***/
415
body {
426
  /* Must be bundled in JAR file. */
437
  font-family: "Vollkorn", serif;
44
  font-size: 16px;
8
  font-size: 12pt;
459
  background-color: #fff;
4610
  margin: 0 auto;
4711
  max-width: 960px;
4812
  line-height: 1.6;
4913
  color: #454545;
50
  padding: 0 1em
14
  padding: 0 1em;
5115
}
5216
...
5923
}
6024
61
/* BLOCKS
62
=============================================================================*/
25
/* BLOCKS ***/
6326
p, blockquote, ul, ol, dl, table, pre {
6427
  margin: 1em 0;
6528
}
6629
67
/* HEADERS
68
=============================================================================*/
30
/* HEADERS ***/
6931
h1, h2, h3, h4, h5, h6 {
7032
  font-weight: bold;
...
7840
7941
h1 {
80
  font-size: 28px;
42
  font-size: 21pt;
8143
}
8244
8345
h2 {
84
  font-size: 24px;
46
  font-size: 18pt;
8547
  border-bottom: 1px solid #ccc;
8648
}
8749
8850
h3 {
89
  font-size: 20px;
51
  font-size: 15pt;
9052
}
9153
9254
h4 {
93
  font-size: 18px;
55
  font-size: 13.5pt;
9456
}
9557
9658
h5 {
97
  font-size: 16px;
59
  font-size: 12pt;
9860
}
9961
10062
h6 {
101
  font-size: 14px;
63
  font-size: 10.5pt;
10264
}
10365
10466
h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
10567
  margin-top: .5em;
10668
}
10769
108
/* LINKS
109
=============================================================================*/
70
/* LINKS ***/
11071
a {
11172
  color: #0077aa;
11273
  text-decoration: none;
11374
}
11475
11576
a:hover {
11677
  text-decoration: underline;
11778
}
11879
119
/* BULLET LISTS
120
=============================================================================*/
80
/* BULLET LISTS ***/
12181
ul, ol {
12282
  display: block;
12383
  list-style: disc outside none;
12484
  margin: 1em 0;
12585
  padding: 0 0 0 2em;
12686
}
12787
12888
ol {
129
 list-style-type: decimal;
89
  list-style-type: decimal;
13090
}
13191
13292
ul ul, ol ul,
13393
ol ol, ul ol {
134
 list-style-position: inside;
135
 margin-left: 1em;
94
  list-style-position: inside;
95
  margin-left: 1em;
13696
}
13797
13898
ul ul, ol ul {
139
 list-style-type: circle;
99
  list-style-type: circle;
140100
}
141101
142102
ol ol, ul ol {
143
 list-style-type: lower-latin;
103
  list-style-type: lower-latin;
144104
}
145105
146
/* DEFINITION LISTS
147
=============================================================================*/
106
/* DEFINITION LISTS ***/
148107
dl {
149108
  /** Horizontal scroll bar will appear if set to 100%. */
...
168127
}
169128
170
/* CODE
171
=============================================================================*/
129
/* CODE ***/
172130
pre, code, tt {
173131
  /* Must be bundled in JAR file. */
174132
  font-family: "Fira Code", monospace;
175
  font-size: 14px;
133
  font-size: 14pt;
176134
  white-space: pre-wrap;
177135
  word-wrap: break-word;
...
215173
}
216174
217
/* QUOTES
218
=============================================================================*/
175
/* QUOTES ***/
219176
blockquote {
220177
  border-left: .25em solid #ccc;
221178
  padding: 0 1em;
222179
  color: #777;
223180
}
224181
225182
blockquote>:first-child {
226
  margin-top: 0px;
183
  margin-top: 0;
227184
}
228185
229186
blockquote>:last-child {
230
  margin-bottom: 0px;
187
  margin-bottom: 0;
231188
}
232189
233
/* HORIZONTAL RULES
234
=============================================================================*/
190
/* HORIZONTAL RULES ***/
235191
hr {
236192
  clear: both;
237193
  margin: 1.5em 0 1.5em;
238
  height: 0px;
194
  height: 0;
239195
  overflow: hidden;
240196
  border: none;
241197
  background: transparent;
242198
  border-bottom: .125em solid #ccc;
243199
}
244200
245
/* TABLES
246
=============================================================================*/
201
/* TABLES ***/
247202
table {
248203
  width: 100%;
...
263218
}
264219
265
/* IMAGES
266
=============================================================================*/
220
/* IMAGES ***/
267221
img {
268222
  max-width: 100%;