<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Google on bramp.net</title>
    <link>https://blog.bramp.net/</link>
    <description>Recent content in Google on bramp.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-GB</language>
    <lastBuildDate>Sun, 21 Jan 2018 16:03:36 -0800</lastBuildDate>
    <atom:link href="https://blog.bramp.net/tags/google/" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Google Font Features</title>
      <link>https://blog.bramp.net/post/2018/01/21/google-font-features/</link>
      <pubDate>Sun, 21 Jan 2018 16:03:36 -0800</pubDate>
      
      <guid>https://blog.bramp.net/post/2018/01/21/google-font-features/</guid>
      <description><blockquote>
<p><strong>tl;dr Google Fonts doesn&rsquo;t supply fonts with OpenType features (such as old-style figures, or small-caps), but you can build and host the fonts yourself to support everything you need.</strong></p>
</blockquote>
<p>I recently posted a <a href="https://blog.bramp.net/post/2018/01/16/measuring-percentile-latency/">article which contained lots of numbers</a>. While I was proofreading the article, I didn’t quite liked how the numbers looked, sometime the digits were below the baseline, for example:</p>
<figure><img src="/post/2018/01/21/google-font-features/oldstyle.png" width="760" height="157"><figcaption>
      <h4>Oldstyle figures</h4>
    </figcaption>
</figure>

<p>Where I would have expected the top and bottom of each digit to be aligned:</p>
<figure><img src="/post/2018/01/21/google-font-features/lining.png" width="760" height="152"><figcaption>
      <h4>Lining figures</h4>
    </figcaption>
</figure>

<p>This made me flashback to all the typography I learnt when <a href="https://github.com/bramp/publication">working with LaTeX</a>. These two styles of figures are called old-style, and lining (or sometimes lowercase and uppercase numbers). The theory is that old-style numbers flow better when mixed with text. Recall, letters like q, j and p, all drop below the baseline, which makes the text nicer to read:</p>
<figure><img src="/post/2018/01/21/google-font-features/quickbrownfox.png" width="760" height="100"><figcaption>
      <h4>Example with characters below the baseline</h4>
    </figcaption>
</figure>

