diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [v1.3.1.0](https://github.com/diagrams/diagrams-lib/tree/v1.3.0.9) (2016-02-14)
+
+- improve path offset calculations
+
+[Full Changelog](https://github.com/diagrams/diagrams-lib/compare/v1.3.0.9...v1.3.1.0)
+
 ## [v1.3.0.9](https://github.com/diagrams/diagrams-lib/tree/v1.3.0.9) (2016-01-14)
 
 - allow `unordered-containers-0.2.6`
diff --git a/diagrams-lib.cabal b/diagrams-lib.cabal
--- a/diagrams-lib.cabal
+++ b/diagrams-lib.cabal
@@ -1,5 +1,5 @@
 Name:                diagrams-lib
-Version:             1.3.0.9
+Version:             1.3.1.0
 Synopsis:            Embedded domain-specific language for declarative graphics
 Description:         Diagrams is a flexible, extensible EDSL for creating
                      graphics of many types.  Graphics can be created
@@ -140,3 +140,14 @@
     RankNTypes, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell,
     TypeOperators, TypeSynonymInstances, UndecidableInstances, ViewPatterns,
     LambdaCase
+
+test-suite tests
+  type: exitcode-stdio-1.0
+  main-is: Test.hs
+  other-modules: Diagrams.TwoD.OffsetTest
+  hs-source-dirs: test
+  build-depends:       base >= 4.2 && < 4.9,
+                       tasty >= 0.10,
+                       tasty-hunit >= 0.9.2,
+                       diagrams-lib
+  default-language:    Haskell2010
diff --git a/src/Diagrams/TwoD/Offset.hs b/src/Diagrams/TwoD/Offset.hs
--- a/src/Diagrams/TwoD/Offset.hs
+++ b/src/Diagrams/TwoD/Offset.hs
@@ -280,8 +280,8 @@
     where
       eps = opts^.offsetEpsilon
       offset = map (bindLoc (offsetSegment eps r)) . locatedTrailSegments
-      ends | isLoop    = (\(a:as) -> as ++ [a]) . trailVertices $ t
-           | otherwise = tail . trailVertices $ t
+      ends | isLoop    = (\(a:as) -> as ++ [a]) . trailPoints $ t
+           | otherwise = tail . trailPoints $ t
       j = fromLineJoin (opts^.offsetJoin)
 
       isLoop = withTrail (const False) (const True) (unLoc t)
@@ -375,7 +375,7 @@
       offset r' = map (bindLoc (offsetSegment eps r')) . locatedTrailSegments
       f r' = joinSegments eps (fromLineJoin (opts^.expandJoin)) False (opts^.expandMiterLimit) r' ends
            . offset r' $ t
-      ends = tail . trailVertices $ t
+      ends = tail . trailPoints $ t
       s = atStart t
       e = atEnd t
       cap = fromLineCap (opts^.expandCap)
@@ -387,7 +387,7 @@
       offset r' = map (bindLoc (offsetSegment eps r')) . locatedTrailSegments
       f r' = joinSegments eps (fromLineJoin (opts^.expandJoin)) True (opts^.expandMiterLimit) r' ends
            . offset r' $ t
-      ends = (\(a:as) -> as ++ [a]) . trailVertices $ t
+      ends = (\(a:as) -> as ++ [a]) . trailPoints $ t
 
 -- | Expand a 'Trail' with the given radius and default options.  See 'expandTrail''.
 expandTrail :: RealFloat n => n -> Located (Trail V2 n) -> Path V2 n
diff --git a/test/Diagrams/TwoD/OffsetTest.hs b/test/Diagrams/TwoD/OffsetTest.hs
new file mode 100644
--- /dev/null
+++ b/test/Diagrams/TwoD/OffsetTest.hs
@@ -0,0 +1,48 @@
+module Diagrams.TwoD.OffsetTest
+    (
+      tests
+    ) where
+
+import Test.Tasty (TestTree)
+import Test.Tasty.HUnit
+
+import Diagrams.Prelude
+import Diagrams.TwoD.Offset
+
+tests :: [TestTree]
+tests =
+    [ testCase "line"
+          (offsetTrailVertices
+              [p2 (0, 0), p2 (1, 0)]
+              [p2 (0, -1), p2 (1, -1)])
+    , testCase "square"
+          (offsetTrailVertices
+              [p2 (0, 0), p2 (1, 0), p2 (1, 1), p2 (0, 1), p2 (0, 0)]
+              [p2 (0, -1), p2 (2, -1), p2 (2, 2), p2 (-1, 2), p2 (-1, 0)])
+    , testCase "square loop"
+          (offsetTrailLoopVertices
+              [p2 (0, 0), p2 (1, 0), p2 (1, 1), p2 (0, 1), p2 (0, 0)]
+              [p2 (2, -1), p2 (2, 2), p2 (-1, 2), p2 (-1, -1)])
+    , testCase "redundant line"
+          (offsetTrailVertices
+              [p2 (0, 0), p2 (0.5, 0), p2 (1, 0)]
+              [p2 (0, -1), p2 (1, -1)])
+    , testCase "redundant square"
+          (offsetTrailVertices
+              [p2 (0, 0), p2 (1, 0), p2 (1, 0.5), p2 (1, 1), p2 (0, 1), p2 (0, 0)]
+              [p2 (0, -1), p2 (2, -1), p2 (2, 2), p2 (-1, 2), p2 (-1, 0)])
+    , testCase "redundant square loop"
+          (offsetTrailLoopVertices
+              [p2 (0, 0), p2 (1, 0), p2 (1, 0.5), p2 (1, 1), p2 (0, 1), p2 (0, 0)]
+              [p2 (2, -1), p2 (2, 2), p2 (-1, 2), p2 (-1, -1)])
+    ]
+
+offsetTrailVertices :: [Point V2 Double] -> [Point V2 Double] -> Assertion
+offsetTrailVertices orig off =
+    (trailVertices . offsetTrail 1 . fromVertices $ orig) @?= off
+
+offsetTrailLoopVertices :: [Point V2 Double] -> [Point V2 Double] -> Assertion
+offsetTrailLoopVertices orig off =
+    (trailVertices . offsetTrail 1 . loopTrailFromVertices $ orig) @?= off
+  where
+    loopTrailFromVertices = (`at` origin) . wrapTrail . glueLine . lineFromVertices
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,10 @@
+import Test.Tasty (defaultMain, testGroup, TestTree)
+
+import qualified Diagrams.TwoD.OffsetTest as TwoD.OffsetTest
+
+tests :: TestTree
+tests = testGroup "unit tests"
+    [ testGroup "TwoD.Offset" TwoD.OffsetTest.tests ]
+
+main :: IO ()
+main = defaultMain tests
