<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://brunoabinader.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://brunoabinader.github.io/" rel="alternate" type="text/html" /><updated>2022-08-13T17:57:46+00:00</updated><id>https://brunoabinader.github.io/feed.xml</id><title type="html">Code &amp;amp; Thoughts</title><subtitle>Made with :heart: from Finland.
</subtitle><author><name>Bruno Abinader</name></author><entry><title type="html">Lock-free Multithreaded “Find Duplicates” support in digiKam 7.3.0</title><link href="https://brunoabinader.github.io/2022/08/07/lock-free-multithreaded-find-duplicates-in-digikam-7.3.0/" rel="alternate" type="text/html" title="Lock-free Multithreaded “Find Duplicates” support in digiKam 7.3.0" /><published>2022-08-07T00:00:00+00:00</published><updated>2022-08-07T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2022/08/07/lock-free-multithreaded-find-duplicates-in-digikam-7.3.0</id><content type="html" xml:base="https://brunoabinader.github.io/2022/08/07/lock-free-multithreaded-find-duplicates-in-digikam-7.3.0/">&lt;h3 id=&quot;preface-juggling-between-multiple-image-hosting-web-services&quot;&gt;Preface: Juggling between multiple image hosting web services&lt;/h3&gt;

&lt;p&gt;Like many other young kids in Brazil in the early 2000s, &lt;a href=&quot;https://en.wikipedia.org/wiki/Fotolog&quot;&gt;Fotolog&lt;/a&gt; (discontinued) was my first photo collection web service. From there, I switched to &lt;a href=&quot;https://www.flickr.com/&quot;&gt;Flickr&lt;/a&gt;, back then a broad image service in which you could store high-resolution photos.&lt;/p&gt;

&lt;p&gt;In the meanwhile, &lt;a href=&quot;https://en.wikipedia.org/wiki/Orkut&quot;&gt;Orkut&lt;/a&gt; (&lt;a href=&quot;http://www.orkut.com/index.html&quot;&gt;re-activated?&lt;/a&gt;) was the most popular social network in Brazil, and I used to store some of my photos in there too. Orkut eventually got replaced with &lt;a href=&quot;https://www.facebook.com/&quot;&gt;Facebook&lt;/a&gt;, which at the time made it simple to store e.g. a batch of photos from my trips around the world.&lt;/p&gt;

&lt;p&gt;Then, came &lt;a href=&quot;https://drive.google.com/&quot;&gt;Google Drive&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Google%2B&quot;&gt;Google+&lt;/a&gt; (discontinued), and later on &lt;a href=&quot;https://photos.google.com/&quot;&gt;Google Photos&lt;/a&gt;. Until 2019, Google Drive and Google Photos were in sync, but &lt;a href=&quot;https://support.google.com/photos/answer/9316089?hl=en&quot;&gt;that service got discontinued too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, my &lt;a href=&quot;https://en.wikipedia.org/wiki/Personal_cloud&quot;&gt;personal NAS&lt;/a&gt; also acted as a photo storage device until recently, when Seagate discontinued its &lt;a href=&quot;https://www.seagate.com/gb/en/support/kb/nas-os-discontinued-remote-access/&quot;&gt;PersonalCloud&lt;/a&gt; web service and its &lt;a href=&quot;https://www.seagate.com/gb/en/support/kb/seagate-and-lacie-nas-os-4-end-of-life/&quot;&gt;NAS OS 4&lt;/a&gt; operating system.&lt;/p&gt;

&lt;p&gt;As you can imagine, my photo collections got scattered over multiple providers and naturally, an increasing amount of duplicated images with varying qualities and sizes evolved over the years.&lt;/p&gt;

&lt;p&gt;To solve this, I decided to put all of these in a single database, and started searching for software to handle the duplicates. As a big fan of the KDE community, I chose &lt;a href=&quot;https://www.digikam.org/&quot;&gt;digiKam&lt;/a&gt;, an open-source professional photo management software.&lt;/p&gt;

&lt;h3 id=&quot;part-1-how-digikam-finds-similar-images&quot;&gt;Part 1: How digiKam finds similar images&lt;/h3&gt;

&lt;p&gt;In order to find similarities between images, digiKam uses the &lt;a href=&quot;https://docs.opencv.org/3.4/db/d28/tutorial_cascade_classifier.html&quot;&gt;Haar cascades classifier&lt;/a&gt; algorithm from OpenCV. An excerpt from its &lt;a href=&quot;https://docs.kde.org/trunk5/en/digikam-doc/digikam/using-digikam.html#using-mainwindow-fuzzysearches&quot;&gt;&lt;em&gt;Fuzzy View&lt;/em&gt; documentation&lt;/a&gt; provides more details:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;digiKam characterizes every image by a lengthy number using a special technique (Haar algorithm) that makes it possible to compare images by comparing this calculated signature. The less numerical difference there is between any two image signatures, the more they resemble each other.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before you can have digiKam finding duplicates their signatures (or fingerprints) have to be calculated. This process is atomic in a sense that each signature can be calculated independently. The image signature is created when the image is imported in the database.&lt;/p&gt;