<p>However, my article had many numbers on the page, sometimes within tables, where old-style just made the numbers look odd. I looked for a way to force the lining style throughout. I quickly found the CSS styling:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">           <span class="k">font-variant-numeric</span><span class="p">:</span> <span class="n">lining-nums</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl">  <span class="kp">-webkit-</span><span class="k">font-feature-settings</span><span class="p">:</span> <span class="s2">&#34;lnum&#34;</span> <span class="kc">on</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">     <span class="kp">-moz-</span><span class="k">font-feature-settings</span><span class="p">:</span> <span class="s2">&#34;lnum&#34;</span> <span class="kc">on</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="kp">-ms-</span><span class="k">font-feature-settings</span><span class="p">:</span> <span class="s2">&#34;lnum&#34;</span> <span class="kc">on</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="k">font-feature-settings</span><span class="p">:</span> <span class="s2">&#34;lnum&#34;</span> <span class="kc">on</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Sadly when I applied this to my site, it did nothing. I wondered if perhaps the font did not support lining figures. A quick search led me to <a href="https://stackoverflow.com/questions/28098992/google-fonts-lining-numbers">Stack Overflow</a> that implied both the font I was using, <a href="https://fonts.google.com/specimen/Raleway">Raleway</a>, and Google Fonts (which hosted the font) did in fact support lining.</p>
<p>So I went deeper down the rabbit hole to figure out what was going wrong. I wanted to confirm for myself that the font supported lining figures. I searched for a while for a simple CLI that would inspect the <a href="https://en.wikipedia.org/wiki/Web_Open_Font_Format">WOFF</a>/<a href="https://en.wikipedia.org/wiki/TrueType">TTF</a> files and tell me what they contained. Sadly, the best I could find was <a href="https://fontforge.github.io/">FontForge</a>, a GUI. That worked, and confirmed the fonts being served by Google did not contain the lining feature, or in fact any feature other than basic ligatures.</p>
<p>Later I found this <a href="https://github.com/google/fonts/issues/1335">GitHub issue</a> which confirmed all features were stripped from the font. So I sought out a way to rebuild the Google font to keep the lining figures.</p>
<p>Before that, I started to <a href="http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html">shave another yak</a>, and decided to create a CLI tool that would easily display the font features. I came across a Go library, <a href="https://github.com/ConradIrwin/font">SFNT</a> that can parse OpenType fonts. Sadly it didn’t implement the parsing of the features. A few hours later, I read the <a href="http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html">OpenType spec</a> and sent them a <a href="https://github.com/ConradIrwin/font/pull/3">pull request</a> to add this functionality. Now I can easily confirm from the command line what features are supported.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ font features raleway-v12-latin-ext_latin-regular.woff
</span></span><span class="line"><span class="cl">Glyph Substitution Table <span class="o">(</span>GSUB<span class="o">)</span>:
</span></span><span class="line"><span class="cl">	Script <span class="s2">&#34;latn&#34;</span> <span class="o">(</span>Latin<span class="o">)</span>:
</span></span><span class="line"><span class="cl">		Default Language:
</span></span><span class="line"><span class="cl">			Feature <span class="s2">&#34;liga&#34;</span> <span class="o">(</span>Standard Ligatures<span class="o">)</span>
</span></span></code></pre></div><p>I decided to play around with <a href="https://developers.google.com/fonts/docs/developer_api">Google Font API</a>, and then eventually the unoffical (but awesome) <a href="https://google-webfonts-helper.herokuapp.com/fonts/raleway">google-webfonts-helper</a> (a hassle-free way to self-host Google Fonts). However, no combination of options would make the font contain the lining figures.</p>
<p>Since the Google Fonts are open source, I downloaded the <a href="https://github.com/google/fonts/tree/master/ofl/raleway">source TTF of the font</a>, and double-checked it did indeed contain the feature:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ font features Raleway-Regular.ttf 
</span></span><span class="line"><span class="cl">Glyph Substitution Table <span class="o">(</span>GSUB<span class="o">)</span>:
</span></span><span class="line"><span class="cl">  Script <span class="s2">&#34;latn&#34;</span> <span class="o">(</span>Latin<span class="o">)</span>:
</span></span><span class="line"><span class="cl">    Default Language:
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;aalt&#34;</span> <span class="o">(</span>Access All Alternates<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;dlig&#34;</span> <span class="o">(</span>Discretionary Ligatures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;liga&#34;</span> <span class="o">(</span>Standard Ligatures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;lnum&#34;</span> <span class="o">(</span>Lining Figures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;onum&#34;</span> <span class="o">(</span>Oldstyle Figures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;salt&#34;</span> <span class="o">(</span>Stylistic Alternates<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;smcp&#34;</span> <span class="o">(</span>Small Capitals<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;ss01&#34;</span> <span class="o">(</span>Stylistic Set 1<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;ss02&#34;</span> <span class="o">(</span>Stylistic Set 2<span class="o">)</span>
</span></span></code></pre></div><p>So my next idea was to take the original Raleway-Regular.ttf and convert it to <a href="https://en.wikipedia.org/wiki/Web_Open_Font_Format">WOFF</a> and <a href="https://www.w3.org/TR/WOFF2/">WOFF2</a>, and strip out the bits I don’t need. Just how Google Fonts does, to ensure the resulting files are lean and performant.</p>
<p>I couldn’t find the pipeline Google Fonts uses to process the files, so I instead took it upon myself to figure this out. I started by using <code>pyftsubset</code> (part of <a href="https://github.com/fonttools/fonttools">FontTools</a>) to remove unneeded character sets, features, and other parts from the original TTF file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip install fonttools
</span></span><span class="line"><span class="cl">$ pyftsubset Raleway-Regular.ttf --layout-features<span class="o">=</span><span class="s1">&#39;*&#39;</span> --unicodes<span class="o">=</span><span class="s2">&#34;U+0000-00FF, U+0100-024F, U+0131, U+0152-0153, U+02DA, U+02DC, U+02BB-02BC, U+02C6, U+0259, U+0370-03FF, U+1E00-1EFF, U+2000-206F, U+2070-209F, U+2074, U+20A0-20CF, U+2122, U+2150-218F, U+2200-22FF, U+2C60-2C7F, U+A720-A7FF&#34;</span> --output-file<span class="o">=</span>Raleway-Regular.subset.ttf
</span></span></code></pre></div><p>Now I had a TTF file with all the features, but only the subset of characters I use on my site. Next I needed to convert this this file to all the <a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization">recommended font formats</a>, so my site would look nice in IE, Chrome, Android and iOS. The resulting CSS would look like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">@</span><span class="k">font-face</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">font-family</span><span class="o">:</span> <span class="s1">&#39;Raleway&#39;</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">src</span><span class="o">:</span> <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.eot&#39;</span><span class="o">);</span>                           <span class="c">/* IE9 Compat Modes */</span>
</span></span><span class="line"><span class="cl">  <span class="nt">src</span><span class="o">:</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;Raleway&#39;</span><span class="o">),</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;Raleway-Regular&#39;</span><span class="o">),</span>
</span></span><span class="line"><span class="cl">       <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.eot?#iefix&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;embedded-opentype&#39;</span><span class="o">),</span> <span class="c">/* IE6-IE8 */</span>
</span></span><span class="line"><span class="cl">       <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.woff2&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;woff2&#39;</span><span class="o">),</span>    <span class="c">/* Super Modern Browsers */</span>
</span></span><span class="line"><span class="cl">       <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.woff&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;woff&#39;</span><span class="o">),</span>     <span class="c">/* Pretty Modern Browsers */</span>
</span></span><span class="line"><span class="cl">       <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.ttf&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;truetype&#39;</span><span class="o">),</span>    <span class="c">/* Safari, Android, iOS */</span>
</span></span><span class="line"><span class="cl">       <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;raleway-regular.subset.svg#ralewayregular&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;svg&#39;</span><span class="o">);</span>    <span class="c">/* Legacy iOS */</span>
</span></span><span class="line"><span class="cl">  <span class="nt">font-style</span><span class="o">:</span> <span class="nt">normal</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">font-weight</span><span class="o">:</span> <span class="nt">400</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I again tried to use <code>pyftsubset</code> to save the files in the required formats. This worked well for TTF, WOFF, and WOFF2. But didn’t support <a href="https://en.wikipedia.org/wiki/Embedded_OpenType">EOT</a> or <a href="http://caniuse.com/svg-fonts">SVG</a> fonts:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ pip install zopfli
</span></span><span class="line"><span class="cl">$ pip install brotli
</span></span><span class="line"><span class="cl">$ pyftsubset ... --flavor<span class="o">=</span>woff --with-zopfli --output-file<span class="o">=</span>Raleway-Regular.subset.woff
</span></span><span class="line"><span class="cl">$ pyftsubset ... --flavor<span class="o">=</span>woff2 --output-file<span class="o">=</span>Raleway-Regular.subset.woff2
</span></span></code></pre></div><p>So instead I searched for a all-in-one solution to converting fonts. I found numerous websites that offered to do it, the one I settled on was <a href="https://www.fontsquirrel.com/tools/webfont-generator">fontsquirrel.com</a>. Here I used the expert feature, to control exactly what was in the font, and to produce compressed versions in all file formats. I originally tried to use the subsetting feature on fontsquirrel, but I couldn’t get it to maintain all the features I needed, so I used <code>pyftsubset</code> locally instead.</p>
<p>After fontsquirrel.com produced the fonts, I checked it contained the features, and compared the resulting file sizes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -ltr
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Google Fonts</span>
</span></span><span class="line"><span class="cl"> 96K  raleway-v12-latin-ext_latin-regular.ttf
</span></span><span class="line"><span class="cl"> 40K  raleway-v12-latin-ext_latin-regular.woff
</span></span><span class="line"><span class="cl"> 31K  raleway-v12-latin-ext_latin-regular.woff2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># My versions</span>
</span></span><span class="line"><span class="cl">140K raleway-regular.subset-webfont.ttf
</span></span><span class="line"><span class="cl"> 61K raleway-regular.subset-webfont.woff
</span></span><span class="line"><span class="cl"> 46K raleway-regular.subset-webfont.woff2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ font features raleway-regular.subset-webfont.woff
</span></span><span class="line"><span class="cl">Glyph Substitution Table <span class="o">(</span>GSUB<span class="o">)</span>:
</span></span><span class="line"><span class="cl">  Script <span class="s2">&#34;latn&#34;</span> <span class="o">(</span>Latin<span class="o">)</span>:
</span></span><span class="line"><span class="cl">    Default Language:
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;aalt&#34;</span> <span class="o">(</span>Access All Alternates<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;dlig&#34;</span> <span class="o">(</span>Discretionary Ligatures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;liga&#34;</span> <span class="o">(</span>Standard Ligatures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;lnum&#34;</span> <span class="o">(</span>Lining Figures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;onum&#34;</span> <span class="o">(</span>Oldstyle Figures<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;salt&#34;</span> <span class="o">(</span>Stylistic Alternates<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;smcp&#34;</span> <span class="o">(</span>Small Capitals<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;ss01&#34;</span> <span class="o">(</span>Stylistic Set 1<span class="o">)</span>
</span></span><span class="line"><span class="cl">      Feature <span class="s2">&#34;ss02&#34;</span> <span class="o">(</span>Stylistic Set 2<span class="o">)</span>
</span></span></code></pre></div><p>The file size didn&rsquo;t vary too much, and thus it was a simple matter of <a href="https://blog.bramp.net/fonts/raleway-regular.subset-webfont.woff2">uploading the fonts</a> to my blog, and updating the CSS.</p>
<p class="text-center">
<span class="onum" style="text-decoration: red underline overline; font-size: 3.5em">1234567890</span> &nbsp;vs&nbsp; <span class="lnum" style="text-decoration: red underline overline; font-size: 3.5em">1234567890</span>
</p></description>
    </item>
    
    <item>
      <title>Teaching Binary to 8th Graders</title>
      <link>https://blog.bramp.net/post/2017/07/15/teaching-binary-to-8th-graders/</link>
      <pubDate>Sat, 15 Jul 2017 12:23:18 -0700</pubDate>
      
      <guid>https://blog.bramp.net/post/2017/07/15/teaching-binary-to-8th-graders/</guid>
      <description><p>This summer, as part of <a href="https://www.google.com/intl/en/giving/people.html#google-serve">GoogleServe</a>, I volunteered in a local school to teach kids about the importance of mathematics. This was part part of a larger program organised by the <a href="svefoundation.org">Silicon Valley Education Foundation</a> (SVEF).</p>
