Add support for the object-position CSS property.

This is hidden behind an "experimental" runtime flag named
"ObjectFitPosition", together with object-fit.

This is an implementation of object-position as described in
http://www.w3.org/TR/2012/CR-css3-images-20120417/#object-position

Object-position is used to offset replaced content within its content
box. Painting is always clipped against the content box, regardless of
the "overflow" property. This property is useful together with
object-fit (to achieve a difference between content box size and
replaced content size, so that specifying alignment is interesting),
but can also be used on its own.

BUG=236333

Review URL: https://chromiumcodereview.appspot.com/24077007

git-svn-id: svn://svn.chromium.org/blink/trunk@158155 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/animations/resources/animation-test-helpers.js b/LayoutTests/animations/resources/animation-test-helpers.js
index 7823838..7cf8465 100644
--- a/LayoutTests/animations/resources/animation-test-helpers.js
+++ b/LayoutTests/animations/resources/animation-test-helpers.js
@@ -367,6 +367,19 @@
         } else {
             pass = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance);
         }
+    } else if (property == "object-position") {
+        computedValue = window.getComputedStyle(document.getElementById(elementId)).objectPosition;
+        var actualArray = computedValue.split(" ");
+        var expectedArray = expectedValue.split(" ");
+        if (actualArray.length != expectedArray.length) {
+            pass = false;
+        } else {
+            for (i = 0; i < expectedArray.length; ++i) {
+                pass = isCloseEnough(parseFloat(actualArray[i]), parseFloat(expectedArray[i]), tolerance);
+                if (!pass)
+                    break;
+            }
+        }
     } else {
         var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
         if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
diff --git a/LayoutTests/fast/css/object-position-expected.html b/LayoutTests/fast/css/object-position-expected.html
new file mode 100644
index 0000000..3cb61a2
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images</title>
+        <style type="text/css">
+            .group > div {
+                display: inline-block;
+                overflow: hidden;
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > div > div { overflow: hidden; height:100%; }
+            .group > div > div > * { display: block; width:100%; height:100%; }
+
+            .group > *:nth-child(1) > div > * { }
+            .group > *:nth-child(2) > div > * { }
+            .group > *:nth-child(3) > div > * { margin-left: 10px; }
+            .group > *:nth-child(4) > div > * { }
+            .group > *:nth-child(5) > div > * { }
+            .group > *:nth-child(6) > div > * { margin-top: -10px; }
+            .group > *:nth-child(7) > div > * { margin-left: 200%; }
+            .group > *:nth-child(8) > div > * { margin-left: 200%; }
+            .group > *:nth-child(9) > div > * { margin-left: 200%; }
+            .group > *:nth-child(10) > div > * { margin-left: 200%; }
+            .group > *:nth-child(11) > div > * { margin-left:30px; margin-top:30px; }
+            .group > *:nth-child(12) > div > * { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+        </div>
+
+  </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-svg-expected.html b/LayoutTests/fast/css/object-position-svg-expected.html
new file mode 100644
index 0000000..5879319
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-svg-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on SVG images</title>
+        <style type="text/css">
+            .group > div {
+                display: inline-block;
+                overflow: hidden;
+                width: 72px;
+                height: 144px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > div > div { position:relative; overflow: hidden; height:100%; }
+            .group > div > div > * { position: absolute; width:36px; height:36px; }
+
+            .group > *:nth-child(1) > div > * { right: 0; }
+            .group > *:nth-child(2) > div > * { left: 0; bottom: 0; }
+            .group > *:nth-child(3) > div > * { left: 10px; bottom: -27px; }
+            .group > *:nth-child(4) > div > * { left: 1000px; }
+            .group > *:nth-child(5) > div > * { left: -1000px; }
+            .group > *:nth-child(6) > div > * { left: -9px; top: -10px; }
+            .group > *:nth-child(7) > div > * { left: 72px; }
+            .group > *:nth-child(8) > div > * { top: 72px; }
+            .group > *:nth-child(9) > div > * { left: -72px; }
+            .group > *:nth-child(10) > div > * { top: -72px; }
+            .group > *:nth-child(11) > div > * { left: 30px; top: 30px; }
+            .group > *:nth-child(12) > div > * { left: 18px; top: 54px; }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+            <div><div><img src="resources/circle-small.svg" type="image/svg+xml"></div></div>
+        </div>
+
+  </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-svg.html b/LayoutTests/fast/css/object-position-svg.html
new file mode 100644
index 0000000..a0dc98a
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-svg.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on SVG images</title>
+        <style type="text/css">
+            img {
+                object-fit: none;
+                width: 72px;
+                height: 144px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group { object-position: 30px 30px; }
+            .group > *:nth-child(1) { object-position: right top; }
+            .group > *:nth-child(2) { object-position: left bottom; }
+            .group > *:nth-child(3) { object-position: 10px 125%; }
+            .group > *:nth-child(4) { object-position: 200%; }
+            .group > *:nth-child(5) { object-position: -100%; }
+            .group > *:nth-child(6) { object-position: -25% -10px; }
+            .group > *:nth-child(7) { object-position: 72px 0px; }
+            .group > *:nth-child(8) { object-position: 0px 72px; }
+            .group > *:nth-child(9) { object-position: -72px 0px; }
+            .group > *:nth-child(10) { object-position: 0px -72px; }
+            .group > *:nth-child(11) { object-position: inherit; }
+            .group > *:nth-child(12) { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+            <img src="resources/circle-small.svg" type="image/svg+xml">
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-contain-expected.html b/LayoutTests/fast/css/object-position-with-fit-contain-expected.html
new file mode 100644
index 0000000..d7236d7
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-contain-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:contain</title>
+        <style type="text/css">
+            .group > div {
+                display: inline-block;
+                overflow: hidden;
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > div > div { overflow: hidden; height:100%; }
+            .group > div > div > * { display: block; width:72px; height:36px; }
+
+            .group > *:nth-child(1) > div > * { }
+            .group > *:nth-child(2) > div > * { margin-top: 36px; }
+            .group > *:nth-child(3) > div > * { margin-left: 10px; margin-top: 45px; }
+            .group > *:nth-child(4) > div > * { margin-top: 18px; }
+            .group > *:nth-child(5) > div > * { margin-top: 18px; }
+            .group > *:nth-child(6) > div > * { margin-top: -10px; }
+            .group > *:nth-child(7) > div > * { margin-top: 100px; }
+            .group > *:nth-child(8) > div > * { margin-top: 100px; }
+            .group > *:nth-child(9) > div > * { margin-top: 100px; }
+            .group > *:nth-child(10) > div > * { margin-top: 100px; }
+            .group > *:nth-child(11) > div > * { margin-left: 30px; margin-top: 30px; }
+            .group > *:nth-child(12) > div > * { margin-top: 18px; }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-contain.html b/LayoutTests/fast/css/object-position-with-fit-contain.html
new file mode 100644
index 0000000..e20046c
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-contain.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:contain</title>
+        <style type="text/css">
+            img {
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > * { object-fit: contain; }
+            .group { object-position: 30px 30px; }
+            .group > *:nth-child(1) { object-position: right top; }
+            .group > *:nth-child(2) { object-position: left bottom; }
+            .group > *:nth-child(3) { object-position: 10px 125%; }
+            .group > *:nth-child(4) { object-position: 200%; }
+            .group > *:nth-child(5) { object-position: -100%; }
+            .group > *:nth-child(6) { object-position: -25% -10px; }
+            .group > *:nth-child(7) { object-position: 72px 0px; }
+            .group > *:nth-child(8) { object-position: 0px 72px; }
+            .group > *:nth-child(9) { object-position: -72px 0px; }
+            .group > *:nth-child(10) { object-position: 0px -72px; }
+            .group > *:nth-child(11) { object-position: inherit; }
+            .group > *:nth-child(12) { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-cover-expected.html b/LayoutTests/fast/css/object-position-with-fit-cover-expected.html
new file mode 100644
index 0000000..a5c2d7e
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-cover-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:cover</title>
+        <style type="text/css">
+            .group > div {
+                display: inline-block;
+                overflow: hidden;
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > div > div { overflow: hidden; height:100%; }
+            .group > div > div > * { display: block; width:144px; height:72px; }
+
+            .group > *:nth-child(1) > div > * { margin-left:-72px;; }
+            .group > *:nth-child(2) > div > * { }
+            .group > *:nth-child(3) > div > * { margin-left: 10px; }
+            .group > *:nth-child(4) > div > * { margin-left: 300px; }
+            .group > *:nth-child(5) > div > * { margin-left: 300px; }
+            .group > *:nth-child(6) > div > * { margin-left: 18px; margin-top:-10px; }
+            .group > *:nth-child(7) > div > * { margin-left: 300px; }
+            .group > *:nth-child(8) > div > * { margin-left: 300px; }
+            .group > *:nth-child(9) > div > * { margin-left: -72px; }
+            .group > *:nth-child(10) > div > * { margin-left: 300px; }
+            .group > *:nth-child(11) > div > * { margin-left: 30px; margin-top:30px; }
+            .group > *:nth-child(12) > div > * { margin-left: -36px; }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+            <div><div><img src="resources/circles-landscape.png"></div></div>
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-cover.html b/LayoutTests/fast/css/object-position-with-fit-cover.html
new file mode 100644
index 0000000..d25d9f6
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-cover.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:cover</title>
+        <style type="text/css">
+            img {
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > * { object-fit: cover; }
+            .group { object-position: 30px 30px; }
+            .group > *:nth-child(1) { object-position: right top; }
+            .group > *:nth-child(2) { object-position: left bottom; }
+            .group > *:nth-child(3) { object-position: 10px 125%; }
+            .group > *:nth-child(4) { object-position: 200%; }
+            .group > *:nth-child(5) { object-position: -100%; }
+            .group > *:nth-child(6) { object-position: -25% -10px; }
+            .group > *:nth-child(7) { object-position: 72px 0px; }
+            .group > *:nth-child(8) { object-position: 0px 72px; }
+            .group > *:nth-child(9) { object-position: -72px 0px; }
+            .group > *:nth-child(10) { object-position: 0px -72px; }
+            .group > *:nth-child(11) { object-position: inherit; }
+            .group > *:nth-child(12) { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-none-expected.html b/LayoutTests/fast/css/object-position-with-fit-none-expected.html
new file mode 100644
index 0000000..6827484
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-none-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:none and smaller images</title>
+        <style type="text/css">
+            .group > div {
+                display: inline-block;
+                overflow: hidden;
+                width: 100px;
+                height: 100px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > div > div { overflow: hidden; height:100%; }
+            .group > div > div > * { display: block; width:72px; height:36px; }
+
+            .group > *:nth-child(1) > div > * { margin-left: 28px; }
+            .group > *:nth-child(2) > div > * { margin-top: 64px; }
+            .group > *:nth-child(3) > div > * { margin-left: 10px; margin-top: 80px; }
+            .group > *:nth-child(4) > div > * { margin-left: 56px; margin-top: 32px; }
+            .group > *:nth-child(5) > div > * { margin-left: -28px; margin-top: 32px; }
+            .group > *:nth-child(6) > div > * { margin-left: -7px; margin-top: -10px; }
+            .group > *:nth-child(7) > div > * { margin-left: 72px; }
+            .group > *:nth-child(8) > div > * { margin-top: 72px; }
+            .group > *:nth-child(9) > div > * { margin-left: 300px; }
+            .group > *:nth-child(10) > div > * { margin-left: 300px; }
+            .group > *:nth-child(11) > div > * { margin-left: 30px; margin-top: 30px; }
+            .group > *:nth-child(12) > div > * { margin-left: 14px; margin-top: 32px; }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+            <div><div><img src="resources/circles-landscape-small.png"></div></div>
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position-with-fit-none.html b/LayoutTests/fast/css/object-position-with-fit-none.html
new file mode 100644
index 0000000..0e5beae
--- /dev/null
+++ b/LayoutTests/fast/css/object-position-with-fit-none.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images with object-fit:none and smaller images</title>
+        <style type="text/css">
+            img {
+                width: 100px;
+                height: 100px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group > * { object-fit: none; }
+            .group { object-position: 30px 30px; }
+            .group > *:nth-child(1) { object-position: right top; }
+            .group > *:nth-child(2) { object-position: left bottom; }
+            .group > *:nth-child(3) { object-position: 10px 125%; }
+            .group > *:nth-child(4) { object-position: 200%; }
+            .group > *:nth-child(5) { object-position: -100%; }
+            .group > *:nth-child(6) { object-position: -25% -10px; }
+            .group > *:nth-child(7) { object-position: 72px 0px; }
+            .group > *:nth-child(8) { object-position: 0px 72px; }
+            .group > *:nth-child(9) { object-position: -72px 0px; }
+            .group > *:nth-child(10) { object-position: 0px -72px; }
+            .group > *:nth-child(11) { object-position: inherit; }
+            .group > *:nth-child(12) { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+            <img src="resources/circles-landscape-small.png">
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/object-position.html b/LayoutTests/fast/css/object-position.html
new file mode 100644
index 0000000..49221ae
--- /dev/null
+++ b/LayoutTests/fast/css/object-position.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>object-position on images</title>
+        <style type="text/css">
+            img {
+                width: 72px;
+                height: 72px;
+                margin: 2px 10px;
+                border: 1px solid black;
+                padding: 5px;
+                background-color: gray;
+            }
+
+            .group { object-position: 30px 30px; }
+            .group > *:nth-child(1) { object-position: right top; }
+            .group > *:nth-child(2) { object-position: left bottom; }
+            .group > *:nth-child(3) { object-position: 10px 125%; }
+            .group > *:nth-child(4) { object-position: 200%; }
+            .group > *:nth-child(5) { object-position: -100%; }
+            .group > *:nth-child(6) { object-position: -25% -10px; }
+            .group > *:nth-child(7) { object-position: 72px 0px; }
+            .group > *:nth-child(8) { object-position: 0px 72px; }
+            .group > *:nth-child(9) { object-position: -72px 0px; }
+            .group > *:nth-child(10) { object-position: 0px -72px; }
+            .group > *:nth-child(11) { object-position: inherit; }
+            .group > *:nth-child(12) { }
+        </style>
+    </head>
+    <body>
+
+        <div class="group">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+            <img src="resources/circles-landscape.png">
+        </div>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/parsing-object-position-expected.txt b/LayoutTests/fast/css/parsing-object-position-expected.txt
new file mode 100644
index 0000000..0fe3aef
--- /dev/null
+++ b/LayoutTests/fast/css/parsing-object-position-expected.txt
@@ -0,0 +1,52 @@
+This tests checks that all of the input values for object-position parse correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS testComputedStyle(";") is "50% 50%"
+PASS testComputedStyle("object-position: 10px;") is "10px 50%"
+PASS testComputedStyle("object-position: 10px 10px;") is "10px 10px"
+PASS testComputedStyle("object-position: right top;") is "100% 0%"
+PASS testComputedStyle("object-position: top right;") is "100% 0%"
+PASS test("object-position: inherit;") is "inherit"
+PASS test("object-position: initial;") is "initial"
+PASS test("object-position: left;") is "0% 50%"
+PASS test("object-position: top;") is "50% 0%"
+PASS test("object-position: top right;") is "100% 0%"
+PASS test("object-position: right top;") is "100% 0%"
+PASS test("object-position: center center;") is "50% 50%"
+PASS test("object-position: center;") is "50% 50%"
+PASS test("object-position: bottom center;") is "50% 100%"
+PASS test("object-position: left center;") is "0% 50%"
+PASS test("object-position: bottom center;") is "50% 100%"
+PASS test("object-position: center left;") is "0% 50%"
+PASS test("object-position: center bottom;") is "50% 100%"
+PASS test("object-position: 100px;") is "100px 50%"
+PASS test("object-position: 100px 100px;") is "100px 100px"
+PASS test("object-position: 100px 200px;") is "100px 200px"
+PASS test("object-position: -50% 0;") is "-50% 0px"
+PASS test("object-position: 3em 0;") is "3em 0px"
+PASS test("object-position: left 33px;") is "0% 33px"
+PASS test("object-position: center 33px;") is "50% 33px"
+PASS test("object-position: 33px center;") is "33px 50%"
+PASS test("object-position: 33px bottom;") is "33px 100%"
+PASS test("object-position: 1vh 1vw;") is "1vh 1vw"
+PASS test("object-position: 100px 100px 100px;") is null
+PASS test("object-position: 100px 100px 200px 200px;") is null
+PASS test("object-position: top left center;") is null
+PASS test("object-position: top top;") is null
+PASS test("object-position: top bottom;") is null
+PASS test("object-position: 33px left;") is null
+PASS test("object-position: top 33px;") is null
+PASS test("object-position: inherit inherit;") is null
+PASS test("object-position: initial initial;") is null
+PASS test("object-position: -webkit-fill-available;") is null
+PASS test("object-position: min-content;") is null
+PASS test("object-position: intrinsic;") is null
+PASS test("object-position: auto;") is null
+PASS test("object-position: none;") is null
+PASS test("object-position: fill;") is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css/parsing-object-position.html b/LayoutTests/fast/css/parsing-object-position.html
new file mode 100644
index 0000000..e6d9c9c
--- /dev/null
+++ b/LayoutTests/fast/css/parsing-object-position.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="../js/resources/js-test-pre.js"></script>
+    </head>
+    <body>
+        <script>
+            description("This tests checks that all of the input values for object-position parse correctly.");
+
+            function test(value)
+            {
+                var div = document.createElement("div");
+                div.setAttribute("style", value);
+                document.body.appendChild(div);
+
+                var result = div.style.getPropertyValue("object-position");
+                document.body.removeChild(div);
+                return result;
+            }
+
+            function testComputedStyle(value)
+            {
+                var div = document.createElement("div");
+                div.setAttribute("style", value);
+                document.body.appendChild(div);
+
+                var result = window.getComputedStyle(div).objectPosition;
+                document.body.removeChild(div);
+                return result;
+            }
+
+            shouldBeEqualToString('testComputedStyle(";")', '50% 50%');
+            shouldBeEqualToString('testComputedStyle("object-position: 10px;")', '10px 50%');
+            shouldBeEqualToString('testComputedStyle("object-position: 10px 10px;")', '10px 10px');
+            shouldBeEqualToString('testComputedStyle("object-position: right top;")', '100% 0%');
+            shouldBeEqualToString('testComputedStyle("object-position: top right;")', '100% 0%');
+
+            shouldBeEqualToString('test("object-position: inherit;")', 'inherit');
+            shouldBeEqualToString('test("object-position: initial;")', 'initial');
+            shouldBeEqualToString('test("object-position: left;")', '0% 50%');
+            shouldBeEqualToString('test("object-position: top;")', '50% 0%');
+            shouldBeEqualToString('test("object-position: top right;")', '100% 0%');
+            shouldBeEqualToString('test("object-position: right top;")', '100% 0%');
+            shouldBeEqualToString('test("object-position: center center;")', '50% 50%');
+            shouldBeEqualToString('test("object-position: center;")', '50% 50%');
+            shouldBeEqualToString('test("object-position: bottom center;")', '50% 100%');
+            shouldBeEqualToString('test("object-position: left center;")', '0% 50%');
+            shouldBeEqualToString('test("object-position: bottom center;")', '50% 100%');
+            shouldBeEqualToString('test("object-position: center left;")', '0% 50%');
+            shouldBeEqualToString('test("object-position: center bottom;")', '50% 100%');
+            shouldBeEqualToString('test("object-position: 100px;")', '100px 50%');
+            shouldBeEqualToString('test("object-position: 100px 100px;")', '100px 100px');
+            shouldBeEqualToString('test("object-position: 100px 200px;")', '100px 200px');
+            shouldBeEqualToString('test("object-position: -50% 0;")', '-50% 0px');
+            shouldBeEqualToString('test("object-position: 3em 0;")', '3em 0px');
+            shouldBeEqualToString('test("object-position: left 33px;")', '0% 33px');
+            shouldBeEqualToString('test("object-position: center 33px;")', '50% 33px');
+            shouldBeEqualToString('test("object-position: 33px center;")', '33px 50%');
+            shouldBeEqualToString('test("object-position: 33px bottom;")', '33px 100%');
+            shouldBeEqualToString('test("object-position: 1vh 1vw;")', '1vh 1vw');
+
+            shouldBeNull('test("object-position: 100px 100px 100px;")');
+            shouldBeNull('test("object-position: 100px 100px 200px 200px;")');
+            shouldBeNull('test("object-position: top left center;")');
+            shouldBeNull('test("object-position: top top;")');
+            shouldBeNull('test("object-position: top bottom;")');
+            shouldBeNull('test("object-position: 33px left;")');
+            shouldBeNull('test("object-position: top 33px;")');
+            shouldBeNull('test("object-position: inherit inherit;")');
+            shouldBeNull('test("object-position: initial initial;")');
+            shouldBeNull('test("object-position: -webkit-fill-available;")');
+            shouldBeNull('test("object-position: min-content;")');
+            shouldBeNull('test("object-position: intrinsic;")');
+            shouldBeNull('test("object-position: auto;")');
+            shouldBeNull('test("object-position: none;")');
+            shouldBeNull('test("object-position: fill;")');
+        </script>
+        <script src="../js/resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/css/resources/circle-small.svg b/LayoutTests/fast/css/resources/circle-small.svg
new file mode 100644
index 0000000..6a57207
--- /dev/null
+++ b/LayoutTests/fast/css/resources/circle-small.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
+              "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36">
+    <circle cx="50%" cy="50%" r="16" style="fill:blue;" />
+</svg>
diff --git a/LayoutTests/transitions/object-position-transition-expected.txt b/LayoutTests/transitions/object-position-transition-expected.txt
new file mode 100644
index 0000000..fecd178
--- /dev/null
+++ b/LayoutTests/transitions/object-position-transition-expected.txt
@@ -0,0 +1,2 @@
+PASS - "object-position" property for "box" element at 0.25s saw something close to: 25px 75px
+
diff --git a/LayoutTests/transitions/object-position-transition.html b/LayoutTests/transitions/object-position-transition.html
new file mode 100644
index 0000000..52ad86e
--- /dev/null
+++ b/LayoutTests/transitions/object-position-transition.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <title>Transitioning object-position</title>
+        <style>
+            #box {
+                width: 400px;
+                height: 400px;
+                object-position:-50px -50px;
+                transition-duration: 0.5s;
+                transition-timing-function: linear;
+                transition-property: object-position;
+            }
+        </style>
+        <script src="../animations/resources/animation-test-helpers.js"></script>
+        <script>
+            const expectedValues = [
+              // [time, element-id, property, expected-value, tolerance]
+              [0.25, 'box', 'object-position', "25px 75px", 10]
+            ];
+
+            function setupTest()
+            {
+                document.getElementById('box').style.objectPosition = "100px 200px";
+            }
+            runTransitionTest(expectedValues, setupTest);
+        </script>
+    </head>
+    <body>
+        <img id="box" src="../animations/resources/stripes-100.png">
+        <div id="result"></div>
+    </body>
+</html>
diff --git a/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt b/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
index b0c05cd..6ece2a1 100644
--- a/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
+++ b/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
@@ -155,6 +155,7 @@
 minZoom
 mixBlendMode
 objectFit
+objectPosition
 opacity
 order
 orientation
diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
index 9d4ef7b..6584765 100644
--- a/Source/core/animation/css/CSSAnimations.cpp
+++ b/Source/core/animation/css/CSSAnimations.cpp
@@ -320,6 +320,7 @@
     case CSSPropertyMaxWidth:
     case CSSPropertyMinHeight:
     case CSSPropertyMinWidth:
+    case CSSPropertyObjectPosition:
     case CSSPropertyOpacity:
     case CSSPropertyOrphans:
     case CSSPropertyOutlineColor:
diff --git a/Source/core/css/CSSComputedStyleDeclaration.cpp b/Source/core/css/CSSComputedStyleDeclaration.cpp
index 01985b62..37ef541 100644
--- a/Source/core/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -157,6 +157,8 @@
     CSSPropertyMinHeight,
     CSSPropertyMinWidth,
     CSSPropertyMixBlendMode,
+    CSSPropertyObjectFit,
+    CSSPropertyObjectPosition,
     CSSPropertyOpacity,
     CSSPropertyOrphans,
     CSSPropertyOutlineColor,
@@ -519,7 +521,7 @@
         verticalRepeat = horizontalRepeat;
     else
         verticalRepeat = cssValuePool().createIdentifierValue(valueForRepeatRule(image.verticalRule()));
-    return cssValuePool().createValue(Pair::create(horizontalRepeat.release(), verticalRepeat.release()));
+    return cssValuePool().createValue(Pair::create(horizontalRepeat.release(), verticalRepeat.release(), Pair::DropIdenticalValues));
 }
 
 static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, const RenderStyle* style)
@@ -2173,6 +2175,12 @@
             return zoomAdjustedPixelValueForLength(style->minWidth(), style.get());
         case CSSPropertyObjectFit:
             return cssValuePool().createValue(style->objectFit());
+        case CSSPropertyObjectPosition:
+            return cssValuePool().createValue(
+                Pair::create(
+                    cssValuePool().createValue(style->objectPosition().x()),
+                    cssValuePool().createValue(style->objectPosition().y()),
+                    Pair::KeepIdenticalValues));
         case CSSPropertyOpacity:
             return cssValuePool().createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
         case CSSPropertyOrphans:
diff --git a/Source/core/css/CSSParser-in.cpp b/Source/core/css/CSSParser-in.cpp
index 368a1f8..5074ae5 100644
--- a/Source/core/css/CSSParser-in.cpp
+++ b/Source/core/css/CSSParser-in.cpp
@@ -145,9 +145,9 @@
     return false;
 }
 
-static PassRefPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
+static PassRefPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, Pair::IdenticalValuesPolicy identicalValuesPolicy = Pair::DropIdenticalValues)
 {
-    return cssValuePool().createValue(Pair::create(first, second));
+    return cssValuePool().createValue(Pair::create(first, second, identicalValuesPolicy));
 }
 
 class AnimationParseContext {
@@ -2005,6 +2005,8 @@
         m_implicitShorthand = false;
         return result;
     }
+    case CSSPropertyObjectPosition:
+        return RuntimeEnabledFeatures::objectFitPositionEnabled() && parseObjectPosition(important);
     case CSSPropertyListStyleImage:     // <uri> | none | inherit
     case CSSPropertyBorderImageSource:
     case CSSPropertyWebkitMaskBoxImageSource:
@@ -6631,6 +6633,20 @@
     return true;
 }
 
+bool CSSParser::parseObjectPosition(bool important)
+{
+    RefPtr<CSSValue> xValue;
+    RefPtr<CSSValue> yValue;
+    parseFillPosition(m_valueList.get(), xValue, yValue);
+    if (!xValue || !yValue)
+        return false;
+    addProperty(
+        CSSPropertyObjectPosition,
+        createPrimitiveValuePair(toCSSPrimitiveValue(xValue.get()), toCSSPrimitiveValue(yValue.get()), Pair::KeepIdenticalValues),
+        important);
+    return true;
+}
+
 struct BorderImageParseContext {
     BorderImageParseContext()
     : m_canAdvance(false)
diff --git a/Source/core/css/CSSParser.h b/Source/core/css/CSSParser.h
index 6d0e270..a63df8f 100644
--- a/Source/core/css/CSSParser.h
+++ b/Source/core/css/CSSParser.h
@@ -239,6 +239,8 @@
 
     bool parseFlex(CSSParserValueList* args, bool important);
 
+    bool parseObjectPosition(bool important);
+
     // Image generators
     bool parseCanvas(CSSParserValueList*, RefPtr<CSSValue>&);
 
diff --git a/Source/core/css/CSSProperties.in b/Source/core/css/CSSProperties.in
index e5e682d..4bcc442 100644
--- a/Source/core/css/CSSProperties.in
+++ b/Source/core/css/CSSProperties.in
@@ -83,6 +83,7 @@
 min-width type_name=Length, initial=initialMinSize, converter=convertLengthSizing
 mix-blend-mode type_name=BlendMode, name_for_methods=BlendMode
 object-fit type_name=ObjectFit
+object-position type_name=LengthPoint, initial=initialObjectPosition, converter=convertLengthPoint
 opacity type_name=float
 order type_name=int
 orphans type_name=short, custom_all
diff --git a/Source/core/css/CSSProperty.cpp b/Source/core/css/CSSProperty.cpp
index 2272c4d..56e95f1 100644
--- a/Source/core/css/CSSProperty.cpp
+++ b/Source/core/css/CSSProperty.cpp
@@ -454,6 +454,7 @@
     case CSSPropertyMinWidth:
     case CSSPropertyMixBlendMode:
     case CSSPropertyObjectFit:
+    case CSSPropertyObjectPosition:
     case CSSPropertyOpacity:
     case CSSPropertyOutline:
     case CSSPropertyOutlineColor:
diff --git a/Source/core/css/CSSPropertyNames.in b/Source/core/css/CSSPropertyNames.in
index ca1bd3e..2f88d93 100644
--- a/Source/core/css/CSSPropertyNames.in
+++ b/Source/core/css/CSSPropertyNames.in
@@ -164,6 +164,7 @@
 outline-style
 outline-width
 object-fit
+object-position
 overflow
 overflow-wrap
 overflow-x
diff --git a/Source/core/css/Pair.h b/Source/core/css/Pair.h
index b4446b3..2c1940f 100644
--- a/Source/core/css/Pair.h
+++ b/Source/core/css/Pair.h
@@ -34,52 +34,69 @@
 // it (eliminating some extra -webkit- internal properties).
 class Pair : public RefCounted<Pair> {
 public:
+    enum IdenticalValuesPolicy { DropIdenticalValues, KeepIdenticalValues };
+
     static PassRefPtr<Pair> create()
     {
         return adoptRef(new Pair);
     }
-    static PassRefPtr<Pair> create(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
+    static PassRefPtr<Pair> create(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, IdenticalValuesPolicy identicalValuesPolicy)
     {
-        return adoptRef(new Pair(first, second));
+        return adoptRef(new Pair(first, second, identicalValuesPolicy));
     }
     virtual ~Pair() { }
 
     CSSPrimitiveValue* first() const { return m_first.get(); }
     CSSPrimitiveValue* second() const { return m_second.get(); }
+    IdenticalValuesPolicy identicalValuesPolicy() const { return m_identicalValuesPolicy; }
 
     void setFirst(PassRefPtr<CSSPrimitiveValue> first) { m_first = first; }
     void setSecond(PassRefPtr<CSSPrimitiveValue> second) { m_second = second; }
+    void setIdenticalValuesPolicy(IdenticalValuesPolicy identicalValuesPolicy) { m_identicalValuesPolicy = identicalValuesPolicy; }
 
     String cssText() const
     {
-
-        return generateCSSString(first()->cssText(), second()->cssText());
+        return generateCSSString(first()->cssText(), second()->cssText(), m_identicalValuesPolicy);
     }
 
-    bool equals(const Pair& other) const { return compareCSSValuePtr(m_first, other.m_first) && compareCSSValuePtr(m_second, other.m_second); }
+    bool equals(const Pair& other) const
+    {
+        return compareCSSValuePtr(m_first, other.m_first)
+            && compareCSSValuePtr(m_second, other.m_second)
+            && m_identicalValuesPolicy == other.m_identicalValuesPolicy;
+    }
 
     String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
     {
-        return generateCSSString(first()->customSerializeResolvingVariables(variables),
-                                 second()->customSerializeResolvingVariables(variables));
+        return generateCSSString(
+            first()->customSerializeResolvingVariables(variables),
+            second()->customSerializeResolvingVariables(variables),
+            m_identicalValuesPolicy);
     }
 
     bool hasVariableReference() const { return first()->hasVariableReference() || second()->hasVariableReference(); }
 
 private:
-    Pair() : m_first(0), m_second(0) { }
-    Pair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
-        : m_first(first), m_second(second) { }
+    Pair()
+        : m_first(0)
+        , m_second(0)
+        , m_identicalValuesPolicy(DropIdenticalValues) { }
 
-    static String generateCSSString(const String& first, const String& second)
+    Pair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, IdenticalValuesPolicy identicalValuesPolicy)
+        : m_first(first)
+        , m_second(second)
+        , m_identicalValuesPolicy(identicalValuesPolicy) { }
+
+    static String generateCSSString(const String& first, const String& second, IdenticalValuesPolicy identicalValuesPolicy)
     {
-        if (first == second)
+        if (identicalValuesPolicy == DropIdenticalValues && first == second)
             return first;
         return first + ' ' + second;
     }
 
     RefPtr<CSSPrimitiveValue> m_first;
     RefPtr<CSSPrimitiveValue> m_second;
+    IdenticalValuesPolicy m_identicalValuesPolicy;
 };
 
 } // namespace
diff --git a/Source/core/css/resolver/StyleBuilderCustom.cpp b/Source/core/css/resolver/StyleBuilderCustom.cpp
index 880e4c1..5f05eca 100644
--- a/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -870,6 +870,15 @@
     return convertLengthSizing(state, value);
 }
 
+LengthPoint StyleBuilderConverter::convertLengthPoint(StyleResolverState& state, CSSValue* value)
+{
+    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+    Pair* pair = primitiveValue->getPairValue();
+    Length x = pair->first()->convertToLength<FixedIntegerConversion | PercentConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
+    Length y = pair->second()->convertToLength<FixedIntegerConversion | PercentConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
+    return LengthPoint(x, y);
+}
+
 LengthSize StyleBuilderConverter::convertRadius(StyleResolverState& state, CSSValue* value)
 {
     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
@@ -1444,6 +1453,7 @@
     case CSSPropertyBorderWidth:
     case CSSPropertyListStyle:
     case CSSPropertyMargin:
+    case CSSPropertyObjectPosition:
     case CSSPropertyOutline:
     case CSSPropertyOverflow:
     case CSSPropertyPadding:
diff --git a/Source/core/css/resolver/StyleBuilderCustom.h b/Source/core/css/resolver/StyleBuilderCustom.h
index 2496b3b..597c501 100644
--- a/Source/core/css/resolver/StyleBuilderCustom.h
+++ b/Source/core/css/resolver/StyleBuilderCustom.h
@@ -44,6 +44,7 @@
     static Length convertLengthOrAuto(StyleResolverState&, CSSValue*);
     static Length convertLengthSizing(StyleResolverState&, CSSValue*);
     static Length convertLengthMaxSizing(StyleResolverState&, CSSValue*);
+    static LengthPoint convertLengthPoint(StyleResolverState&, CSSValue*);
     static LengthSize convertRadius(StyleResolverState&, CSSValue*);
     static float convertSpacing(StyleResolverState&, CSSValue*);
     template <CSSValueID IdForNone> static AtomicString convertString(StyleResolverState&, CSSValue*);
diff --git a/Source/core/page/RuntimeCSSEnabled.cpp b/Source/core/page/RuntimeCSSEnabled.cpp
index 715fdf2..42934b3 100644
--- a/Source/core/page/RuntimeCSSEnabled.cpp
+++ b/Source/core/page/RuntimeCSSEnabled.cpp
@@ -92,6 +92,11 @@
         CSSPropertyGridTemplate
     };
     setCSSPropertiesEnabled(cssGridLayoutProperties, WTF_ARRAY_LENGTH(cssGridLayoutProperties), RuntimeEnabledFeatures::cssGridLayoutEnabled());
+    CSSPropertyID cssObjectFitPositionProperties[] = {
+        CSSPropertyObjectFit,
+        CSSPropertyObjectPosition
+    };
+    setCSSPropertiesEnabled(cssObjectFitPositionProperties, WTF_ARRAY_LENGTH(cssObjectFitPositionProperties), RuntimeEnabledFeatures::objectFitPositionEnabled());
 
     CSSPropertyID animationProperties[] = {
         CSSPropertyAnimation,
@@ -112,7 +117,6 @@
     RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyTouchAction, RuntimeEnabledFeatures::cssTouchActionEnabled());
     RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyPaintOrder, RuntimeEnabledFeatures::svgPaintOrderEnabled());
     RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyVariable, RuntimeEnabledFeatures::cssVariablesEnabled());
-    RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyObjectFit, RuntimeEnabledFeatures::objectFitPositionEnabled());
     RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyMaskSourceType, RuntimeEnabledFeatures::cssMaskSourceTypeEnabled());
 }
 
diff --git a/Source/core/page/UseCounter.cpp b/Source/core/page/UseCounter.cpp
index 780f009..652e04e6 100644
--- a/Source/core/page/UseCounter.cpp
+++ b/Source/core/page/UseCounter.cpp
@@ -496,6 +496,7 @@
     case CSSPropertyPaintOrder: return 434;
     case CSSPropertyMaskSourceType: return 435;
     case CSSPropertyIsolation: return 436;
+    case CSSPropertyObjectPosition: return 437;
 
     // Add new features above this line (don't change the assigned numbers of the existing
     // items) and update maximumCSSSampleId() with the new maximum value.
@@ -510,7 +511,7 @@
     return 0;
 }
 
-static int maximumCSSSampleId() { return 434; }
+static int maximumCSSSampleId() { return 437; }
 
 UseCounter::UseCounter()
 {
diff --git a/Source/core/page/animation/CSSPropertyAnimation.cpp b/Source/core/page/animation/CSSPropertyAnimation.cpp
index 5b31b8c..4f5ab98 100644
--- a/Source/core/page/animation/CSSPropertyAnimation.cpp
+++ b/Source/core/page/animation/CSSPropertyAnimation.cpp
@@ -85,6 +85,11 @@
                       blendFunc(anim, from.height(), to.height(), progress));
 }
 
+static inline LengthPoint blendFunc(const AnimationBase* anim, const LengthPoint& from, const LengthPoint& to, double progress)
+{
+    return LengthPoint(blendFunc(anim, from.x(), to.x(), progress), blendFunc(anim, from.y(), to.y(), progress));
+}
+
 static inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from, const IntSize& to, double progress)
 {
     return IntSize(blendFunc(anim, from.width(), to.width(), progress),
@@ -1110,6 +1115,8 @@
     gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
     gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
 
+    gPropertyWrappers->append(new PropertyWrapper<LengthPoint>(CSSPropertyObjectPosition, &RenderStyle::objectPosition, &RenderStyle::setObjectPosition));
+
     gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFontSize,
         // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size
         // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
diff --git a/Source/core/platform/LengthPoint.h b/Source/core/platform/LengthPoint.h
new file mode 100644
index 0000000..151a852
--- /dev/null
+++ b/Source/core/platform/LengthPoint.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, Opera Software ASA. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Opera Software ASA nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LengthPoint_h
+#define LengthPoint_h
+
+#include "core/platform/Length.h"
+
+namespace WebCore {
+
+struct LengthPoint {
+public:
+    LengthPoint()
+    {
+    }
+
+    LengthPoint(Length x, Length y)
+        : m_x(x)
+        , m_y(y)
+    {
+    }
+
+    bool operator==(const LengthPoint& o) const { return m_x == o.m_x && m_y == o.m_y; }
+    bool operator!=(const LengthPoint& o) const { return m_x != o.m_x || m_y != o.m_y; }
+
+    void setX(Length x) { m_x = x; }
+    Length x() const { return m_x; }
+
+    void setY(Length y) { m_y = y; }
+    Length y() const { return m_y; }
+
+private:
+    Length m_x;
+    Length m_y;
+};
+
+} // namespace WebCore
+
+#endif // LengthPoint_h
diff --git a/Source/core/rendering/RenderImage.cpp b/Source/core/rendering/RenderImage.cpp
index e622c9c..8a2c637 100644
--- a/Source/core/rendering/RenderImage.cpp
+++ b/Source/core/rendering/RenderImage.cpp
@@ -517,6 +517,9 @@
     // Background shows in padding area.
     if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
         return false;
+    // Object-position may leave parts of the content box empty, regardless of the value of object-fit.
+    if (style()->objectPosition() != RenderStyle::initialObjectPosition())
+        return false;
     // Object-fit may leave parts of the content box empty.
     ObjectFit objectFit = style()->objectFit();
     if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
diff --git a/Source/core/rendering/RenderReplaced.cpp b/Source/core/rendering/RenderReplaced.cpp
index 900fa7d..f83db58 100644
--- a/Source/core/rendering/RenderReplaced.cpp
+++ b/Source/core/rendering/RenderReplaced.cpp
@@ -316,7 +316,7 @@
     LayoutRect contentRect = contentBoxRect();
     ObjectFit objectFit = style()->objectFit();
 
-    if (objectFit == ObjectFitFill) {
+    if (objectFit == ObjectFitFill && style()->objectPosition() == RenderStyle::initialObjectPosition()) {
         if (!isVideo() || RuntimeEnabledFeatures::objectFitPositionEnabled())
             return contentRect;
         objectFit = ObjectFitContain;
@@ -339,13 +339,13 @@
         finalRect.setSize(intrinsicSize);
         break;
     case ObjectFitFill:
+        break;
+    default:
         ASSERT_NOT_REACHED();
     }
 
-    // FIXME: This is where object-position should be taken into account, but since it's not
-    // implemented yet, assume the initial value of "50% 50%".
-    LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2;
-    LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2;
+    LayoutUnit xOffset = minimumValueForLength(style()->objectPosition().x(), contentRect.width() - finalRect.width(), view());
+    LayoutUnit yOffset = minimumValueForLength(style()->objectPosition().y(), contentRect.height() - finalRect.height(), view());
     finalRect.move(xOffset, yOffset);
 
     return finalRect;
diff --git a/Source/core/rendering/style/RenderStyle.cpp b/Source/core/rendering/style/RenderStyle.cpp
index 9f4b8dd..ece4c74 100644
--- a/Source/core/rendering/style/RenderStyle.cpp
+++ b/Source/core/rendering/style/RenderStyle.cpp
@@ -663,6 +663,7 @@
         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
         || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
+        || rareNonInheritedData->m_objectPosition != other->rareNonInheritedData->m_objectPosition
         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
         return StyleDifferenceRepaint;
 
diff --git a/Source/core/rendering/style/RenderStyle.h b/Source/core/rendering/style/RenderStyle.h
index 2c26814..ce0e752 100644
--- a/Source/core/rendering/style/RenderStyle.h
+++ b/Source/core/rendering/style/RenderStyle.h
@@ -829,6 +829,7 @@
     TextOrientation textOrientation() const { return static_cast<TextOrientation>(rareInheritedData->m_textOrientation); }
 
     ObjectFit objectFit() const { return static_cast<ObjectFit>(rareNonInheritedData->m_objectFit); }
+    LengthPoint objectPosition() const { return rareNonInheritedData->m_objectPosition; }
 
     // Return true if any transform related property (currently transform, transformStyle3D or perspective)
     // indicates that we are transforming
@@ -1267,6 +1268,7 @@
     bool setTextOrientation(TextOrientation);
 
     void setObjectFit(ObjectFit f) { SET_VAR(rareNonInheritedData, m_objectFit, f); }
+    void setObjectPosition(LengthPoint position) { SET_VAR(rareNonInheritedData, m_objectPosition, position); }
 
     void setRubyPosition(RubyPosition position) { SET_VAR(rareInheritedData, m_rubyPosition, position); }
 
@@ -1477,6 +1479,7 @@
     static TextCombine initialTextCombine() { return TextCombineNone; }
     static TextOrientation initialTextOrientation() { return TextOrientationVerticalRight; }
     static ObjectFit initialObjectFit() { return ObjectFitFill; }
+    static LengthPoint initialObjectPosition() { return LengthPoint(Length(50.0, Percent), Length(50.0, Percent)); }
     static EDisplay initialDisplay() { return INLINE; }
     static EEmptyCell initialEmptyCells() { return SHOW; }
     static EFloat initialFloating() { return NoFloat; }
diff --git a/Source/core/rendering/style/StyleRareNonInheritedData.cpp b/Source/core/rendering/style/StyleRareNonInheritedData.cpp
index a821778..5428546 100644
--- a/Source/core/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/core/rendering/style/StyleRareNonInheritedData.cpp
@@ -48,6 +48,7 @@
     , m_clipPath(RenderStyle::initialClipPath())
     , m_visitedLinkBackgroundColor(RenderStyle::initialBackgroundColor())
     , m_order(RenderStyle::initialOrder())
+    , m_objectPosition(RenderStyle::initialObjectPosition())
     , m_flowThread(RenderStyle::initialFlowThread())
     , m_regionThread(RenderStyle::initialRegionThread())
     , m_regionFragment(RenderStyle::initialRegionFragment())
@@ -122,6 +123,7 @@
     , m_visitedLinkBorderTopColor(o.m_visitedLinkBorderTopColor)
     , m_visitedLinkBorderBottomColor(o.m_visitedLinkBorderBottomColor)
     , m_order(o.m_order)
+    , m_objectPosition(o.m_objectPosition)
     , m_flowThread(o.m_flowThread)
     , m_regionThread(o.m_regionThread)
     , m_regionFragment(o.m_regionFragment)
@@ -199,6 +201,7 @@
         && m_visitedLinkBorderTopColor == o.m_visitedLinkBorderTopColor
         && m_visitedLinkBorderBottomColor == o.m_visitedLinkBorderBottomColor
         && m_order == o.m_order
+        && m_objectPosition == o.m_objectPosition
         && m_flowThread == o.m_flowThread
         && m_regionThread == o.m_regionThread
         && m_regionFragment == o.m_regionFragment
diff --git a/Source/core/rendering/style/StyleRareNonInheritedData.h b/Source/core/rendering/style/StyleRareNonInheritedData.h
index aae823a..eadba19 100644
--- a/Source/core/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/core/rendering/style/StyleRareNonInheritedData.h
@@ -25,6 +25,7 @@
 #ifndef StyleRareNonInheritedData_h
 #define StyleRareNonInheritedData_h
 
+#include "core/platform/LengthPoint.h"
 #include "core/rendering/ClipPathOperation.h"
 #include "core/rendering/style/BasicShapes.h"
 #include "core/rendering/style/CounterDirectives.h"
@@ -143,6 +144,8 @@
 
     int m_order;
 
+    LengthPoint m_objectPosition;
+
     AtomicString m_flowThread;
     AtomicString m_regionThread;
     unsigned m_regionFragment : 1; // RegionFragment