Ticket #8367: edge3x.diff.2.v2

File edge3x.diff.2.v2, 26.0 KB (added by SF/ewelsh42, 20 years ago)
Line 
1diff -ruN -u scummvm_old/backends/sdl/graphics.cpp scummvm_new/backends/sdl/graphics.cpp
2--- scummvm_old/backends/sdl/graphics.cpp 2004-10-15 17:28:12.000000000 -0500
3+++ scummvm_new/backends/sdl/graphics.cpp 2004-11-06 04:54:22.000000000 -0600
4@@ -38,6 +38,7 @@
5 {"hq3x", "HQ3x", GFX_HQ3X},
6 {"tv2x", "TV2x", GFX_TV2X},
7 {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
8+ {"edge3x", "Edge3x", GFX_EDGE3X},
9 {0, 0, 0}
10 };
11
12@@ -105,6 +106,10 @@
13 newScaleFactor = 2;
14 newScalerProc = DotMatrix;
15 break;
16+ case GFX_EDGE3X:
17+ newScaleFactor = 3;
18+ newScalerProc = Edge3x;
19+ break;
20
21 default:
22 warning("unknown gfx mode %d", mode);
23diff -ruN -u scummvm_old/backends/sdl/sdl-common.h scummvm_new/backends/sdl/sdl-common.h
24--- scummvm_old/backends/sdl/sdl-common.h 2004-10-15 17:28:12.000000000 -0500
25+++ scummvm_new/backends/sdl/sdl-common.h 2004-11-06 04:54:22.000000000 -0600
26@@ -44,7 +44,8 @@
27 { GFX_NORMAL, GFX_SUPER2XSAI, -1, -1 },
28 { GFX_NORMAL, GFX_SUPEREAGLE, -1, -1 },
29 { GFX_NORMAL, GFX_TV2X, -1, -1 },
30- { GFX_NORMAL, GFX_DOTMATRIX, -1, -1 }
31+ { GFX_NORMAL, GFX_DOTMATRIX, -1, -1 },
32+ { GFX_NORMAL, -1, GFX_EDGE3X, -1 }
33 };
34
35
36diff -ruN -u scummvm_old/base/gameDetector.cpp scummvm_new/base/gameDetector.cpp
37--- scummvm_old/base/gameDetector.cpp 2004-11-05 19:41:30.000000000 -0600
38+++ scummvm_new/base/gameDetector.cpp 2004-11-06 04:54:22.000000000 -0600
39@@ -56,7 +56,7 @@
40 " -F, --no-fullscreen Force windowed mode\n"
41 " -g, --gfx-mode=MODE Select graphics scaler (normal,2x,3x,2xsai,\n"
42 " super2xsai,supereagle,advmame2x,advmame3x,hq2x,\n"
43- " hq3x,tv2x,dotmatrix)\n"
44+ " hq3x,tv2x,dotmatrix,edge3x)\n"
45 " -e, --music-driver=MODE Select music driver (see README for details)\n"
46 " -q, --language=LANG Select language (en,de,fr,it,pt,es,jp,zh,kr,se,gb,\n"
47 " hb,ru,cz)\n"
48diff -ruN -u scummvm_old/common/module.mk scummvm_new/common/module.mk
49--- scummvm_old/common/module.mk 2004-08-26 16:01:22.000000000 -0500
50+++ scummvm_new/common/module.mk 2004-11-06 04:54:22.000000000 -0600
51@@ -20,7 +20,8 @@
52 common/scaler/hq3x.o \
53 common/scaler/scale2x.o \
54 common/scaler/scale3x.o \
55- common/scaler/scalebit.o
56+ common/scaler/scalebit.o \
57+ common/scaler/edge3x.o
58
59 ifdef HAVE_NASM
60 MODULE_OBJS += \
61diff -ruN -u scummvm_old/common/scaler/edge3x.cpp scummvm_new/common/scaler/edge3x.cpp
62--- scummvm_old/common/scaler/edge3x.cpp 1969-12-31 18:00:00.000000000 -0600
63+++ scummvm_new/common/scaler/edge3x.cpp 2004-11-06 04:54:34.000000000 -0600
64@@ -0,0 +1,816 @@
65+/* ScummVM - Scumm Interpreter
66+ * Copyright (C) 2001 Ludvig Strigeus
67+ * Copyright (C) 2001-2004 The ScummVM project
68+ *
69+ * This program is free software; you can redistribute it and/or
70+ * modify it under the terms of the GNU General Public License
71+ * as published by the Free Software Foundation; either version 2
72+ * of the License, or (at your option) any later version.
73+
74+ * This program is distributed in the hope that it will be useful,
75+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
76+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77+ * GNU General Public License for more details.
78+
79+ * You should have received a copy of the GNU General Public License
80+ * along with this program; if not, write to the Free Software
81+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
82+ *
83+ * $Header: /cvsroot/scummvm/scummvm/common/scaler/hq3x.h,v 1.2 2004/01/06 12:45:28 fingolfin Exp $
84+ *
85+ */
86+
87+/* Another edge-directed 3x anti-aliasing scaler for ScummVM
88+ *
89+ * Author: Eric A. Welsh
90+ *
91+ * Features:
92+ *
93+ * More anti-aliasing than advmame3x, but at the cost of some blurriness
94+ * Low contrast areas are sharper than hq3x (which is very blurry)
95+ * High contrast areas aren't as nice as hq3x (which is VERY nice)
96+ * Overall, it strikes a good balance between sharpness and blurriness
97+ * It could probably use some further speed optimization
98+ * It's a bit slow... but ScummVM runs everything fine on my 1.53 Gz Athlon
99+ */
100+
101+#include "common/stdafx.h"
102+#include "common/scummsys.h"
103+#include "common/system.h"
104+
105+#define SIN45 0.7071067811865 /* sin of 45 degrees */
106+#define LUMA_SHIFT 13
107+
108+int32 luma_table[65536] = {0};
109+int edge3x_init_flag = 0;
110+const uint16 *src_addr_min; /* start of src screen array */
111+const uint16 *src_addr_max; /* end of src screen array */
112+uint16 div3[189]; /* tables for pixel interpolation */
113+uint16 div9[567];
114+
115+/* faster than FPU atan(), nearly as accurate as single precision */
116+double fast_atan(double v0)
117+{
118+ double v2;
119+ double v;
120+
121+ v = fabs(v0);
122+ v2 = v*v;
123+ if (v > 1)
124+ {
125+ v2 = 1.570796326795 -
126+ v * (0.446350590597 + v2) /
127+ ((0.0900271979249 + v2) * (0.689454091687 + v2));
128+ if (v0 < 0) return -v2;
129+ return v2;
130+ }
131+ v2 = v * (16.11094124024 + 7.191128136096 * v2) /
132+ ((1.450422895714 + v2) * (11.10775435761 + v2));
133+
134+ if (v0 < 0) return -v2;
135+ return v2;
136+}
137+
138+/* More complicated and slower than most algorithms, but it fails far less
139+ * often (ie. assigning diagonal when it should be horizontal, or 90 degrees
140+ * from what it should be). Slow, but necessary to avoid artifacts.
141+ *
142+ * Edge detection takes up a whopping 53% of the CPU time spent in ScummVM.
143+ * Perhaps this could be optimized a bit more ... ?
144+ */
145+char convolve_edges_compass_luma(uint16 *pixels, int x_orig, int y_orig,
146+ int w)
147+{
148+ int32 *bptr;
149+ uint16 *pptr;
150+ int32 bplane[9];
151+ int32 sums_dir1, sums_dir2, sums_dir3, sums_dir4; /* NE E SE S */
152+ int32 max_sums;
153+ int32 mag, mag1, mag2;
154+ double angle;
155+ double new_angle = 999;
156+ int n;
157+
158+ /* fill the 9 pixel window with luma values */
159+ bptr = bplane;
160+ pptr = pixels;
161+ for (n = 0; n < 9; n++)
162+ *bptr++ = luma_table[*pptr++];
163+ bptr = bplane;
164+
165+ /* bi-directional edge detection */
166+ /* mis-detections are easier to correct than the vector-based method */
167+ mag = (bptr[2] + bptr[4] + bptr[6]) << 1;
168+ mag1 = labs((3 * (bptr[1] + bptr[3]) - mag) >> 1);
169+ mag2 = labs((3 * (bptr[5] + bptr[7]) - mag) >> 1);
170+ mag = mag1;
171+ if (mag2 > mag) mag = mag2;
172+ sums_dir1 = mag;
173+
174+ mag = bptr[3] + bptr[4] + bptr[5];
175+ mag1 = labs(bptr[0] + bptr[1] + bptr[2] - mag);
176+ mag2 = labs(bptr[6] + bptr[7] + bptr[8] - mag);
177+ mag = mag1;
178+ if (mag2 > mag) mag = mag2;
179+ sums_dir2 = mag;
180+
181+ mag = (bptr[0] + bptr[4] + bptr[8]) << 1;
182+ mag1 = labs((3 * (bptr[1] + bptr[5]) - mag) >> 1);
183+ mag2 = labs((3 * (bptr[3] + bptr[7]) - mag) >> 1);
184+ mag = mag1;
185+ if (mag2 > mag) mag = mag2;
186+ sums_dir3 = mag;
187+
188+ mag = bptr[1] + bptr[4] + bptr[7];
189+ mag1 = labs(bptr[0] + bptr[3] + bptr[6] - mag);
190+ mag2 = labs(bptr[2] + bptr[5] + bptr[8] - mag);
191+ mag = mag1;
192+ if (mag2 > mag) mag = mag2;
193+ sums_dir4 = mag;
194+
195+ /* find the strongest edge */
196+ max_sums = sums_dir1;
197+ if (sums_dir2 > max_sums) max_sums = sums_dir2;
198+ if (sums_dir3 > max_sums) max_sums = sums_dir3;
199+ if (sums_dir4 > max_sums) max_sums = sums_dir4;
200+
201+ n = 0;
202+ if (max_sums == sums_dir1)
203+ {
204+ new_angle = 135;
205+ n++;
206+ }
207+ if (max_sums == sums_dir2)
208+ {
209+ new_angle = 0;
210+ n++;
211+ }
212+ if (max_sums == sums_dir3)
213+ {
214+ new_angle = 45;
215+ n++;
216+ }
217+ if (max_sums == sums_dir4)
218+ {
219+ new_angle = 90;
220+ n++;
221+ }
222+
223+ if (max_sums == 0) /* grid of solid color */
224+ return 0;
225+ if (max_sums && n == 1) /* we found a strong edge */
226+ {
227+ angle = new_angle;
228+ }
229+ else if (n == 4) /* x, +, . type patterns */
230+ {
231+ return '*';
232+ }
233+ else /* difficult edge, try vector method */
234+ {
235+ double x, y;
236+
237+ sums_dir1 = (3 * (bptr[1] - bptr[3] + bptr[5] - bptr[7])) >> 1;
238+
239+ sums_dir2 = bptr[0] + bptr[1] + bptr[2] -
240+ bptr[6] - bptr[7] - bptr[8];
241+
242+ sums_dir3 = (3 * (bptr[1] + bptr[3] - bptr[5] - bptr[7])) >> 1;
243+
244+ sums_dir4 = bptr[0] - bptr[2] + bptr[3] -
245+ bptr[5] + bptr[6] - bptr[8];
246+
247+ /* add the vectors in x,y space, North points up */ /* NE E SE S */
248+ x = sums_dir1 * SIN45;
249+ x += sums_dir2;
250+ x += sums_dir3 * SIN45;
251+ y = sums_dir1 * SIN45;
252+ y -= sums_dir3 * SIN45;
253+ y -= sums_dir4;
254+
255+ if (x)
256+ {
257+ angle = 57.29577951307 * fast_atan(y / x);
258+ if (x < 0) angle += 180;
259+ }
260+ else
261+ {
262+ if (y > 0) angle = 90;
263+ else if (y < 0) angle = -90;
264+ else return '*';
265+ }
266+ }
267+
268+ /* fix detection errors that are off by 90 degrees */
269+ {
270+ int32 dist1, dist2;
271+ int32 dist_good, dist_bad;
272+
273+ if (angle < 0) angle += 360;
274+
275+ /* horizontal */
276+ if ((angle > (180 - 22.5) && angle < (180 + 22.5)) ||
277+ angle < 22.5 || angle > (360 - 22.5))
278+ {
279+ dist1 = bptr[4] - bptr[3];
280+ dist2 = bptr[4] - bptr[5];
281+ dist_good = dist1*dist1 + dist2*dist2;
282+
283+ dist1 = bptr[4] - bptr[1];
284+ dist2 = bptr[4] - bptr[7];
285+ dist_bad = dist1*dist1 + dist2*dist2;
286+
287+ if (dist_good <= dist_bad)
288+ return '-';
289+
290+ return '|';
291+ }
292+
293+ /* vertical */
294+ if ((angle > (90 - 22.5) && angle < (90 + 22.5)) ||
295+ (angle > (90 - 22.5 + 180) && angle < (90 + 22.5 + 180)))
296+ {
297+ dist1 = bptr[4] - bptr[1];
298+ dist2 = bptr[4] - bptr[7];
299+ dist_good = dist1*dist1 + dist2*dist2;
300+
301+ dist1 = bptr[4] - bptr[3];
302+ dist2 = bptr[4] - bptr[5];
303+ dist_bad = dist1*dist1 + dist2*dist2;
304+
305+ if (dist_good <= dist_bad)
306+ return '|';
307+
308+ return '-';
309+ }
310+
311+ /* 45 */
312+ if ((angle > (45 - 22.5) && angle < (45 + 22.5)) ||
313+ (angle > (45 - 22.5 + 180) && angle < (45 + 22.5 + 180)))
314+ {
315+ dist1 = bptr[4] - bptr[0];
316+ dist2 = bptr[4] - bptr[8];
317+ dist_good = dist1*dist1 + dist2*dist2;
318+
319+ /* side diags */
320+ dist1 = bptr[1] - bptr[5];
321+ dist2 = bptr[3] - bptr[7];
322+ dist_good += dist1*dist1 + dist2*dist2;
323+
324+ dist1 = bptr[4] - bptr[2];
325+ dist2 = bptr[4] - bptr[6];
326+ dist_bad = dist1*dist1 + dist2*dist2;
327+
328+ /* side diags */
329+ dist1 = bptr[1] - bptr[3];
330+ dist2 = bptr[5] - bptr[7];
331+ dist_bad += dist1*dist1 + dist2*dist2;
332+
333+ if (dist_good <= dist_bad)
334+ return '\\';
335+
336+ return '/';
337+ }
338+
339+ /* 135 */
340+ if ((angle > (135 - 22.5) && angle < (135 + 22.5)) ||
341+ (angle > (135 - 22.5 + 180) && angle < (135 + 22.5 + 180)))
342+ {
343+ dist1 = bptr[4] - bptr[2];
344+ dist2 = bptr[4] - bptr[6];
345+ dist_good = dist1*dist1 + dist2*dist2;
346+
347+ /* side diags */
348+ dist1 = bptr[1] - bptr[3];
349+ dist2 = bptr[5] - bptr[7];
350+ dist_good += dist1*dist1 + dist2*dist2;
351+
352+ dist1 = bptr[4] - bptr[0];
353+ dist2 = bptr[4] - bptr[8];
354+ dist_bad = dist1*dist1 + dist2*dist2;
355+
356+ /* side diags */
357+ dist1 = bptr[1] - bptr[5];
358+ dist2 = bptr[3] - bptr[7];
359+ dist_bad += dist1*dist1 + dist2*dist2;
360+
361+ if (dist_good <= dist_bad)
362+ return '/';
363+
364+ return '\\';
365+ }
366+ }
367+
368+ return '*';
369+}
370+
371+/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */
372+#define highBits 0xF7DEF7DE
373+#define lowBits 0x08210821
374+#define qhighBits 0xE79CE79C
375+#define qlowBits 0x18631863
376+#define redblueMask 0xF81F
377+#define greenMask 0x07E0
378+
379+/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */
380+/**
381+ * Interpolate two 16 bit pixel pairs at once with equal weights 1.
382+ * In particular, A and B can contain two pixels/each in the upper
383+ * and lower halves.
384+ */
385+uint32 INTERPOLATE(uint32 A, uint32 B)
386+{
387+ return (((A & highBits) >> 1) + ((B & highBits) >> 1) + (A & B & lowBits));
388+}
389+
390+/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */
391+/**
392+ * Interpolate four 16 bit pixel pairs at once with equal weights 1.
393+ * In particular, A and B can contain two pixels/each in the upper
394+ * and lower halves.
395+ */
396+uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D)
397+{
398+ uint32 x = ((A & qhighBits) >> 2) + ((B & qhighBits) >> 2) + ((C & qhighBits) >> 2) + ((D & qhighBits) >> 2);
399+ uint32 y = ((A & qlowBits) + (B & qlowBits) + (C & qlowBits) + (D & qlowBits)) >> 2;
400+
401+ y &= qlowBits;
402+ return x + y;
403+}
404+
405+uint16 average_three_pixels(uint16 pixel1, uint16 pixel2, uint16 pixel3)
406+{
407+ uint32 rsum, gsum, bsum;
408+
409+ rsum = (pixel1 & 0xF800);
410+ rsum += (pixel2 & 0xF800);
411+ rsum += (pixel3 & 0xF800);
412+ rsum = div3[rsum >> 11];
413+
414+ gsum = (pixel1 & 0x07E0);
415+ gsum += (pixel2 & 0x07E0);
416+ gsum += (pixel3 & 0x07E0);
417+ gsum = div3[gsum >> 5];
418+
419+ bsum = (pixel1 & 0x001F);
420+ bsum += (pixel2 & 0x001F);
421+ bsum += (pixel3 & 0x001F);
422+ bsum = div3[bsum];
423+
424+ return ((rsum << 11) | (gsum << 5) | bsum);
425+}
426+
427+uint16 average_one_third(uint16 pixel1, uint16 pixel2)
428+{
429+ uint32 rsum, gsum, bsum;
430+
431+ rsum = (pixel1 & 0xF800) << 1;
432+ rsum += (pixel2 & 0xF800);
433+ rsum = div3[rsum >> 11];
434+
435+ gsum = (pixel1 & 0x07E0) << 1;
436+ gsum += (pixel2 & 0x07E0);
437+ gsum = div3[gsum >> 5];
438+
439+ bsum = (pixel1 & 0x001F) << 1;
440+ bsum += (pixel2 & 0x001F);
441+ bsum = div3[bsum];
442+
443+ return ((rsum << 11) | (gsum << 5) | bsum);
444+}
445+
446+/* interpolate a diagnoal pixel for linear interpolation on a 3x3 grid */
447+uint16 average_four_pixels_radial(uint16 pixel1, uint16 pixel2,
448+ uint16 pixel3, uint16 pixel4)
449+{
450+ uint32 rsum, gsum, bsum;
451+
452+ rsum = (pixel1 & 0xF800) << 2;
453+ rsum += (pixel2 & 0xF800) << 1;
454+ rsum += (pixel3 & 0xF800) << 1;
455+ rsum += (pixel4 & 0xF800);
456+ rsum = div9[rsum >> 11];
457+
458+ gsum = (pixel1 & 0x07E0) << 2;
459+ gsum += (pixel2 & 0x07E0) << 1;
460+ gsum += (pixel3 & 0x07E0) << 1;
461+ gsum += (pixel4 & 0x07E0);
462+ gsum = div9[gsum >> 5];
463+
464+ bsum = (pixel1 & 0x001F) << 2;
465+ bsum += (pixel2 & 0x001F) << 1;
466+ bsum += (pixel3 & 0x001F) << 1;
467+ bsum += (pixel4 & 0x001F);
468+ bsum = div9[bsum];
469+
470+ return ((rsum << 11) | (gsum << 5) | bsum);
471+}
472+
473+/* perform different interpolations depending on the detected edge */
474+void anti_alias_grid(uint8 *dptr, int dstPitch,
475+ uint16 *pixels, char edge_type)
476+{
477+ uint16 *dptr2;
478+ uint16 tmp_pixel;
479+ uint16 center = pixels[4];
480+ static uint16 tmp[9];
481+ uint16 *ptmp;
482+
483+ switch (edge_type)
484+ {
485+ case 0:
486+ dptr2 = ((uint16 *) (dptr - dstPitch)) - 1;
487+ *dptr2++ = center;
488+ *dptr2++ = center;
489+ *dptr2 = center;
490+ dptr2 = ((uint16 *) dptr) - 1;
491+ *dptr2++ = center;
492+ *dptr2++ = center;
493+ *dptr2 = center;
494+ dptr2 = ((uint16 *) (dptr + dstPitch)) - 1;
495+ *dptr2++ = center;
496+ *dptr2++ = center;
497+ *dptr2 = center;
498+
499+ return;
500+
501+ break;
502+
503+ case '-':
504+ tmp[0] = tmp[3] = tmp[6] = average_one_third(center, pixels[3]);
505+ tmp[1] = tmp[4] = tmp[7] = center;
506+ tmp[2] = tmp[5] = tmp[8] = average_one_third(center, pixels[5]);
507+
508+ if (center == pixels[0]) tmp[0] = center;
509+ if (center == pixels[2]) tmp[2] = center;
510+ if (center == pixels[6]) tmp[6] = center;
511+ if (center == pixels[8]) tmp[8] = center;
512+
513+ if (center == pixels[0] || center == pixels[6])
514+ tmp[3] = INTERPOLATE(tmp[0], tmp[6]);
515+ if (center == pixels[2] || center == pixels[8])
516+ tmp[5] = INTERPOLATE(tmp[2], tmp[8]);
517+
518+ break;
519+
520+ case '|':
521+ tmp[0] = tmp[1] = tmp[2] = average_one_third(center, pixels[1]);
522+ tmp[3] = tmp[4] = tmp[5] = center;
523+ tmp[6] = tmp[7] = tmp[8] = average_one_third(center, pixels[7]);
524+
525+ if (center == pixels[0]) tmp[0] = center;
526+ if (center == pixels[2]) tmp[2] = center;
527+ if (center == pixels[6]) tmp[6] = center;
528+ if (center == pixels[8]) tmp[8] = center;
529+
530+ if (center == pixels[0] || center == pixels[2])
531+ tmp[1] = INTERPOLATE(tmp[0], tmp[2]);
532+ if (center == pixels[6] || center == pixels[8])
533+ tmp[7] = INTERPOLATE(tmp[6], tmp[8]);
534+
535+ break;
536+
537+ case '/':
538+ if (pixels[1] == center && center == pixels[6])
539+ tmp[0] = Q_INTERPOLATE(pixels[1], pixels[3],
540+ center, pixels[6]);
541+ else if (pixels[2] == pixels[3] && pixels[3] == center)
542+ tmp[0] = Q_INTERPOLATE(pixels[1], pixels[2],
543+ pixels[3], center);
544+ else
545+ tmp[0] = average_three_pixels(pixels[1], pixels[3], center);
546+
547+ tmp[2] = average_one_third(center, pixels[2]);
548+
549+ if (pixels[1] == center)
550+ tmp[1] = center;
551+ else
552+ {
553+ tmp_pixel = average_one_third(pixels[1], center);
554+ tmp[1] = Q_INTERPOLATE(tmp_pixel, center,
555+ tmp[0],
556+ tmp[2]);
557+ }
558+
559+ tmp[6] = average_one_third(center, pixels[6]);
560+ if (pixels[2] == center && center == pixels[7])
561+ tmp[8] = Q_INTERPOLATE(pixels[2], center,
562+ pixels[5], pixels[7]);
563+ else if (center == pixels[5] && pixels[5] == pixels[6])
564+ tmp[8] = Q_INTERPOLATE(center, pixels[5],
565+ pixels[6], pixels[7]);
566+ else
567+ tmp[8] = average_three_pixels(center, pixels[5], pixels[7]);
568+
569+ if (pixels[7] == center)
570+ tmp[7] = center;
571+ else
572+ {
573+ tmp_pixel = average_one_third(pixels[7], center);
574+ tmp[7] = Q_INTERPOLATE(tmp_pixel, center,
575+ tmp[6],
576+ tmp[8]);
577+ }
578+
579+ if (pixels[3] == center)
580+ tmp[3] = center;
581+ else
582+ {
583+ tmp_pixel = average_one_third(pixels[3], center);
584+ tmp[3] = Q_INTERPOLATE(tmp_pixel, center,
585+ tmp[0],
586+ tmp[6]);
587+ }
588+
589+ tmp[4] = center;
590+
591+ if (pixels[5] == center)
592+ tmp[5] = center;
593+ else
594+ {
595+ tmp_pixel = average_one_third(pixels[5], center);
596+ tmp[5] = Q_INTERPOLATE(tmp_pixel, center,
597+ tmp[2],
598+ tmp[8]);
599+ }
600+
601+ break;
602+
603+ case '\\':
604+ tmp[0] = average_one_third(center, pixels[0]);
605+
606+ if (pixels[1] == center && center == pixels[8])
607+ tmp[2] = Q_INTERPOLATE(pixels[1], center,
608+ pixels[5], pixels[8]);
609+ else if (pixels[0] == center && center == pixels[5])
610+ tmp[2] = Q_INTERPOLATE(pixels[0], pixels[1],
611+ center, pixels[5]);
612+ else
613+ tmp[2] = average_three_pixels(pixels[1], center, pixels[5]);
614+
615+ if (pixels[1] == center)
616+ tmp[1] = center;
617+ else
618+ {
619+ tmp_pixel = average_one_third(pixels[1], center);
620+ tmp[1] = Q_INTERPOLATE(tmp_pixel, center,
621+ tmp[0],
622+ tmp[2]);
623+ }
624+
625+ if (pixels[0] == center && center == pixels[7])
626+ tmp[6] = Q_INTERPOLATE(pixels[0], pixels[3],
627+ center, pixels[7]);
628+ else if (pixels[3] == center && center == pixels[8])
629+ tmp[6] = Q_INTERPOLATE(pixels[3], center,
630+ pixels[7], pixels[8]);
631+ else
632+ tmp[6] = average_three_pixels(pixels[3], center, pixels[7]);
633+
634+ tmp[8] = average_one_third(center, pixels[8]);
635+
636+ if (pixels[7] == center)
637+ tmp[7] = center;
638+ else
639+ {
640+ tmp_pixel = average_one_third(pixels[7], center);
641+ tmp[7] = Q_INTERPOLATE(tmp_pixel, center,
642+ tmp[6],
643+ tmp[8]);
644+ }
645+
646+ if (pixels[3] == center)
647+ tmp[3] = center;
648+ else
649+ {
650+ tmp_pixel = average_one_third(pixels[3], center);
651+ tmp[3] = Q_INTERPOLATE(tmp_pixel, center,
652+ tmp[0],
653+ tmp[6]);
654+ }
655+
656+ tmp[4] = center;
657+
658+ if (pixels[5] == center)
659+ tmp[5] = center;
660+ else
661+ {
662+ tmp_pixel = average_one_third(pixels[5], center);
663+ tmp[5] = Q_INTERPOLATE(tmp_pixel, center,
664+ tmp[2],
665+ tmp[8]);
666+ }
667+
668+ break;
669+
670+ case '*':
671+ tmp[0] = average_four_pixels_radial(center, pixels[1],
672+ pixels[3], pixels[0]);
673+ tmp[1] = average_one_third(center, pixels[1]);
674+ tmp[2] = average_four_pixels_radial(center, pixels[1],
675+ pixels[5], pixels[2]);
676+ tmp[3] = average_one_third(center, pixels[3]);
677+ tmp[4] = center;
678+ tmp[5] = average_one_third(center, pixels[5]);
679+ tmp[6] = average_four_pixels_radial(center, pixels[3],
680+ pixels[7], pixels[6]);
681+ tmp[7] = average_one_third(center, pixels[7]);
682+ tmp[8] = average_four_pixels_radial(center, pixels[5],
683+ pixels[7], pixels[8]);
684+
685+
686+ if (center == pixels[1])
687+ tmp[0] = tmp[2] = center;
688+ if (center == pixels[3])
689+ tmp[0] = tmp[6] = center;
690+ if (center == pixels[5])
691+ tmp[2] = tmp[8] = center;
692+ if (center == pixels[7])
693+ tmp[6] = tmp[8] = center;
694+
695+ if (center == pixels[0])
696+ tmp[0] = center;
697+ if (center == pixels[2])
698+ tmp[2] = center;
699+ if (center == pixels[6])
700+ tmp[6] = center;
701+ if (center == pixels[8])
702+ tmp[8] = center;
703+
704+ break;
705+
706+ default:
707+ return;
708+
709+ break;
710+ }
711+
712+ ptmp = tmp;
713+ dptr2 = ((uint16 *) (dptr - dstPitch)) - 1;
714+ *dptr2++ = *ptmp++;
715+ *dptr2++ = *ptmp++;
716+ *dptr2 = *ptmp++;
717+ dptr2 = ((uint16 *) dptr) - 1;
718+ *dptr2++ = *ptmp++;
719+ *dptr2++ = *ptmp++;
720+ *dptr2 = *ptmp++;
721+ dptr2 = ((uint16 *) (dptr + dstPitch)) - 1;
722+ *dptr2++ = *ptmp++;
723+ *dptr2++ = *ptmp++;
724+ *dptr2 = *ptmp;
725+}
726+
727+/* perform edge detection, then interpolate */
728+void anti_alias_pass(const uint8 *src, uint8 *dst,
729+ int w, int h, int w_new, int h_new,
730+ int srcPitch, int dstPitch)
731+{
732+ int x, y;
733+ const uint16 *sptr16;
734+ uint16 *dptr16;
735+
736+ for (y = 0; y < h; y++)
737+ {
738+ sptr16 = ((const uint16 *) (src + y * srcPitch)) + 0;
739+ dptr16 = ((uint16 *) (dst + y * dstPitch * 3 + dstPitch)) + 1 + 0;
740+ for (x = 0; x < w; x++, sptr16++, dptr16 += 3)
741+ {
742+ const uint16 *sptr2, *addr3;
743+ static uint16 pixels[9];
744+ uint16 *pptr = pixels;
745+ char edge_type;
746+
747+ sptr2 = ((const uint16 *) ((const uint8 *) sptr16 - srcPitch)) - 1;
748+ addr3 = ((const uint16 *) ((const uint8 *) sptr16 + srcPitch)) + 1;
749+
750+ /* fill the 3x3 grid */
751+ if (sptr2 >= src_addr_min && addr3 <= src_addr_max)
752+ {
753+ memcpy(pixels, sptr2, 3*sizeof(uint16));
754+ memcpy(pixels+3, sptr16 - 1, 3*sizeof(uint16));
755+ memcpy(pixels+6, addr3 - 2, 3*sizeof(uint16));
756+ }
757+ else /* if we go off the screen, set the pixel to 0 */
758+ {
759+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
760+ *pptr++ = *sptr2++;
761+ else {
762+ *pptr++ = 0;
763+ sptr2++;
764+ }
765+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
766+ *pptr++ = *sptr2++;
767+ else {
768+ *pptr++ = 0;
769+ sptr2++;
770+ }
771+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
772+ *pptr++ = *sptr2;
773+ else
774+ *pptr++ = 0;
775+
776+ sptr2 = sptr16 - 1;
777+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
778+ *pptr++ = *sptr2++;
779+ else {
780+ *pptr++ = 0;
781+ sptr2++;
782+ }
783+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
784+ *pptr++ = *sptr2++;
785+ else {
786+ *pptr++ = 0;
787+ sptr2++;
788+ }
789+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
790+ *pptr++ = *sptr2;
791+ else
792+ *pptr++ = 0;
793+
794+ sptr2 = addr3 - 2;
795+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
796+ *pptr++ = *sptr2++;
797+ else {
798+ *pptr++ = 0;
799+ sptr2++;
800+ }
801+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
802+ *pptr++ = *sptr2++;
803+ else {
804+ *pptr++ = 0;
805+ sptr2++;
806+ }
807+ if (sptr2 >= src_addr_min && sptr2 <= src_addr_max)
808+ *pptr = *sptr2;
809+ else
810+ *pptr = 0;
811+ }
812+
813+ edge_type = convolve_edges_compass_luma(pixels, x, y, w);
814+ anti_alias_grid((uint8 *) dptr16, dstPitch, pixels, edge_type);
815+ }
816+ }
817+}
818+
819+void initialize_tables(const uint8 *srcPtr, uint32 srcPitch,
820+ uint8 *dstPtr, uint32 dstPitch,
821+ int width, int height)
822+{
823+ double r_float, g_float, b_float, luma;
824+ int r, g, b;
825+
826+ /* initialize luma table */
827+ for (r = 0; r < 32; r++)
828+ {
829+ r_float = r / 31.0;
830+
831+ for (g = 0; g < 64; g++)
832+ {
833+ g_float = g / 63.0;
834+
835+ for (b = 0; b < 32; b++)
836+ {
837+ b_float = b / 31.0;
838+
839+ luma = 0.299*r_float + 0.587*g_float + 0.114*b_float;
840+ luma_table[(r << 11) | (g << 5) | b] =
841+ (int32)(luma * (1 << LUMA_SHIFT) + 0.5);
842+ }
843+ }
844+ }
845+
846+ /* initialize interpolation division tables */
847+ for (r = 0; r <= 189; r++)
848+ div3[r] = ((r<<1)+1) / 6;
849+ for (r = 0; r <= 567; r++)
850+ div9[r] = ((r<<1)+1) / 18;
851+
852+ /* set initial best guess on min/max screen addresses */
853+ src_addr_min = (const uint16 *) srcPtr;
854+ src_addr_max = ((const uint16 *) (srcPtr + (height - 1) * srcPitch)) +
855+ (width - 1);
856+}
857+
858+void Edge3x(const uint8 *srcPtr, uint32 srcPitch,
859+ uint8 *dstPtr, uint32 dstPitch, int width, int height)
860+{
861+ /* initialize stuff */
862+ if (!edge3x_init_flag)
863+ {
864+ initialize_tables(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
865+ edge3x_init_flag = 1;
866+ }
867+
868+ /* ah ha, we're doing the whole screen, so we can save the bounds of the
869+ src array for later bounds checking */
870+ if (width == g_system->getWidth() &&
871+ height == g_system->getHeight())
872+ {
873+ src_addr_min = (const uint16 *) srcPtr;
874+ src_addr_max = ((const uint16 *) (srcPtr + (height - 1) * srcPitch)) +
875+ (width - 1);
876+ }
877+
878+ anti_alias_pass(srcPtr, dstPtr, width, height,
879+ 3*width, 3*height, srcPitch, dstPitch);
880+}
881diff -ruN -u scummvm_old/common/scaler.h scummvm_new/common/scaler.h
882--- scummvm_old/common/scaler.h 2004-05-21 15:43:08.000000000 -0500
883+++ scummvm_new/common/scaler.h 2004-11-06 04:54:22.000000000 -0600
884@@ -45,6 +45,7 @@
885 DECLARE_SCALER(DotMatrix);
886 DECLARE_SCALER(HQ2x);
887 DECLARE_SCALER(HQ3x);
888+DECLARE_SCALER(Edge3x);
889
890 FORCEINLINE int real2Aspect(int y) {
891 return y + (y + 1) / 5;
892@@ -70,7 +71,8 @@
893 GFX_HQ2X = 8,
894 GFX_HQ3X = 9,
895 GFX_TV2X = 10,
896- GFX_DOTMATRIX = 11
897+ GFX_DOTMATRIX = 11,
898+ GFX_EDGE3X = 12
899 };
900
901