<p>I had 90 minutes, to introduce myself, talk a little about Google, and then spend the majority of the time teaching a topic of my choosing. Not knowing anything about teaching 8th graders I went to the Internet to find some material.</p>
<p>I quickly found <a href="http://cse4k12.org">cse4k12.org</a>, and the excellent <a href="https://www.youtube.com/user/csunplugged">YouTube series</a> by <a href="http://csunplugged.org">csunplugged.org</a>. I decided I would teach about counting in binary. The <a href="http://csunplugged.org/binary-numbers/">csunplugged videos</a> showed how to introduced this material in a way that seemed fun and got got the kids to work out the concepts on their own. I decided to mix the teaching with worksheets from <a href="http://cse4k12.org">cse4k12.org</a> (to reinforce what the kids just learnt). Since I only had ~90 minutes to cover a lot, I took what I found on cse4k12.org and simplified their activities. I went ahead and created new worksheets, and am providing them here today for others to use. The rough schedule I used was:</p>
<ul>
<li>
<p>10min Intro to counting in binary, with kids holding up <a href="https://docs.google.com/document/d/1dCmZc3_v16eIqP230j0DyLXIsS2SVY1Ia8TmGo4b0vQ/edit?usp=sharing">bits</a> (similar to <a href="https://youtu.be/Pz7dLWvi2w0">this video</a>).</p>
</li>
<li>
<p>15min Work on this “<a href="https://docs.google.com/document/d/1u3ITluIYx7K4x7yqy9101DB813TWI9_TYnUu8VxHBgs/edit#bookmark=id.rsbu3f59m3ry">Counting In Binary</a>” worksheet.</p>
</li>
<li>
<p>10min Representing text (again <a href="https://youtu.be/xc0stfTVE_8">similar to this video</a>)</p>
</li>
<li>
<p>15min Using “<a href="https://docs.google.com/document/d/1u3ITluIYx7K4x7yqy9101DB813TWI9_TYnUu8VxHBgs/edit#bookmark=id.gpxpgtxg156z">Encoding Table</a>” and “<a href="https://docs.google.com/document/d/1u3ITluIYx7K4x7yqy9101DB813TWI9_TYnUu8VxHBgs/edit#bookmark=id.1r2yly29a01u">Encoding Message</a>” worksheets to write some secret messages to each other.</p>
</li>
<li>
<p>10min Representing images with binary.</p>
</li>
<li>
<p>15min Using the “<a href="https://docs.google.com/document/d/1u3ITluIYx7K4x7yqy9101DB813TWI9_TYnUu8VxHBgs/edit#bookmark=id.1gznllvnujnk">Bitmaps</a>” worksheets to encode their own images, and if time allows swapping encoded images with each other to decode.</p>
</li>
</ul>
<p>All in all, this worked quite well. I learnt a lot, and was happy to see the class engaged! I will certainly be taking part in activities like this again.</p>
<p>P.S I found printing all sheets double sided worked really well. Oh and no computers needed! Put those laptops away.</p>
</description>
    </item>
    
    <item>
      <title>Maven Plugins on Java 8</title>
      <link>https://blog.bramp.net/post/2017/04/01/maven-plugins-on-java-8/</link>
      <pubDate>Sat, 01 Apr 2017 15:21:27 -0700</pubDate>
      
      <guid>https://blog.bramp.net/post/2017/04/01/maven-plugins-on-java-8/</guid>
      <description><p>As part of my standard Maven configuration, I like to use two plugins backed by Google technologies, the first to help keep my code formatted correctly, and the second to check for compile time errors. However, Google recently moved to require JDK 1.8, which broke anyone trying to compile my projects with an older JDK. In this article I&rsquo;ll quickly explain how to configure Maven to work around this problem.</p>
