diff --git a/crates/text/src/lib.rs b/crates/text/src/lib.rs
--- a/crates/text/src/lib.rs
+++ b/crates/text/src/lib.rs
@@ -777,9 +777,7 @@ fn shape_para(ctx: &Ctx, shape: &Shape, body: &TextBody, pi: usize, scale: f64,
                 Some(c) => c.to_string(),
                 None => map_symbol_bullet(char, props.bullet_font.as_deref()),
             };
-            if !st.face.covers(ch.chars().next().unwrap_or('•')) {
-                st.face = db.face("Inter", "Regular");
-            }
+            bullet_face(db, &mut st, &ch);
             Some((ch, st))
         }
         Some(Bullet::AutoNum { scheme, start_at }) => {
@@ -1419,7 +1417,9 @@ pub fn map_symbol_bullet(c: &str, font: Option<&str>) -> String {
         };
         return m.to_string();
     }
-    if f.contains("wingdings") || f.contains("symbol") || ('\u{f000}'..='\u{f0ff}').contains(&first) {
+    // Only the legacy symbol fonts: "Noto Sans Symbols" and the like are Unicode fonts whose
+    // characters (❑ ❖) are drawn as they are.
+    if f.contains("wingdings") || f == "symbol" || ('\u{f000}'..='\u{f0ff}').contains(&first) {
         let code = (first as u32) & 0xff;
         // Wingdings 2 and 3 put different shapes at the same codes.
         if f.starts_with("wingdings 2") {
diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs
--- a/crates/text/src/tests.rs
+++ b/crates/text/src/tests.rs
@@ -177,6 +177,23 @@ fn only_the_first_character_of_a_bullet_is_drawn() {
     assert_eq!(map_symbol_bullet("e\u{301}x", None), "e\u{301}");
 }
 
+#[test]
+fn bullet_in_an_unavailable_unicode_symbol_font_keeps_its_character() {
+    // Google Slides bullets in "Noto Sans Symbols" (not installed) draw ❑ ❖, not a generic dot (#1347).
+    for c in ["\u{2751}", "\u{2756}"] {
+        assert_eq!(map_symbol_bullet(c, Some("Noto Sans Symbols")), c);
+    }
+    // The legacy symbol fonts still map their codes.
+    assert_eq!(map_symbol_bullet("q", Some("Wingdings")), "\u{2751}");
+    let (p, mut sh) = setup("One", 600.0, 300.0);
+    let para = &mut sh.text.as_mut().unwrap().paragraphs[0];
+    para.props.bullet = Some(Bullet::Char { char: "\u{2751}".into() });
+    para.props.bullet_font = Some("Noto Sans Symbols".into());
+    let l = lay(&p, &sh, 600.0, 300.0);
+    let bullet = l.runs.iter().find(|r| r.chars == (0, 0)).expect("bullet run");
+    assert_eq!(bullet.glyphs.len(), 1);
+}
+
 #[test]
 fn shrink_on_overflow() {
     let text = (0..30).map(|i| format!("Line number {i}")).collect::<Vec<_>>().join("\n");
