• 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 UNUSED */
79 
80 #include "android/skin/argb.h"
81 
82 
83 void
skin_scaler_get_scaled_rect(SkinScaler * scaler,SkinRect * srect,SkinRect * drect)84 skin_scaler_get_scaled_rect( SkinScaler*  scaler,
85                              SkinRect*    srect,
86                              SkinRect*    drect )
87 {
88     int sx = srect->pos.x;
89     int sy = srect->pos.y;
90     int sw = srect->size.w;
91     int sh = srect->size.h;
92     double scale = scaler->scale;
93 
94     if (!scaler->valid) {
95         drect[0] = srect[0];
96         return;
97     }
98 
99     drect->pos.x = (int)(sx * scale + scaler->xdisp);
100     drect->pos.y = (int)(sy * scale + scaler->ydisp);
101     drect->size.w = (int)(ceil((sx + sw) * scale + scaler->xdisp)) - drect->pos.x;
102     drect->size.h = (int)(ceil((sy + sh) * scale + scaler->ydisp)) - drect->pos.y;
103 }
104 
105 void
skin_scaler_scale(SkinScaler * scaler,SDL_Surface * dst_surface,SDL_Surface * src_surface,int sx,int sy,int sw,int sh)106 skin_scaler_scale( SkinScaler*   scaler,
107                    SDL_Surface*  dst_surface,
108                    SDL_Surface*  src_surface,
109                    int           sx,
110                    int           sy,
111                    int           sw,
112                    int           sh )
113 {
114     ScaleOp   op;
115 
116     if ( !scaler->valid )
117         return;
118 
119     SDL_LockSurface( src_surface );
120     SDL_LockSurface( dst_surface );
121     {
122         op.scale     = scaler->scale;
123         op.src_pitch = src_surface->pitch;
124         op.src_line  = src_surface->pixels;
125         op.src_w     = src_surface->w;
126         op.src_h     = src_surface->h;
127         op.dst_pitch = dst_surface->pitch;
128         op.dst_line  = dst_surface->pixels;
129 
130         /* compute the destination rectangle */
131         op.rd.x = (int)(sx * scaler->scale + scaler->xdisp);
132         op.rd.y = (int)(sy * scaler->scale + scaler->ydisp);
133         op.rd.w = (int)(ceil((sx + sw) * scaler->scale + scaler->xdisp)) - op.rd.x;
134         op.rd.h = (int)(ceil((sy + sh) * scaler->scale + scaler->ydisp)) - op.rd.y;
135 
136         /* compute the starting source position in 16.16 format
137          * and the corresponding increments */
138         op.sx = (int)((op.rd.x - scaler->xdisp) * scaler->invscale * 65536);
139         op.sy = (int)((op.rd.y - scaler->ydisp) * scaler->invscale * 65536);
140 
141         op.ix = (int)( scaler->invscale * 65536 );
142         op.iy = op.ix;
143 
144         op.dst_line += op.rd.x*4 + op.rd.y*op.dst_pitch;
145 
146         if (op.scale >= 0.5 && op.scale <= 1.0)
147             scale_05_to_10( &op );
148         else if (op.scale > 1.0)
149             scale_up_bilinear( &op );
150         else
151             scale_generic( &op );
152     }
153     SDL_UnlockSurface( dst_surface );
154     SDL_UnlockSurface( src_surface );
155 
156     SDL_UpdateRects( dst_surface, 1, &op.rd );
157 }
158