<p>Specifically I use the following two plugins:</p>
<ul>
<li>
<p><a href="https://github.com/coveo/fmt-maven-plugin">coveo/fmt-maven-plugin</a> (which uses <a href="https://github.com/google/google-java-format">google-java-format</a>). This follows the <a href="https://google.github.io/styleguide/javaguide.html">Google&rsquo;s Java Style</a> guide, and reformats the code to ensure it stays consistent. This is great when accepting external contributions, as it keeps the code base uniform, and avoids style discussion on pull requests.</p>
</li>
<li>
<p><a href="https://github.com/codehaus-plexus/plexus-compiler">plexus-compiler-javac-errorprone</a> (which uses Google&rsquo;s <a href="https://github.com/google/error-prone">errorprone</a>). This is a static code analysis tool, that checks for simple errors at compile time, and fails the build if they are found. Again, this helps improve the quality of the code.</p>
</li>
</ul>
<p>Even though my projects typically target 1.7, these plugins require to run under 1.8. Really I&rsquo;d prefer I could bump all my projects to target 1.8+, but since a few of my projects are libraries (which other people include into their projects), that is easier said than done. To deal with this, I changed my Maven configuration to only run these two plugins when run under the sufficient JDK. This means those using a older JDK don&rsquo;t get the benefits, but since locally I use JDK 8, and all my open source projects use <a href="https://travis-ci.org">Travis CI</a>, eventually these issues will be identified.</p>
<p>So if you get an error like</p>
<pre tabindex="0"><code>java.lang.UnsupportedClassVersionError: com/google/googlejavaformat/java/FormatterException : Unsupported major.minor version 52.0
</code></pre><p>or</p>
<pre tabindex="0"><code>An API incompatibility was encountered while executing org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile: java.lang.UnsupportedClassVersionError: javax/tools/DiagnosticListener : Unsupported major.minor version 52.0
</code></pre><p>Please update to JDK 1.8, or update your Maven configuration to restrict these plugins to when run on a modern JDK:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;project&gt;</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;profiles&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;profile&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;id&gt;</span>java18<span class="nt">&lt;/id&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;activation&gt;</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&lt;jdk&gt;</span>1.8<span class="nt">&lt;/jdk&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;/activation&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;build&gt;</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&lt;plugins&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&lt;plugin&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;groupId&gt;</span>com.coveo<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;artifactId&gt;</span>fmt-maven-plugin<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;executions&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;execution&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;goals&gt;</span>
</span></span><span class="line"><span class="cl">                                    <span class="nt">&lt;goal&gt;</span>format<span class="nt">&lt;/goal&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;/goals&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;/execution&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;/executions&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&lt;/plugin&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&lt;plugin&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;artifactId&gt;</span>maven-compiler-plugin<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;configuration&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;compilerId&gt;</span>javac-with-errorprone<span class="nt">&lt;/compilerId&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;forceJavacCompilerUse&gt;</span>true<span class="nt">&lt;/forceJavacCompilerUse&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;showWarnings&gt;</span>true<span class="nt">&lt;/showWarnings&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;compilerArgs&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;arg&gt;</span>-Xlint:all<span class="nt">&lt;/arg&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;/compilerArgs&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;/configuration&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;dependencies&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;dependency&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;groupId&gt;</span>org.codehaus.plexus<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;artifactId&gt;</span>plexus-compiler-javac-errorprone<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;version&gt;</span>2.8.1<span class="nt">&lt;/version&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;/dependency&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="c">&lt;!-- override plexus-compiler-javac-errorprone&#39;s dependency on
</span></span></span><span class="line"><span class="cl"><span class="c">                                 Error Prone with the latest version --&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;dependency&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;groupId&gt;</span>com.google.errorprone<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;artifactId&gt;</span>error_prone_core<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">                                <span class="nt">&lt;version&gt;</span>2.0.19<span class="nt">&lt;/version&gt;</span>
</span></span><span class="line"><span class="cl">                            <span class="nt">&lt;/dependency&gt;</span>
</span></span><span class="line"><span class="cl">                        <span class="nt">&lt;/dependencies&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nt">&lt;/plugin&gt;</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&lt;/plugins&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;/build&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;/profile&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/profiles&gt;</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/project&gt;</span>
</span></span></code></pre></div><p>This defines a new profile, that is only &ldquo;activated&rdquo; under Java 1.8. When activated the <code>&lt;build&gt;</code> section has the two additional plugins added.
Ensure that these plugins are no longer mentioned in the regular <code>&lt;build&gt;</code> section, and only in the <code>&lt;profile&gt;&lt;build&gt;</code> section.</p>
<p>An example of this change can be found in <a href="https://github.com/bramp/ffmpeg-cli-wrapper/commit/4985ba3ab3ef84839bc0f4ca8b63573b77e33c67">recent commit</a>.</p>
</description>
    </item>
    
    <item>
      <title>Old school’s not cool.</title>
      <link>https://blog.bramp.net/post/2010/06/09/old-schools-not-cool/</link>
      <pubDate>Wed, 09 Jun 2010 00:00:00 +0000</pubDate>
      
      <guid>https://blog.bramp.net/post/2010/06/09/old-schools-not-cool/</guid>
      <description><p>Google Chrome today pestered me with a message which I thought was quite funny. It reads:</p>
