123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- #version 130
- uniform sampler2D sampler;
- uniform int swidth;
- uniform int sheight;
- uniform float xscale;
- uniform float yscale;
- uniform float xoffset;
- uniform float yoffset;
- uniform float xfrompixelratio;
- uniform float yfrompixelratio;
- uniform float xtopixelratio;
- uniform float ytopixelratio;
- varying vec2 tex_coord;
- // This mode makes the scaling work like maskedTextureFragmentShader.glsl
- // (instead of like plain textureVertexShader.glsl).
- #ifdef MASKED
- varying vec2 mask_coord;
- uniform sampler2D mask;
- #endif
- #ifdef USE_REDUCED_REGISTER_VARIANT
- vec4 getTexel(int x, int y)
- {
- vec2 pos = vec2( x * xfrompixelratio + xoffset, y * yfrompixelratio + yoffset );
- vec4 texel = texture2D(sampler, pos);
- #ifdef MASKED
- texel.a = 1.0 - texture2D(mask, pos - tex_coord.st + mask_coord.st).r;
- #endif
- return texel;
- }
- void main(void)
- {
- // Convert to pixel coordinates again.
- int dx = int(( tex_coord.s - xoffset ) * xtopixelratio );
- int dy = int(( tex_coord.t - yoffset ) * ytopixelratio );
- // Compute the range of source pixels which will make up this destination pixel.
- float fsx1 = min(dx * xscale, float(swidth - 1));
- float fsx2 = min(fsx1 + xscale, float(swidth - 1));
- float fsy1 = min(dy * yscale, float(sheight - 1));
- float fsy2 = min(fsy1 + yscale, float(sheight - 1));
- // To whole pixel coordinates.
- int xstart = int(floor(fsx1));
- int xend = int(floor(fsx2));
- int ystart = int(floor(fsy1));
- int yend = int(floor(fsy2));
- float xlength = fsx2 - fsx1;
- float ylength = fsy2 - fsy1;
- float xContribution[3];
- xContribution[0] = (1.0 - max(0.0, fsx1 - xstart)) / xlength;
- xContribution[1] = 1.0 / xlength;
- xContribution[2] = (1.0 - max(0.0, (xend + 1) - fsx2)) / xlength;
- float yContribution[3];
- yContribution[0] = (1.0 - max(0.0, fsy1 - ystart)) / ylength;
- yContribution[1] = 1.0 / ylength;
- yContribution[2] = (1.0 - max(0.0, (yend + 1) - fsy2)) / ylength;
- vec4 sumAll = vec4(0.0, 0.0, 0.0, 0.0);
- vec4 texel;
- // First Y pass
- {
- vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0);
- sumX += getTexel(xstart, ystart) * xContribution[0];
- for (int x = xstart + 1; x < xend; ++x)
- {
- sumX += getTexel(x, ystart) * xContribution[1];
- }
- sumX += getTexel(xend, ystart) * xContribution[2];
- sumAll += sumX * yContribution[0];
- }
- // Middle Y Passes
- for (int y = ystart + 1; y < yend; ++y)
- {
- vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0);
- sumX += getTexel(xstart, y) * xContribution[0];
- for (int x = xstart + 1; x < xend; ++x)
- {
- sumX += getTexel(x, y) * xContribution[1];
- }
- sumX += getTexel(xend, y) * xContribution[2];
- sumAll += sumX * yContribution[1];
- }
- // Last Y pass
- {
- vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0);
- sumX += getTexel(xstart, yend) * xContribution[0];
- for (int x = xstart + 1; x < xend; ++x)
- {
- sumX += getTexel(x, yend) * xContribution[1];
- }
- sumX += getTexel(xend, yend) * xContribution[2];
- sumAll += sumX * yContribution[2];
- }
- gl_FragColor = sumAll;
- }
- #else
- void main(void)
- {
- // Convert to pixel coordinates again.
- int dx = int(( tex_coord.s - xoffset ) * xtopixelratio );
- int dy = int(( tex_coord.t - yoffset ) * ytopixelratio );
- // How much each column/row will contribute to the resulting pixel.
- // Note: These values are always the same for the same X (or Y),
- // so they could be precalculated in C++ and passed to the shader,
- // but GLSL has limits on the size of uniforms passed to it,
- // so it'd need something like texture buffer objects from newer
- // GLSL versions, and it seems the hassle is not really worth it.
- float xratio[ 16 + 2 ];
- float yratio[ 16 + 2 ];
- // For finding the first and last source pixel.
- int xpixel[ 16 + 2 ];
- int ypixel[ 16 + 2 ];
- int xpos = 0;
- int ypos = 0;
- // Compute the range of source pixels which will make up this destination pixel.
- float fsx1 = dx * xscale;
- float fsx2 = fsx1 + xscale;
- // To whole pixel coordinates.
- int sx1 = int( ceil( fsx1 ) );
- int sx2 = int( floor( fsx2 ) );
- // Range checking.
- sx2 = min( sx2, swidth - 1 );
- sx1 = min( sx1, sx2 );
- // How much one full column contributes to the resulting pixel.
- float width = min( xscale, swidth - fsx1 );
- if( sx1 - fsx1 > 0.001 )
- { // The first column contributes only partially.
- xpixel[ xpos ] = sx1 - 1;
- xratio[ xpos ] = ( sx1 - fsx1 ) / width;
- ++xpos;
- }
- for( int sx = sx1; sx < sx2; ++sx )
- { // Columns that fully contribute to the resulting pixel.
- xpixel[ xpos ] = sx;
- xratio[ xpos ] = 1.0 / width;
- ++xpos;
- }
- if( fsx2 - sx2 > 0.001 )
- { // The last column contributes only partially.
- xpixel[ xpos ] = sx2;
- xratio[ xpos ] = min( min( fsx2 - sx2, 1.0 ) / width, 1.0 );
- ++xpos;
- }
- // The same for Y.
- float fsy1 = dy * yscale;
- float fsy2 = fsy1 + yscale;
- int sy1 = int( ceil( fsy1 ) );
- int sy2 = int( floor( fsy2 ) );
- sy2 = min( sy2, sheight - 1 );
- sy1 = min( sy1, sy2 );
- float height = min( yscale, sheight - fsy1 );
- if( sy1 - fsy1 > 0.001 )
- {
- ypixel[ ypos ] = sy1 - 1;
- yratio[ ypos ] = ( sy1 - fsy1 ) / height;
- ++ypos;
- }
- for( int sy = sy1; sy < sy2; ++sy )
- {
- ypixel[ ypos ] = sy;
- yratio[ ypos ] = 1.0 / height;
- ++ypos;
- }
- if( fsy2 - sy2 > 0.001 )
- {
- ypixel[ ypos ] = sy2;
- yratio[ ypos ] = min( min( fsy2 - sy2, 1.0 ) / height, 1.0 );
- ++ypos;
- }
- int xstart = xpixel[ 0 ];
- int xend = xpixel[ xpos - 1 ];
- int ystart = ypixel[ 0 ];
- int yend = ypixel[ ypos - 1 ];
- vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );
- ypos = 0;
- for( int y = ystart; y <= yend; ++y, ++ypos )
- {
- vec4 tmp = vec4( 0.0, 0.0, 0.0, 0.0 );
- xpos = 0;
- for( int x = xstart; x <= xend; ++x, ++xpos )
- {
- vec2 pos = vec2( x * xfrompixelratio + xoffset, y * yfrompixelratio + yoffset );
- #ifndef MASKED
- tmp += texture2D( sampler, pos ) * xratio[ xpos ];
- #else
- vec4 texel;
- texel = texture2D( sampler, pos );
- texel.a = 1.0 - texture2D( mask, pos - tex_coord.st + mask_coord.st ).r;
- tmp += texel * xratio[ xpos ];
- #endif
- }
- sum += tmp * yratio[ ypos ];
- }
- gl_FragColor = sum;
- }
- #endif
- /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|