&lt;p&gt;Once the list of images to compare is calculated, their fingerprints are obtained from the database and stored in a memory cache on-demand for faster look-ups.&lt;/p&gt;

&lt;p&gt;Once the fingerprints are known, the images are then ready to be compared against each other. This process translates in the pseudo-code below:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imagesToCompare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;similarImages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;querySignatureFromDatabase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imagesToCompare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;querySignatureFromDatabase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculateDiff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signatureCache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;similarImages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;otherId&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;similarImagesDatabase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similarImages&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;part-2-optimizing-the-sequential-logic&quot;&gt;Part 2: Optimizing the sequential logic&lt;/h3&gt;

&lt;p&gt;This operation is implemented using a naïve &lt;em&gt;O(n²)&lt;/em&gt; solution, and until recently was implemented sequentially on a single worker thread (&lt;em&gt;search job&lt;/em&gt;). On a significantly large collection of photos, finding similar images could be an hours-long process that sub-utilized the computer’s capabilities.&lt;/p&gt;

&lt;p&gt;Because each image gets its own similar images list, I realized this process could be broken down using in lock-free parallel threads. For that, I implemented the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Resolve all image ids before starting the searches jobs.&lt;/li&gt;
  &lt;li&gt;Create a shared Haar interface with signature cache to be used by all searches jobs in parallel.&lt;/li&gt;
  &lt;li&gt;Spawn a given amount of worker threads (&lt;em&gt;searches jobs&lt;/em&gt;) depending on the amount of CPU cores.&lt;/li&gt;
  &lt;li&gt;Break down the whole “images to scan” set into iterator ranges, and assign each range to a dedicated worker thread.&lt;/li&gt;
  &lt;li&gt;Rebuild (or update) the search albums in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The step 3) can be run lock-free with some adjustments e.g. because we’re using constant iterator ranges, it is not possible to remove unused images from the cache when running multi-thread. Also, because we use ranges in step 3), sometimes the same search album is generated multiple times in separate threads using different reference images.&lt;/p&gt;

&lt;p&gt;In step 4) we ensure the aggregated results are filtered so there’s only one search album with similar images per duplicates found.&lt;/p&gt;

