• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "android/skin/scaler.h"
13 #include <stdint.h>
14 #include <math.h>
15 
16 struct SkinScaler {
17     double  scale;
18     double  xdisp, ydisp;
19     double  invscale;
20     int     valid;
21 };
22 
23 static SkinScaler  _scaler0;
24 
25 SkinScaler*
skin_scaler_create(void)26 skin_scaler_create( void )
27 {
28     _scaler0.scale    = 1.0;
29     _scaler0.xdisp    = 0.0;
30     _scaler0.ydisp    = 0.0;
31     _scaler0.invscale = 1.0;
32     return &_scaler0;
33 }
34 
35 /* change the scale of a given scaler. returns 0 on success, or -1 in case of
36  * problem (unsupported scale) */
37 int
skin_scaler_set(SkinScaler * scaler,double scale,double xdisp,double ydisp)38 skin_scaler_set( SkinScaler*  scaler, double  scale, double xdisp, double ydisp )
39 {
40     /* right now, we only support scales in the 0.5 .. 1.0 range */
41     if (scale < 0.1)
42         scale = 0.1;
43     else if (scale > 6.0)
44         scale = 6.0;
45 
46     scaler->scale    = scale;
47     scaler->xdisp    = xdisp;
48     scaler->ydisp    = ydisp;
49     scaler->invscale = 1/scale;
50     scaler->valid    = 1;
51 
52     return 0;
53 }
54 
55 void
skin_scaler_free(SkinScaler * scaler)56 skin_scaler_free( SkinScaler*  scaler )
57 {
58     scaler=scaler;
59 }
60 
61 typedef struct {
62     SDL_Rect    rd;         /* destination rectangle */
63     int         sx, sy;     /* source start position in 16.16 format */
64     int         ix, iy;     /* source increments in 16.16 format */
65     int         src_pitch;
66     int         src_w;
67     int         src_h;
68     int         dst_pitch;
69     uint8_t*    dst_line;
70     uint8_t*    src_line;
71     double      scale;
72 } ScaleOp;
73 
74 
75 #define  ARGB_SCALE_GENERIC       scale_generic
76 #define  ARGB_SCALE_05_TO_10      scale_05_to_10
77 #define  ARGB_SCALE_UP_BILINEAR   scale_up_bilinear
78 #define  ARGB_SCALE_UP_QUICK_4x4  scale_up_quick_4x4
79 
80 #include "android/skin/argb.h"
81 
82 
83 void
skin_scaler_scale(SkinScaler * scaler,SDL_Surface * dst_surface,SDL_Surface * src_surface,int sx,int sy,int sw,int sh)84 skin_scaler_scale( SkinScaler*   scaler,
85                    SDL_Surface*  dst_surface,
86                    SDL_Surface*  src_surface,
87                    int           sx,
88                    int           sy,
89                    int           sw,
90                    int           sh )
91 {
92     ScaleOp   op;
93 
94     if ( !scaler->valid )
95         return;
96 
97     SDL_LockSurface( src_surface );
98     SDL_LockSurface( dst_surface );
99     {
100         op.scale     = scaler->scale;
101         op.src_pitch = src_surface->pitch;
102         op.src_line  = src_surface->pixels;
103         op.src_w     = src_surface->w;
104         op.src_h     = src_surface->h;
105         op.dst_pitch = dst_surface->pitch;
106         op.dst_line  = dst_surface->pixels;
107 
108         /* compute the destination rectangle */
109         op.rd.x = (int)(sx * scaler->scale + scaler->xdisp);
110         op.rd.y = (int)(sy * scaler->scale + scaler->ydisp);
111         op.rd.w = (int)(ceil((sx + sw) * scaler->scale + scaler->xdisp)) - op.rd.x;
112         op.rd.h = (int)(ceil((sy + sh) * scaler->scale + scaler->ydisp)) - op.rd.y;
113 
114         /* compute the starting source position in 16.16 format
115          * and the corresponding increments */
116         op.sx = (int)((op.rd.x - scaler->xdisp) * scaler->invscale * 65536);
117         op.sy = (int)((op.rd.y - scaler->ydisp) * scaler->invscale * 65536);
118 
119         op.ix = (int)( scaler->invscale * 65536 );
120         op.iy = op.ix;
121 
122         op.dst_line += op.rd.x*4 + op.rd.y*op.dst_pitch;
123 
124         if (op.scale >= 0.5 && op.scale <= 1.0)
125             scale_05_to_10( &op );
126         else if (op.scale > 1.0)
127             scale_up_bilinear( &op );
128         else
129             scale_generic( &op );
130     }
131     SDL_UnlockSurface( dst_surface );
132     SDL_UnlockSurface( src_surface );
133 
134     SDL_UpdateRects( dst_surface, 1, &op.rd );
135 }
136