diff --git a/src/ufonormalizer.py b/src/ufonormalizer.py
index ff76f91..796bb37 100644
--- a/src/ufonormalizer.py
+++ b/src/ufonormalizer.py
@@ -4,6 +4,7 @@ from __future__ import print_function, unicode_literals
 
 import time
 import os
+import re
 import shutil
 from xml.etree import cElementTree as ET
 import plistlib
@@ -158,11 +159,9 @@ else:
 class UFONormalizerError(Exception):
     pass
 
-
 DEFAULT_FLOAT_PRECISION = 10
 FLOAT_FORMAT = "%%.%df" % DEFAULT_FLOAT_PRECISION
 
-
 def normalizeUFO(ufoPath, outputPath=None, onlyModified=True,
                  floatPrecision=DEFAULT_FLOAT_PRECISION, writeModTimes=True):
     global FLOAT_FORMAT
@@ -1178,6 +1177,8 @@ class XMLWriter(object):
         self.raw(line)
 
     def text(self, text):
+        text = text.strip("\n")
+        text = dedent_tabs(text)
         text = text.strip()
         text = xmlEscapeText(text)
         paragraphs = []
@@ -1358,6 +1359,64 @@ def xmlConvertFloat(value):
 def xmlConvertInt(value):
     return str(value)
 
+
+# ---------------
+# Text Operations
+# ---------------
+
+WHITESPACE_ONLY_RE = re.compile('^[\s\t]+$', re.MULTILINE)
+LEADING_WHITESPACE_RE = re.compile('(^(?:\s{4}|\t)*)(?:[^\t\n])', re.MULTILINE)
+
+def dedent_tabs(text):
+    """
+    Based on `textwrap.dedent`, but modified to only work on tabs and 4-space indents
+
+    Remove any common leading tabs from every line in `text`.
+    This can be used to make triple-quoted strings line up with the left
+    edge of the display, while still presenting them in the source code
+    in indented form.
+
+    Entirely blank lines are normalized to a newline character.
+    """
+    # Look for the longest leading string of spaces and tabs common to
+    # all lines.
+    margin = None
+    text = WHITESPACE_ONLY_RE.sub('', text)
+    indents = LEADING_WHITESPACE_RE.findall(text)
+    for indent in indents:
+        if margin is None:
+            margin = indent
+
+        # Current line more deeply indented than previous winner:
+        # no change (previous winner is still on top).
+        elif indent.startswith(margin):
+            pass
+
+        # Current line consistent with and no deeper than previous winner:
+        # it's the new winner.
+        elif margin.startswith(indent):
+            margin = indent
+
+        # Find the largest common whitespace between current line and previous
+        # winner.
+        else:
+            for i, (x, y) in enumerate(zip(margin, indent)):
+                if x != y:
+                    margin = margin[:i]
+                    break
+
+    # sanity check (testing/debugging only)
+    if 0 and margin:
+        for line in text.split("\n"):
+            assert not line or line.startswith(margin), \
+                   "line = %r, margin = %r" % (line, margin)
+
+    if margin:
+        text = re.sub(r'(?m)^' + margin, '', text)
+    return text
+
+
+
 # ---------------
 # Path Operations
 # ---------------

diff --git a/tests/test_ufonormalizer.py b/tests/test_ufonormalizer.py
index 910d5ae..cde30e0 100644
--- a/tests/test_ufonormalizer.py
+++ b/tests/test_ufonormalizer.py
@@ -836,6 +836,53 @@ class UFONormalizerTest(unittest.TestCase):
             writer.getText(),
             "<note>\n\tLine1\n\t\n\t    Line3\n</note>")
 
+        # Normalizer should not indent Line2 and Line3 more than already indented
+        element = ET.fromstring(
+            "<note>\n\tLine1\n\tLine2\n\tLine3\n</note>")
+        writer = XMLWriter(declaration=None)
+        _normalizeGlifNote(element, writer)
+        self.assertEqual(
+            writer.getText(),
+            "<note>\n\tLine1\n\tLine2\n\tLine3\n</note>")
+
+        # Normalizer should keep the extra tab in line 2
+        element = ET.fromstring(
+            "<note>\n\tLine1\n\t\tLine2\n\tLine3\n</note>")
+        writer = XMLWriter(declaration=None)
+        _normalizeGlifNote(element, writer)
+        self.assertEqual(
+            writer.getText(),
+            "<note>\n\tLine1\n\t\tLine2\n\tLine3\n</note>")
+
+        # Normalizer should keep the extra spaces on line 2
+        element = ET.fromstring(
+            "<note>\n\tLine1\n\t    Line2\n\tLine3\n</note>")
+        writer = XMLWriter(declaration=None)
+        _normalizeGlifNote(element, writer)
+        self.assertEqual(
+            writer.getText(),
+            "<note>\n\tLine1\n\t    Line2\n\tLine3\n</note>")
+
+        # Normalizer should remove the extra tab all lines have in common,
+        # but leave the additional tab on line 2
+        element = ET.fromstring(
+            "<note>\n\t\tLine1\n\t\t\tLine2\n\t\tLine3\n</note>")
+        writer = XMLWriter(declaration=None)
+        _normalizeGlifNote(element, writer)
+        self.assertEqual(
+            writer.getText(),
+            "<note>\n\tLine1\n\t\tLine2\n\tLine3\n</note>")
+
+        # Normalizer should remove the extra 4-space all lines have in common,
+        # but leave the additional 4-space on line 2
+        element = ET.fromstring(
+            "<note>\n        Line1\n            Line2\n        Line3\n</note>")
+        writer = XMLWriter(declaration=None)
+        _normalizeGlifNote(element, writer)
+        self.assertEqual(
+            writer.getText(),
+            "<note>\n\tLine1\n\t    Line2\n\tLine3\n</note>")
+
     def test_normalizeGLIF_note_undefined(self):
         element = ET.fromstring("<note></note>")
         writer = XMLWriter(declaration=None)