&lt;p&gt;This work has since been released in the &lt;a href=&quot;https://www.digikam.org/news/2021-07-12-7.3.0_release_announcement/&quot;&gt;digiKam 7.3.0 release&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/digikam-find-duplicates.jpeg&quot; alt=&quot;digiKam&quot; class=&quot;center&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;Find Duplicates tool in digiKam&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Special thanks to &lt;a href=&quot;https://invent.kde.org/cgilles&quot;&gt;Gilles Caulier&lt;/a&gt; and &lt;a href=&quot;https://invent.kde.org/mqualmann&quot;&gt;Maik Qualmann&lt;/a&gt; for their code reviews :bow:&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Preface: Juggling between multiple image hosting web services</summary></entry><entry><title type="html">Restart</title><link href="https://brunoabinader.github.io/2022/08/05/restart/" rel="alternate" type="text/html" title="Restart" /><published>2022-08-05T00:00:00+00:00</published><updated>2022-08-05T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2022/08/05/restart</id><content type="html" xml:base="https://brunoabinader.github.io/2022/08/05/restart/">&lt;p&gt;Time flies if you don’t pay attention to it! Thanks to the Internet Archive, I found a couple of different iterations of my personal blog websites: &lt;a href=&quot;https://web.archive.org/web/2/http://brunoabinader.blogspot.com/&quot;&gt;brunoabinader.blogspot.com&lt;/a&gt;, &lt;a href=&quot;https://web.archive.org/web/2/http://abinader.com.br/&quot;&gt;abinader.com.br&lt;/a&gt;, and &lt;a href=&quot;https://web.archive.org/web/20101101040632/http://cabledogs.org/abinader&quot;&gt;cabledogs.org/abinader&lt;/a&gt; as well as posts made in the &lt;a href=&quot;https://www.qt.io/blog&quot;&gt;Qt blog&lt;/a&gt; and &lt;a href=&quot;https://www.mapbox.com/blog&quot;&gt;Mapbox blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am bringing some of these old posts back (in chronological order):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2007/12/02/issc-generic-bluetooth-dongle-on-windows/&quot;&gt;&lt;em&gt;ISSC Generic Bluetooth Dongle on Windows (XP, Vista)&lt;/em&gt;&lt;/a&gt; (Dec 2, 2007)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/05/12/atheros-ar5bxb63-on-ubuntu-hardy-with-madwifi/&quot;&gt;&lt;em&gt;Atheros AR5BXB63 on Ubuntu Hardy Heron 8.04 with madwifi&lt;/em&gt;&lt;/a&gt; (May 12, 2008)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2008/09/25/sending-patches-using-git-email/&quot;&gt;&lt;em&gt;Sending patches using git-email&lt;/em&gt;&lt;/a&gt; (Sep 25, 2008)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2009/12/07/how-cmake-simplifies-the-build-process-part-1-basic-build-system/&quot;&gt;&lt;em&gt;How CMake simplifies the build process (Part 1: Basic build system)&lt;/em&gt;&lt;/a&gt; (Dec 7, 2009)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2009/12/09/how-cmake-simplifies-the-build-process-part-2-advanced-build-system/&quot;&gt;&lt;em&gt;How CMake simplifies the build process (Part 2: Advanced build system)&lt;/em&gt;&lt;/a&gt; (Dec 9, 2009)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2010/04/19/new-kid-on-the-block-plasma-water-animation/&quot;&gt;&lt;em&gt;New kid on the block: Plasma Water Animation&lt;/em&gt;&lt;/a&gt; (Apr 19, 2010)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/04/11/a-guide-for-qt5webkit2-development-setup-for-nokia-n9-on-ubuntu-linux/&quot;&gt;&lt;em&gt;A guide for Qt5/WebKit2 development setup for Nokia N9 on Ubuntu Linux&lt;/em&gt;&lt;/a&gt; (Apr 11, 2012)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/04/12/vim-quicktip-navigating-to-function-implementation-with-ctags/&quot;&gt;&lt;em&gt;Vim Quicktip: Navigating to function implementation with ctags&lt;/em&gt;&lt;/a&gt; (Apr 12, 2012)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2012/08/01/webkit-css3-text-decoration-properties-preview/&quot;&gt;&lt;em&gt;WebKit CSS3 text-decoration properties (preview)&lt;/em&gt;&lt;/a&gt; (Aug 1, 2012)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2013/05/15/css-level-3-text-decoration-on-webkit-and-blink-status/&quot;&gt;&lt;em&gt;CSS Level 3 Text Decoration on WebKit and Blink - status&lt;/em&gt;&lt;/a&gt; (May 15, 2013)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2013/08/20/css-level-3-text-decoration-properties-now-available-in-google-chrome-canary/&quot;&gt;&lt;em&gt;CSS Level 3 Text Decoration properties now available in Google Chrome Canary!&lt;/em&gt;&lt;/a&gt; (Aug 20, 2013)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2014/01/28/converting-c-like-enums-to-string-values-in-rust/&quot;&gt;&lt;em&gt;Converting C-Like Enums to String values in Rust&lt;/em&gt;&lt;/a&gt; (Jan 28, 2014)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2016/05/09/qt-framework-officially-supported/&quot;&gt;&lt;em&gt;Qt Framework officially supported&lt;/em&gt;&lt;/a&gt; (May 9, 2016)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk/&quot;&gt;&lt;em&gt;Customizable vector maps with the Mapbox Qt SDK&lt;/em&gt;&lt;/a&gt; (Oct 4, 2016)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2018/02/20/hd-vector-maps-in-rightware-kanzi/&quot;&gt;&lt;em&gt;HD Vector Maps in Rightware’s Kanzi&lt;/em&gt;&lt;/a&gt; (Feb 20, 2018)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2018/05/30/qt-navigation-sdk-for-automotive-and-embedded-devices/&quot;&gt;&lt;em&gt;Qt Navigation SDK for automotive and embedded devices&lt;/em&gt;&lt;/a&gt; (May 30, 2018)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2022/03/14/interview-with-team-helsinki/&quot;&gt;&lt;em&gt;Interview With Team Helsinki&lt;/em&gt;&lt;/a&gt; (Mar 14, 2022)&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Time flies if you don’t pay attention to it! Thanks to the Internet Archive, I found a couple of different iterations of my personal blog websites: brunoabinader.blogspot.com, abinader.com.br, and cabledogs.org/abinader as well as posts made in the Qt blog and Mapbox blog.</summary></entry><entry><title type="html">Interview With Team Helsinki</title><link href="https://brunoabinader.github.io/2022/03/14/interview-with-team-helsinki/" rel="alternate" type="text/html" title="Interview With Team Helsinki" /><published>2022-03-14T00:00:00+00:00</published><updated>2022-03-14T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2022/03/14/interview-with-team-helsinki</id><content type="html" xml:base="https://brunoabinader.github.io/2022/03/14/interview-with-team-helsinki/">&lt;blockquote&gt;
  &lt;p&gt;Excerpt from: &lt;a href=&quot;https://www.mapbox.com/blog/interview-with-team-helsinki-hyvaa-vuosipaivaa-helsinki&quot;&gt;https://www.mapbox.com/blog/interview-with-team-helsinki-hyvaa-vuosipaivaa-helsinki&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;bruno-youre-part-of-the-helsinki-office-as-a-co-founder-tell-us-more-about-what-you-do-and-what-the-team-in-helsinki-works-on&quot;&gt;&lt;em&gt;Bruno, you’re part of the Helsinki office as a co-founder. Tell us more about what you do and what the team in Helsinki works on.&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Bruno:&lt;/strong&gt; I joined Mapbox in 2015, just three months after Thiago, who invited me to join this &lt;em&gt;“cool SF-based startup doing amazing tech with maps!”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I started as a Software Engineer in the GL Native team and focused on the ongoing partnerships with our automotive customers which eventually led me into building a spin-off team named Core SDK in 2019, where I am currently an Engineering Manager.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/mapbox-espoo-rimac.png&quot; alt=&quot;Mapbox Espoo Office &amp;amp; Rimac&quot; class=&quot;center&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;First day at the Mapbox Espoo office in 2015. Mapbox featured in Rimac’s beautiful dashboard.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Core SDK team initially was responsible for providing custom-tailored solutions to our automotive customers. That work has helped us to learn about opportunities for converging solutions across teams, and we have since changed its scope to being a platform team providing shared solutions to our internal SDK teams.&lt;/p&gt;

