Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / opengl / areaScaleFragmentShader.glsl
blobb95b8698a26f9464483668d27a0f3b5702308760
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
10 #version 120
11 #if __VERSION__ < 130
12 int min( int a, int b ) { return a < b ? a : b; }
13 float min( float a, float b ) { return a < b ? a : b; }
14 #endif
16 /* TODO Use textureOffset for newest version of GLSL */
18 uniform sampler2D sampler;
19 uniform int swidth;
20 uniform int sheight;
21 uniform float xscale;
22 uniform float yscale;
23 uniform float xsrcconvert;
24 uniform float ysrcconvert;
25 uniform float xdestconvert;
26 uniform float ydestconvert;
28 varying vec2 tex_coord;
30 // This mode makes the scaling work like maskedTextureFragmentShader.glsl
31 // (instead of like plain textureVertexShader.glsl).
32 #ifdef MASKED
33 varying vec2 mask_coord;
34 uniform sampler2D mask;
35 #endif
37 void main(void)
39     // Convert to pixel coordinates again.
40     int dx = int( tex_coord.s * xdestconvert );
41     int dy = int( tex_coord.t * ydestconvert );
43     // Note: These values are always the same for the same X (or Y),
44     // so they could be precalculated in C++ and passed to the shader,
45     // but GLSL has limits on the size of uniforms passed to it,
46     // so it'd need something like texture buffer objects from newer
47     // GLSL versions, and it seems the hassle is not really worth it.
49     // How much each column/row will contribute to the resulting pixel.
50     // assert( xscale <= 100 ); assert( yscale <= 100 );
51     float xratio[ 100 + 2 ];
52     float yratio[ 100 + 2 ];
53     // For finding the first and last source pixel.
54     int xpixel[ 100 + 2 ];
55     int ypixel[ 100 + 2 ];
57     int xpos = 0;
58     int ypos = 0;
60     // Compute the range of source pixels which will make up this destination pixel.
61     float fsx1 = dx * xscale;
62     float fsx2 = fsx1 + xscale;
63     // To whole pixel coordinates.
64     int sx1 = int( ceil( fsx1 ) );
65     int sx2 = int( floor( fsx2 ) );
66     // Range checking.
67     sx2 = min( sx2, swidth - 1 );
68     sx1 = min( sx1, sx2 );
70     // How much one full column contributes to the resulting pixel.
71     float width = min( xscale, swidth - fsx1 );
73     if( sx1 - fsx1 > 0.001 )
74     {   // The first column contributes only partially.
75         xpixel[ xpos ] = sx1 - 1;
76         xratio[ xpos ] = ( sx1 - fsx1 ) / width;
77         ++xpos;
78     }
79     for( int sx = sx1; sx < sx2; ++sx )
80     {   // Columns that fully contribute to the resulting pixel.
81         xpixel[ xpos ] = sx;
82         xratio[ xpos ] = 1.0 / width;
83         ++xpos;
84     }
85     if( fsx2 - sx2 > 0.001 )
86     {   // The last column contributes only partially.
87         xpixel[ xpos ] = sx2;
88         xratio[ xpos ] = min( min( fsx2 - sx2, 1.0 ) / width, 1.0 );
89         ++xpos;
90     }
92     // The same for Y.
93     float fsy1 = dy * yscale;
94     float fsy2 = fsy1 + yscale;
95     int sy1 = int( ceil( fsy1 ) );
96     int sy2 = int( floor( fsy2 ) );
97     sy2 = min( sy2, sheight - 1 );
98     sy1 = min( sy1, sy2 );
100     float height = min( yscale, sheight - fsy1 );
102     if( sy1 - fsy1 > 0.001 )
103     {
104         ypixel[ ypos ] = sy1 - 1;
105         yratio[ ypos ] = ( sy1 - fsy1 ) / height;
106         ++ypos;
107     }
108     for( int sy = sy1; sy < sy2; ++sy )
109     {
110         ypixel[ ypos ] = sy;
111         yratio[ ypos ] = 1.0 / height;
112         ++ypos;
113     }
114     if( fsy2 - sy2 > 0.001 )
115     {
116         ypixel[ ypos ] = sy2;
117         yratio[ ypos ] = min( min( fsy2 - sy2, 1.0 ) / height, 1.0 );
118         ++ypos;
119     }
121     int xstart = xpixel[ 0 ];
122     int xend = xpixel[ xpos - 1 ];
123     int ystart = ypixel[ 0 ];
124     int yend = ypixel[ ypos - 1 ];
126     vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );
128     ypos = 0;
129     for( int y = ystart; y <= yend; ++y, ++ypos )
130     {
131         vec4 tmp = vec4( 0.0, 0.0, 0.0, 0.0 );
132         xpos = 0;
133         for( int x = xstart; x <= xend; ++x, ++xpos )
134         {
135             vec2 offset = vec2( x * xsrcconvert, y * ysrcconvert );
136 #ifndef MASKED
137             tmp += texture2D( sampler, offset ) * xratio[ xpos ];
138 #else
139             vec4 texel;
140             texel = texture2D( sampler, offset );
141             texel.a = 1.0 - texture2D( mask, offset ).r;
142             tmp += texel * xratio[ xpos ];
143 #endif
144         }
145         sum += tmp * yratio[ ypos ];
146     }
148     gl_FragColor = sum;
151 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */