Upgrade plotters-backend to 0.3.4 am: 9bbb63e272 am: d66cdd7ef4

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/plotters-backend/+/2348425

Change-Id: I9b544513d8a7284cc425fc213e3f62c0e9ed80b7
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 46b53e4..08b1a92 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "def8d8b4033af35963bc9b11cdb444cf99f91b5a"
-  }
-}
+    "sha1": "6bd30045e545e7308b1349c6ffaaa22a4c6eeb94"
+  },
+  "path_in_vcs": "plotters-backend"
+}
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 5cde165..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-version: 2
-updates:
-- package-ecosystem: cargo
-  directory: "/"
-  schedule:
-    interval: daily
-  open-pull-requests-limit: 10
diff --git a/Android.bp b/Android.bp
index 588c73a..717e030 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,7 +25,11 @@
     host_supported: true,
     crate_name: "plotters_backend",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.3.2",
+    cargo_pkg_version: "0.3.4",
     srcs: ["src/lib.rs"],
     edition: "2018",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
diff --git a/Cargo.toml b/Cargo.toml
index 582dabc..dc4d6b3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,22 +3,21 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
 name = "plotters-backend"
-version = "0.3.2"
+version = "0.3.4"
 authors = ["Hao Hou <[email protected]>"]
 description = "Plotters Backend API"
 homepage = "https://plotters-rs.github.io"
 readme = "README.md"
 license = "MIT"
-repository = "https://github.com/plotters-rs/plotters-backend"
+repository = "https://github.com/plotters-rs/plotters"
 
 [dependencies]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 0d27003..9a2ba85 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,12 +1,12 @@
 [package]
 name = "plotters-backend"
-version = "0.3.2"
+version = "0.3.4"
 authors = ["Hao Hou <[email protected]>"]
 edition = "2018"
 license = "MIT"
 description = "Plotters Backend API"
 homepage = "https://plotters-rs.github.io"
-repository = "https://github.com/plotters-rs/plotters-backend"
+repository = "https://github.com/plotters-rs/plotters"
 readme = "README.md"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/METADATA b/METADATA
index f2afc06..f4439cd 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/plotters-backend
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "plotters-backend"
 description: "Plotters Backend API"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/plotters-backend/plotters-backend-0.3.2.crate"
+    value: "https://static.crates.io/crates/plotters-backend/plotters-backend-0.3.4.crate"
   }
-  version: "0.3.2"
+  version: "0.3.4"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 8
-    day: 9
+    year: 2022
+    month: 12
+    day: 13
   }
 }