&lt;p&gt;Today, the Helsinki team spans beyond hosting both GL Native and Core SDK teams, and also includes Android, iOS, graphics, and backend engineers, map designers, and many more &lt;a href=&quot;https://www.mapbox.com/careers&quot;&gt;exciting roles&lt;/a&gt; that we have open!&lt;/p&gt;

&lt;h4 id=&quot;what-are-the-biggest-projects-and-customers-you-get-to-work-with-inhelsinki-that-you-can-share-with-us&quot;&gt;&lt;em&gt;What are the biggest projects and customers you get to work with in Helsinki that you can share with us?&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/mapbox-qt-rimac.png&quot; alt=&quot;&quot; class=&quot;center&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;Mapbox featured in Qt’s Automotive and Rightware’s Kanzi UIs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;‍&lt;strong&gt;Bruno:&lt;/strong&gt; My very first project at Mapbox was about adapting our maps rendering engine to run inside a leading EV manufacturer’s user interface. Back then, the customer had its UI implemented in Qt and Thiago had just the right proof of concept ready. Thus, the work Thiago and I did implementing the Mapbox Maps SDK for Qt has been key to some of our early automotive partnerships. Starting with our &lt;a href=&quot;https://blog.mapbox.com/qt-framework-officially-supported-40b60bfbb0d0&quot;&gt;Qt framework official support&lt;/a&gt;, then leading to a &lt;a href=&quot;https://blog.mapbox.com/qt-navigation-sdk-for-automotive-and-embedded-devices-cbd8c95fe343&quot;&gt;Qt Navigation SDK for automotive and embedded devices&lt;/a&gt;, as well as implementing &lt;a href=&quot;https://blog.mapbox.com/hd-vector-maps-in-rightwares-kanzi-2f6363a44700&quot;&gt;HD Vector Maps in Rightware’s Kanzi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I worked closely with automotive partners like the &lt;a href=&quot;https://www.qt.io/company&quot;&gt;Qt Company&lt;/a&gt;, &lt;a href=&quot;https://rightware.com/&quot;&gt;Rightware&lt;/a&gt;, and &lt;a href=&quot;https://nng.com/&quot;&gt;NNG&lt;/a&gt;, as well as customers like &lt;a href=&quot;https://www.rimac-automobili.com/&quot;&gt;Rimac&lt;/a&gt;, &lt;a href=&quot;https://www.porsche.com/&quot;&gt;Porsche&lt;/a&gt;, and others.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Excerpt from: https://www.mapbox.com/blog/interview-with-team-helsinki-hyvaa-vuosipaivaa-helsinki</summary></entry><entry><title type="html">Qt Navigation SDK for automotive and embedded devices</title><link href="https://brunoabinader.github.io/2018/05/30/qt-navigation-sdk-for-automotive-and-embedded-devices/" rel="alternate" type="text/html" title="Qt Navigation SDK for automotive and embedded devices" /><published>2018-05-30T00:00:00+00:00</published><updated>2018-05-30T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2018/05/30/qt-navigation-sdk-for-automotive-and-embedded-devices</id><content type="html" xml:base="https://brunoabinader.github.io/2018/05/30/qt-navigation-sdk-for-automotive-and-embedded-devices/">&lt;blockquote&gt;
  &lt;p&gt;Link: &lt;a href=&quot;https://blog.mapbox.com/qt-navigation-sdk-for-automotive-and-embedded-devices-cbd8c95fe343&quot;&gt;https://blog.mapbox.com/qt-navigation-sdk-for-automotive-and-embedded-devices-cbd8c95fe343&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.mapbox.com/qt/&quot;&gt;Mapbox Navigation SDK for Qt&lt;/a&gt; is now available with &lt;a href=&quot;https://blog.qt.io/blog/2018/05/22/qt-5-11-released/&quot;&gt;the latest Qt 5.11 release&lt;/a&gt;, enabling turn-by-turn navigation with real-time traffic, lane level guidance, and voice instructions. These features add to the beautiful hardware accelerated vector maps and address/point of interest search that we’ve made available since Qt 5.9.&lt;/p&gt;

