00001 // $Id: bevtrap.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 #include "camtypes.h" 00099 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00100 #include "pathproc.h" 00101 #include "pathtrap.h" 00102 #include "bevtrap.h" 00103 #include "beveler.h" 00104 #include "ppbevel.h" 00105 00106 CC_IMPLEMENT_DYNCREATE(CCreateBevelTrapezoids, CCObject) 00107 00108 /******************************************************************************************** 00109 > BOOL CCreateBevelTrapezoids::ProcessPath(Path * pPath, TrapsList *RetnTraps, INT32 indent); 00110 00111 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00112 Created: 20/11/98 00113 Purpose: Turns the path into trapezoids which can be used for the bevelling 00114 Inputs: The source path and the trapezoid list (already initialised) to use 00115 Returns: - 00116 Coments: Only works on single paths i.e. only ones with PT_MOVETO as coord (0) and 00117 no-where else. In other words, no sub-paths are allowed. 00118 SeeAlso: - 00119 00120 ********************************************************************************************/ 00121 #if 0 // It is not clear what was commented out here and when and why - there are 3 ProcessPath functions! - AB20060106 00122 /* 00123 BOOL CCreateBevelTrapezoids::ProcessPath(Path * pPath, TrapsList *RetnTraps, INT32 indent, 00124 BOOL bOuterBevel, JointType jType) 00125 { 00126 if (!pPath) 00127 return TRUE; 00128 00129 if (pPath->GetNumCoords() < 3) 00130 return TRUE; 00131 00132 BevelHelpers::EliminateMultiplePoints(pPath); 00133 00134 // calculate all the normals 00135 TrapEdgeList * pEdgeList = RetnTraps->AddEdgeList(); 00136 TrapEdge * pEdge = NULL; 00137 TrapEdge * pEdgeBefore = NULL; 00138 TrapEdge * pEdgeAfter = NULL; 00139 00140 NormCoord nctmp1; 00141 NormCoord nctmp2; 00142 NormCoord nc1; 00143 NormCoord nc2; 00144 NormCoord nc3; 00145 00146 double len1 = 0.0; 00147 double len2 = 0.0; 00148 double dot = 0.0; 00149 double len = 0.0; 00150 00151 for (INT32 i = 0; i < pPath->GetNumCoords()-1; i++) 00152 { 00153 nc1.x = -(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].x - pPath->GetCoordArray()[i].x); 00154 nc1.y = -(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].y - pPath->GetCoordArray()[i].y); 00155 nc2.x = +(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].x - pPath->GetCoordArray()[i].x); 00156 nc2.y = +(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].y - pPath->GetCoordArray()[i].y); 00157 len1 = nc1.GetLength(); 00158 len2 = nc2.GetLength(); 00159 00160 if (len1 > 0.0 && 00161 len2 > 0.0 && 00162 (nc1.x != 0 || nc1.y != 0) && 00163 (nc2.x != 0 || nc2.y != 0)) 00164 { 00165 nc1.x /= len1; 00166 nc1.y /= len1; 00167 nc2.x /= len2; 00168 nc2.y /= len2; 00169 00170 NormCoord nc4( -nc1.y,+nc1.x ) ; 00171 NormCoord nc5( -nc2.y,+nc2.x ) ; 00172 00173 dot = nc1.x*nc2.x+nc1.y*nc2.y; 00174 00175 if ( bOuterBevel != nc2.y*nc1.x>nc2.x*nc1.y ) 00176 if ( jType==RoundJoin ) 00177 { 00178 AddEdgeToList (pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00179 CreateRoundJoin(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, &nc5 ); 00180 AddEdgeToList (pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00181 00182 } 00183 else if ( jType==BevelledJoin ) 00184 // else if ( (jType==BevelledJoin || jType==MitreJoin && dot<-0.707) ) 00185 { 00186 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00187 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00188 } 00189 else 00190 { 00191 if ( dot+1.0>0.0 ) 00192 { 00193 len = 1.0/(dot+1.0) ; 00194 nc3.x = (nc4.x+nc5.x)*len; 00195 nc3.y = (nc4.y+nc5.y)*len; 00196 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 0); 00197 } 00198 } 00199 else 00200 { 00201 // add a single edge to the list to be coped with later 00202 // marking it with position 1 00203 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00204 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00205 } 00206 } 00207 } 00208 00209 // add first edge as the last edge in the list 00210 if (pEdgeList && pEdgeList->GetNumEdges() > 0) 00211 { 00212 pEdge = pEdgeList->GetTrapEdge(0); 00213 if (pEdge) 00214 AddEdgeToList(pEdgeList, &(pEdge->Centre), &(pEdge->Normal), pEdge->Position); 00215 } 00216 00217 return TRUE; 00218 } 00219 */ 00220 /* 00221 BOOL CCreateBevelTrapezoids::ProcessPath(Path * pPath, TrapsList *RetnTraps, INT32 indent, 00222 BOOL bOuterBevel, JointType jType) 00223 { 00224 if (!pPath) 00225 return TRUE; 00226 00227 if (pPath->GetNumCoords() < 3) 00228 return TRUE; 00229 00230 // calculate all the normals 00231 TrapEdgeList * pEdgeList = RetnTraps->AddEdgeList(); 00232 TrapEdge * pEdge = NULL; 00233 TrapEdge * pEdge2 = NULL; 00234 00235 for (INT32 i = 0; i < pPath->GetNumCoords()-1; i++) 00236 { 00237 NormCoord nc1; 00238 NormCoord nc2; 00239 nc1.x = -(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].x - pPath->GetCoordArray()[i].x); 00240 nc1.y = -(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].y - pPath->GetCoordArray()[i].y); 00241 nc2.x = +(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].x - pPath->GetCoordArray()[i].x); 00242 nc2.y = +(pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].y - pPath->GetCoordArray()[i].y); 00243 double len1 = nc1.GetLength(); 00244 double len2 = nc2.GetLength(); 00245 00246 if (len1 > 0.0 && 00247 len2 > 0.0 && 00248 (nc1.x != 0 || nc1.y != 0) && 00249 (nc2.x != 0 || nc2.y != 0)) 00250 { 00251 nc1.x /= len1; 00252 nc1.y /= len1; 00253 nc2.x /= len2; 00254 nc2.y /= len2; 00255 00256 NormCoord nc4( -nc1.y,+nc1.x ) ; 00257 NormCoord nc5( -nc2.y,+nc2.x ) ; 00258 00259 bool bOuter = bOuterBevel != nc2.y*nc1.x>nc2.x*nc1.y ; 00260 00261 if ( bOuter && jType==RoundJoin ) 00262 { 00263 AddEdgeToList (pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00264 CreateRoundJoin(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, &nc5 ); 00265 AddEdgeToList (pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00266 } 00267 else if ( bOuter && jType==BevelledJoin ) 00268 // else if ( bOuter && (jType==BevelledJoin || jType==MitreJoin && dot<-0.707) ) 00269 { 00270 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00271 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00272 } 00273 else 00274 { 00275 double dot = nc1.x*nc2.x+nc1.y*nc2.y; 00276 if ( dot!=-1.0 ) 00277 { 00278 double len = 1.0/(dot+1.0) ; 00279 NormCoord nc3; 00280 nc3.x = (nc4.x+nc5.x)*len; 00281 nc3.y = (nc4.y+nc5.y)*len; 00282 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 0); 00283 // AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, !bOuter); 00284 } 00285 } 00286 } 00287 } 00288 00289 // FlattenInnerPoints(pEdgeList, indent, bOuterBevel); 00290 00291 // add first edge as the last edge in the list 00292 if (pEdgeList && pEdgeList->GetNumEdges() > 0) 00293 { 00294 pEdge = pEdgeList->GetTrapEdge(0); 00295 if (pEdge) 00296 { 00297 // MUST do it this way since the original edge memory allocation may 00298 // change with a change in the list 00299 DocCoord Centre2 = pEdge->Centre; 00300 NormCoord Normal2 = pEdge->Normal; 00301 00302 AddEdgeToList(pEdgeList, &Centre2, &Normal2, 0); 00303 } 00304 } 00305 00306 return TRUE; 00307 } 00308 */ 00309 /* 00310 BOOL CCreateBevelTrapezoids::ProcessPath(Path * pPath, TrapsList *RetnTraps, INT32 indent, 00311 BOOL bOuterBevel, JointType jType) 00312 { 00313 if (!pPath) 00314 return TRUE; 00315 00316 if (pPath->GetNumCoords() < 3) 00317 return TRUE; 00318 00319 // calculate all the normals 00320 TrapEdgeList * pEdgeList = RetnTraps->AddEdgeList(); 00321 TrapEdge * pEdge = NULL; 00322 TrapEdge * pEdge2 = NULL; 00323 00324 NormCoord nc1; 00325 NormCoord nc2; 00326 NormCoord nc3; 00327 00328 NormCoord nc4; 00329 NormCoord nc5; 00330 00331 double dot = 0; 00332 double len1 = 0; 00333 double len2 = 0; 00334 double len3 = 0; 00335 double len = 0; 00336 00337 BOOL bOuter = FALSE; 00338 00339 double dTmp = 0; 00340 00341 for (INT32 i = 0; i < pPath->GetNumCoords()-1; i++) 00342 { 00343 nc1.x = pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].x - pPath->GetCoordArray()[i].x; 00344 nc1.y = pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, -1)].y - pPath->GetCoordArray()[i].y; 00345 nc1.x = -nc1.x; 00346 nc1.y = -nc1.y; 00347 00348 len1 = nc1.GetLength(); 00349 00350 nc2.x = pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].x - pPath->GetCoordArray()[i].x; 00351 nc2.y = pPath->GetCoordArray()[AlterIndex(i, pPath->GetNumCoords()-1, +1)].y - pPath->GetCoordArray()[i].y; 00352 len2 = nc2.GetLength(); 00353 00354 if (len1 > 0.0 && 00355 len2 > 0.0 && 00356 (nc1.x != 0 || nc1.y != 0) && 00357 (nc2.x != 0 || nc2.y != 0)) 00358 { 00359 nc1.x /= len1; 00360 nc1.y /= len1; 00361 nc2.x /= len2; 00362 nc2.y /= len2; 00363 00364 dot = nc1.x * nc2.x + nc1.y * nc2.y; 00365 00366 bOuter = bOuterBevel^IsOuterTurn(&nc1, &nc2); 00367 00368 nc3.x = (-nc1.x) + nc2.x; 00369 nc3.y = (-nc1.y) + nc2.y; 00370 00371 if (dot >= 0.05) 00372 { 00373 // flat cap, for large outer turn 00374 // rotate both normals in & out by 90 degrees 00375 00376 nc4.x = -nc1.y; 00377 nc4.y = nc1.x; 00378 00379 nc5.x = -nc2.y; 00380 nc5.y = nc2.x; 00381 00382 if (bOuter) 00383 { 00384 00385 nc3.x = (nc4.x + nc5.x) / 2.0; 00386 nc3.y = (nc4.y + nc5.y) / 2.0; 00387 00388 len = nc3.GetLength(); 00389 00390 if (len > 0) 00391 { 00392 nc3.x /= len; 00393 nc3.y /= len; 00394 } 00395 00396 if (len > 0) 00397 { 00398 if (jType == RoundJoin) 00399 { 00400 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00401 CreateRoundJoin(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, &nc5, &nc3); 00402 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00403 } 00404 else if (jType == MitreJoin) 00405 { 00406 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 0); 00407 } 00408 else if (jType == BevelledJoin) 00409 { 00410 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00411 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00412 } 00413 } 00414 } 00415 else 00416 { 00417 00418 nc3.x = (nc4.x + nc5.x); 00419 nc3.y = (nc4.y + nc5.y); 00420 00421 len = nc3.GetLength(); 00422 if (len > 0) 00423 { 00424 if (!bOuterBevel || dot > 0.707) 00425 { 00426 nc3.x /= len; 00427 nc3.y /= len; 00428 } 00429 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 1); 00430 } 00431 } 00432 } 00433 else 00434 { 00435 00436 nc4.x = -nc1.y; 00437 nc4.y = nc1.x; 00438 00439 nc5.x = -nc2.y; 00440 nc5.y = nc2.x; 00441 00442 // calculate the centre point 00443 nc3.x = nc2.x - nc1.x; 00444 nc3.y = nc2.y - nc1.y; 00445 00446 if (!bOuterBevel) 00447 { 00448 if (bOuter) 00449 { 00450 len3 = nc3.GetLength(); 00451 if (len3 > 0) 00452 { 00453 nc3.x /= len3; 00454 nc3.y /= len3; 00455 00456 } 00457 00458 if (jType == RoundJoin) 00459 { 00460 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00461 CreateRoundJoin(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, &nc5, &nc3); 00462 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00463 } 00464 else if (jType == MitreJoin) 00465 { 00466 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 0); 00467 } 00468 else if (jType == BevelledJoin) 00469 { 00470 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00471 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00472 } 00473 } 00474 else 00475 { 00476 nc3.x = -nc3.x; 00477 nc3.y = -nc3.y; 00478 00479 len = nc3.GetLength(); 00480 00481 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 1); 00482 } 00483 } 00484 else 00485 { 00486 // rotate these by 90 degrees 00487 nc4.x = nc1.x; 00488 nc4.y = nc1.y; 00489 00490 dTmp = nc4.x; 00491 nc4.x = -nc4.y; 00492 nc4.y = dTmp; 00493 00494 nc5.x = -nc2.x; 00495 nc5.y = -nc2.y; 00496 00497 nc3.x = -nc3.x; 00498 nc3.y = -nc3.y; 00499 00500 dTmp = nc5.x; 00501 00502 nc5.x = nc5.y; 00503 nc5.y = -dTmp; 00504 00505 if (bOuter) 00506 { 00507 len3 = nc3.GetLength(); 00508 if (len3 > 0) 00509 { 00510 nc3.x /= len3; 00511 nc3.y /= len3; 00512 } 00513 00514 if (jType == RoundJoin) 00515 { 00516 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00517 CreateRoundJoin(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, &nc5, &nc3); 00518 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00519 } 00520 else if (jType == MitreJoin) 00521 { 00522 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 0); 00523 } 00524 else if (jType == BevelledJoin) 00525 { 00526 nc4.x = -nc1.y; 00527 nc4.y = nc1.x; 00528 00529 nc5.x = -nc2.y; 00530 nc5.y = nc2.x; 00531 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc4, 0); 00532 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc5, 0); 00533 } 00534 } 00535 else 00536 { 00537 nc3.x = -nc3.x; 00538 nc3.y = -nc3.y; 00539 00540 len = nc3.GetLength(); 00541 00542 if (len > 0) 00543 { 00544 if (!bOuterBevel || dot < -0.707) 00545 { 00546 nc3.x /= len; 00547 nc3.y /= len; 00548 } 00549 } 00550 00551 if (len > 0) 00552 { 00553 AddEdgeToList(pEdgeList, &(pPath->GetCoordArray()[i]), &nc3, 1); 00554 } 00555 00556 } 00557 } 00558 } 00559 } 00560 } 00561 00562 FlattenInnerPoints(pEdgeList, indent, bOuterBevel); 00563 00564 // add first edge as the last edge in the list 00565 if (pEdgeList) 00566 { 00567 if (pEdgeList->GetNumEdges() > 0) 00568 { 00569 pEdge = pEdgeList->GetTrapEdge(0); 00570 00571 if (pEdge) 00572 { 00573 AddEdgeToList(pEdgeList, &(pEdge->Centre), &(pEdge->Normal), pEdge->Position); 00574 } 00575 } 00576 } 00577 00578 return TRUE; 00579 } 00580 */ 00581 00582 /******************************************************************************************** 00583 > void CCreateBevelTrapezoids::ProcessTrapsForBevelling(Path * pPath, 00584 TrapsList *RetnTraps, INT32 indent) 00585 00586 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00587 Created: 25/10/98 00588 Purpose: Takes a path and gives out the trapezoid list to use 00589 Inputs: The traps list to use as source, the traps list to enter the data into 00590 and the indent to use (if negative, then this denotes an outer bevel). 00591 Returns: - 00592 Coments: 'Rounds' corners according to line cap. 00593 Inner turns are rounded so that highlights occur 00594 Outer turns are capped 00595 SeeAlso: - 00596 00597 ********************************************************************************************/ 00598 00599 BOOL CCreateBevelTrapezoids::ProcessTrapsForBevelling(Path *pPath, TrapsList *RetnTraps, 00600 INT32 indent, JointType jType, 00601 BOOL bOuter) 00602 { 00603 if (!pPath || !RetnTraps || indent == 0) 00604 return FALSE; 00605 00606 BOOL bSmooth = FALSE; 00607 00608 if (bOuter || CBeveler::m_bQuick) 00609 bSmooth = FALSE; 00610 00611 // temporary traps list 00612 TrapsList * pTmpTraps = new TrapsList; 00613 00614 // first, flatten the path 00615 Path FlatPath; 00616 FlatPath.Initialise(); 00617 00618 ProcessFlatten pf(BEVEL_FLATNESS); 00619 ProcessFlags pfFlags(TRUE, FALSE, FALSE); 00620 pf.FlattenPath(pfFlags, pPath, &FlatPath); 00621 00622 Path SubPath; 00623 SubPath.Initialise(); 00624 00625 Path EliminatedPath; 00626 EliminatedPath.Initialise(); 00627 00628 EliminateMultpilePoints(&FlatPath, &EliminatedPath); 00629 pPath = &EliminatedPath; 00630 00631 DocCoord LastPoint(0,0); 00632 DocCoord ThisPoint; 00633 DocCoord dc1; 00634 DocCoord dc2; 00635 00636 TrapsList * pDestTraps = NULL; 00637 00638 // don't do smoothing when told not to 00639 if (!bSmooth) 00640 { 00641 pDestTraps = RetnTraps; 00642 } 00643 else 00644 { 00645 pDestTraps = pTmpTraps; 00646 } 00647 00648 // need to seperate subpaths out, and then use ProcessPath to turn them into trapezoid lists 00649 for (INT32 i = 0 ; i < FlatPath.GetNumCoords(); i++) 00650 { 00651 // new sub-path ? 00652 if (FlatPath.GetVerbArray()[i] == PT_MOVETO || (i == FlatPath.GetNumCoords() - 1)) 00653 { 00654 // make sure we don't miss the last point 00655 if (i == FlatPath.GetNumCoords() - 1) 00656 { 00657 // since path has been flattened, then just add the points in as line-tos 00658 ThisPoint = FlatPath.GetCoordArray()[i]; 00659 00660 if (ThisPoint.x != LastPoint.x || 00661 ThisPoint.y != LastPoint.y) 00662 { 00663 SubPath.AddLineTo(ThisPoint); 00664 } 00665 00666 LastPoint = ThisPoint; 00667 } 00668 00669 // process the path into trapezoids 00670 if (SubPath.GetNumCoords() > 0 && i > 0) 00671 { 00672 // call process path 00673 // but check that the first point & last points in the paths are 00674 // the same (i.e. it is closed !) 00675 dc1 = SubPath.GetCoordArray()[0]; 00676 dc2 = SubPath.GetCoordArray()[SubPath.GetNumCoords() - 1]; 00677 00678 if (dc1.x != dc2.x || 00679 dc1.y != dc2.y) 00680 { 00681 SubPath.AddLineTo(dc1); 00682 } 00683 00684 if (!ProcessPath(&SubPath, pDestTraps, indent, bOuter, jType)) 00685 { 00686 delete pTmpTraps; 00687 pTmpTraps = NULL; 00688 return FALSE; 00689 } 00690 } 00691 00692 // clear the path and add the new point 00693 SubPath.ClearPath(FALSE); 00694 SubPath.AddMoveTo(FlatPath.GetCoordArray()[i]); 00695 } 00696 else 00697 { 00698 // since path has been flattened, then just add the points in as line-tos 00699 ThisPoint = FlatPath.GetCoordArray()[i]; 00700 00701 if (ThisPoint.x != LastPoint.x || 00702 ThisPoint.y != LastPoint.y) 00703 { 00704 SubPath.AddLineTo(ThisPoint); 00705 } 00706 00707 LastPoint = ThisPoint; 00708 } 00709 } 00710 00711 if (bSmooth) 00712 { 00713 if (!SmoothCorners(pDestTraps, RetnTraps, (double)indent, bOuter)) 00714 { 00715 delete pTmpTraps; 00716 pTmpTraps = NULL; 00717 return FALSE; 00718 } 00719 } 00720 00721 delete pTmpTraps; 00722 pTmpTraps = NULL; 00723 00724 return TRUE; 00725 } 00726 #endif 00727 00728 /******************************************************************************************** 00729 > void CCreateBevelTrapezoids::CalculateIntersection(DocCoord * start1, NormCoord * dir1, 00730 DocCoord * start2, NormCoord * dir2, 00731 DocCoord * point, double * p, double * q) 00732 00733 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00734 Created: 24/9/98 00735 Purpose: Calculates the intersection between 2 lines 00736 Inputs: Start point and direction of each of the lines 00737 Returns: The point in *point and the distance along dir1 from start1 of this point. 00738 Also returns FALSE if the lines are in the same direction (i.e. no intersection) 00739 SeeAlso: - 00740 00741 ********************************************************************************************/ 00742 00743 BOOL CCreateBevelTrapezoids::CalculateIntersection(const DocCoord * start1, const NormCoord * dir1, 00744 const DocCoord * start2, const NormCoord * dir2, 00745 DocCoord * point, double * p, double * q) 00746 { 00747 // just turning the start points into doubles 00748 NormCoord nStart1; 00749 NormCoord nStart2; 00750 00751 nStart1.x = start1->x; 00752 nStart1.y = start1->y; 00753 00754 nStart2.x = start2->x; 00755 nStart2.y = start2->y; 00756 00757 double div = (dir2->y * dir1->x - dir2->x * dir1->y); 00758 if (div == 0) 00759 return FALSE; 00760 00761 // find the parametric value for the first line defining the point 00762 double rdiv = 1.0/div; 00763 00764 double a = dir2->y * (nStart2.x - nStart1.x) + dir2->x * (nStart1.y - nStart2.y); 00765 a *= rdiv; 00766 00767 point->x = (INT32)(nStart1.x + dir1->x * a); 00768 point->y = (INT32)(nStart1.y + dir1->y * a); 00769 00770 *p = a; 00771 00772 a = dir1->y * (nStart2.x - nStart1.x) + dir1->x * (nStart1.y - nStart2.y); 00773 a *= rdiv; 00774 00775 *q = a; 00776 00777 return TRUE; 00778 } 00779 #if 0 00780 /******************************************************************************************** 00781 > BOOL CCreateBevelTrapezoids::IsOuterTurn(NormCoord * nc1, NormCoord * nc2); 00782 00783 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00784 Created: 26/10/98 00785 Purpose: Given the two vectors, from the trapezoid list, returns whether a right 00786 or left turn exists (right turns are outer) 00787 Inputs: Two direction vectors, in & out of a single point 00788 Returns: TRUE for outer & FALSE for inner turns 00789 SeeAlso: - 00790 00791 ********************************************************************************************/ 00792 00793 BOOL CCreateBevelTrapezoids::IsOuterTurn(NormCoord * nc1, NormCoord * nc2) 00794 { 00795 return nc2->y*nc1->x > nc2->x*nc1->y ; 00796 } 00797 00798 /******************************************************************************************** 00799 > BOOL CCreateBevelTrapezoids::AddEdgeToList(TrapEdgeList * pList, DocCoord * Centre, 00800 NormCoord * Normal, double Position, 00801 NormCoord * pNormal2=NULL) 00802 00803 00804 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00805 Created: 26/10/98 00806 Purpose: Adds an edge to the given list 00807 Inputs: Traps list to add this to, the centre point, normal and position of the edge 00808 Can also use a secondary normal - used when marking points 00809 Returns: TRUE for success 00810 SeeAlso: - 00811 00812 ********************************************************************************************/ 00813 00814 BOOL CCreateBevelTrapezoids::AddEdgeToList(TrapEdgeList * pList, DocCoord * Centre, 00815 NormCoord * Normal, double Position, NormCoord * pNormal2) 00816 { 00817 if (!Normal || !pList || !Centre) 00818 return TRUE; 00819 00820 if (Normal->x == 0 && Normal->y == 0) 00821 { 00822 return TRUE; 00823 } 00824 00825 if (!pList->AddEdge(Centre, TrapJoin_MitredOrBevelled)) 00826 { 00827 ERROR3("Add edge failed"); 00828 return FALSE; 00829 } 00830 00831 TrapEdge * pNewEdge = pList->GetTrapEdge(pList->GetNumEdges()-1); 00832 00833 if (pNewEdge) 00834 { 00835 pNewEdge->Normal.x = Normal->x; 00836 pNewEdge->Normal.y = Normal->y; 00837 pNewEdge->Position = Position; 00838 00839 if (pNormal2) 00840 { 00841 pNewEdge->Normal2.x = pNormal2->x; 00842 pNewEdge->Normal2.y = pNormal2->y; 00843 } 00844 } 00845 else 00846 { 00847 return FALSE; 00848 } 00849 00850 return TRUE; 00851 } 00852 00853 /******************************************************************************************** 00854 > BOOL CCreateBevelTrapezoids::SmoothCorners(TrapsList * pList, TrapsList * RetnList, 00855 double Indent, BOOL bOuterBevel) 00856 00857 00858 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 00859 Created: 10/11/98 00860 Purpose: Creates a traps list with the corners smoothed out 00861 Inputs: Input traps list and output traps list 00862 Returns: TRUE for success 00863 SeeAlso: - 00864 00865 ********************************************************************************************/ 00866 00867 BOOL CCreateBevelTrapezoids::SmoothCorners(TrapsList * pList, TrapsList * RetnList, double Indent, 00868 BOOL bOuterBevel) 00869 { 00870 TrapEdgeList * pEdgeList = NULL; 00871 TrapEdge * pEdge = NULL; 00872 TrapEdge * pEdgeBefore = NULL; 00873 TrapEdge * pEdgeAfter = NULL; 00874 TrapEdge * pTmpEdge = NULL; 00875 00876 TrapEdgeList * pNewEdgeList = NULL; 00877 00878 NormCoord ncBefore; 00879 NormCoord ncAfter; 00880 00881 // perpendiculars to the above 00882 NormCoord ncPerpBefore; 00883 NormCoord ncPerpAfter; 00884 00885 NormCoord ncNormal; 00886 00887 DocCoord dcInnerPoint; 00888 00889 DocCoord dcIntersection; 00890 00891 double MOneDivIndent = -1/Indent; 00892 00893 // parametric variables 00894 double p = 0; 00895 double q = 0; 00896 00897 double dot = 0; 00898 UINT32 j = 0; 00899 00900 BOOL bOuter = FALSE; 00901 00902 for (UINT32 i = 0; i < pList->GetNumTraps(); i++) 00903 { 00904 pEdgeList = pList->GetTrapEdgeList(i); 00905 00906 pNewEdgeList = RetnList->AddEdgeList(); 00907 00908 for (j = 0; j < pEdgeList->GetNumEdges()-1; j++) 00909 { 00910 pEdge = pEdgeList->GetTrapEdge(j); 00911 00912 if (pEdge) 00913 { 00914 00915 // set up the before and after edges (start & end edges are the same so 00916 // need treating differently) 00917 if (j == 0) 00918 { 00919 pEdgeBefore = pEdgeList->GetTrapEdge(pEdgeList->GetNumEdges() - 2); 00920 pEdgeAfter = pEdgeList->GetTrapEdge(1); 00921 } 00922 else 00923 { 00924 pEdgeAfter = pEdgeList->GetTrapEdge(j + 1); 00925 pEdgeBefore = pEdgeList->GetTrapEdge(j - 1); 00926 } 00927 00928 // ok, now we work out the vectors before and after the point on the path 00929 if (pEdgeBefore) 00930 { 00931 ncBefore.x = pEdgeBefore->Centre.x - pEdge->Centre.x; 00932 ncBefore.y = pEdgeBefore->Centre.y - pEdge->Centre.y; 00933 } 00934 else 00935 { 00936 ncBefore.x = 0; 00937 ncBefore.y = 0; 00938 } 00939 00940 if (pEdgeAfter) 00941 { 00942 ncAfter.x = pEdgeAfter->Centre.x - pEdge->Centre.x ; 00943 ncAfter.y = pEdgeAfter->Centre.y - pEdge->Centre.y ; 00944 } 00945 else 00946 { 00947 ncAfter.x = 0; 00948 ncAfter.y = 0; 00949 } 00950 00951 // calculate the inner point according to the edge normal 00952 dcInnerPoint.x = (INT32)(((double)(pEdge->Centre.x)) - (pEdge->Normal.x * Indent)); 00953 dcInnerPoint.y = (INT32)(((double)(pEdge->Centre.y)) - (pEdge->Normal.y * Indent)); 00954 00955 // now, calculate the perpendicular intersections with the before & after lines 00956 ncPerpBefore.x = ncBefore.y; 00957 ncPerpBefore.y = -ncBefore.x; 00958 00959 ncPerpAfter.x = -ncAfter.y; 00960 ncPerpAfter.y = ncAfter.x; 00961 00962 // is this an inner or outer turn ? 00963 bOuter = bOuterBevel^IsOuterTurn(&ncPerpBefore, &ncPerpAfter); 00964 00965 // get the dot product - only do on near to 90 degree angles 00966 dot = ncBefore.x * ncAfter.x + ncBefore.y * ncAfter.y; 00967 00968 // calculate the intersection before 00969 if (CalculateIntersection(&dcInnerPoint, &ncPerpBefore, 00970 &(pEdge->Centre), &ncBefore, 00971 &dcIntersection, &p, &q) && !bOuter && dot > -0.1 && dot < 0.1) 00972 { 00973 // ok, intersection successful so add the point in 00974 // only add the point up to half way along the outside path, otherwise we 00975 // generate overlaps 00976 if (q > 0.5) 00977 { 00978 // recalculate intersection 00979 dcIntersection.x = (INT32)( (ncBefore.x * 0.5) + pEdge->Centre.x ); 00980 dcIntersection.y = (INT32)( (ncBefore.y * 0.5) + pEdge->Centre.y ); 00981 } 00982 00983 // start half way along 00984 // dcIntersection.x = (dcIntersection.x + pEdge->Centre.x) / 2; 00985 // dcIntersection.y = (dcIntersection.y + pEdge->Centre.y) / 2; 00986 00987 RecursivelyAddEdges(pNewEdgeList, &dcIntersection, &(pEdge->Centre), 00988 &dcInnerPoint, MOneDivIndent, 0); 00989 } 00990 00991 // insert the original edge 00992 AddEdgeToList(pNewEdgeList, &(pEdge->Centre), &(pEdge->Normal), pEdge->Position); 00993 00994 // calculate the intersection after 00995 if (CalculateIntersection(&dcInnerPoint, &ncPerpAfter, 00996 &(pEdge->Centre), &ncAfter, 00997 &dcIntersection, &p, &q) && !bOuter && dot > -0.1 && dot < 0.1) 00998 { 00999 // ok, intersection successful so add the point in 01000 // only add the point up to half way along the outside path, otherwise we 01001 // generate overlaps 01002 01003 if (q > 0.5) 01004 { 01005 // recalculate intersection 01006 dcIntersection.x = (INT32)( (ncAfter.x * 0.5) + pEdge->Centre.x ); 01007 dcIntersection.y = (INT32)( (ncAfter.y * 0.5) + pEdge->Centre.y ); 01008 } 01009 01010 // start half way along 01011 // dcIntersection.x = (dcIntersection.x + pEdge->Centre.x) / 2; 01012 // dcIntersection.y = (dcIntersection.y + pEdge->Centre.y) / 2; 01013 01014 RecursivelyAddEdges(pNewEdgeList, &(pEdge->Centre), &dcIntersection, 01015 &dcInnerPoint, MOneDivIndent, 0); 01016 } 01017 } 01018 01019 // all done ! 01020 } 01021 01022 // add the first edge in for the last edge 01023 pEdge = pNewEdgeList->GetTrapEdge(0); 01024 01025 if (pEdge) 01026 { 01027 AddEdgeToList(pNewEdgeList, &(pEdge->Centre), &(pEdge->Normal), pEdge->Position); 01028 } 01029 } 01030 01031 return TRUE; 01032 } 01033 01034 #ifdef _DEBUG 01035 void CCreateBevelTrapezoids::DumpList(TrapsList * pList) 01036 { 01037 // dump the traps list 01038 TrapEdgeList * pEdgeList = NULL; 01039 TrapEdge * pEdge = NULL; 01040 for (UINT32 i = 0 ; i < pList->GetNumTraps(); i++) 01041 { 01042 pEdgeList = pList->GetTrapEdgeList(i); 01043 TRACE( _T("//////////////////////\nEdge list %d\n"), i); 01044 01045 for (UINT32 j = 0 ; j < pEdgeList->GetNumEdges(); j++) 01046 { 01047 pEdge = pEdgeList->GetTrapEdge(j); 01048 01049 TRACE( _T("Edge : %d : %d %d, %f %f\n"), 01050 j, pEdge->Centre.x, pEdge->Centre.y, pEdge->Normal.x, pEdge->Normal.y); 01051 } 01052 } 01053 } 01054 01055 #endif 01056 01057 /******************************************************************************************** 01058 > void CCreateBevelTrapezoids::CalcInnerPoint(TrapEdge * pEdge, INT32 indent, DocCoord *dc) 01059 01060 01061 01062 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01063 Created: 20/11/98 01064 Purpose: Calculates the inner point of an edge and puts it indc 01065 Inputs: 01066 Returns: 01067 SeeAlso: - 01068 01069 ********************************************************************************************/ 01070 01071 void CCreateBevelTrapezoids::CalcInnerPoint(TrapEdge * pEdge, INT32 indent, DocCoord *dc, 01072 BOOL bOuter) 01073 { 01074 if (!bOuter) 01075 { 01076 dc->x = (INT32)((double)pEdge->Centre.x - pEdge->Normal.x * indent); 01077 dc->y = (INT32)((double)pEdge->Centre.y - pEdge->Normal.y * indent); 01078 } 01079 else 01080 { 01081 dc->x = (INT32)((double)pEdge->Centre.x + pEdge->Normal.x * indent); 01082 dc->y = (INT32)((double)pEdge->Centre.y + pEdge->Normal.y * indent); 01083 } 01084 01085 } 01086 01087 /******************************************************************************************** 01088 > void CCreateBevelTrapezoids::RecursivelyAddEdges(TrapEdgeList * pList, 01089 DocCoord * pCentre1, DocCoord * pCentre2, 01090 DocCoord * pInnerPoint, double MOneDivIndent, INT32 depth = 0); 01091 01092 01093 01094 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01095 Created: 20/1/98 01096 Purpose: Recursively adds edges between centre1 and centre 2 with the same inner point 01097 Inputs: 01098 Returns: 01099 SeeAlso: - 01100 01101 ********************************************************************************************/ 01102 01103 void CCreateBevelTrapezoids::RecursivelyAddEdges(TrapEdgeList * pList, DocCoord * pCentre1, DocCoord * pCentre2, 01104 DocCoord * pInnerPoint, double MOneDivIndent, INT32 depth) 01105 { 01106 // calculate centre point 01107 DocCoord dcIntersection; 01108 dcIntersection.x = (INT32)((pCentre1->x + pCentre2->x) * 0.5); 01109 dcIntersection.y = (INT32)((pCentre1->y + pCentre2->y) * 0.5); 01110 01111 NormCoord ncNormal; 01112 ncNormal.x = pInnerPoint->x - dcIntersection.x; 01113 ncNormal.y = pInnerPoint->y - dcIntersection.y; 01114 01115 ncNormal.x *= MOneDivIndent; 01116 ncNormal.y *= MOneDivIndent; 01117 01118 if (depth >= 2) 01119 { 01120 AddEdgeToList(pList, &dcIntersection, &ncNormal, 1); 01121 return; 01122 } 01123 01124 RecursivelyAddEdges(pList, pCentre1, &dcIntersection, pInnerPoint, MOneDivIndent, depth + 1); 01125 AddEdgeToList(pList, &dcIntersection, &ncNormal, 1); 01126 RecursivelyAddEdges(pList, &dcIntersection, pCentre2, pInnerPoint, MOneDivIndent, depth + 1); 01127 } 01128 01129 01130 01131 INT32 CCreateBevelTrapezoids::AlterIndex(INT32 index, INT32 max, INT32 offset) 01132 { 01133 index += offset; 01134 01135 while (index >= max) 01136 { 01137 index -= max; 01138 } 01139 01140 while (index < 0) 01141 { 01142 index += max; 01143 } 01144 01145 return index; 01146 } 01147 01148 /******************************************************************************************** 01149 > BOOL CCreateBevelTrapezoids::EliminateMultpilePoints(Path * pSrc, Path * pDest); 01150 01151 01152 01153 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01154 Created: 22/11/98 01155 Purpose: Eliminates any multiple points in the given path 01156 Inputs: Source path to eliminate the multiple points and the destination path 01157 to put the new path into : pDest must be cleared & initialised 01158 Returns: 01159 SeeAlso: - 01160 01161 ********************************************************************************************/ 01162 01163 BOOL CCreateBevelTrapezoids::EliminateMultpilePoints(Path * pSrc, Path * pDest) 01164 { 01165 if (!pSrc || !pDest) 01166 { 01167 return FALSE; 01168 } 01169 01170 pDest->ClearPath(FALSE); 01171 01172 DocCoord dcLastCoord = pSrc->GetCoordArray()[0]; 01173 01174 // add first point into the new path 01175 pDest->AddMoveTo(dcLastCoord); 01176 01177 for (INT32 i = 1 ; i < pSrc->GetNumCoords(); i++) 01178 { 01179 if (pSrc->GetVerbArray()[i] == PT_MOVETO) 01180 { 01181 dcLastCoord = pSrc->GetCoordArray()[i]; 01182 pDest->AddMoveTo(dcLastCoord); 01183 } 01184 else 01185 { 01186 // ok, is this point the same as the last ? 01187 if (dcLastCoord.x != pSrc->GetCoordArray()[i].x || 01188 dcLastCoord.y != pSrc->GetCoordArray()[i].y) 01189 { 01190 dcLastCoord = pSrc->GetCoordArray()[i]; 01191 pDest->AddLineTo(dcLastCoord); 01192 } 01193 else 01194 { 01195 } 01196 } 01197 } 01198 01199 return TRUE; 01200 } 01201 01202 /******************************************************************************************** 01203 > void CCreateBevelTrapezoids::CreateRoundJoin(TrapEdgeList * pList, DocCoord * pCentre, 01204 DocCoord * pStartNorm, 01205 DocCoord * pEndNorm, INT32 depth) 01206 01207 01208 01209 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01210 Created: 24/11/98 01211 Purpose: Creates a round join at end of the given list 01212 Inputs: pList - The trap edge list to add the join to 01213 pCentre - The centre point of the join 01214 pStartNorm - The starting normal 01215 pEndNorm - The end normal 01216 depth - The recursion depth 01217 01218 Returns: 01219 SeeAlso: - 01220 01221 ********************************************************************************************/ 01222 01223 void CCreateBevelTrapezoids::CreateRoundJoin(TrapEdgeList * pList, DocCoord * pCentre, 01224 NormCoord * pStartNorm, NormCoord * pEndNorm, 01225 INT32 depth) 01226 { 01227 double dot = pStartNorm->x*pEndNorm->x+pStartNorm->y*pEndNorm->y; 01228 01229 if ( dot<0.9915 && depth<6 ) // Rely on angle (arccos dot) not depth as 01230 { // limit of recursion. Angle is about 7.5 degrees. 01231 01232 // Work out the centre normal coordinate 01233 NormCoord nc; 01234 nc.x = pStartNorm->x+pEndNorm->x ; 01235 nc.y = pStartNorm->y+pEndNorm->y ; 01236 01237 double len = nc.GetLength(); 01238 if ( len==0.0 ) 01239 return ; 01240 len = 1.0/len ; 01241 nc.x *= len; 01242 nc.y *= len; 01243 // Recurse downwards, add in the centre point and recurse rightwards 01244 CreateRoundJoin(pList, pCentre, pStartNorm, &nc, depth + 1); 01245 AddEdgeToList (pList, pCentre, &nc, 0 ); 01246 CreateRoundJoin(pList, pCentre, &nc, pEndNorm, depth + 1); 01247 } 01248 } 01249 01250 /******************************************************************************************** 01251 > void CCreateBevelTrapezoids::FlattenInnerPoints(TrapEdgeList * pList, INT32 indent) 01252 01253 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01254 Created: 2/12/98 01255 Purpose: Takes a trap edge list, and flattens all inner points so that they are 01256 consistant with the distances of the outer points 01257 Inputs: The trap edge list to flatten, and the indent we're using 01258 Returns: - 01259 Coments: All inner points must be defined with their normals 01260 SeeAlso: 01261 01262 ********************************************************************************************/ 01263 01264 void CCreateBevelTrapezoids::FlattenInnerPoints(TrapEdgeList * pList, INT32 indent, BOOL bOuter) 01265 { 01266 if (!pList || indent == 0) 01267 return; 01268 01269 // find the first outer edge 01270 UINT32 StartIndex = 0; 01271 BOOL bFound = FALSE; 01272 01273 TrapEdge * pEdge = NULL; 01274 TrapEdge * pNextEdge = NULL; 01275 TrapEdge * pNextEdge2 = NULL; 01276 01277 for (UINT32 i = 0 ; i < pList->GetNumEdges()-1; i++) 01278 { 01279 pEdge = pList->GetTrapEdge(i); 01280 01281 if (pEdge) 01282 { 01283 if (pEdge->Position == 0) 01284 { 01285 // ok, we've found an outer point 01286 StartIndex = i; 01287 i = pList->GetNumEdges(); 01288 bFound = TRUE; 01289 } 01290 } 01291 } 01292 01293 if (!bFound) 01294 { 01295 // no outer points found, so exit 01296 return; 01297 } 01298 01299 DocCoord dc1; 01300 01301 NormCoord nc1; 01302 NormCoord nc2; 01303 01304 DocCoord intersection; 01305 double p = 0; 01306 double q = 0; 01307 double nc1RLen = 0; 01308 double len = 0; 01309 double OldLen = 0; 01310 double dot = 0; 01311 DocRect BevBounds; 01312 01313 pEdge = pList->GetTrapEdge(0); 01314 CalcInnerPoint(pEdge, indent, &dc1, bOuter); 01315 BevBounds.lo.x = dc1.x; 01316 BevBounds.lo.y = dc1.y; 01317 BevBounds.hi.x = dc1.x + 1; 01318 BevBounds.hi.y = dc1.y + 1; 01319 01320 // get the bounding rect for the traps list 01321 for (i = 1 ; i < pList->GetNumEdges(); i++) 01322 { 01323 pEdge = pList->GetTrapEdge(i); 01324 CalcInnerPoint(pEdge, indent, &dc1, bOuter); 01325 BevBounds.IncludePoint(dc1); 01326 } 01327 01328 for (i = 0; i < pList->GetNumEdges()-1; i++) 01329 { 01330 // get the trap edge and the next trap edge 01331 pEdge = pList->GetTrapEdge(AlterIndex(i, pList->GetNumEdges(), StartIndex )); 01332 pNextEdge = pList->GetTrapEdge(AlterIndex(i, pList->GetNumEdges(), StartIndex + 1)); 01333 if (pEdge && pNextEdge) 01334 { 01335 // indicates an inner point 01336 if (pNextEdge->Position == 1) 01337 { 01338 CalcInnerPoint(pEdge, indent, &dc1, bOuter); 01339 01340 // calculate the vector between the two centres 01341 nc1.x = pNextEdge->Centre.x - pEdge->Centre.x; 01342 nc1.y = pNextEdge->Centre.y - pEdge->Centre.y; 01343 nc1RLen = 1/nc1.GetLength(); 01344 01345 // now, do the intersection 01346 if (nc1Len > 0) 01347 { 01348 nc1.x *= nc1Len; 01349 nc1.y *= nc1Len; 01350 01351 pNextEdge->Normal.Normalise(); 01352 01353 // check for the dot product being zero 01354 if (CalculateIntersection(&dc1, &nc1, 01355 &(pNextEdge->Centre), &(pNextEdge->Normal), 01356 &intersection, &p, &q)) 01357 { 01358 // check that the intersection point is inside the bounds of 01359 // the original list - if not it's probably a glitch 01360 if (BevBounds.lo.x <= intersection.x && 01361 BevBounds.lo.y <= intersection.y && 01362 BevBounds.hi.x >= intersection.x && 01363 BevBounds.hi.y >= intersection.y) 01364 { 01365 // alter the normal to the intersection point 01366 nc2.x = pNextEdge->Centre.x - intersection.x; 01367 nc2.y = pNextEdge->Centre.y - intersection.y; 01368 01369 double R = 1/(double)indent; 01370 nc2.x *= R; 01371 nc2.y *= R; 01372 01373 if (bOuter) 01374 { 01375 nc2.x = -nc2.x; 01376 nc2.y = -nc2.y; 01377 } 01378 01379 pNextEdge->Normal = nc2; 01380 } 01381 } 01382 } 01383 01384 } 01385 } 01386 } 01387 } 01388 01389 /******************************************************************************************** 01390 > void CCreateBevelTrapezoids::GetPathFromTraps(const TrapsList * pTraps, 01391 const MILLIPOINT Width, 01392 Path * pPath) 01393 01394 Author: David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> 01395 Created: 2/12/98 01396 Purpose: Builds a path from 01397 Inputs: The trap list to use, the width to generate (can be negative) and 01398 the path to deliver the result into (must have been initialised) 01399 Returns: - 01400 Coments: 01401 SeeAlso: 01402 01403 ********************************************************************************************/ 01404 01405 void CCreateBevelTrapezoids::GetPathFromTraps(TrapsList * pTraps, const MILLIPOINT Width, 01406 Path * pPath) 01407 { 01408 pPath->ClearPath(); 01409 01410 UINT32 i = 0; 01411 INT32 j = 0; 01412 01413 // builds a path from all the given trapezoid list 01414 UINT32 NumTraps = pTraps->GetNumTraps(); 01415 01416 INT32 NumEdges = 0; 01417 01418 TrapEdgeList* pEdgeList = NULL; 01419 TrapEdge* pEdge = 0; 01420 01421 double dX = 0; 01422 double dY = 0; 01423 01424 DocCoord dc; 01425 DocCoord Start; 01426 01427 // first, find out how many faces are required 01428 for (i = 0 ; i < NumTraps; i++) 01429 { 01430 pEdgeList = pTraps->GetTrapEdgeList(i); 01431 NumEdges = static_cast<INT32> ( pEdgeList->GetNumEdges() ); 01432 01433 pEdge = pEdgeList->GetTrapEdge(0); 01434 01435 /* 01436 pPath->AddMoveTo(pEdge->Centre); 01437 01438 for (j = 1; j < NumEdges; j++) 01439 { 01440 // do the start points first 01441 pEdge = pEdgeList->GetTrapEdge(j); 01442 01443 pPath->AddLineTo(pEdge->Centre); 01444 } 01445 01446 pEdge = pEdgeList->GetTrapEdge(0); 01447 01448 pPath->AddLineTo(pEdge->Centre); 01449 */ 01450 01451 // now, add in the outer path 01452 for (j = NumEdges - 1; j >= 0; j--) 01453 { 01454 pEdge = pEdgeList->GetTrapEdge(j); 01455 01456 dX = pEdge->Centre.x; 01457 dX += pEdge->Normal.x * Width; 01458 dY = pEdge->Centre.y; 01459 dY += pEdge->Normal.y * Width; 01460 01461 dc.x = (MILLIPOINT)dX; 01462 dc.y = (MILLIPOINT)dY; 01463 01464 if (j == NumEdges - 1) 01465 { 01466 pPath->AddMoveTo(dc); 01467 Start = dc; 01468 } 01469 else 01470 pPath->AddLineTo(dc); 01471 } 01472 } 01473 } 01474 01475 #endif