00001 // $Id: doccoord.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 00099 00100 #include "camtypes.h" 00101 //#include "doccoord.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00102 00103 #if !defined(EXCLUDE_FROM_XARLIB) 00104 #include "usercord.h" 00105 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "paper.h" 00107 //#include "xmatrix.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 #include "chapter.h" 00110 //#include "oilcoord.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 00114 00115 /******************************************************************************************** 00116 00117 > Matrix ComposeDocToOilMat( DocCoord& ChapterPos, 00118 XLONG& ChapterLogHiY, 00119 FIXED16& ViewScale, 00120 WorkCoord& Scroll, 00121 ) 00122 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00123 Created: 5/8/93 00124 Inputs: Chapter physical position 00125 Accumulated depth of previous chapters 00126 View scale factor (always 1:1 aspect ratio) 00127 Individual millipoint to pixel scale factors 00128 Scroll offsets 00129 Final device-dependant mapping matrix 00130 Outputs: None. 00131 Returns: Document to Oil matrix for a specific chapter. 00132 Purpose: Creates a Document to Oil matrix for a specific chapter. 00133 Errors: None. 00134 00135 ********************************************************************************************/ 00136 /* 00137 Technical notes: 00138 Assumes that the top corner of logical space is at 0,0 and y gets more negative downwards 00139 Assumes that the top corner of workarea space is at 0,0... 00140 Assumes that scroll.x is positive and that scroll.y is negative. 00141 Assumes that Document space can never be rotated with respect to OS space! 00142 00143 ********************************************************************************************/ 00144 00145 Matrix ComposeDocToOilMat( const DocCoord& ChapterPos, // Top left coord of chapter 00146 const XLONG& ChapterDepth, // Accumulated height of previous chaps 00147 const FIXED16& ViewScale, // User viewing scale 00148 const WorkCoord& ScrollOffset // Scroll offsets 00149 ) 00150 { 00151 // Scale ChapterDepth into device units so that it can be combined with the scroll offset 00152 // BEFORE we build the scroll translation matrix. In this way we avoid storing 64-bit 00153 // translation values in our final matrix... 00154 // 00155 // If we COULD store 64-bit E and F values temporarilly during this composition then 00156 // we would not need to perform this trick at all. This would have the knock-on advantage 00157 // that the OSMapping matrix supplied by the OIL layer could contain the scroll offsets! 00158 // 00159 // NOTE: This adjustment can be removed when testing the system! 00160 00161 Matrix DocToOil; 00162 00163 //********************************************************************** 00164 // Is it just me or is there gunna be a problem with this ? 00165 // If ChapterDepth is big (atfer all it is an XLONG) and ViewScale 00166 // is big too (Say we are zoomed to 1000%) won't this go VERY wrong ? 00167 // 00168 // - Will. 00169 00170 Matrix Scroll( -ScrollOffset.x, 00171 -(ScrollOffset.y + (ChapterDepth * (ViewScale))) 00172 ); 00173 00174 //********************************************************************** 00175 00176 Matrix ScaleMat(ViewScale,ViewScale); 00177 Matrix Translate(-((Coord)ChapterPos)); 00178 00179 // The following matrix compositions MUST be performed in this order. If you are tempted 00180 // to optimise this code MAKE SURE THAT THEY ARE STILL IN THIS ORDER WHEN YOU'VE FINISHED! 00181 // 00182 // Apply translation to get coordinates into logical column... 00183 DocToOil *= Translate; 00184 00185 // Apply scale factors to convert from millipoint distances to pixel distances... 00186 DocToOil *= ScaleMat; 00187 00188 // Apply scroll-offset translation to move origin to viewing position... 00189 DocToOil *= Scroll; 00190 00191 return DocToOil; 00192 } 00193 00194 00195 /******************************************************************************************** 00196 00197 > Matrix ComposeDocToWorkXMat(DocCoord ChapterPos, 00198 XLONG ChapterDepth, 00199 FIXED16 ViewScale 00200 ) 00201 Author: Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> 00202 Created: 30/5/93 00203 Inputs: Chapter physical position 00204 Accumulated depth of previous chapters 00205 View scale factor (always 1:1 aspect ratio) 00206 Individual millipoint to pixel scale factors 00207 Outputs: None. 00208 Returns: Document to WorkArea matrix for a specific chapter. 00209 Purpose: Creates a Document to WorkArea matrix for a specific chapter. 00210 Errors: None. 00211 00212 ********************************************************************************************/ 00213 /* 00214 Technical notes: 00215 Assumes that the top corner of logical space is at 0,0 and y gets more negative downwards 00216 Assumes that the top corner of workarea space is at 0,0... 00217 Assumes that scroll.x is positive and that scroll.y is negative. 00218 00219 ********************************************************************************************/ 00220 00221 XMatrix ComposeDocToWorkXMat(const DocCoord ChapterPos, // Top left coord of chapter 00222 const XLONG ChapterDepth, // Accumulated height of previous chaps 00223 const FIXED16 ViewScale // User viewing scale 00224 ) 00225 { 00226 00227 XMatrix ScaleMat(ViewScale,ViewScale); 00228 00229 // Conversion of chapter position from DocCoords to WorkCoords 00230 // WorkCoord WrkChapPos(MakeXLong(ChapterPos.x), MakeXLong(ChapterPos.y)); 00231 WorkCoord WrkChapPos(MakeXLong(ChapterPos.x), MakeXLong(ChapterPos.y)+ChapterDepth); 00232 00233 // DocToOS matrix is initialised as the Translate matrix: saving space and performance 00234 // by the exclusion of an extra multiplication. 00235 XMatrix DocToWork(-(WrkChapPos)); 00236 00237 // The following matrix compositions MUST be performed in this order. If you are tempted 00238 // to optimise this code MAKE SURE THAT THEY ARE STILL IN THIS ORDER WHEN YOU'VE FINISHED! 00239 // 00240 00241 // Apply scale factors to convert from millipoint distances to pixel distances... 00242 DocToWork *= ScaleMat; 00243 00244 return DocToWork; 00245 } 00246 00247 /******************************************************************************************** 00248 00249 > WorkCoord DocCoord::ToWork(Document *pDocument, View *pView) 00250 00251 Author: Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> (with modifications by Phil (and Tim)) 00252 Created: 26/5/93 00253 Inputs: The document we are converting within. 00254 The view we are converting within. 00255 Outputs: None. 00256 Returns: Returns a Workarea coordinate. 00257 Purpose: Converts a document coordinate to a work area coordnate - slowly! 00258 Note that if you are performing this conversion often and you want to do it 00259 fast then you should use the approriate "Compose" function to build a matrix 00260 which does the job and repeatedly apply that matrix. 00261 Errors: None. 00262 00263 ********************************************************************************************/ 00264 /* 00265 Technical notes: 00266 00267 ********************************************************************************************/ 00268 00269 WorkCoord DocCoord::ToWork(Document *pDocument, View *pView) 00270 { 00271 WorkCoord WrkPoint(MakeXLong(this->x), MakeXLong(this->y)); 00272 DocCoord ChapterPos; // To hold the top-left of the found chapter 00273 XLONG ChapterDepth; // To hold the accumulated depth of the chapter 00274 XMatrix ConvertToWorkMat; // Transformation matrix 00275 00276 // Find chapter and its log depth 00277 this->FindEnclosingChapter(pDocument, &ChapterPos, &ChapterDepth, pView); 00278 00279 // This builds the 64-bit conversion matrix needed for Document To WorkArea 00280 // coordinate mappings. 00281 ConvertToWorkMat = ComposeDocToWorkXMat(ChapterPos, 00282 ChapterDepth, 00283 pView->GetViewScale()); 00284 00285 // Apply the matrix to the DocCoord... 00286 ConvertToWorkMat.transform(&WrkPoint, 1); 00287 00288 return (WrkPoint); 00289 } 00290 00291 /******************************************************************************************** 00292 00293 > WorkCoord DocCoord::ToWork( Spread *pSpread, const FIXED16 ViewScale) 00294 00295 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00296 Created: 15/12/93 00297 Inputs: - 00298 Outputs: - 00299 Returns: - 00300 Purpose: Convert a document coordinate to a Work Coordinate, given the spread 00301 that the coordinate is on. 00302 Errors: - 00303 SeeAlso: - 00304 00305 ********************************************************************************************/ 00306 00307 WorkCoord DocCoord::ToWork( Spread *pSpread, View *pView) 00308 { 00309 WorkCoord WrkPoint(MakeXLong(this->x), MakeXLong(this->y)); 00310 DocCoord ChapterPos; // To hold the top-left of the found chapter 00311 XLONG ChapterDepth; // To hold the accumulated depth of the chapter 00312 XMatrix ConvertToWorkMat; // Transformation matrix 00313 00314 Chapter *pChapter = (Chapter *) pSpread->FindParent(); 00315 ENSURE(pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), "Spread's parent is not a chapter"); 00316 00317 00318 // Find top left of chapter pasteboard 00319 DocRect ChapterRect = pChapter->GetPasteboardRect(TRUE, pView); 00320 ChapterPos.x = ChapterRect.lo.x; 00321 ChapterPos.y = ChapterRect.hi.y; 00322 00323 // Find chapter depth 00324 ChapterDepth = pChapter->GetChapterDepth(); 00325 00326 // This builds the 64-bit conversion matrix needed for Document To WorkArea 00327 // coordinate mappings. 00328 00329 ConvertToWorkMat = ComposeDocToWorkXMat(ChapterPos, 00330 ChapterDepth, 00331 pView->GetViewScale()); 00332 00333 // Apply the matrix to the DocCoord... 00334 ConvertToWorkMat.transform(&WrkPoint, 1); 00335 00336 return (WrkPoint); 00337 } 00338 00339 00340 WorkCoord DocCoord::ToLogical(Spread* pSpread, View *pView) 00341 { 00342 // Check that we have not been fed garbage 00343 ENSURE( pSpread!=NULL, "DocCoord::ToLogical was passed a NULL spread" ); 00344 00345 // Find the chapter 00346 Chapter* pChapter = (Chapter*) pSpread->FindParent(); 00347 ENSURE( pChapter!=NULL, "DocCoord::ToLogical. Spread did not have a parent chapter" ); 00348 ENSURE( pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), "DocCoord::ToLogical. Chapter is not a chapter" ); 00349 00350 // Find out about the chapter 00351 DocRect ChapterRect = pChapter->GetPasteboardRect(TRUE, pView); 00352 XLONG ChapterDepth = pChapter->GetChapterDepth(); 00353 00354 // Build the logical coord from the doccoord 00355 WorkCoord Result( MakeXLong(x), MakeXLong(y) ); 00356 Result.x = Result.x - ChapterRect.lo.x; 00357 Result.y = Result.y - ChapterRect.hi.y; 00358 Result.y = Result.y - ChapterDepth; 00359 00360 // return the coord 00361 return Result; 00362 } 00363 00364 00365 /*********************************************************************************************** 00366 > DocCoord DocCoord::ToSpread(Spread* pSpread, View* pView) 00367 00368 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00369 Created: 5/9/95 00370 Inputs: pSpread - 00371 pView - 00372 Returns: SpreadCoord 00373 Purpose: Convert DocCoord to a SpreadCoord 00374 00375 SeeAlso: Spread::SpreadCoordToDocCoord 00376 *********************************************************************************************/ 00377 00378 DocCoord DocCoord::ToSpread(Spread* pSpread, View* pView) 00379 { 00380 ERROR3IF((pSpread==NULL || pView==NULL), "DocCoord::ToSpread() - pSpread==NULL || pView==NULL"); 00381 00382 DocCoord temp(x, y); 00383 00384 if (pSpread != NULL) 00385 pSpread->DocCoordToSpreadCoord(&temp); 00386 00387 return(temp); 00388 } 00389 00390 00391 /*********************************************************************************************** 00392 > DocCoord DocCoord::ToDoc(Spread* pSpread, View* pView) 00393 00394 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00395 Created: 5/9/95 00396 Inputs: pSpread - 00397 pView - 00398 Returns: SpreadCoord 00399 Purpose: Convert SpreadCoord to a DocCoord 00400 00401 SeeAlso: Spread::SpreadCoordToDocCoord 00402 *********************************************************************************************/ 00403 00404 DocCoord DocCoord::ToDoc(Spread* pSpread, View* pView) 00405 { 00406 ERROR3IF(pSpread == NULL || pView == NULL, "DocCoord::ToDoc() - pSpread==NULL || pView==NULL"); 00407 00408 DocCoord temp(x, y); 00409 00410 if (pSpread != NULL) 00411 pSpread->SpreadCoordToDocCoord(&temp); 00412 00413 return(temp); 00414 } 00415 00416 00417 /*********************************************************************************************** 00418 > UserCoord DocCoord::ToUser(Spread* pSpread) 00419 00420 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00421 Created: 11/9/95 00422 Inputs: pSpread - 00423 Returns: UserCoord 00424 Purpose: Convert SpreadCoord to a UserCoord 00425 *********************************************************************************************/ 00426 00427 UserCoord DocCoord::ToUser(Spread* pSpread) 00428 { 00429 DocCoord UserOrigin(0,0); 00430 if (pSpread!=NULL) 00431 UserOrigin=pSpread->GetUserOrigin(); 00432 else 00433 ERROR3("DocCoord::ToUser() - pSpread==NULL"); 00434 00435 return UserCoord(this->x-UserOrigin.x, this->y-UserOrigin.y); 00436 } 00437 00438 00439 /*********************************************************************************************** 00440 > OilCoord DocCoord::ToOil(Spread* pSpread, View* pView) 00441 00442 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00443 Created: 11/9/95 00444 Inputs: pSpread - 00445 pView - 00446 Returns: OilCoord 00447 Purpose: Convert SpreadCoord (AKA DocCoord) to an OilCoord 00448 *********************************************************************************************/ 00449 00450 OilCoord DocCoord::ToOil(Spread* pSpread, View* pView) 00451 { 00452 WorkCoord ScrollOffsets(0,0); 00453 if (pView!=NULL) 00454 ScrollOffsets=pView->GetScrollOffsets(); 00455 else 00456 ERROR3("DocCoord::ToOil() - pView==NULL"); 00457 00458 return ToDoc(pSpread,pView).ToWork(pSpread,pView).ToOil(ScrollOffsets); 00459 } 00460 00461 00462 /*********************************************************************************************** 00463 00464 > Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, 00465 DocCoord* ChapterPos, 00466 XLONG* ChapterDepth); 00467 00468 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00469 Created: 30/4/93 00470 Inputs: pDocument - the document we are converting in. 00471 pView - the View to use for pixelising. 00472 Outputs: ChapterPos: The top left hand corner of the chapters pasteboard rectangle 00473 ChapterDepth: The Sum of the lengths of all preceding chapters 00474 00475 Returns: If this coord is enclosed within a chapter then the chapter is returned 00476 else NULL is returned (In the non DEBUG version). 00477 00478 Purpose: For finding the enclosing chapter of a DocCoord, the position of the start 00479 of the enclosing chapter, and the chapters depth. 00480 00481 Scope: Private 00482 00483 Errors: An ERROR3 will occur if the DocCoord is not in any chapter 00484 NOTE: The Spread Coordinate Origin for a spread MAY NOT reside INSIDE a 00485 Chapter's Pasteboard bounds! See Spread::GetSpreadCoordOrigin for full 00486 details of this. 00487 00488 SeeAlso: - 00489 00490 *********************************************************************************************/ 00491 00492 Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, 00493 DocCoord* ChapterPos, 00494 XLONG* ChapterDepth, 00495 View *pView) 00496 { 00497 Chapter* CurrentChapter = Node::FindFirstChapter(pDocument); 00498 // Search all chapters 00499 *ChapterDepth = 0; 00500 DocRect CurrentChaptersPasteboardRect; 00501 00502 while (CurrentChapter != NULL) 00503 { 00504 CurrentChaptersPasteboardRect = CurrentChapter->GetPasteboardRect(TRUE, pView); 00505 00506 if (CurrentChaptersPasteboardRect.ContainsRectCoord(*this)) 00507 { 00508 // Chapter position is the top left hand corner of the chapters pasteboard 00509 ChapterPos->x = CurrentChaptersPasteboardRect.LowCorner().x; 00510 ChapterPos->y = CurrentChaptersPasteboardRect.HighCorner().y; 00511 return (CurrentChapter); 00512 } 00513 00514 (*ChapterDepth) += CurrentChaptersPasteboardRect.Height(); 00515 CurrentChapter = CurrentChapter->FindNextChapter(); 00516 } 00517 00518 // The DocCoord was not found in any chapter 00519 ERROR3("DocCoord::FindEnclosingChapter: Coord wasn't in any chapter. See the function help for debugging tips"); 00520 return(NULL); 00521 } 00522 00523 00524 00525 00526 00527 00528 /********************************************************************************************* 00529 > BOOL DocCoord::Pixelise(View* pView) 00530 00531 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00532 Created: 21/11/94 00533 Inputs: The view we are pixelising for. 00534 Purpose: Modifies this DocCoord to lie on an exact pixel boundary. 00535 Scope: Public 00536 SeeAlso: DocCoord::SetScaledPixelSize() 00537 00538 **********************************************************************************************/ 00539 /* 00540 Technical notes: 00541 This routine ensures that the coordinate is aligned to a whole pixel boundary at all times 00542 by dividing and re-multiplying by the pixel size (YUK). 00543 00544 Note that when a negative value is divided in C++ it is done so without regard for the 00545 sign of the value. 00546 E.g. 00547 21 / 4 = 5 Result has been truncated towards 0, moving Y coordinates down 00548 -21/ 4 = -5 Result has been truncated towards 0 again, moving Y coordinates UP!!! 00549 In other words when the values are coordinates the division truncates them in different 00550 directions depending which side of the origin they are on! 00551 This is obviously not required and so any negative values are adjusted before the division 00552 to ensure the end result is movement in the same direction as positive values. 00553 00554 Range of scaled pixel width/height: 00555 Min: ScaledPixelsize = 1(millipoint) / 40 (4000%) = 0.025 00556 Max: ScaledPixelSize = 2000 (1/36th of an inch) / 0.05 (5%) = 40,000 00557 These values fit nicely into a Fixed16 so they should be correct on the way into the 00558 pixelising maths. However, Fixed16s cannot be combined with INT32s easily and they would not 00559 be accuarate enough to hold the possible pixel values. So, the pixelising maths is all done 00560 using floating point doubles. 00561 00562 ********************************************************************************************/ 00563 00564 BOOL DocCoord::Pixelise(View* pView) 00565 { 00566 // See if the view is ok 00567 if (pView==NULL) 00568 return FALSE; 00569 00570 FIXED16 pw,ph; 00571 pView->GetScaledPixelSize(&pw,&ph); 00572 x = (INT32) ( (floor(0.5 + (double)x / pw.MakeDouble())) * pw.MakeDouble() ); 00573 y = (INT32) ( (floor(0.5 + (double)y / ph.MakeDouble())) * ph.MakeDouble() ); 00574 00575 return TRUE; 00576 } 00577 00578 00579 /********************************************************************************************* 00580 > BOOL DocCoord::IsPixelised(View* pView) 00581 00582 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00583 Created: 21/11/94 00584 Inputs: The view we are pixelising for. 00585 Outputs: - 00586 Returns: TRUE if this DocCoord is already pixelised 00587 FALSE otherwise 00588 Purpose: Modifies this DocCoord to lie on an exact pixel boundary. 00589 Scope: Public 00590 00591 **********************************************************************************************/ 00592 00593 BOOL DocCoord::IsPixelised(View* pView) 00594 { 00595 // See if the view is ok 00596 if (pView==NULL) 00597 return FALSE; 00598 00599 // Now pixelise a temp copy of this coord and see if it changed at all... 00600 DocCoord temp(x,y); 00601 temp.Pixelise(pView); 00602 return (x==temp.x && y==temp.y); 00603 } 00604 00605 00606 /********************************************************************************************* 00607 00608 > static BOOL DocCoord::Pixelise() 00609 00610 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00611 Created: 21/11/94 00612 Inputs: - 00613 Outputs: - 00614 Returns: - 00615 Purpose: Modifies this DocCoord to lie on an exact pixel boundary. 00616 Errors: - 00617 Scope: Public 00618 SeeAlso: DocCoord::SetScaledPixelSize() 00619 00620 **********************************************************************************************/ 00621 00622 // NB. This is a bodge until I fix all the callers of Pixelise to pass in the View (Tim). 00623 00624 BOOL DocCoord::Pixelise() 00625 { 00626 // BODGE: ...until I can be bothered to get callers to pass view in... (Tim) 00627 return Pixelise(View::GetCurrent()); 00628 } 00629 00630 #endif // EXCLUDE_FROM_XARLIB 00631 00632 /******************************************************************************************** 00633 00634 > DocCoord operator + (const DocCoord& One, const DocCoord& Two) 00635 00636 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00637 Created: 15/12/94 00638 Inputs: One - The first DocCoord 00639 Two - The second DocCoord 00640 Returns: The result of adding the two DocCoords together. 00641 Purpose: Adds two DocCoords together. ie One.x+Two.x, One.y+Two.y 00642 00643 ********************************************************************************************/ 00644 00645 DocCoord operator + (const DocCoord& One, const DocCoord& Two) 00646 { 00647 DocCoord Result; 00648 00649 // Add the two DocCoords together 00650 Result.x = One.x + Two.x; 00651 Result.y = One.y + Two.y; 00652 00653 // return the result 00654 return Result; 00655 } 00656 00657 00658 /******************************************************************************************** 00659 00660 > DocCoord operator - (const DocCoord& One, const DocCoord& Two) 00661 00662 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00663 Created: 15/12/94 00664 Inputs: One - The first DocCoord 00665 Two - The second DocCoord 00666 Returns: the DocCoord that is the first DocCoord minus the second DocCoord 00667 Purpose: Subtracts the two DocCoords. ie One.x-Two.x, One.y-Two.y 00668 00669 ********************************************************************************************/ 00670 00671 DocCoord operator - (const DocCoord& One, const DocCoord& Two) 00672 { 00673 DocCoord Result; 00674 00675 // Subtract the two DocCoords from each other 00676 Result.x = One.x - Two.x; 00677 Result.y = One.y - Two.y; 00678 00679 // return the result 00680 return Result; 00681 } 00682 00683 /******************************************************************************************** 00684 00685 > const DocCoord& DocCoord::operator += ( const DocCoord &Other ) 00686 00687 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00688 Created: 29/4/00 00689 Inputs: Other - The other DocCoord value, that's being added to the original. 00690 Returns: A reference to the current object, for concatentation 00691 Purpose: Adds a DocCoord value onto the current object. 00692 00693 ********************************************************************************************/ 00694 00695 const DocCoord& DocCoord::operator += ( const DocCoord &Other ) 00696 { 00697 // Add the other DocCoord's values onto this object's. 00698 x += Other.x; 00699 y += Other.y; 00700 00701 return *this; 00702 } 00703 00704 /******************************************************************************************** 00705 00706 > const DocCoord& DocCoord::operator -= ( const DocCoord &Other ) 00707 00708 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00709 Created: 29/4/00 00710 Inputs: Other - The other DocCoord value, that's being subtracted from this one. 00711 Returns: A reference to the current object, for concatentation 00712 Purpose: Subtracts a DocCoord value from the current object. 00713 00714 ********************************************************************************************/ 00715 00716 const DocCoord& DocCoord::operator -= ( const DocCoord &Other ) 00717 { 00718 // Add the other DocCoord's values onto this object's. 00719 x -= Other.x; 00720 y -= Other.y; 00721 00722 return *this; 00723 } 00724 00725 /******************************************************************************************* 00726 > static DocCoord DocCoord::PositionPointFromRatio(const DocCoord& StartPoint, const DocCoord& EndPoint, const double Ratio) 00727 00728 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00729 Created: 12/12/95 00730 Inputs: StartPoint and EndPoint define the start and end of a line 00731 Ratio is the ratio of the distance from start to end that you want the coordinate of 00732 Outputs: - 00733 Returns: The coordinate of the position of the ratio (err, does that make sense?) 00734 Purpose: Gives the coordinate of a point specified by a ratio along a line defined by 00735 two other points. A ratio of zero gives the same point as the start of the 00736 line, 0.5 gives the mid point of the line, etc. Negative ratio give a point 00737 before the start, ratios greater than 1 give points beyond the end 00738 ********************************************************************************************/ 00739 DocCoord DocCoord::PositionPointFromRatio(const DocCoord& StartPoint, const DocCoord& EndPoint, const double Ratio) 00740 { 00741 DocCoord result; 00742 00743 result.x = StartPoint.x + (INT32)((EndPoint.x - StartPoint.x)*Ratio) ; 00744 result.y = StartPoint.y + (INT32)((EndPoint.y - StartPoint.y)*Ratio) ; 00745 00746 return result; 00747 } 00748 00749 00750 /******************************************************************************************* 00751 > static double DocCoord::DistanceFromLine(const DocCoord& Line1, const DocCoord& Line2, const DocCoord& Point) 00752 00753 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00754 Created: 12/12/95 00755 Inputs: Line1 and Line2 are two points defining a line that passes through those points 00756 Point is another point 00757 Outputs: - 00758 Returns: The perpendicular distance from the line to the point. 00759 Purpose: Gets the shortest distance from the line to the point. 00760 Errors: Will return -1 if a division by zero case was detected 00761 ********************************************************************************************/ 00762 double DocCoord::DistanceFromLine(const DocCoord& Line1, const DocCoord& Line2, const DocCoord& Point) 00763 { 00764 // Obtain perpendicular distance from the axes line (see A-Level maths page 24) 00765 const double X1 = Line1.x; 00766 const double Y1 = Line1.y; 00767 const double X2 = Line2.x; 00768 const double Y2 = Line2.y; 00769 00770 const double a = -Y2+Y1; 00771 const double b = X2-X1; 00772 const double c = -(Y1*X2) + (Y1*X1) + (X1*Y2) - (X1*Y1); 00773 00774 const double divisor = sqrt( a*a + b*b ); 00775 00776 // We don't want any nasty floating point div 0, thank you 00777 double Distance = -1.0; 00778 if (divisor >= 0.0001) 00779 Distance = fabs(( a*Point.x + b*Point.y + c )/divisor); 00780 00781 return Distance; 00782 } 00783 00784 00785 00786 /******************************************************************************************* 00787 > static DocCoord DocCoord::OneThird(const DocCoord& Start, const DocCoord& End) 00788 00789 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00790 Created: 12/12/95 00791 Inputs: Start and End are two coordinates 00792 Outputs: - 00793 Returns: The point one third of the way from Start to End 00794 Purpose: For getting a point one third of the way between two other points 00795 ********************************************************************************************/ 00796 DocCoord DocCoord::OneThird(const DocCoord& Start, const DocCoord& End) 00797 { 00798 DocCoord result; 00799 00800 result.x = Start.x + (INT32)((End.x - Start.x)/3) ; 00801 result.y = Start.y + (INT32)((End.y - Start.y)/3) ; 00802 00803 return result; 00804 } 00805 00806 00807 00808 /******************************************************************************************* 00809 > static DocCoord DocCoord::TwoThirds(const DocCoord& Start, const DocCoord& End) 00810 00811 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00812 Created: 12/12/95 00813 Inputs: Start and End are two coordinates 00814 Outputs: - 00815 Returns: The point two thirds of the way from Start to End 00816 Purpose: For getting a point two thirds of the way between two other points 00817 ********************************************************************************************/ 00818 DocCoord DocCoord::TwoThirds(const DocCoord& Start, const DocCoord& End) 00819 { 00820 DocCoord result; 00821 00822 result.x = Start.x + (INT32)((End.x - Start.x)*(2.0/3.0)) ; 00823 result.y = Start.y + (INT32)((End.y - Start.y)*(2.0/3.0)) ; 00824 00825 return result; 00826 } 00827 00828 00829 00830 /******************************************************************************************* 00831 > static DocCoord DocCoord::OneHalf(const DocCoord& Start, const DocCoord& End) 00832 00833 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00834 Created: 12/12/95 00835 Inputs: Start and End are two coordinates 00836 Outputs: - 00837 Returns: The point one half of the way from Start to End 00838 Purpose: For getting a point midway between two other points 00839 ********************************************************************************************/ 00840 DocCoord DocCoord::OneHalf(const DocCoord& Start, const DocCoord& End) 00841 { 00842 DocCoord result; 00843 00844 result.x = Start.x + (INT32)((End.x - Start.x)/2) ; 00845 result.y = Start.y + (INT32)((End.y - Start.y)/2) ; 00846 00847 return result; 00848 } 00849 00850 00851 00852 /******************************************************************************************** 00853 > BOOL DocCoord::IsJoinAcute(const DocCoord* pJoin, const DocCoord* pOtherEndOfJoin, const DocCoord* pOtherPoint) 00854 00855 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00856 Created: 13/12/95 00857 Inputs: pJoin - the coordinate where two lines join 00858 pOtherEndOfJoin - another point that with pJoin defines a line 00859 pOtherPoint - another point that with pJoin defines another line 00860 Outputs: - 00861 Returns: TRUE if the angle between the two lines is an acute angle 00862 Purpose: For seeing the perpendicual distance from pOtherPoint to the line 00863 pJoin-pOtherEndOfJoin end on the line or before pJoin. Used when dragging 00864 along a line to see if the drag point has gon back beyond the start of the 00865 line. 00866 ********************************************************************************************/ 00867 BOOL DocCoord::IsJoinAcute(const DocCoord* pJoin, const DocCoord* pOtherEndOfJoin, const DocCoord* pOtherPoint) 00868 { 00869 // Translate the points so the join is on the origin and the other points are relative to that 00870 DocCoord OriginLine = *pOtherEndOfJoin - *pJoin; 00871 DocCoord OriginOther = *pOtherPoint - *pJoin; 00872 double LineAngle = atan2((double)OriginLine.y, (double)OriginLine.x); 00873 double OtherAngle = atan2((double)OriginOther.y, (double)OriginOther.x); 00874 00875 double diff = OtherAngle - LineAngle; 00876 if (diff < -PI) 00877 diff += 2*PI; 00878 if (diff > PI) 00879 diff -= 2*PI; 00880 00881 if ( (diff < -(PI/2)) || (diff > (PI/2)) ) 00882 return FALSE; 00883 else 00884 return TRUE; 00885 } 00886 00887 /******************************************************************************************** 00888 00889 > void DocCoord::Scale(const DocCoord dcOrigin, const double dDPI=96.0) 00890 00891 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com> 00892 Created: 16/4/97 00893 Inputs: dDPI The DPI by which to scale the coord 00894 dcOrigin The origin by which to scale the coord 00895 00896 Purpose: Scales the DocCoord by the specified DPI and origin. 00897 00898 That is, this function does the following to this DocCoord: 00899 00900 a. Subtracts the origin dcOrigin 00901 b. Inverts the y-axis 00902 c. Multiplies the coordinate to convert them to the number 00903 of DPI specified. 00904 00905 Used in imagemaps. 00906 00907 Note that, technically, what this function produces should be 00908 a WorkCoord. But that causes problems, because this 00909 function is called to scale paths to bitmap coordinates - and 00910 you can't specify a path in terms of WorkCoords. 00911 00912 SeeAlso: Path::Scale(), Imagemap::AddPolygon() 00913 00914 ********************************************************************************************/ 00915 00916 void DocCoord::Scale(const DocCoord dcOrigin, const double dDPI) 00917 { 00918 //Subtract the origin from this coord 00919 x-=dcOrigin.x; 00920 y-=dcOrigin.y; 00921 00922 //And scale by the appropriate DPI, inverting the y-axis 00923 //and rounding to the nearest pixel 00924 x=INT32(x*(dDPI/72000.0)+0.5); 00925 y=INT32(-y*(dDPI/72000.0)+0.5); 00926 00927 } 00928 00929