{"id":134,"date":"2018-12-04T23:59:21","date_gmt":"2018-12-04T23:59:21","guid":{"rendered":"https:\/\/stuff.tamius.net\/sacred-texts\/?p=134"},"modified":"2018-12-05T00:06:59","modified_gmt":"2018-12-05T00:06:59","slug":"home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3","status":"publish","type":"post","link":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/","title":{"rendered":"How to make speech bubbles draw themselves: a story of pain (part 3)"},"content":{"rendered":"<p>In the <a href=\"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/11\/13\/how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-2\/\" target=\"_blank\">part two<\/a> of this saga, we&#8217;ve discovered that <i>not<\/i> using brute force is <i>not<\/i> gonna be an option. After <a href=\"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/10\/29\/how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-1\/\" target=\"_blank\">our first attempt at brute force failed miserably<\/a>, we&#8217;ll have to find another way.<\/p>\n<h1>Me orc, me smash: Brute force revisited<\/h1>\n<p>Upon review, it turns out that our first solution was actually kinda close to working. Our algorithm kinda looked like this:<\/p>\n<ol>\n<li>Find the center of the ellipse<\/li>\n<li>Find aspect ratio of the text<\/li>\n<li>Assume that the aspect ratio we found is the same as the aspect ratio of our ellipse<\/li>\n<li>Squash text into the square and draw a circle around it<\/li>\n<li>Calculate the radius of the circle using maths<\/li>\n<li>Unsquash the circle, get ellipse (or two radii that define it)<\/li>\n<\/ol>\n<p>The obvious problems with this approach were:<\/p>\n<ul>\n<li>assumption under point #3 is incorrect<\/li>\n<li>this means the radius we calculated was also wrong, and often too tight<\/li>\n<\/ul>\n<p>We can work around that. We only really need to add very little on top of what we already have:<\/p>\n<ol start=4>\n<li>&#8230;<\/li>\n<li>Calculate radius of the circle using maths<\/li>\n<li>**Increase that radius by some factor in order to give us some breathing room**<\/li>\n<li>Unsquash the circle, get ellipse (or two radii that define it)<\/li>\n<li>**Try to make ellipse smaller, one small step at a time**<\/li>\n<li>Repeat #8 a few times, use the best result you get<\/li>\n<\/ol>\n<p>Steps 8\/9 can be done using a kind of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Binary_search_algorithm\" target=\"_blank\">binary search<\/a>, and it goes roughly like this:<\/p>\n<ol>\n<li>Calculate whether all points are in the ellipse for given radii.<\/li>\n<li>If all points are inside the ellipse, decrease radii for half of a step<\/li>\n<li>If any of the points are outside the ellipse, increase radii for half of a step<\/li>\n<li>Decrease step by half<\/li>\n<li>If step is sufficiently small, you can stop<\/li>\n<li>If step isn&#8217;t sufficiently small, go back to #1<\/li>\n<\/ol>\n<p>In our case, we have two &#8216;steps&#8217; (each for one of the radii). Before starting our algorith, we determine two values for each of the radii:<\/p>\n<ul>\n<li>&#8220;Radius can&#8217;t be bigger than this&#8221; number (e.g. width of a given line of text)<\/li>\n<li>&#8220;Radius can&#8217;t be smaller than this&#8221; number (e.g. half of the width of a given line of text)<\/li>\n<\/ul>\n<p>Step is the difference between the two (different for each radius). We use the bigger of the two numbers as our radius.<\/p>\n<p>This works great, but we can improve it even further. Inside every step, we can try decreasing size of one radius while keeping the other radius the same. This can help us find smaller, better-fitting ellipses at the expense of some extra calculations (to the tune of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Big_O_notation\" target=\"_blank\">O(n\u00b2)<\/a>).<\/p>\n<h1>Trying it out<\/h1>\n<p>Now that we wrote the code, it&#8217;s time to try it out. Results ended up being slightly disappointing:<\/p>\n<figure id=\"attachment_139\" aria-describedby=\"caption-attachment-139\" style=\"width: 642px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg\" alt=\"\" width=\"642\" height=\"898\" class=\"size-full wp-image-139\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg 642w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1-214x300.jpg 214w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><figcaption id=\"caption-attachment-139\" class=\"wp-caption-text\">Yikes. That&#8217;s worse than our previous test. We even managed to fail to draw a rectangle properly.<\/figcaption><\/figure>\n<p>What is worse: there doesn&#8217;t seem to be neither reason nor rhyme to why things don&#8217;t work. Our brute force approach was used at least five times and has two failures (where bubble is way too small). Multiline texts \u2014 the ones that very probably don&#8217;t use the bruteforce approach at all \u2014 are often off-center and sometimes even too small (all off-center bubbles are too small, so text doesn&#8217;t fit in the ellipse):<\/p>\n<figure id=\"attachment_140\" aria-describedby=\"caption-attachment-140\" style=\"width: 688px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt2.jpg\" alt=\"\" width=\"688\" height=\"866\" class=\"size-full wp-image-140\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt2.jpg 688w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt2-238x300.jpg 238w\" sizes=\"auto, (max-width: 688px) 100vw, 688px\" \/><figcaption id=\"caption-attachment-140\" class=\"wp-caption-text\">Those four texts must be related to Cinderella.<\/figcaption><\/figure>\n<h1>What gives?<\/h1>\n<p>Upon closer examination, it turns out that some ellipses that should be drawn with brute force method weren&#8217;t drawn by brute-force method. Secondly, despite determining ellipse&#8217;s radius by brute force, we still always use our matrix to determine one or both center coordinates. Our &#8216;high maths&#8217; approach is giving us slightly suspect \u2014 and possibly even wrong \u2014 results.<\/p>\n<p>The one thing to consider when writing code is that computers are generally fairly terrible with very tiny (and very big) numbers. The tinier your number (we&#8217;re talking anything past fifth decimal), the less &#8220;accurate&#8221; it is. The values the matrix calculation spat out contained some very tiny numbers. When those numbers were used to perform further calculations, the errors grew and we got garbage results.<\/p>\n<p>Let&#8217;s forget the &#8216;high maths&#8217; approach for a while and try to brute force everything.<\/p>\n<h1>Giving brute force another try<\/h1>\n<h2>Step 1: determining the center of the ellipse<\/h2>\n<p>This one is going to be easy. We still only work with 4 points at the time. To get the &#8216;center point&#8217;, we find the average of the four coordinates. Then, we try to find the intersection between the lines connecting the points at the opposite sides of the quadrangle the four points form. If the point of intersection is mirrored over the &#8216;center point,&#8217; it gives us the center of our ellipse.<\/p>\n<h2>Step 2: apply smash, remove smart<\/h2>\n<p>We feed the center of the ellipse we got from step 1 into the brute force algorithm we discussed earlier, run some test and &#8230;<\/p>\n<figure id=\"attachment_144\" aria-describedby=\"caption-attachment-144\" style=\"width: 1367px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242.png\" alt=\"\" width=\"1367\" height=\"816\" class=\"size-full wp-image-144\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242.png 1367w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242-300x179.png 300w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242-768x458.png 768w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242-1024x611.png 1024w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/Screenshot_20181205_002242-1200x716.png 1200w\" sizes=\"auto, (max-width: 1367px) 100vw, 1367px\" \/><figcaption id=\"caption-attachment-144\" class=\"wp-caption-text\">So close, yet so far. Something crashed the script on the last bubble.<\/figcaption><\/figure>\n<p>Good news is: brute force does find better results than attempt at using high maths. No bubble is drawn off-center, all bubbles are correctly sized. The reason for the crash is a weird point selection: one of the diagonals (in at least one of the 4-point subsets of the last bubble) is vertical. In order to calculate the center of our to-be-ellipse, we need to know the slope of thes line between the opposing sides. There&#8217;s a bit of a problem though: if you&#8217;re trying to calculate the slope of a vertical line in a coordinate system, you&#8217;re going to faceplant into a division by zero.<\/p>\n<p>Computers don&#8217;t like dividng by zero.<\/p>\n<figure id=\"attachment_145\" aria-describedby=\"caption-attachment-145\" style=\"width: 708px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_003627.png\" alt=\"\" width=\"708\" height=\"293\" class=\"size-full wp-image-145\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_003627.png 708w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_003627-300x124.png 300w\" sizes=\"auto, (max-width: 708px) 100vw, 708px\" \/><figcaption id=\"caption-attachment-145\" class=\"wp-caption-text\">Trying to find an intersection in this point combination is going to be problematic.<\/figcaption><\/figure>\n<p>We can quickly see another thing: if we try to determine the center for our ellipse using these four points, we&#8217;ll just get less-than-optimal solution. That means we can skip it \u2014 all it would do is waste our time.<\/p>\n<p>Let&#8217;s see if that fixed our probem:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_004652.png\" alt=\"\" width=\"958\" height=\"891\" class=\"aligncenter size-full wp-image-146\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_004652.png 958w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_004652-300x279.png 300w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_004652-768x714.png 768w\" sizes=\"auto, (max-width: 958px) 100vw, 958px\" \/><\/p>\n<p>And all is right. As far as performance goes, &#8220;stopwatch test&#8221; says brute-force approach isn&#8217;t really that much slower than the &#8220;proper&#8221;, &#8220;high maths&#8221; approach.<\/p>\n<h1>This leads us to the conclusion:<\/h1>\n<p>Lots of people love the &#8220;work smart, not hard&#8221; approach to things. Sure, using a little bit of brainpower to avoid using a lot of force is nice. But let&#8217;s not forget that sometimes, the opposite applies: a little bit of brute force can save us from using lots of brainpower.<\/p>\n<p>Moral of the story: don&#8217;t overthink your programs, I guess? Sometimes, simple is better and &#8216;approximate&#8217; is good enough.<\/p>\n<figure id=\"attachment_147\" aria-describedby=\"caption-attachment-147\" style=\"width: 827px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_005647.png\" alt=\"\" width=\"827\" height=\"128\" class=\"size-full wp-image-147\" srcset=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_005647.png 827w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_005647-300x46.png 300w, https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/12\/Screenshot_20181205_005647-768x119.png 768w\" sizes=\"auto, (max-width: 827px) 100vw, 827px\" \/><figcaption id=\"caption-attachment-147\" class=\"wp-caption-text\">You&#8217;re looking at one or two weeks of my free time going down the drain. Just like that.<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In the part two of this saga, we&#8217;ve discovered that not using brute force is not gonna be an option. After our first attempt at brute force failed miserably, we&#8217;ll have to find another way. Me orc, me smash: Brute force revisited Upon review, it turns out that our first solution was actually kinda close to working. Our algorithm kinda looked like this: Find<span class=\"more-dots\">&#8230;<\/span> <span class=\"more-tag d-block mt-05\"><a class=\"more-link\" href=\"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/\">Continue Reading...<span class=\"screen-reader-text\"> \"How to make speech bubbles draw themselves: a story of pain (part 3)\"<\/span><\/a><\/span><!-- .more-tag --><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pgc_sgb_lightbox_settings":"","footnotes":""},"categories":[14,13,8],"tags":[],"class_list":["post-134","post","type-post","status-publish","format-standard","hentry","category-gimp","category-programming","category-software","no-post-thumbnail"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts\" \/>\n<meta property=\"og:description\" content=\"In the part two of this saga, we&#8217;ve discovered that not using brute force is not gonna be an option. After our first attempt at brute force failed miserably, we&#8217;ll have to find another way. Me orc, me smash: Brute force revisited Upon review, it turns out that our first solution was actually kinda close to working. Our algorithm kinda looked like this: Find...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"Tamius&#039; sacred texts\" \/>\n<meta property=\"article:published_time\" content=\"2018-12-04T23:59:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-12-05T00:06:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg\" \/>\n<meta name=\"author\" content=\"Tamius Han\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tamius Han\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/\"},\"author\":{\"name\":\"Tamius Han\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/#\\\/schema\\\/person\\\/4677d05a4f45974f27cd21481c561c21\"},\"headline\":\"How to make speech bubbles draw themselves: a story of pain (part 3)\",\"datePublished\":\"2018-12-04T23:59:21+00:00\",\"dateModified\":\"2018-12-05T00:06:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/\"},\"wordCount\":1175,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/tt1.jpg\",\"articleSection\":[\"GIMP\",\"Programming\",\"Software\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/\",\"url\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/\",\"name\":\"How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/tt1.jpg\",\"datePublished\":\"2018-12-04T23:59:21+00:00\",\"dateModified\":\"2018-12-05T00:06:59+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/#\\\/schema\\\/person\\\/4677d05a4f45974f27cd21481c561c21\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#primaryimage\",\"url\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/tt1.jpg\",\"contentUrl\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/tt1.jpg\",\"width\":642,\"height\":898,\"caption\":\"Yikes. That's worse than our previous test.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/2018\\\/12\\\/04\\\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to make speech bubbles draw themselves: a story of pain (part 3)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/#website\",\"url\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/\",\"name\":\"Tamius&#039; sacred texts\",\"description\":\"... containing one of the weirdest mix of pointless topics.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/#\\\/schema\\\/person\\\/4677d05a4f45974f27cd21481c561c21\",\"name\":\"Tamius Han\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg\",\"caption\":\"Tamius Han\"},\"url\":\"https:\\\/\\\/stuff.tamius.net\\\/sacred-texts\\\/author\\\/tamius-han\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/","og_locale":"en_US","og_type":"article","og_title":"How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts","og_description":"In the part two of this saga, we&#8217;ve discovered that not using brute force is not gonna be an option. After our first attempt at brute force failed miserably, we&#8217;ll have to find another way. Me orc, me smash: Brute force revisited Upon review, it turns out that our first solution was actually kinda close to working. Our algorithm kinda looked like this: Find...","og_url":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/","og_site_name":"Tamius&#039; sacred texts","article_published_time":"2018-12-04T23:59:21+00:00","article_modified_time":"2018-12-05T00:06:59+00:00","og_image":[{"url":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg","type":"","width":"","height":""}],"author":"Tamius Han","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Tamius Han","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#article","isPartOf":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/"},"author":{"name":"Tamius Han","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/#\/schema\/person\/4677d05a4f45974f27cd21481c561c21"},"headline":"How to make speech bubbles draw themselves: a story of pain (part 3)","datePublished":"2018-12-04T23:59:21+00:00","dateModified":"2018-12-05T00:06:59+00:00","mainEntityOfPage":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/"},"wordCount":1175,"commentCount":0,"image":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg","articleSection":["GIMP","Programming","Software"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/","url":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/","name":"How to make speech bubbles draw themselves: a story of pain (part 3) - Tamius&#039; sacred texts","isPartOf":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/#website"},"primaryImageOfPage":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#primaryimage"},"image":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg","datePublished":"2018-12-04T23:59:21+00:00","dateModified":"2018-12-05T00:06:59+00:00","author":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/#\/schema\/person\/4677d05a4f45974f27cd21481c561c21"},"breadcrumb":{"@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#primaryimage","url":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg","contentUrl":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-content\/uploads\/2018\/11\/tt1.jpg","width":642,"height":898,"caption":"Yikes. That's worse than our previous test."},{"@type":"BreadcrumbList","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/2018\/12\/04\/home-blog-how-to-train-your-dungeons-dragon-my-github-how-to-make-speech-bubbles-draw-themselves-a-story-of-pain-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/stuff.tamius.net\/sacred-texts\/"},{"@type":"ListItem","position":2,"name":"How to make speech bubbles draw themselves: a story of pain (part 3)"}]},{"@type":"WebSite","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/#website","url":"https:\/\/stuff.tamius.net\/sacred-texts\/","name":"Tamius&#039; sacred texts","description":"... containing one of the weirdest mix of pointless topics.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/stuff.tamius.net\/sacred-texts\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/stuff.tamius.net\/sacred-texts\/#\/schema\/person\/4677d05a4f45974f27cd21481c561c21","name":"Tamius Han","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1ce12569905c4aff5d48778af8527565f1175c254ad56cc5e5221666ff1e222b?s=96&d=blank&r=pg","caption":"Tamius Han"},"url":"https:\/\/stuff.tamius.net\/sacred-texts\/author\/tamius-han\/"}]}},"_links":{"self":[{"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/posts\/134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/comments?post=134"}],"version-history":[{"count":4,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/posts\/134\/revisions"}],"predecessor-version":[{"id":148,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/posts\/134\/revisions\/148"}],"wp:attachment":[{"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/media?parent=134"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/categories?post=134"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/stuff.tamius.net\/sacred-texts\/wp-json\/wp\/v2\/tags?post=134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}