vflattencmd.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002, 2003 The Karbon Developers
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "vflattencmd.h"
21#include <tdelocale.h>
22
23#include <core/vpath.h>
24#include <core/vsegment.h>
25
26// TODO: Think about if we want to adapt this:
27
28/*
29 * <cite from GNU ghostscript's gxpflat.c>
30 *
31 * To calculate how many points to sample along a path in order to
32 * approximate it to the desired degree of flatness, we define
33 * dist((x,y)) = abs(x) + abs(y);
34 * then the number of points we need is
35 * N = 1 + sqrt(3/4 * D / flatness),
36 * where
37 * D = max(dist(p0 - 2*p1 + p2), dist(p1 - 2*p2 + p3)).
38 * Since we are going to use a power of 2 for the number of intervals,
39 * we can avoid the square root by letting
40 * N = 1 + 2^(ceiling(log2(3/4 * D / flatness) / 2)).
41 * (Reference: DEC Paris Research Laboratory report #1, May 1989.)
42 *
43 * We treat two cases specially. First, if the curve is very
44 * short, we halve the flatness, to avoid turning short shallow curves
45 * into short straight lines. Second, if the curve forms part of a
46 * character (indicated by flatness = 0), we let
47 * N = 1 + 2 * max(abs(x3-x0), abs(y3-y0)).
48 * This is probably too conservative, but it produces good results.
49 *
50 * </cite from GNU ghostscript's gxpflat.c>
51 */
52
53
54VFlattenCmd::VFlattenCmd( VDocument *doc, double flatness )
55 : VReplacingCmd( doc, i18n( "Flatten Curves" ) )
56{
57 m_flatness = flatness > 0.0 ? flatness : 1.0;
58}
59
60void
61VFlattenCmd::visitVSubpath( VSubpath& path )
62{
63 path.first();
64
65 // Ommit first segment.
66 while( path.next() )
67 {
68 while( !path.current()->isFlat( m_flatness ) )
69 {
70 // Split at midpoint.
71 path.insert(
72 path.current()->splitAt( 0.5 ) );
73 }
74
75 // Convert to line.
76 path.current()->setDegree( 1 );
77
78 if( !success() )
79 setSuccess();
80 }
81}
82
All non-visual, static doc info is in here.
Definition vdocument.h:53
VReplacingCmd is a generic command.
bool isFlat(double flatness=VGlobal::flatnessTolerance) const
Returns true if the segment is flat.
Definition vsegment.cpp:139
void setDegree(unsigned short deg)
Sets the segment's degree and thus resizes the array of node data.
Definition vsegment.cpp:72
VSegment * splitAt(double t)
Splits the segment at parameter 0 <= t <= 1.
Definition vsegment.cpp:857
VSubpath provides a sophisticated list of VSegment.
Definition vpath.h:43