Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: Source/core/paint/BoxPainter.cpp

Issue 1164573003: Move NinePieceImage painting to a separate class (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "core/paint/BoxPainter.h" 6 #include "core/paint/BoxPainter.h"
7 7
8 #include "core/HTMLNames.h" 8 #include "core/HTMLNames.h"
9 #include "core/frame/Settings.h" 9 #include "core/frame/Settings.h"
10 #include "core/html/HTMLFrameOwnerElement.h" 10 #include "core/html/HTMLFrameOwnerElement.h"
11 #include "core/layout/ImageQualityController.h" 11 #include "core/layout/ImageQualityController.h"
12 #include "core/layout/LayoutBox.h" 12 #include "core/layout/LayoutBox.h"
13 #include "core/layout/LayoutBoxModelObject.h" 13 #include "core/layout/LayoutBoxModelObject.h"
14 #include "core/layout/LayoutObject.h" 14 #include "core/layout/LayoutObject.h"
15 #include "core/layout/LayoutTable.h" 15 #include "core/layout/LayoutTable.h"
16 #include "core/layout/LayoutTheme.h" 16 #include "core/layout/LayoutTheme.h"
17 #include "core/layout/LayoutView.h" 17 #include "core/layout/LayoutView.h"
18 #include "core/layout/compositing/CompositedDeprecatedPaintLayerMapping.h" 18 #include "core/layout/compositing/CompositedDeprecatedPaintLayerMapping.h"
19 #include "core/style/BorderEdge.h" 19 #include "core/style/BorderEdge.h"
20 #include "core/style/ShadowList.h" 20 #include "core/style/ShadowList.h"
21 #include "core/paint/BackgroundImageGeometry.h" 21 #include "core/paint/BackgroundImageGeometry.h"
22 #include "core/paint/BoxDecorationData.h" 22 #include "core/paint/BoxDecorationData.h"
23 #include "core/paint/DeprecatedPaintLayer.h" 23 #include "core/paint/DeprecatedPaintLayer.h"
24 #include "core/paint/LayoutObjectDrawingRecorder.h" 24 #include "core/paint/LayoutObjectDrawingRecorder.h"
25 #include "core/paint/NinePieceImagePainter.h"
25 #include "core/paint/PaintInfo.h" 26 #include "core/paint/PaintInfo.h"
26 #include "core/paint/RoundedInnerRectClipper.h" 27 #include "core/paint/RoundedInnerRectClipper.h"
27 #include "core/paint/ThemePainter.h" 28 #include "core/paint/ThemePainter.h"
28 #include "platform/LengthFunctions.h" 29 #include "platform/LengthFunctions.h"
29 #include "platform/geometry/LayoutPoint.h" 30 #include "platform/geometry/LayoutPoint.h"
30 #include "platform/geometry/LayoutRectOutsets.h" 31 #include "platform/geometry/LayoutRectOutsets.h"
31 #include "platform/graphics/GraphicsContextStateSaver.h" 32 #include "platform/graphics/GraphicsContextStateSaver.h"
32 #include "platform/graphics/paint/CompositingDisplayItem.h" 33 #include "platform/graphics/paint/CompositingDisplayItem.h"
33 34
34 namespace blink { 35 namespace blink {
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicS ize.height() : 1; 938 ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicS ize.height() : 1;
938 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor); 939 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor);
939 return IntSize(std::max(1l, lround(imageIntrinsicSize.width() * scaleFac tor)), std::max(1l, lround(imageIntrinsicSize.height() * scaleFactor))); 940 return IntSize(std::max(1l, lround(imageIntrinsicSize.width() * scaleFac tor)), std::max(1l, lround(imageIntrinsicSize.height() * scaleFactor)));
940 } 941 }
941 } 942 }
942 943
943 ASSERT_NOT_REACHED(); 944 ASSERT_NOT_REACHED();
944 return IntSize(); 945 return IntSize();
945 } 946 }
946 947
947 static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, L ayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent)
948 {
949 if (borderSlice.isNumber())
950 return borderSlice.number() * borderSide;
951 if (borderSlice.length().isAuto())
952 return imageSide;
953 return valueForLength(borderSlice.length(), boxExtent);
954 }
955
956 bool BoxPainter::paintNinePieceImage(LayoutBoxModelObject& obj, GraphicsContext* graphicsContext, const LayoutRect& rect, const ComputedStyle& style, const Nine PieceImage& ninePieceImage, SkXfermode::Mode op) 948 bool BoxPainter::paintNinePieceImage(LayoutBoxModelObject& obj, GraphicsContext* graphicsContext, const LayoutRect& rect, const ComputedStyle& style, const Nine PieceImage& ninePieceImage, SkXfermode::Mode op)
957 { 949 {
958 StyleImage* styleImage = ninePieceImage.image(); 950 NinePieceImagePainter ninePieceImagePainter(obj);
959 if (!styleImage) 951 return ninePieceImagePainter.paint(graphicsContext, rect, style, ninePieceIm age, op);
960 return false;
961
962 if (!styleImage->isLoaded())
963 return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
964
965 if (!styleImage->canRender(obj, style.effectiveZoom()))
966 return false;
967
968 // FIXME: border-image is broken with full page zooming when tiling has to h appen, since the tiling function
969 // doesn't have any understanding of the zoom that is in effect on the tile.
970 LayoutRect rectWithOutsets = rect;
971 rectWithOutsets.expand(style.imageOutsets(ninePieceImage));
972 IntRect borderImageRect = pixelSnappedIntRect(rectWithOutsets);
973
974 IntSize imageSize = obj.calculateImageIntrinsicDimensions(styleImage, border ImageRect.size(), LayoutBoxModelObject::DoNotScaleByEffectiveZoom);
975
976 // If both values are 'auto' then the intrinsic width and/or height of the i mage should be used, if any.
977 styleImage->setContainerSizeForLayoutObject(&obj, imageSize, style.effective Zoom());
978
979 int imageWidth = imageSize.width();
980 int imageHeight = imageSize.height();
981
982 float imageScaleFactor = styleImage->imageScaleFactor();
983 int topSlice = std::min<int>(imageHeight, valueForLength(ninePieceImage.imag eSlices().top(), imageHeight)) * imageScaleFactor;
984 int rightSlice = std::min<int>(imageWidth, valueForLength(ninePieceImage.ima geSlices().right(), imageWidth)) * imageScaleFactor;
985 int bottomSlice = std::min<int>(imageHeight, valueForLength(ninePieceImage.i mageSlices().bottom(), imageHeight)) * imageScaleFactor;
986 int leftSlice = std::min<int>(imageWidth, valueForLength(ninePieceImage.imag eSlices().left(), imageWidth)) * imageScaleFactor;
987
988 ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
989 ENinePieceImageRule vRule = ninePieceImage.verticalRule();
990
991 int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), s tyle.borderTopWidth(), topSlice, borderImageRect.height());
992 int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right( ), style.borderRightWidth(), rightSlice, borderImageRect.width());
993 int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().botto m(), style.borderBottomWidth(), bottomSlice, borderImageRect.height());
994 int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style.borderLeftWidth(), leftSlice, borderImageRect.width());
995
996 // Reduce the widths if they're too large.
997 // The spec says: Given Lwidth as the width of the border image area, Lheigh t as its height, and Wside as the border image width
998 // offset for the side, let f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbo ttom)). If f < 1, then all W are reduced by
999 // multiplying them by f.
1000 int borderSideWidth = std::max(1, leftWidth + rightWidth);
1001 int borderSideHeight = std::max(1, topWidth + bottomWidth);
1002 float borderSideScaleFactor = std::min((float)borderImageRect.width() / bord erSideWidth, (float)borderImageRect.height() / borderSideHeight);
1003 if (borderSideScaleFactor < 1) {
1004 topWidth *= borderSideScaleFactor;
1005 rightWidth *= borderSideScaleFactor;
1006 bottomWidth *= borderSideScaleFactor;
1007 leftWidth *= borderSideScaleFactor;
1008 }
1009
1010 bool drawLeft = leftSlice > 0 && leftWidth > 0;
1011 bool drawTop = topSlice > 0 && topWidth > 0;
1012 bool drawRight = rightSlice > 0 && rightWidth > 0;
1013 bool drawBottom = bottomSlice > 0 && bottomWidth > 0;
1014 bool drawMiddle = ninePieceImage.fill() && (imageWidth - leftSlice - rightSl ice) > 0 && (borderImageRect.width() - leftWidth - rightWidth) > 0
1015 && (imageHeight - topSlice - bottomSlice) > 0 && (borderImageRect.height () - topWidth - bottomWidth) > 0;
1016
1017 RefPtr<Image> image = styleImage->image(&obj, imageSize);
1018
1019 float destinationWidth = borderImageRect.width() - leftWidth - rightWidth;
1020 float destinationHeight = borderImageRect.height() - topWidth - bottomWidth;
1021
1022 float sourceWidth = imageWidth - leftSlice - rightSlice;
1023 float sourceHeight = imageHeight - topSlice - bottomSlice;
1024
1025 float leftSideScale = drawLeft ? (float)leftWidth / leftSlice : 1;
1026 float rightSideScale = drawRight ? (float)rightWidth / rightSlice : 1;
1027 float topSideScale = drawTop ? (float)topWidth / topSlice : 1;
1028 float bottomSideScale = drawBottom ? (float)bottomWidth / bottomSlice : 1;
1029
1030 InterpolationQuality interpolationQuality = chooseInterpolationQuality(obj, graphicsContext, image.get(), 0, rectWithOutsets.size());
1031 InterpolationQuality previousInterpolationQuality = graphicsContext->imageIn terpolationQuality();
1032 graphicsContext->setImageInterpolationQuality(interpolationQuality);
1033
1034 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", " data", InspectorPaintImageEvent::data(obj, *styleImage));
1035 if (drawLeft) {
1036 // Paint the top and bottom left corners.
1037
1038 // The top left corner rect is (tx, ty, leftWidth, topWidth)
1039 // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
1040 if (drawTop) {
1041 graphicsContext->drawImage(image.get(), IntRect(borderImageRect.loca tion(), IntSize(leftWidth, topWidth)),
1042 LayoutRect(0, 0, leftSlice, topSlice), op);
1043 }
1044
1045 // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
1046 // The rect to use from within the image is (0, imageHeight - bottomSlic e, leftSlice, botomSlice)
1047 if (drawBottom) {
1048 graphicsContext->drawImage(image.get(), IntRect(borderImageRect.x(), borderImageRect.maxY() - bottomWidth, leftWidth, bottomWidth),
1049 LayoutRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice) , op);
1050 }
1051
1052 // Paint the left edge.
1053 // Have to scale and tile into the border rect.
1054 if (sourceHeight > 0) {
1055 graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect .x(), borderImageRect.y() + topWidth, leftWidth, destinationHeight),
1056 IntRect(0, topSlice, leftSlice, sourceHeight), FloatSize(leftSid eScale, leftSideScale), Image::StretchTile, (Image::TileRule)vRule, op);
1057 }
1058 }
1059
1060 if (drawRight) {
1061 // Paint the top and bottom right corners
1062 // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, to pWidth)
1063 // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
1064 if (drawTop) {
1065 graphicsContext->drawImage(image.get(), IntRect(borderImageRect.maxX () - rightWidth, borderImageRect.y(), rightWidth, topWidth),
1066 LayoutRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op );
1067 }
1068
1069 // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottom Width, rightWidth, bottomWidth)
1070 // The rect to use from within the image is (imageWidth - rightSlice, im ageHeight - bottomSlice, rightSlice, bottomSlice)
1071 if (drawBottom) {
1072 graphicsContext->drawImage(image.get(), IntRect(borderImageRect.maxX () - rightWidth, borderImageRect.maxY() - bottomWidth, rightWidth, bottomWidth),
1073 LayoutRect(imageWidth - rightSlice, imageHeight - bottomSlice, r ightSlice, bottomSlice), op);
1074 }
1075
1076 // Paint the right edge.
1077 if (sourceHeight > 0) {
1078 graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect .maxX() - rightWidth, borderImageRect.y() + topWidth, rightWidth,
1079 destinationHeight),
1080 IntRect(imageWidth - rightSlice, topSlice, rightSlice, sourceHei ght),
1081 FloatSize(rightSideScale, rightSideScale),
1082 Image::StretchTile, (Image::TileRule)vRule, op);
1083 }
1084 }
1085
1086 // Paint the top edge.
1087 if (drawTop && sourceWidth > 0) {
1088 graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.x() + leftWidth, borderImageRect.y(), destinationWidth, topWidth),
1089 IntRect(leftSlice, 0, sourceWidth, topSlice),
1090 FloatSize(topSideScale, topSideScale), (Image::TileRule)hRule, Image ::StretchTile, op);
1091 }
1092
1093 // Paint the bottom edge.
1094 if (drawBottom && sourceWidth > 0) {
1095 graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.x() + leftWidth, borderImageRect.maxY() - bottomWidth,
1096 destinationWidth, bottomWidth),
1097 IntRect(leftSlice, imageHeight - bottomSlice, sourceWidth, bottomSli ce),
1098 FloatSize(bottomSideScale, bottomSideScale),
1099 (Image::TileRule)hRule, Image::StretchTile, op);
1100 }
1101
1102 // Paint the middle.
1103 if (drawMiddle) {
1104 FloatSize middleScaleFactor(1, 1);
1105 if (drawTop)
1106 middleScaleFactor.setWidth(topSideScale);
1107 else if (drawBottom)
1108 middleScaleFactor.setWidth(bottomSideScale);
1109 if (drawLeft)
1110 middleScaleFactor.setHeight(leftSideScale);
1111 else if (drawRight)
1112 middleScaleFactor.setHeight(rightSideScale);
1113
1114 // For "stretch" rules, just override the scale factor and replace. We o nly had to do this for the
1115 // center tile, since sides don't even use the scale factor unless they have a rule other than "stretch".
1116 // The middle however can have "stretch" specified in one axis but not t he other, so we have to
1117 // correct the scale here.
1118 if (hRule == StretchImageRule)
1119 middleScaleFactor.setWidth(destinationWidth / sourceWidth);
1120
1121 if (vRule == StretchImageRule)
1122 middleScaleFactor.setHeight(destinationHeight / sourceHeight);
1123
1124 graphicsContext->drawTiledImage(image.get(),
1125 IntRect(borderImageRect.x() + leftWidth, borderImageRect.y() + topWi dth, destinationWidth, destinationHeight),
1126 IntRect(leftSlice, topSlice, sourceWidth, sourceHeight),
1127 middleScaleFactor, (Image::TileRule)hRule, (Image::TileRule)vRule, o p);
1128 }
1129 graphicsContext->setImageInterpolationQuality(previousInterpolationQuality);
1130 return true;
1131 } 952 }
1132 953
1133 static FloatRect calculateSideRect(const FloatRoundedRect& outerBorder, const Bo rderEdge& edge, int side) 954 static FloatRect calculateSideRect(const FloatRoundedRect& outerBorder, const Bo rderEdge& edge, int side)
1134 { 955 {
1135 FloatRect sideRect = outerBorder.rect(); 956 FloatRect sideRect = outerBorder.rect();
1136 int width = edge.width; 957 int width = edge.width;
1137 958
1138 if (side == BSTop) 959 if (side == BSTop)
1139 sideRect.setHeight(width); 960 sideRect.setHeight(width);
1140 else if (side == BSBottom) 961 else if (side == BSBottom)
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 2119
2299 FloatPoint secondQuad[4]; 2120 FloatPoint secondQuad[4];
2300 secondQuad[0] = quad[0]; 2121 secondQuad[0] = quad[0];
2301 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); 2122 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy);
2302 secondQuad[2] = quad[2]; 2123 secondQuad[2] = quad[2];
2303 secondQuad[3] = quad[3]; 2124 secondQuad[3] = quad[3];
2304 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches); 2125 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches);
2305 } 2126 }
2306 2127
2307 } // namespace blink 2128 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698