/*
* Copyright 2012 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand.calc;
import com.mandelsoft.mand.*;
/**
*
* @author Uwe Krueger
*/
public class OptimizedAreaCalculator extends AreaCalculator {
protected void calc(PixelIterator pi, CalculationContext c)
{ int u;
int sy=c.getSY();
int sx=c.getSX();
int ny=c.getNY();
int nx=c.getNX();
calcHLine(pi,c,sx, sy, nx);
calcHLine(pi,c,sx, sy+ny-1, nx);
calcVLine(pi,c,sx, sy+1, ny-2);
u=calcVLine(pi,c,sx+nx-1, sy+1, ny-2);
calcBox(pi,c, u, sx,sy,nx,ny);
}
private int calcHLine(PixelIterator pi, CalculationContext c,
int sx, int sy, int n)
{
pi.setX(sx);
pi.setY(sy);
int u=handle(pi,c, sx,sy);
for (int x=sx+1; x<sx+n; x++) {
pi.setX(x);
int it=handle(pi,c, x,sy);
if (it!=u) u=-1;
}
return u;
}
private int calcVLine(PixelIterator pi, CalculationContext c, int sx, int sy, int n)
{
pi.setX(sx);
pi.setY(sy);
int u=handle(pi,c, sx,sy);
for (int y=sy+1; y<sy+n; y++) {
pi.setY(y);
int it=handle(pi,c, sx,y);
if (it!=u) u=-1;
}
return u;
}
private void calcBox(PixelIterator pi, CalculationContext c,
int u, int sx, int sy, int nx, int ny)
{
//System.out.println("calcBox "+sx+","+sy+"("+nx+"x"+ny+")");
if (nx<=2 || ny<=2) return;
if (u>=0) {
u=checkHLine(c, u, sx, sy, nx);
u=checkHLine(c, u, sx, sy+ny-1, nx);
u=checkVLine(c, u, sx, sy+1, ny-2);
u=checkVLine(c, u, sx+nx-1, sy+1, ny-2);
if (u>=0) {
fillBox(c, sx+1,sy+1,nx-2,ny-2,u);
return;
}
}
if (nx>ny) {
// divide horizontally
int s=(nx-1)/2;
if (s!=0) {
//System.out.println("s="+s);
u=calcVLine(pi,c, sx+s,sy+1,ny-2);
calcBox(pi,c, u,sx,sy,s+1,ny);
calcBox(pi,c, u,sx+s,sy,nx-s,ny);
}
}
else {
// divide vertically
int s=(ny-1)/2;
if (s!=0) {
u=calcHLine(pi,c, sx+1,sy+s,nx-2);
calcBox(pi,c, u,sx,sy,nx,s+1);
calcBox(pi,c, u,sx,sy+s,nx,ny-s);
}
}
}
private int checkHLine(CalculationContext c, int u, int sx, int sy, int n)
{
if (u>=0) for (int x=sx; x<sx+n; x++) {
if (c.getDataRel(x,sy)!=u) return -1;
}
return u;
}
private int checkVLine(CalculationContext c, int u, int sx, int sy, int n)
{
if (u>=0) for (int y=sy; y<sy+n; y++) {
if (c.getDataRel(sx,y)!=u) return -1;
}
return u;
}
private void fillBox(CalculationContext c, int sx, int sy, int nx, int ny, int u)
{
//System.out.println("fill "+sx+","+sy+"("+nx+"x"+ny+") with "+u);
for (int y=sy; y<sy+ny; y++) {
for (int x=sx; x<sx+nx; x++) {
c.setDataRel(x,y,u);
}
}
if (u==0) c.addMCnt(nx*ny);
}
}