&lt;p&gt;The SDK comes with professionally-designed &lt;a href=&quot;https://blog.mapbox.com/designing-maps-for-navigation-186fe1c67363&quot;&gt;maps for navigation&lt;/a&gt; and user interface templates optimized for driver safety and efficiency — only the most important information is surfaced to drivers at the right time. The maps and UI are also fully customizable.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/mapbox-rimac.jpeg&quot; alt=&quot;Navigation SDK for Qt&quot; class=&quot;center&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;The Navigation SDK for Qt is a drop-in library that adds turn-by-turn navigation to automotive and embedded applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We partnered closely with the Qt Company to build the first navigation solution for Qt Location, delivering maps, search, and routing services through Qt Location APIs. This release makes the Navigation SDK available as a new &lt;a href=&quot;http://doc-snapshots.qt.io/qt5-5.11/qml-navigator.html&quot;&gt;Navigator QML Type&lt;/a&gt; allowing for ease of integration via QML.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.mapbox.com/qt/&quot;&gt;Navigation SDK for Qt&lt;/a&gt; is now available in alpha release. For more information and to enroll as an alpha tester, head to &lt;a href=&quot;https://www.mapbox.com/qt/&quot;&gt;mapbox.com/qt&lt;/a&gt; and sign up.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Link: https://blog.mapbox.com/qt-navigation-sdk-for-automotive-and-embedded-devices-cbd8c95fe343</summary></entry><entry><title type="html">HD Vector Maps in Rightware’s Kanzi</title><link href="https://brunoabinader.github.io/2018/02/20/hd-vector-maps-in-rightware-kanzi/" rel="alternate" type="text/html" title="HD Vector Maps in Rightware’s Kanzi" /><published>2018-02-20T00:00:00+00:00</published><updated>2018-02-20T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2018/02/20/hd-vector-maps-in-rightware-kanzi</id><content type="html" xml:base="https://brunoabinader.github.io/2018/02/20/hd-vector-maps-in-rightware-kanzi/">&lt;blockquote&gt;
  &lt;p&gt;Link: &lt;a href=&quot;https://blog.mapbox.com/hd-vector-maps-in-rightwares-kanzi-2f6363a44700&quot;&gt;https://blog.mapbox.com/hd-vector-maps-in-rightwares-kanzi-2f6363a44700&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rightware’s Kanzi Studio is like Photoshop for designing and building the human-machine interface (HMI) in cars and other interfaces for the automotive industry. The latest Kanzi Studio plug-in now adds our &lt;a href=&quot;/millimeter-precision-hd-vector-maps-874327d8327c&quot;&gt;HD Vector Maps&lt;/a&gt; into their 3D design environment. From digital instrument clusters to infotainment (IVI) systems to head-up displays (HUDs) the Kanzi software is deployed by 35 automotive brands and live in millions of cars worldwide. Here is a look at the new maps design studio:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/rightware-kanzi.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The HD Vector Maps use Protocol Buffers for serialization and it is optimized to the exact resolution required by the dataset. This makes streaming streets, satellite imagery, and terrain data into Kanzi insanely fast and radically saves bandwidth for streaming data to a car and reduces storage size for larger area coverage offline. Vector tiles offer styling flexibility, and the result is accelerated development while introducing a unique appearance, true to the OEM brand identity.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/rightware-kanzi-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Kanzi Maps provide car manufacturers, automotive suppliers, and design studios a streamlined tool for creating beautiful maps that run in digital instrument clusters, infotainment systems, and head-up displays.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/rightware-kanzi-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’re a Kanzi Technology Partner working closely with the Rightware team to make maps available out-of-the-box. Follow me &lt;a href=&quot;https://twitter.com/brunoabinader&quot;&gt;@brunoabinader&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/RightwareLtd&quot;&gt;@RightwareLtd&lt;/a&gt; to track our progress.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Link: https://blog.mapbox.com/hd-vector-maps-in-rightwares-kanzi-2f6363a44700</summary></entry><entry><title type="html">Customizable vector maps with the Mapbox Qt SDK</title><link href="https://brunoabinader.github.io/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk/" rel="alternate" type="text/html" title="Customizable vector maps with the Mapbox Qt SDK" /><published>2016-10-04T00:00:00+00:00</published><updated>2016-10-04T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk</id><content type="html" xml:base="https://brunoabinader.github.io/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk/">&lt;blockquote&gt;
  &lt;p&gt;Link: &lt;a href=&quot;https://www.qt.io/blog/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk&quot;&gt;https://www.qt.io/blog/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mapbox is a mapping platform that makes it easy to integrate location into any mobile and online application. We are pleased to showcase the &lt;a href=&quot;https://www.mapbox.com/blog/qt-framework-support/&quot;&gt;Mapbox Qt SDK&lt;/a&gt; as a target platform for our open source vector maps rendering engine. Our Qt SDK is a key component in &lt;a href=&quot;https://www.mapbox.com/blog/drive/&quot;&gt;Mapbox Drive&lt;/a&gt;, the first lane guidance map designed for car companies to control the in-car experience. The Qt SDK also brings high quality, OpenGL accelerated and &lt;a href=&quot;https://www.mapbox.com/mapbox-studio/&quot;&gt;customizable&lt;/a&gt; maps to Qt native and QtQuick.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/mapbox-qml-example.gif&quot; alt=&quot;Mapbox QML Properties&quot; width=&quot;300&quot; /&gt; | &lt;img src=&quot;/assets/images/mapbox-qml-runtime-example.gif&quot; alt=&quot;Mapbox QML Runtime Style&quot; width=&quot;300&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;Mapbox QML properties and runtime style examples&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The combination of &lt;a href=&quot;https://www.mapbox.com/blog/native-gl-yocto/&quot;&gt;Qt and Yocto&lt;/a&gt; is perfect for bringing our maps to a whole series of embedded devices, ranging from professional NVIDIA and i.MX6 based boards to the popular Raspberry Pi 3.&lt;/p&gt;

