diff --git a/backend/svg.c b/backend/svg.c
index d6b2775f..0ca80259 100644
--- a/backend/svg.c
+++ b/backend/svg.c
@@ -306,38 +306,48 @@ int svg_plot(struct zint_symbol *symbol) {
                 }
             }
             row_posn += yoffset;
-
-            i = 0;
-            if (module_is_set(symbol, this_row, 0)) {
-                latch = 1;
-            } else {
-                latch = 0;
-            }
-
-            do {
-                block_width = 0;
-                do {
-                    block_width++;
-                } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
-                if ((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) {
-                    addon_text_posn = (row_posn + 8.0) * scaler;
-                    addon_latch = 1;
-                }
-                if (latch == 1) {
-                    /* a bar */
-                    if (addon_latch == 0) {
-                        fprintf(fsvg, "      <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, row_posn * scaler, block_width * scaler, row_height * scaler);
-                    } else {
-                        fprintf(fsvg, "      <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, (row_posn + 10.0) * scaler, block_width * scaler, (row_height - 5.0) * scaler);
+            
+            if ((symbol->output_options & BARCODE_DOTTY_MODE) != 0) { 
+                /* Use (currently undocumented) dot mode - see SF ticket #29 */
+                for (i = 0; i < symbol->width; i++) {
+                    if (module_is_set(symbol, this_row, i)) {
+                        fprintf(fsvg, "      <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", ((i + xoffset) * scaler) + (scaler / 2.0), (row_posn * scaler) + (scaler / 2.0), (2.0 / 5.0) * scaler, symbol->fgcolour);
                     }
-                    latch = 0;
-                } else {
-                    /* a space */
-                    latch = 1;
                 }
-                i += block_width;
+            } else {
+                /* Normal mode, with rectangles */
+                i = 0;
+                if (module_is_set(symbol, this_row, 0)) {
+                    latch = 1;
+                } else {
+                    latch = 0;
+                }
+                
+                do {
+                    block_width = 0;
+                    do {
+                        block_width++;
+                    } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
+                    if ((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) {
+                        addon_text_posn = (row_posn + 8.0) * scaler;
+                        addon_latch = 1;
+                    }
+                    if (latch == 1) {
+                        /* a bar */
+                        if (addon_latch == 0) {
+                            fprintf(fsvg, "      <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, row_posn * scaler, block_width * scaler, row_height * scaler);
+                        } else {
+                            fprintf(fsvg, "      <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, (row_posn + 10.0) * scaler, block_width * scaler, (row_height - 5.0) * scaler);
+                        }
+                        latch = 0;
+                    } else {
+                        /* a space */
+                        latch = 1;
+                    }
+                    i += block_width;
 
-            } while (i < symbol->width);
+                } while (i < symbol->width);
+            }
         }
     }
     /* That's done the actual data area, everything else is human-friendly */
diff --git a/backend/zint.h b/backend/zint.h
index f0f8cefb..d8aa72cd 100644
--- a/backend/zint.h
+++ b/backend/zint.h
@@ -200,6 +200,7 @@ extern "C" {
 #define SMALL_TEXT		32
 #define BOLD_TEXT               64
 #define CMYK_COLOUR             128
+#define BARCODE_DOTTY_MODE      256
 
 #define DATA_MODE	0
 #define UNICODE_MODE	1
diff --git a/frontend/main.c b/frontend/main.c
index d950b127..efffef5c 100644
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -476,6 +476,7 @@ int main(int argc, char **argv) {
             {"mirror", 0, 0, 0},
             {"mirroreps", 0, 0, 0},
             {"mirrorsvg", 0, 0, 0},
+            {"dotty", 0, 0, 0},
             {0, 0, 0, 0}
         };
         c = getopt_long(argc, argv, "htb:w:d:o:i:rcmp", long_options, &option_index);
@@ -501,6 +502,9 @@ int main(int argc, char **argv) {
                 if (!strcmp(long_options[option_index].name, "cmyk")) {
                     my_symbol->output_options += CMYK_COLOUR;
                 }
+                if (!strcmp(long_options[option_index].name, "dotty")) {
+                    my_symbol->output_options += BARCODE_DOTTY_MODE;
+                }
                 if (!strcmp(long_options[option_index].name, "directeps")) {
                     my_symbol->output_options += BARCODE_STDOUT;
                     strncpy(my_symbol->outfile, "dummy.eps", 10);