Trouble normalizing the indention of new lines in Glyph Notes
Hi, 

We've been noticing that if a glyph has line returns in a note, the Normalizer has some trouble formatting it.

For instance, here is how a note started out after it was added, and its first Normalization: 
```xml
<note>
  	Line1
  	Line2
</note>
```
and with each round of normalization, all the lines after the first get indented an extra level

Once:
```xml
<note>
  	Line1
  		  	Line2
</note>
```

Twice:
```xml
<note>
  	Line1
  		  		  	Line2
</note>
```


Thrice:
```xml
<note>
  	Line1
  		  		  		  	Line2
</note>
```

etc.
tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_note_defined
tests/test_ufonormalizer.py::UFONormalizerErrorTest::test_str tests/test_ufonormalizer.py::UFONormalizerTest::test_main_input_does_not_exist tests/test_ufonormalizer.py::UFONormalizerTest::test_main_input_not_ufo tests/test_ufonormalizer.py::UFONormalizerTest::test_main_invalid_float_precision tests/test_ufonormalizer.py::UFONormalizerTest::test_main_no_metainfo_plist tests/test_ufonormalizer.py::UFONormalizerTest::test_main_no_path tests/test_ufonormalizer.py::UFONormalizerTest::test_main_verbose_or_quiet tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_horizontal_x_is_zero tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_invalid_angle tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_invalid_x tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_invalid_y tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_angle tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_color tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_identifier tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_x tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_no_y tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_vertical_y_is_zero tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_guidelines_zero_is_not_None tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeFontInfoPlist_no_guidelines tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_advance_defaults tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_advance_height tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_advance_invalid_values tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_advance_undefined tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_advance_width tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_no_color tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_no_identifier tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_no_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_no_x tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_anchor_no_y tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_formats_1_and_2 tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_guideline_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_guideline_invalid tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_image_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_image_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_image_no_color tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_image_no_file_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_image_no_transformation tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_lib_undefined tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_no_formats tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_note_undefined tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_outline_format1_element_order tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_outline_format1_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_unicode_with_hex tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGLIF_unicode_without_hex tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_attributes_format1_defaults tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_attributes_format1_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_attributes_format1_no_base tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_attributes_format1_no_transformation tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_attributes_format2_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_format1_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_format1_no_base tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_component_format1_subelement tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_implied_anchor tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_implied_anchor_with_empty_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_implied_anchor_without_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_normal tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_point_without_attributes tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_unkown_child_element tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format1_unkown_point_type tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format2_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format2_normal tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format2_point_without_attributes tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_contour_format2_unknown_child_element tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_outline_format2_element_order tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_outline_format2_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_empty_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_invalid_x tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_invalid_y tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_no_name tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_no_x tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_no_y tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_subelement tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format1_type_and_smooth tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_point_attributes_format2_everything tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_transformation_default tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_transformation_empty tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_transformation_invalid_value tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_transformation_non_default tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeGlif_transformation_unknown_attribute tests/test_ufonormalizer.py::UFONormalizerTest::test_normalizeLayerInfoPlist_color tests/test_ufonormalizer.py::UFONormalizerTest::test_normalize_color_string tests/test_ufonormalizer.py::XMLWriterTest::test_attributesToString tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_array tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_boolean tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_dict tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_float tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_integer tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_none tests/test_ufonormalizer.py::XMLWriterTest::test_propertyListObject_string tests/test_ufonormalizer.py::XMLWriterTest::test_xmlConvertFloat tests/test_ufonormalizer.py::XMLWriterTest::test_xmlConvertFloat_custom_precision tests/test_ufonormalizer.py::XMLWriterTest::test_xmlConvertFloat_no_rounding tests/test_ufonormalizer.py::XMLWriterTest::test_xmlConvertInt tests/test_ufonormalizer.py::XMLWriterTest::test_xmlConvertValue tests/test_ufonormalizer.py::XMLWriterTest::test_xmlEscapeAttribute tests/test_ufonormalizer.py::XMLWriterTest::test_xmlEscapeText tests/test_ufonormalizer.py::SubpathTest::test_readModTimes tests/test_ufonormalizer.py::SubpathTest::test_storeModTimes tests/test_ufonormalizer.py::SubpathTest::test_subpathExists tests/test_ufonormalizer.py::SubpathTest::test_subpathGetModTime tests/test_ufonormalizer.py::SubpathTest::test_subpathJoin tests/test_ufonormalizer.py::SubpathTest::test_subpathNeedsRefresh tests/test_ufonormalizer.py::SubpathTest::test_subpathReadFile tests/test_ufonormalizer.py::SubpathTest::test_subpathRemoveFile tests/test_ufonormalizer.py::SubpathTest::test_subpathRenameDirectory tests/test_ufonormalizer.py::SubpathTest::test_subpathRenameFile tests/test_ufonormalizer.py::SubpathTest::test_subpathSplit tests/test_ufonormalizer.py::SubpathTest::test_subpathWriteFile tests/test_ufonormalizer.py::SubpathTest::test_subpathWriteFile_newline tests/test_ufonormalizer.py::SubpathTest::test_subpathWritePlist tests/test_ufonormalizer.py::NameTranslationTest::test_handleClash1 tests/test_ufonormalizer.py::NameTranslationTest::test_handleClash1_max_file_length tests/test_ufonormalizer.py::NameTranslationTest::test_handleClash2 tests/test_ufonormalizer.py::NameTranslationTest::test_userNameToFileName