&lt;p&gt;As part of our &lt;a href=&quot;https://github.com/mapbox/mapbox-gl-native/tree/master/platform/qt&quot;&gt;Mapbox Qt SDK&lt;/a&gt;, we expose Mapbox GL to Qt in two separate APIs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMapboxGL&lt;/code&gt; - implements a C++03x-conformant API that has been tested from Qt 4.7 onwards (Travis CI currently builds it using both Qt 4 and Qt 5).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QQuickMapboxGL&lt;/code&gt; - implements a Qt Quick (QML) item that can be added to a scene. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QQuickFramebufferObject&lt;/code&gt;has been added in Qt version 5.2, we support this API from this version onwards. The QML item interface matches the &lt;a href=&quot;http://doc.qt.io/qt-5/qml-qtlocation-map.html&quot;&gt;Qt Map QML type&lt;/a&gt; almost entirely, making it easy to exchange from the upstream solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;QMapboxGL&lt;/em&gt; and &lt;em&gt;QQuickMapboxGL&lt;/em&gt; solve different problems. The former is backwards-compatible with previous versions of Qt and is easily integrated into pure C++ environments. The latter takes advantage of Qt Quick’s modern user interface technology, and is the perfect tool for adding navigation maps on embedded platforms. So far we have been testing our code on Linux and macOS desktops, as well as on Linux based embedded devices.&lt;/p&gt;

&lt;p&gt;Mapbox is on a joint effort with the Qt Company to make the Mapbox Qt SDK also available through the official Qt Location module - we are aligning APIs to make sure Mapbox-specific features like runtime styles are available.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;QQuickMapboxGL&lt;/em&gt; API matches &lt;a href=&quot;http://doc.qt.io/qt-5/qml-qtlocation-map.html&quot;&gt;Qt’s Map QML Type&lt;/a&gt;, as you can see from the example below:&lt;/p&gt;

&lt;div class=&quot;language-qml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QtPositioning&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QtQuick&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QtQuick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Controls&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QQuickMapboxGL&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;ApplicationWindow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;visible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;QQuickMapboxGL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;anchors.fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parent&lt;/span&gt;

        &lt;span class=&quot;nl&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;MapParameter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;property&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;property&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mapbox://styles/mapbox/streets-v9&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;nl&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QtPositioning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;60.170448&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;24.942046&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Helsinki&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;zoomLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mapbox Qt SDK is currently in beta stage. We’re continuously adding new features and improving documentation is one of our immediate goals. Your patches and ideas are always welcome!&lt;/p&gt;

