pen.cpp

Go to the documentation of this file.
00001 // $Id: pen.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 // Support for Graphics Tablets with Pressure Sensitive Pens
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 
00105 #include "pen.h"
00106 
00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "will.h"
00109 #include "camelot.h"
00110 //#include "gdihlp16.h"
00111 //#include "oilmods.h"
00112 //#include "mainfrm.h"
00113 
00114 //#include "rik.h"
00115 //#include "barsdlgs.h"
00116 
00117 //#include "tablet.h"
00118 
00119 #include "keypress.h"
00120 #include "pathtrap.h"
00121 
00122 
00123 DECLARE_SOURCE("$Revision: 1282 $");
00124 
00125 CC_IMPLEMENT_DYNAMIC(CCPen, CCObject);
00126 CC_IMPLEMENT_DYNCREATE(OpTogglePressure, Operation);
00127 
00128 #define new CAM_DEBUG_NEW
00129 
00130 // Default pressure mode preference. This indicates the last pressure mode
00131 // the user used (no-pressure, use pressure pen, or simulate pressure with mouse)
00132 PressureMode CCPen::DefaultPressureMode = PressureMode_None;
00133 
00134 
00135 
00136 
00137 /********************************************************************************************
00138 
00139 >   CCPen *CCPen::Init()
00140 
00141     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00142     Created:    26/9/94
00143     Inputs:     -
00144     Outputs:    -
00145     Returns:    Pointer to applications CCPen object, or NULL if failed.
00146     Purpose:    Application.LateInit calls this to obtain the default pen object.
00147     Errors:     ->SetError if FALSE
00148     Scope:      Static
00149 
00150 ********************************************************************************************/
00151 
00152 CCPen *CCPen::Init()
00153 {
00154     PORTNOTETRACE("other","CCPen::Init - do nothing");
00155 #ifndef EXCLUDE_FROM_XARALX
00156     // Check the ini file to see what state we're in
00157     if (Camelot.DeclareSection("PenSupport", 4))
00158         Camelot.DeclarePref("PenSupport", "PressureMode", (INT32 *)&DefaultPressureMode, PressureMode_None, PressureMode_MaxEnum);
00159 
00160     // Create a pressure sensitive pen. We create a derived class WinTab pen
00161     // which will call back to the base class if a WinTab device is unavailable.
00162     return(new WinTabPressurePen);
00163 #else
00164     return NULL;
00165 #endif
00166 }
00167 
00168 
00169 
00170 /********************************************************************************************
00171 
00172 >   CCPen::CCPen()
00173 
00174     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00175     Created:    23/5/94
00176     Inputs:     -
00177     Outputs:    -
00178     Returns:    -
00179     Purpose:    CCPen constructor.
00180     SeeAlso:    -
00181     Errors:     -
00182 
00183 ********************************************************************************************/
00184 
00185 CCPen::CCPen()
00186 {
00187     PORTNOTETRACE("other","CCPen::CCPen - do nothing");
00188 #ifndef EXCLUDE_FROM_XARALX
00189     // See if it is likely that we'll be able to initialise as a "real" pen
00190     PressureAvailable = FALSE;
00191 
00192     // Initalise member variables
00193     wxWindow           *pMainFrame = GetMainFrame();
00194     ERROR3IF(pMainFrame == NULL, "No main frame window when CCPen initialised");
00195     hMainframeWnd = pMainFrame->m_hWnd;
00196 
00197     PenPressure = 0;
00198     PressureMax = MAXPRESSURE;          // Set the default Maximum Pressure Value
00199 
00200     CurrentPressureMode = DefaultPressureMode;
00201     if (CurrentPressureMode == PressureMode_None)
00202         PenPressure = PressureMax;
00203 
00204     LastMousePoint = CPoint(0,0);
00205 #endif
00206 }
00207 
00208 
00209 
00210 /********************************************************************************************
00211 
00212 >   CCPen::~CCPen()
00213 
00214     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00215     Created:    23/5/94
00216     Inputs:     -
00217     Outputs:    -
00218     Returns:    -
00219     Purpose:    CCPen destructor.
00220     Errors:     -
00221 
00222 ********************************************************************************************/
00223 
00224 CCPen::~CCPen()
00225 {
00226 }
00227 
00228 
00229 
00230 /********************************************************************************************
00231 
00232 >   virtual void CCPen::StartStroke(void)
00233 
00234     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00235     Created:    24/1/97
00236 
00237     Purpose:    Informs the Pen class that you are starting a stroke (a drag
00238                 operation for which you wish to record pressure information)
00239 
00240                 If you do not call this method, then pressure information
00241                 will be "faked" based on mouse speed/direction information.
00242 
00243                 It should be called when you start your drag (on button down)
00244 
00245                 When the stroke finishes, remember to call CCPen::EndStroke
00246 
00247 ********************************************************************************************/
00248 
00249 void CCPen::StartStroke(void)
00250 {
00251     CurrentPressureMode = DefaultPressureMode;
00252 }
00253 
00254 
00255 
00256 /********************************************************************************************
00257 
00258 >   virtual void CCPen::EndStroke(void)
00259 
00260     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00261     Created:    24/1/97
00262 
00263     Purpose:    Informs the Pen class that you are completing a stroke (a drag
00264                 operation for which you recorded pressure information)
00265 
00266                 This function must be called to "cancel" out a call to StartStroke.
00267                 It should be called in your drag completion routine, and should
00268                 be called under all "end of drag" circumstances.
00269 
00270 ********************************************************************************************/
00271 
00272 void CCPen::EndStroke(void)
00273 {
00274     // Base class does nothing
00275 }
00276 
00277 
00278 
00279 /********************************************************************************************
00280 
00281 >   virtual void CCPen::ReadTabletPressureData(void)
00282 
00283     Author:     Martin_Donelly (Xara Group Ltd) <camelotdev@xara.com>
00284     Created:    24/1/97
00285 
00286     Returns:    TRUE if it read pressure successfully
00287                 FALSE if it failed - in this case, the caller (base class) will default
00288                 to calculating a faked pressure value from movement information. (e.g.
00289                 if you stop getting pen pressure packets, revert to using movement
00290                 rather than always returning zero!)
00291 
00292     Purpose:    Records the latest pressure info from the pressure sensitive tablet
00293                 Does nothing if this is not a "real" pen
00294 
00295                 Does nothing in the base class.
00296 
00297 ********************************************************************************************/
00298 
00299 BOOL CCPen::ReadTabletPressureData(void)
00300 {
00301     if (!PressureAvailable)
00302         return(FALSE);
00303 
00304     // Base class does nothing
00305     return(FALSE);
00306 }
00307 
00308 
00309 
00310 /********************************************************************************************
00311 
00312 >   void CCPen::CheckMouseMessage(UINT32 Message, CPoint point)
00313 
00314     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00315     Created:    15/6/94
00316     Inputs:     Message - WM_MOUSEMOVE if the mouse is moving, or WM_{L/R/M}BUTTONDOWN if 
00317                             we're starting a drag
00318                 point - the mouse position
00319     
00320     Outputs:    -
00321     Returns:    -
00322     Purpose:    Checks a mouse message to see if it came from a pen, and if so sets the
00323                 current pressure value.
00324     Errors:     -
00325 
00326 ********************************************************************************************/
00327 
00328 void CCPen::CheckMouseMessage(UINT32 Message, wxPoint point)
00329 {
00330     PORTNOTETRACE("other","CCPen::CheckMouseMessage - do nothing");
00331 #ifndef EXCLUDE_FROM_XARALX
00332     if (IsRealPen() && CurrentPressureMode == PressureMode_Pen)
00333     {
00334         // Go and check the tablet for new pressure data. If it fails, we will drop through
00335         // to the normal mouse handler - this means if a pen user puts down the pen and
00336         // uses the mouse, we automatically drop back to reading the mouse when we fail to
00337         // recieve pen packets.
00338         if (ReadTabletPressureData())
00339             return;
00340     }
00341 
00342     switch(CurrentPressureMode)
00343     {
00344         case PressureMode_None:
00345             PenPressure = PressureMax;
00346             break;
00347 
00348         case PressureMode_Pen:
00349             // We want to read values from a real pen, but that is unavailable,
00350             // so we drop through to fake something up based on mouse speed.
00351             // NOBREAK
00352 
00353             // 12/8/2000 This has changed, we no longer want to fake pressure at all
00354             PenPressure = PressureMax;
00355             break;
00356         case PressureMode_Speed:
00357             // We've got a fake pen. We use mouse travel speed to generate pressure info
00358             if (Message == WM_MOUSEMOVE)
00359             {
00360                 // Diccon - disabled mouse speed pressure for now
00361                 
00362                 PenPressure = PressureMax / 2 ;// - (INT32)(Speed * (double)PressureMax);
00363 //              PenPressure = (INT32)(Speed * (double)PressureMax);
00364             }
00365             else
00366                 PenPressure = 0;        // Must be mouse down. Init pressure to 0
00367             break;
00368 
00369 
00370         case PressureMode_Direction:
00371             // We've got a fake pen. We use mouse travel direction to generate pressure info
00372             if (Message == WM_MOUSEMOVE)
00373             {
00374                 // Work out direction of travel to do a calligraphic pen
00375                 NormCoord TravelDir(point.x - LastMousePoint.x, point.y - LastMousePoint.y);
00376 
00377                 if (TravelDir.x != 0.0 && TravelDir.y != 0.0)
00378                 {
00379                     TravelDir.Normalise();
00380 
00381                     NormCoord PenAngle(1.0, 1.0);
00382                     PenAngle.Normalise();
00383 
00384                     // Take the dot product of the travel direction and the brush angle (which gives
00385                     // us cos(angle between them)), which makes an excellent pressure (width) value
00386                     // This actually gives us a value between -1 and +1, which we scale into 0..1 range
00387                     double DotProd = TravelDir.DotProduct(PenAngle);
00388                     DotProd = (DotProd + 1.0) / 2.0;
00389 
00390                     PenPressure = (INT32) (DotProd * (double)PressureMax);
00391                 }
00392             }
00393             else
00394                 PenPressure = 0;        // Must be mouse down. Init pressure to 0
00395             break;
00396     }
00397 
00398     // And remember the last mouse position
00399     LastMousePoint = point;
00400 #endif
00401 }
00402 
00403 
00404 
00405 /********************************************************************************************
00406 
00407 >   void CCPen::SetPressureFromJoystick(WPARAM Buttons, LPARAM JoyPos)
00408 
00409     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00410     Created:    29/6/94
00411     Inputs:     The JoyPos as passed in from the Message Handler (in CCamView) 
00412     Outputs:    -
00413     Returns:    -
00414     Purpose:    Set the pretend Pen Pressure from the Joytick Position.
00415 
00416 ********************************************************************************************/
00417 
00418 void CCPen::SetPressureFromJoystick(WPARAM Buttons, LPARAM JoyPos)
00419 {
00420     PORTNOTETRACE("other","CCPen::SetPressureFromJoystick - do nothing");
00421 #ifndef EXCLUDE_FROM_XARALX
00422     if (this->IsRealPen())
00423         return;     // Ignore this call if we are a Real Pen
00424 
00425     if (!(Buttons & JOY_BUTTON1))
00426         return;     // Button1 must be down for the Pressure to be valid
00427 
00428     INT32 Ypos = HIWORD(JoyPos) - (JOYMAX/2);       // Get Y Offset from Joystick Centre
00429 
00430     // Convert the distance from the joystick centre pos, into a value between
00431     // 0 and PressureMax
00432     PenPressure = (Ypos<0 ? -Ypos : Ypos)*PressureMax/(JOYMAX/2);
00433 #endif
00434 }
00435 
00436 
00437 /********************************************************************************************
00438                         TOGGLE PRESSURE ON/OFF OPERATION
00439 */
00440 /********************************************************************************************
00441 
00442 >   OpTogglePressure::OpTogglePressure() : Operation()
00443 
00444     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00445     Created:    20/6/94
00446     Inputs:     -
00447     Outputs:    -
00448     Returns:    -
00449     Purpose:    Constructs an OpTogglePressure object.
00450     Errors:     -
00451     SeeAlso:    -
00452 
00453 ********************************************************************************************/
00454 
00455 OpTogglePressure::OpTogglePressure() : Operation()
00456 {
00457 
00458 }
00459 
00460 /********************************************************************************************
00461 
00462 >   OpTogglePressure::~OpTogglePressure()
00463 
00464     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00465     Created:    20/6/94
00466     Inputs:     -
00467     Outputs:    -
00468     Returns:    -
00469     Purpose:    Destructs an OpTogglePressure object.
00470     Errors:     -
00471     SeeAlso:    -
00472 
00473 ********************************************************************************************/
00474 
00475 OpTogglePressure::~OpTogglePressure()
00476 {
00477     // Empty
00478 }
00479 
00480 
00481 
00482 /********************************************************************************************
00483 
00484 >   void OpTogglePressure::Do(OpDescriptor*)
00485 
00486     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00487     Created:    20/6/93
00488     Inputs:     Pointer to Operation Descriptor
00489     Outputs:    -
00490     Returns:    -
00491     Purpose:    Actually "DO" a TogglePressure operation.
00492     Errors:     -
00493     SeeAlso:    -
00494 
00495 ********************************************************************************************/
00496 
00497 void OpTogglePressure::Do(OpDescriptor*)
00498 {
00499     PORTNOTETRACE("other","CCPen::Do - do nothing");
00500 #ifndef EXCLUDE_FROM_XARALX
00501     CCPen *pPen = Camelot.GetPressurePen();
00502     if (pPen != NULL)
00503     {
00504         PressureMode NewState = (pPen->IsPressureOn()) ? PressureMode_None : PressureMode_Pen;
00505         pPen->SetPressureMode(NewState);
00506     }
00507 #endif
00508 
00509     End();
00510 }
00511 
00512 
00513 
00514 /********************************************************************************************
00515 
00516 >   OpState OpTogglePressure::GetState(String_256* UIDescription, OpDescriptor*)
00517 
00518     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00519     Created:    20/6/94
00520     Inputs:     Pointer to Operation Descriptor
00521                 Text Description
00522     Outputs:    -
00523     Returns:    -
00524     Purpose:    Find the state of the OpTogglePressure operation.
00525     Errors:     -
00526     SeeAlso:    -
00527 
00528 ********************************************************************************************/
00529 
00530 OpState OpTogglePressure::GetState(String_256* UIDescription, OpDescriptor*)
00531 {
00532     OpState Bob;
00533     PORTNOTETRACE("other","CCPen::GetState - do nothing");
00534 #ifndef EXCLUDE_FROM_XARALX
00535     Bob.Ticked = (Camelot.GetPressurePen())->IsPressureOn();
00536     Bob.Greyed = FALSE;
00537 #endif
00538     return(Bob);
00539 }
00540 
00541 
00542 
00543 /********************************************************************************************
00544 
00545 >   BOOL OpTogglePressure::Init()
00546 
00547     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00548     Created:    20/6/94
00549     Inputs:     -
00550     Outputs:    -
00551     Returns:    -
00552     Purpose:    Create an OpDescriptor for the TogglePressure operation
00553     Errors:     -
00554     SeeAlso:    -
00555 
00556 ********************************************************************************************/
00557 
00558 BOOL OpTogglePressure::Init()   
00559 {
00560 PORTNOTE("other","Removed init stuff")
00561 #ifndef EXCLUDE_FROM_XARALX
00562     return(Operation::RegisterOpDescriptor(
00563                                             0,
00564                                             _R(IDS_TOGGLE_PRESSURE),
00565                                             CC_RUNTIME_CLASS(OpTogglePressure), 
00566                                             OPTOKEN_TOGGLEPRESSURE,
00567                                             OpTogglePressure::GetState,
00568                                             _R(IDS_FREEHANDPRESSURE),       // Help string ID
00569                                             _R(IDBBL_FREEHANDPRESSURE),     // Bubble help ID
00570                                             _R(IDD_FREEHANDTOOL),           // resource ID
00571                                             _R(IDC_FREEHANDPRESSURE),       // control ID
00572                                             SYSTEMBAR_EDIT,             // Bar ID
00573                                             TRUE,                       // Recieve system messages
00574                                             FALSE,                      // No smart duplicate operation
00575                                             TRUE,                       // Clean operation
00576                                             NULL,                       // No vertical counterpart
00577                                             NULL,                       // String for one copy only error
00578                                             0                           // Auto state flags
00579                                         ));
00580 #endif
00581     return false;
00582 }
00583 
00584 

Generated on Sat Nov 10 03:48:46 2007 for Camelot by  doxygen 1.4.4