diff --git a/src/lib.rs b/src/lib.rs
index f4a92b0..d4fd904 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -174,6 +174,7 @@
             for end in path.into_iter() {
                 if let Some(begin) = begin {
                     let result = self.draw_line(begin, end, style);
+                    #[allow(clippy::question_mark)]
                     if result.is_err() {
                         return result;
                     }
@@ -290,11 +291,11 @@
     /// TODO: The default implementation of bitmap blitting assumes that the bitmap is RGB, but
     /// this may not be the case. But for bitmap backend it's actually ok if we use the bitmap
     /// element that matches the pixel format, but we need to fix this.
-    fn blit_bitmap<'a>(
+    fn blit_bitmap(
         &mut self,
         pos: BackendCoord,
         (iw, ih): (u32, u32),
-        src: &'a [u8],
+        src: &[u8],
     ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
         let (w, h) = self.get_size();
 
@@ -315,6 +316,7 @@
                     rgb: (r, g, b),
                 };
                 let result = self.draw_pixel((pos.0 + dx as i32, pos.1 + dy as i32), color);
+                #[allow(clippy::question_mark)]
                 if result.is_err() {
                     return result;
                 }
diff --git a/src/rasterizer/circle.rs b/src/rasterizer/circle.rs
index 779f095..0584167 100644
--- a/src/rasterizer/circle.rs
+++ b/src/rasterizer/circle.rs
@@ -322,8 +322,8 @@
 
         if fill {
             check_result!(b.draw_line((left, y), (right, y), &style.color()));
-            check_result!(b.draw_line((x, top), (x, up), &style.color()));
-            check_result!(b.draw_line((x, down), (x, bottom), &style.color()));
+            check_result!(b.draw_line((x, top), (x, up - 1), &style.color()));
+            check_result!(b.draw_line((x, down + 1), (x, bottom), &style.color()));
         } else {
             check_result!(b.draw_pixel((left, y), style.color().mix(1.0 - v)));
             check_result!(b.draw_pixel((right, y), style.color().mix(1.0 - v)));
diff --git a/src/rasterizer/line.rs b/src/rasterizer/line.rs
index 7a646f4..17836d9 100644
--- a/src/rasterizer/line.rs
+++ b/src/rasterizer/line.rs
@@ -109,7 +109,7 @@
         y += grad;
     }
 
-    if to.0 >= batch_limit + 1 && y < f64::from(to.1) {
+    if to.0 > batch_limit && y < f64::from(to.1) {
         let x = batch_limit as i32 + 1;
         if 1.0 + y.floor() - y > 1e-5 {
             check_result!(put_pixel((x, y as i32), 1.0 + y.floor() - y));
diff --git a/src/rasterizer/mod.rs b/src/rasterizer/mod.rs
index 11835f4..d322391 100644
--- a/src/rasterizer/mod.rs
+++ b/src/rasterizer/mod.rs
@@ -6,10 +6,19 @@
 
 */
 
-// TODO: ? operator is very slow. See issue #58 for details
+// TODO: We need to revisit this. It has been a long time since last time we figured out
+// the question mark operator has a huge performance impact due to LLVM unable to handle it.
+// So the question is if this trick is still useful, or LLVM is smart enough to handle it since
+// then.
+// 
+// --
+// Original comment:
+//
+// ? operator is very slow. See issue #58 for details
 macro_rules! check_result {
     ($e:expr) => {
         let result = $e;
+        #[allow(clippy::question_mark)]
         if result.is_err() {
             return result;
         }
diff --git a/src/rasterizer/path.rs b/src/rasterizer/path.rs
index b2db356..35ae604 100644
--- a/src/rasterizer/path.rs
+++ b/src/rasterizer/path.rs
@@ -1,5 +1,6 @@
 use crate::BackendCoord;
 
+// Compute the tanginal and normal vectors of the given straight line.
 fn get_dir_vector(from: BackendCoord, to: BackendCoord, flag: bool) -> ((f64, f64), (f64, f64)) {
     let v = (i64::from(to.0 - from.0), i64::from(to.1 - from.1));
     let l = ((v.0 * v.0 + v.1 * v.1) as f64).sqrt();
@@ -13,10 +14,17 @@
     }
 }
 
-fn compute_polygon_vertex(triple: &[BackendCoord; 3], d: f64) -> BackendCoord {
+// Compute the polygonized vertex of the given angle
+// d is the distance between the polygon edge and the actual line.
+// d can be negative, this will emit a vertex on the other side of the line.
+fn compute_polygon_vertex(triple: &[BackendCoord; 3], d: f64, buf: &mut Vec<BackendCoord>) {
+    buf.clear();
+
+    // Compute the tanginal and normal vectors of the given straight line.
     let (a_t, a_n) = get_dir_vector(triple[0], triple[1], false);
     let (b_t, b_n) = get_dir_vector(triple[2], triple[1], true);
 
+    // Compute a point that is d away from the line for line a and line b.
     let a_p = (
         f64::from(triple[1].0) + d * a_n.0,
         f64::from(triple[1].1) + d * a_n.1,
@@ -26,12 +34,25 @@
         f64::from(triple[1].1) + d * b_n.1,
     );
 
+    // If they are actually the same point, then the 3 points are colinear, so just emit the point.
+    if a_p.0 as i32 == b_p.0 as i32 && a_p.1 as i32 == b_p.1 as i32 {
+        buf.push((a_p.0 as i32, a_p.1 as i32));
+        return;
+    }
+
+    // So we are actually computing the intersection of two lines:
+    // a_p + u * a_t and b_p + v * b_t.
+    // We can solve the following vector equation:
     // u * a_t + a_p = v * b_t + b_p
+    //
+    // which is actually a equation system:
     // u * a_t.0 - v * b_t.0 = b_p.0 - a_p.0
     // u * a_t.1 - v * b_t.1 = b_p.1 - a_p.1
-    if a_p.0 as i32 == b_p.0 as i32 && a_p.1 as i32 == b_p.1 as i32 {
-        return (a_p.0 as i32, a_p.1 as i32);
-    }
+
+    // The following vars are coefficients of the linear equation system.
+    // a0*u + b0*v = c0
+    // a1*u + b1*v = c1
+    // in which x and y are the coordinates that two polygon edges intersect.
 
     let a0 = a_t.0;
     let b0 = -b_t.0;
@@ -40,17 +61,30 @@
     let b1 = -b_t.1;
     let c1 = b_p.1 - a_p.1;
 
-    // This is the coner case that
-    if (a0 * b1 - a1 * b0).abs() < 1e-10 {
-        return (a_p.0 as i32, a_p.1 as i32);
+    let mut x = f64::INFINITY;
+    let mut y = f64::INFINITY;
+
+    // Well if the determinant is not 0, then we can actuall get a intersection point.
+    if (a0 * b1 - a1 * b0).abs() > f64::EPSILON {
+        let u = (c0 * b1 - c1 * b0) / (a0 * b1 - a1 * b0);
+
+        x = a_p.0 + u * a_t.0;
+        y = a_p.1 + u * a_t.1;
     }
 
-    let u = (c0 * b1 - c1 * b0) / (a0 * b1 - a1 * b0);
+    let cross_product = a_t.0 * b_t.1 - a_t.1 * b_t.0;
+    if (cross_product < 0.0 && d < 0.0) || (cross_product > 0.0 && d > 0.0) {
+        // Then we are at the outter side of the angle, so we need to consider a cap.
+        let dist_square = (x - triple[1].0 as f64).powi(2) + (y - triple[1].1 as f64).powi(2);
+        // If the point is too far away from the line, we need to cap it.
+        if dist_square > d * d * 16.0 {
+            buf.push((a_p.0.round() as i32, a_p.1.round() as i32));
+            buf.push((b_p.0.round() as i32, b_p.1.round() as i32));
+            return;
+        }
+    }
 
-    let x = a_p.0 + u * a_t.0;
-    let y = a_p.1 + u * a_t.1;
-
-    (x.round() as i32, y.round() as i32)
+    buf.push((x.round() as i32, y.round() as i32));
 }
 
 fn traverse_vertices<'a>(
@@ -78,6 +112,7 @@
     ));
 
     let mut recent = [(0, 0), *a, *b];
+    let mut vertex_buf = Vec::with_capacity(3);
 
     for p in vertices {
         if *p == recent[2] {
@@ -86,7 +121,8 @@
         recent.swap(0, 1);
         recent.swap(1, 2);
         recent[2] = *p;
-        op(compute_polygon_vertex(&recent, f64::from(width) / 2.0));
+        compute_polygon_vertex(&recent, f64::from(width) / 2.0, &mut vertex_buf);
+        vertex_buf.iter().cloned().for_each(&mut op);
     }
 
     let b = recent[1];
diff --git a/src/text.rs b/src/text.rs
index 58cc9f2..16e2c66 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -233,6 +233,7 @@
 
     fn family(&self) -> FontFamily;
 
+    #[allow(clippy::type_complexity)]
     fn layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>;
 
     fn draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>(