&lt;p&gt;We also invite you to join us next month at &lt;a href=&quot;https://www.qtworldsummit.com/&quot;&gt;Qt World Summit 2016&lt;/a&gt; and contribute to Mapbox on &lt;a href=&quot;https://github.com/mapbox/mapbox-gl-native/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Link: https://www.qt.io/blog/2016/10/04/customizable-vector-maps-with-the-mapbox-qt-sdk</summary></entry><entry><title type="html">Qt Framework officially supported</title><link href="https://brunoabinader.github.io/2016/05/09/qt-framework-officially-supported/" rel="alternate" type="text/html" title="Qt Framework officially supported" /><published>2016-05-09T00:00:00+00:00</published><updated>2016-05-09T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2016/05/09/qt-framework-officially-supported</id><content type="html" xml:base="https://brunoabinader.github.io/2016/05/09/qt-framework-officially-supported/">&lt;blockquote&gt;
  &lt;p&gt;Link: &lt;a href=&quot;https://blog.mapbox.com/qt-framework-officially-supported-40b60bfbb0d0&quot;&gt;https://blog.mapbox.com/qt-framework-officially-supported-40b60bfbb0d0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mapbox/mapbox-gl-native&quot;&gt;Mapbox GL Native&lt;/a&gt; now officially supports &lt;a href=&quot;https://www.qt.io/&quot;&gt;Qt&lt;/a&gt;, an open-source cross-platform application framework designed to &lt;em&gt;write once, deploy everywhere&lt;/em&gt;. Qt is widely used in many industries, including mobile, automotive, avionics and much more due to its fast development cycle, extensive documentation and big community.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/mapbox-qml-example.gif&quot; alt=&quot;Mapbox QML example&quot; class=&quot;center&quot; /&gt;
&lt;em class=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;Mapbox QML example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are committed to Qt and Mapbox GL Native now welcomes it as a first-class platform. &lt;a href=&quot;https://github.com/mapbox/mapbox-gl-native/tree/master/platform/qt&quot;&gt;Mapbox Qt SDK&lt;/a&gt; provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMapboxGL&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QQuickMapboxGL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMapboxGL&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QQuickMapboxGL&lt;/code&gt; solve different problems. The former is a low-level implementation that can be used on previous versions of Qt and is easily integrated into pure C++ environments. The latter takes advantage of Qt Quick’s modern user interface technology, and is the perfect tool for adding navigation maps on embedded platforms.&lt;/p&gt;

