karbon
vflattencmd.cc
00001 /* This file is part of the KDE project 00002 Copyright (C) 2002, 2003 The Karbon Developers 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "vflattencmd.h" 00021 #include <klocale.h> 00022 00023 #include <core/vpath.h> 00024 #include <core/vsegment.h> 00025 00026 // TODO: Think about if we want to adapt this: 00027 00028 /* 00029 * <cite from GNU ghostscript's gxpflat.c> 00030 * 00031 * To calculate how many points to sample along a path in order to 00032 * approximate it to the desired degree of flatness, we define 00033 * dist((x,y)) = abs(x) + abs(y); 00034 * then the number of points we need is 00035 * N = 1 + sqrt(3/4 * D / flatness), 00036 * where 00037 * D = max(dist(p0 - 2*p1 + p2), dist(p1 - 2*p2 + p3)). 00038 * Since we are going to use a power of 2 for the number of intervals, 00039 * we can avoid the square root by letting 00040 * N = 1 + 2^(ceiling(log2(3/4 * D / flatness) / 2)). 00041 * (Reference: DEC Paris Research Laboratory report #1, May 1989.) 00042 * 00043 * We treat two cases specially. First, if the curve is very 00044 * short, we halve the flatness, to avoid turning short shallow curves 00045 * into short straight lines. Second, if the curve forms part of a 00046 * character (indicated by flatness = 0), we let 00047 * N = 1 + 2 * max(abs(x3-x0), abs(y3-y0)). 00048 * This is probably too conservative, but it produces good results. 00049 * 00050 * </cite from GNU ghostscript's gxpflat.c> 00051 */ 00052 00053 00054 VFlattenCmd::VFlattenCmd( VDocument *doc, double flatness ) 00055 : VReplacingCmd( doc, i18n( "Flatten Curves" ) ) 00056 { 00057 m_flatness = flatness > 0.0 ? flatness : 1.0; 00058 } 00059 00060 void 00061 VFlattenCmd::visitVSubpath( VSubpath& path ) 00062 { 00063 path.first(); 00064 00065 // Ommit first segment. 00066 while( path.next() ) 00067 { 00068 while( !path.current()->isFlat( m_flatness ) ) 00069 { 00070 // Split at midpoint. 00071 path.insert( 00072 path.current()->splitAt( 0.5 ) ); 00073 } 00074 00075 // Convert to line. 00076 path.current()->setDegree( 1 ); 00077 00078 if( !success() ) 00079 setSuccess(); 00080 } 00081 } 00082