File: BoxShadowOutsetRenderer.js

package info (click to toggle)
css3pie 1.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 564 kB
  • sloc: xml: 104; makefile: 2; php: 2
file content (136 lines) | stat: -rw-r--r-- 6,157 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
 * Renderer for outset box-shadows
 * @constructor
 * @param {Element} el The target element
 * @param {Object} styleInfos The StyleInfo objects
 * @param {PIE.RootRenderer} parent
 */
PIE.BoxShadowOutsetRenderer = PIE.RendererBase.newRenderer( {

    boxZIndex: 1,
    boxName: 'outset-box-shadow',

    needsUpdate: function() {
        var si = this.styleInfos;
        return si.boxShadowInfo.changed() || si.borderRadiusInfo.changed();
    },

    isActive: function() {
        var boxShadowInfo = this.styleInfos.boxShadowInfo;
        return boxShadowInfo.isActive() && boxShadowInfo.getProps().outset[0];
    },

    draw: function() {
        var me = this,
            el = this.targetElement,
            box = this.getBox(),
            styleInfos = this.styleInfos,
            shadowInfos = styleInfos.boxShadowInfo.getProps().outset,
            radii = styleInfos.borderRadiusInfo.getProps(),
            len = shadowInfos.length,
            i = len, j,
            bounds = this.boundsInfo.getBounds(),
            w = bounds.w,
            h = bounds.h,
            clipAdjust = PIE.ieVersion === 8 ? 1 : 0, //workaround for IE8 bug where VML leaks out top/left of clip region by 1px
            corners = [ 'tl', 'tr', 'br', 'bl' ], corner,
            shadowInfo, shape, fill, ss, xOff, yOff, spread, blur, shrink, color, alpha, path,
            totalW, totalH, focusX, focusY, isBottom, isRight;


        function getShadowShape( index, corner, xOff, yOff, color, blur, path ) {
            var shape = me.getShape( 'shadow' + index + corner, 'fill', box, len - index ),
                fill = shape.fill;

            // Position and size
            shape['coordsize'] = w * 2 + ',' + h * 2;
            shape['coordorigin'] = '1,1';

            // Color and opacity
            shape['stroked'] = false;
            shape['filled'] = true;
            fill.color = color.colorValue( el );
            if( blur ) {
                fill['type'] = 'gradienttitle'; //makes the VML gradient follow the shape's outline - hooray for undocumented features?!?!
                fill['color2'] = fill.color;
                fill['opacity'] = 0;
            }

            // Path
            shape.path = path;

            // This needs to go last for some reason, to prevent rendering at incorrect size
            ss = shape.style;
            ss.left = xOff;
            ss.top = yOff;
            ss.width = w;
            ss.height = h;

            return shape;
        }


        while( i-- ) {
            shadowInfo = shadowInfos[ i ];
            xOff = shadowInfo.xOffset.pixels( el );
            yOff = shadowInfo.yOffset.pixels( el );
            spread = shadowInfo.spread.pixels( el );
            blur = shadowInfo.blur.pixels( el );
            color = shadowInfo.color;
            // Shape path
            shrink = -spread - blur;
            if( !radii && blur ) {
                // If blurring, use a non-null border radius info object so that getBoxPath will
                // round the corners of the expanded shadow shape rather than squaring them off.
                radii = PIE.BorderRadiusStyleInfo.ALL_ZERO;
            }
            path = this.getBoxPath( { t: shrink, r: shrink, b: shrink, l: shrink }, 2, radii );

            if( blur ) {
                totalW = ( spread + blur ) * 2 + w;
                totalH = ( spread + blur ) * 2 + h;
                focusX = totalW ? blur * 2 / totalW : 0;
                focusY = totalH ? blur * 2 / totalH : 0;
                if( blur - spread > w / 2 || blur - spread > h / 2 ) {
                    // If the blur is larger than half the element's narrowest dimension, we cannot do
                    // this with a single shape gradient, because its focussize would have to be less than
                    // zero which results in ugly artifacts. Instead we create four shapes, each with its
                    // gradient focus past center, and then clip them so each only shows the quadrant
                    // opposite the focus.
                    for( j = 4; j--; ) {
                        corner = corners[j];
                        isBottom = corner.charAt( 0 ) === 'b';
                        isRight = corner.charAt( 1 ) === 'r';
                        shape = getShadowShape( i, corner, xOff, yOff, color, blur, path );
                        fill = shape.fill;
                        fill['focusposition'] = ( isRight ? 1 - focusX : focusX ) + ',' +
                                                ( isBottom ? 1 - focusY : focusY );
                        fill['focussize'] = '0,0';

                        // Clip to show only the appropriate quadrant. Add 1px to the top/left clip values
                        // in IE8 to prevent a bug where IE8 displays one pixel outside the clip region.
                        shape.style.clip = 'rect(' + ( ( isBottom ? totalH / 2 : 0 ) + clipAdjust ) + 'px,' +
                                                     ( isRight ? totalW : totalW / 2 ) + 'px,' +
                                                     ( isBottom ? totalH : totalH / 2 ) + 'px,' +
                                                     ( ( isRight ? totalW / 2 : 0 ) + clipAdjust ) + 'px)';
                    }
                } else {
                    // TODO delete old quadrant shapes if resizing expands past the barrier
                    shape = getShadowShape( i, '', xOff, yOff, color, blur, path );
                    fill = shape.fill;
                    fill['focusposition'] = focusX + ',' + focusY;
                    fill['focussize'] = ( 1 - focusX * 2 ) + ',' + ( 1 - focusY * 2 );
                }
            } else {
                shape = getShadowShape( i, '', xOff, yOff, color, blur, path );
                alpha = color.alpha();
                if( alpha < 1 ) {
                    // shape.style.filter = 'alpha(opacity=' + ( alpha * 100 ) + ')';
                    // ss.filter = 'progid:DXImageTransform.Microsoft.BasicImage(opacity=' + ( alpha  ) + ')';
                    shape.fill.opacity = alpha;
                }
            }
        }
    }

} );