&lt;p&gt;Grab our open source code &lt;a href=&quot;https://github.com/mapbox/mapbox-gl-native&quot;&gt;on GitHub&lt;/a&gt; and join us at &lt;a href=&quot;https://blog.qt.io/blog/2016/02/18/qtcon-in-berlin-1st-4th-september-2016/&quot;&gt;QtCon&lt;/a&gt; this September in Berlin.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Link: https://blog.mapbox.com/qt-framework-officially-supported-40b60bfbb0d0</summary></entry><entry><title type="html">Converting C-Like Enums to String values in Rust</title><link href="https://brunoabinader.github.io/2014/01/28/converting-c-like-enums-to-string-values-in-rust/" rel="alternate" type="text/html" title="Converting C-Like Enums to String values in Rust" /><published>2014-01-28T00:00:00+00:00</published><updated>2014-01-28T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2014/01/28/converting-c-like-enums-to-string-values-in-rust</id><content type="html" xml:base="https://brunoabinader.github.io/2014/01/28/converting-c-like-enums-to-string-values-in-rust/">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The contents of this post are based on an API that is now deprecated. For latest guidance over Rust usage of
enums from a C/C++ perspective, I recommend reading fasterthanlime’s &lt;a href=&quot;https://fasterthanli.me/articles/peeking-inside-a-rust-enum&quot;&gt;&lt;em&gt;Peeking inside a rust
enum&lt;/em&gt;&lt;/a&gt; guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose you have a C-like enumerator in Rust:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SomeValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OtherValue&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: C-Like enumerations in Rust have no parameters (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SomeValue(~str)&lt;/code&gt;), and can have their discriminator values explicitly set to a constant value (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SomeValue = 0&lt;/code&gt;). See the Rust book &lt;a href=&quot;https://static.rust-lang.org/doc/master/book/enums.html&quot;&gt;section 4.13 Enums&lt;/a&gt; for details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want to obtain the string value (i.e. “SomeValue”) given an unsigned integer, the trick is to first cast it as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; value, then use &lt;a href=&quot;https://doc.rust-lang.org/std/fmt/&quot;&gt;format&lt;/a&gt; to obtain its string representation. For the former step, first we need to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; implement the &lt;a href=&quot;http://static.rust-lang.org/doc/master/collections/enum_set/trait.CLike.html&quot;&gt;CLike&lt;/a&gt; &lt;a href=&quot;http://static.rust-lang.org/doc/master/tutorial.html#traits&quot;&gt;trait&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;enum_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CLike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[repr(uint)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SomeValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OtherValue&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CLike&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The latter step is easy, we just need to format the output as string.
The simplest way is to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; derive from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ToStr&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;enum_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CLike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;to_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToStr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[repr(uint)]&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;#[deriving(ToStr)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SomeValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OtherValue&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CLike&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CLike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output for this code is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SomeValue&lt;/code&gt;.&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">Note: The contents of this post are based on an API that is now deprecated. For latest guidance over Rust usage of enums from a C/C++ perspective, I recommend reading fasterthanlime’s Peeking inside a rust enum guide.</summary></entry><entry><title type="html">CSS Level 3 Text Decoration properties now available in Google Chrome Canary!</title><link href="https://brunoabinader.github.io/2013/08/20/css-level-3-text-decoration-properties-now-available-in-google-chrome-canary/" rel="alternate" type="text/html" title="CSS Level 3 Text Decoration properties now available in Google Chrome Canary!" /><published>2013-08-20T00:00:00+00:00</published><updated>2013-08-20T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2013/08/20/css-level-3-text-decoration-properties-now-available-in-google-chrome-canary</id><content type="html" xml:base="https://brunoabinader.github.io/2013/08/20/css-level-3-text-decoration-properties-now-available-in-google-chrome-canary/">&lt;p&gt;As of Monday (August 19th), &lt;a href=&quot;https://www.google.com/intl/en/chrome/browser/canary.html&quot;&gt;Google Chrome Canary&lt;/a&gt; now supports CSS3 Text Decoration shorthand property. Once in Canary, you can enable the &lt;em&gt;Experimental Web Platform Features&lt;/em&gt; runtime flag by checking the link below:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;chrome://flags/#enable-experimental-web-platform-features&quot;&gt;chrome://flags/#enable-experimental-web-platform-features&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After enabling it, restart your browser and you should be able to use
the following pattern:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;text-decoration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;underline&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;dashed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Gives the following result: &lt;span style=&quot;text-decoration: underline dashed red;&quot;&gt;underline dashed red&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;As specified in &lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/#text-decoration-property&quot;&gt;CSS Level 3 Text Decoration shorthand specification&lt;/a&gt;. I am also &lt;a href=&quot;https://lists.webkit.org/pipermail/webkit-dev/2013-August/025297.html&quot;&gt;proposing these properties to go enabled by default in WebKit&lt;/a&gt; - stay tuned for further updates!&lt;/p&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">As of Monday (August 19th), Google Chrome Canary now supports CSS3 Text Decoration shorthand property. Once in Canary, you can enable the Experimental Web Platform Features runtime flag by checking the link below:</summary></entry><entry><title type="html">CSS Level 3 Text Decoration on WebKit and Blink - status</title><link href="https://brunoabinader.github.io/2013/05/15/css-level-3-text-decoration-on-webkit-and-blink-status/" rel="alternate" type="text/html" title="CSS Level 3 Text Decoration on WebKit and Blink - status" /><published>2013-05-15T00:00:00+00:00</published><updated>2013-05-15T00:00:00+00:00</updated><id>https://brunoabinader.github.io/2013/05/15/css-level-3-text-decoration-on-webkit-and-blink-status</id><content type="html" xml:base="https://brunoabinader.github.io/2013/05/15/css-level-3-text-decoration-on-webkit-and-blink-status/">&lt;p&gt;It’s been a while since I wrote the last post about progress on implementing &lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/&quot;&gt;CSS Level 3 Text Decoration&lt;/a&gt; features in WebKit. I’ve been involved with other projects but now I can finally resume this work. So far I have implemented:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-decoration-line&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/#text-decoration-style&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-decoration-style&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/#text-decoration-color&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-decoration-color&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.w3.org/TR/css-text-decor-3/#text-underline-position&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-underline-position&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These properties are currently available under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-webkit-&lt;/code&gt; prefix on WebKit, and guarded by a feature flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSS3_TEXT&lt;/code&gt; which is enabled by default on both EFL and GTK ports. On Blink, plans are to get these properties un-prefixed and under a runtime flag, which can be activated by enabling the &lt;a href=&quot;http://src.chromium.org/viewvc/chrome?view=revision&amp;amp;revision=210820&quot;&gt;“Experimental Web Platform Features”&lt;/a&gt; flag (see &lt;a href=&quot;chrome://flags/#enable-experimental-web-platform-features&quot;&gt;chrome://flags&lt;/a&gt; inside Google Chrome/Chromium).&lt;/p&gt;

&lt;p&gt;There are still some &lt;a href=&quot;https://skia.org/&quot;&gt;Skia&lt;/a&gt;-related issues to fix on Blink to enable proper &lt;span style=&quot;text-decoration: underline dashed;&quot;&gt;dashed&lt;/span&gt; and &lt;span style=&quot;text-decoration: overline dotted&quot;&gt;dotted&lt;/span&gt; text decoration styles to be displayed. In the near future, we shall also have the text-decoration shorthand as specified on CSS Level 3 specification.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Do not confuse text-decoration-line’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blink&lt;/code&gt; value with Google’s Blink project :smile:&lt;/p&gt;
&lt;/blockquote&gt;</content><author><name>Bruno Abinader</name></author><summary type="html">It’s been a while since I wrote the last post about progress on implementing CSS Level 3 Text Decoration features in WebKit. I’ve been involved with other projects but now I can finally resume this work. So far I have implemented:</summary></entry></feed>