<blockquote>
<p>Old school’s not cool. Google Chrome is woefully out of date because it hasn’t crashed or restarted in at least two weeks. Restart to apply update.</p>
</blockquote>
<figure><img src="/post/2010/06/09/old-schools-not-cool/chrome-old-school.jpg" width="665" height="410"><figcaption>
      <h4>Old school&#39;s not cool</h4>
    </figcaption>
</figure>

</description>
    </item>
    
    <item>
      <title>Google DNS Benchmarked</title>
      <link>https://blog.bramp.net/post/2009/12/04/google-dns-benchmarked/</link>
      <pubDate>Fri, 04 Dec 2009 00:00:00 +0000</pubDate>
      
      <guid>https://blog.bramp.net/post/2009/12/04/google-dns-benchmarked/</guid>
      <description><p>Today <a href="http://googleblog.blogspot.com/2009/12/introducing-google-public-dns.html">Google announced</a> a public DNS service they are hosting. They claim that their DNS infrastructure is <a href="http://code.google.com/speed/public-dns/docs/performance.html">faster and more secure</a>, because their servers do some clever things. I wanted to test their performance claims, so I wrote a <a href="dns.php">little script</a> to measure a lookup times for different domains across a number of DNS servers.</p>
<h3 id="methodology">Methodology</h3>
<p>Firstly I found a <a href="http://www.quantcast.com/top-sites-1">list of the 1 million most popular sites</a>. I then picked a number of DNS servers to test against. I chose <a href="http://code.google.com/speed/public-dns/">Google</a>‘s, <a href="http://www.opendns.com/">OpenDNS</a>‘s, my ISP (<a href="http://broadband.sky.com/">Sky/Easynet</a>) and my old ISP’s (<a href="http://www.plus.net/">Plus.net</a>).</p>
<p>I decided I would query an <a href="http://en.wikipedia.org/wiki/List_of_DNS_record_types">A record</a> for each of the domains in the list, one at a time, starting with the most popular. I would query each server three times for the same domain name. The ordering was like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="k">foreach</span> <span class="p">(</span><span class="nx">domain</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">   <span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span><span class="mi">3</span><span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">foreach</span> <span class="p">(</span><span class="nx">server</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="nx">query</span><span class="p">(</span><span class="nx">server</span><span class="p">,</span> <span class="nx">domain</span><span class="p">)</span>
</span></span></code></pre></div><p>I recorded the time it took for each query to be answered, and I also recorded the replies. I was curious to see if some servers replied with different answers, or if some returned more information, i.e. additional records.</p>
<p>I <a href="dns.php">wrote a script</a> in PHP 5.3, and ran it from the command line on my Windows Server 2008 machine. The script used PEAR&rsquo;s Net_DNS to craft and send the DNS questions. I was not using my operating system&rsquo;s resolver, and I was not using any form of client side caching. I ran the experiments from my home ADSL connection and as far as I know my ISP was not interfering with my DNS requests in any way. I live in the North West of the UK.</p>
<h3 id="results">Results</h3>
<p>After letting this run for a few hours, and querying roughly the top 10,000 domains, I have some preliminary results.</p>















<table class="table">
  <thead>
      <tr>
          <th>DNS Server</th>
          <th class="text- center">Min (ms)</th>
          <th class="text- center">Max (ms)</th>
          <th class="text- center">Median</th>
          <th class="text- center">Mean (ms)</th>
          <th class="text- center">Standard Dev (ms)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Google A (8.8.8.8)</td>
          <td class="text- center">38.50</td>
          <td class="text- center">4932</td>
          <td class="text- center">42.45</td>
          <td class="text- center">122.8</td>
          <td class="text- center">181.6</td>
      </tr>
      <tr>
          <td>Google B (8.8.4.4)</td>
          <td class="text- center">38.65</td>
          <td class="text- center">4927</td>
          <td class="text- center">41.84</td>
          <td class="text- center">94.52</td>
          <td class="text- center">154.8</td>
      </tr>
      <tr>
          <td>OpenDNS A (208.67.222.222)</td>
          <td class="text- center">29.77</td>
          <td class="text- center">4035</td>
          <td class="text- center">31.87</td>
          <td class="text- center">74.37</td>
          <td class="text- center">115.4</td>
      </tr>
      <tr>
          <td>OpenDNS B (208.67.220.220)</td>
          <td class="text- center">29.76</td>
          <td class="text- center">1171</td>
          <td class="text- center">31.82</td>
          <td class="text- center">35.28</td>
          <td class="text- center">32.4</td>
      </tr>
      <tr>
          <td>Easynet A (90.207.238.97)</td>
          <td class="text- center">33.90</td>
          <td class="text- center">2578</td>
          <td class="text- center">61.29</td>
          <td class="text- center">105.2</td>
          <td class="text- center">103.7</td>
      </tr>
      <tr>
          <td>Easynet B (90.207.238.99)</td>
          <td class="text- center">33.65</td>
          <td class="text- center">4253</td>
          <td class="text- center">44.96</td>
          <td class="text- center">96.11</td>
          <td class="text- center">104.8</td>
      </tr>
      <tr>
          <td>Plusnet A (212.159.11.150)</td>
          <td class="text- center">43.78</td>
          <td class="text- center">4423</td>
          <td class="text- center">52.56</td>
          <td class="text- center">100.8</td>
          <td class="text- center">156.5</td>
      </tr>
      <tr>
          <td>Plusnet B (212.159.13.150)</td>
          <td class="text- center">38.87</td>
          <td class="text- center">4991</td>
          <td class="text- center">42.76</td>
          <td class="text- center">90.78</td>
          <td class="text- center">169.1</td>
      </tr>
  </tbody>
</table>

<p>From this table of results, we can see that Google&rsquo;s median response time is 41-42ms, however, OpenDNS performs much better with a result of ~31ms. Both my current ISP and my old ISP don&rsquo;t perform as well and each achieved a result between 42ms and 61ms. To get a better feel for the data I plotted an empirical CDF of the lookup times for each server.</p>
<p><a href="ecdf_overview.pdf"><figure><img src="/post/2009/12/04/google-dns-benchmarked/ecdf_overview.png" width="700" height="700"><figcaption>
      <h4>Click for a larger PDF version</h4>
    </figcaption>
</figure>
</a></p>
<p>The first impression I can make from this CDF is that OpenDNS serves far more of the queries faster than anyone else. Secondly the secondary DNS servers all seem to be faster than their primaries. I suspect this is because most hosts query the primary, and rarely query the secondary. I even read that <a href="https://www.isc.org/software/bind">BIND</a> (a popular DNS server) has/had <a href="http://homepages.tesco.net/J.deBoynePollard/FGA/dns-database-replication.html">a bug in it which favoured the primary DNS</a>.</p>
<p>The minimum lookup time for each pair of DNS servers seems to be the same, most likely caused by the network latency between me and the servers. Even so, if we normalise all the data by taking the servers&rsquo; minimum value away from each sample, we still find that OpenDNS performs better than Google, and Google performs slightly better than Plus.net and quite a bit better than my current ISP, Easynet.</p>
<p>Rather worryingly is that the latency to OpenDNS is smaller than the latency to my own ISP&rsquo;s DNS servers. This makes me wonder where the hell my ISP hosts their DNS servers. Also, the ~38ms minimum time with Google indicates that at least some of their DNS servers are hosted in Europe, and possibly the UK.</p>
<p>SInce I ran each lookup three times, I wanted to compare the lookup times for each request. This time I plotted the empirical CDF of each iteration of request.</p>
<p><a href="ecdf_requests.pdf"><figure><img src="/post/2009/12/04/google-dns-benchmarked/ecdf_requests.png" width="700" height="700"><figcaption>
      <h4>Click for a larger PDF version</h4>
    </figcaption>
</figure>
</a></p>
<p>This CDF seems to show that the 2nd and 3rd requests always get served quicker than the first. In most cases the 2nd and 3rd request have equal ranking, but the first is always slow. This could easily be attributed to the fact that the caching DNS server does not have the record in its cache, and thus must be fetched. The second time I request the domain name (only moments later), the server already has the query, and most likely has it stored in RAM or L1/L2 CPU cache.</p>
<p>OpenDNS_B seems to respond equally quick for the first, second and third request. This could be because I would always query OpenDNS_A first, then move on to B. If A and B were actually the same machine, it would be like sending 6 requests to the machine instead of 3. Therefore, B&rsquo;s 1st request is actually its second. Even if A and B were different machines, there could be some clever replication, or shared caching going on to cause this behaviour.</p>
<p>Finally, I&rsquo;m surprised that the 2nd and 3rd requests are slower, especially since I&rsquo;m requesting the most popular domain names. Surely others would have already requested the domain name, and thus the DNS server has no need to fetch it. Looking through the list of domain names I see that none of them have the www prefix. I personally never type the www and just hope the site works, but perhaps many users do. Maybe I should re-run the experiment with the www prefix.</p>
<h3 id="conclusion">Conclusion</h3>
<p>For now I would stick to using OpenDNS, as this is clearly the winner. However, the Google DNS service is very new, so perhaps the servers haven&rsquo;t had enough time to fill their caches, and their admins haven&rsquo;t had enough time to tweak them. I will perhaps rerun this experiment in a few weeks and see what happens.</p>
<h3 id="todo">TODO</h3>
<p>I still have some analysis to do, for example, looking at packet loss, the type of records returned, and anything else I can think of.</p>
</description>
    </item>
    
    <item>
      <title>What happens when you mix…</title>
      <link>https://blog.bramp.net/post/2009/01/27/what-happens-when-you-mix/</link>
      <pubDate>Tue, 27 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>https://blog.bramp.net/post/2009/01/27/what-happens-when-you-mix/</guid>
      <description><p>What happens when you mix; Haggis, Vodka, a room full of nerds, and a average of 1.4 laptops per person?</p>
<figure><img src="/post/2009/01/27/what-happens-when-you-mix/google-phone.jpg"><figcaption>
      <h4>someone buys a phone at 1am while drunk</h4>
    </figcaption>
</figure>

</description>
    </item>
    
    <item>
      <title>Google Calendar Exploit</title>
      <link>https://blog.bramp.net/post/2008/04/28/google-calendar-exploit/</link>
      <pubDate>Mon, 28 Apr 2008 00:00:00 +0000</pubDate>
      
      <guid>https://blog.bramp.net/post/2008/04/28/google-calendar-exploit/</guid>
      <description><p>Whilst using Google Calendar I noticed an interesting feature, which I&rsquo;m unsure if it should be there are not. I&rsquo;ve contacted google twice about this bug but never received a reply. So I figured I would post about it here.</p>
<p>When creating a Google Calendar you may share the calendar with your friends and allow them to alter it. You do this by clicking &ldquo;Share this calendar&rdquo; and then typing in their email address. I noticed something odd when I typed in a friend&rsquo;s Gmail address and clicked &ldquo;Add Person&rdquo;. His name appeared next to the newly entered email address. I thought this might be because I previously spoke to this person via email, or he was a friend on GTalk.</p>
<p>I asked around and collected a selection of address which I had never contacted or even seen before. I entered each one, and sure enough their owner&rsquo;s names appeared! Then I tried to enter invalid Gmail addresses, and sure enough those were accepted, but did not display any name.</p>
<p>I think this is a very simple way to obtain information from a email address, and to even test if the email exists or not. Hopefully this isn&rsquo;t a feature and in fact Google made a mistake.</p>
</description>
    </item>
    
  </channel>
</rss>
