home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / deans.zip / PAINTBRU.CPP < prev    next >
C/C++ Source or Header  |  1994-09-14  |  90KB  |  2,797 lines

  1. //
  2. // NAME: CIDLib_PaintBrush.Cpp
  3. //
  4. // DESCRIPTION:
  5. //
  6. //  This module implements the PAINTBRUSH class, which is the means by which
  7. //  graphical output is accomplished to windows.
  8. //
  9. //
  10. // AUTHOR: Dean Roddey
  11. //
  12. // CREATE DATE: 09/26/93
  13. //
  14. // COPYRIGHT: 1992..1994, 'CIDCorp
  15. //
  16. // CAVEATS/GOTCHAS:
  17. //
  18. // MODIFICATION LOG:
  19. //
  20.  
  21.  
  22.  
  23. // -----------------------------------------------------------------------------
  24. //  Local defines
  25. // -----------------------------------------------------------------------------
  26. #define        CIDGUI_PAINTBRUSH_CPP
  27.  
  28. #define     INCL_GPICONTROL
  29. #define     INCL_GPILCIDS
  30. #define     INCL_GPILOGCOLORTABLE
  31. #define     INCL_GPIPATHS
  32. #define     INCL_GPIPRIMITIVES
  33. #define     INCL_WINWINDOWMGR
  34.  
  35. #define     INCL_CIDGUI_ERRORIDS
  36. #define     INCL_CIDGUI_FACOBJECT
  37. #define     INCL_CIDGUI_FONTS
  38. #define     INCL_CIDGUI_GRAPHICS
  39.  
  40. #define     INCL_CIDLIB_MEMORY
  41. #define     INCL_CIDLIB_METRICS
  42. #define     INCL_CIDLIB_PROCESS
  43. #define     INCL_CIDLIB_TEXTFILES
  44.  
  45.  
  46. // -----------------------------------------------------------------------------
  47. //  Facility specific includes
  48. // -----------------------------------------------------------------------------
  49. #include    "CIDGui_.Hpp"
  50.  
  51.  
  52.  
  53.  
  54.  
  55. // -----------------------------------------------------------------------------
  56. //  Local data declarations
  57. //
  58. //  __apszLineDesc
  59. //      A list of description strings for the line types.
  60. //
  61. //  __apszMixDesc
  62. //      A list of description strings for the mix mode enum.
  63. //
  64. //  __apszPatDesc
  65. //      A list of description strings for the pattern types.
  66. // -----------------------------------------------------------------------------
  67. tCIDLib::CH* __apszLineDesc[] = {
  68.                                       "Default"
  69.                                       , "Dot"
  70.                                       , "ShortDash"
  71.                                       , "DashDot"
  72.                                       , "DoubleDot"
  73.                                       , "LongDash"
  74.                                       , "DashDoubleDot"
  75.                                       , "Solid"
  76.                                       , "Invisible"
  77.                                 };
  78. const tCIDLib::CARD4 c4LineMax  = (sizeof(__apszLineDesc)
  79.                                                 /sizeof(__apszLineDesc[0]));
  80.  
  81.  
  82. tCIDLib::CH* __apszMixDesc[] =  {
  83.                                     "Default"
  84.                                     , "Or"
  85.                                     , "OverPaint"
  86.                                     , "?3"
  87.                                     , "Xor"
  88.                                     , "Leavalone"
  89.                                     , "And"
  90.                                     , "SubTract"
  91.                                     , "MaskSrcNot"
  92.                                     , "Zero"
  93.                                     , "NotMergeSrc"
  94.                                     , "NotXorSrc"
  95.                                     , "Invert"
  96.                                     , "MergeSrcNot"
  97.                                     , "NotCopySrc"
  98.                                     , "MergeNotSrc"
  99.                                     , "NotMaskSrc"
  100.                                     , "One"
  101.                                 };
  102. const tCIDLib::CARD4 c4MixMax   = (sizeof(__apszMixDesc)
  103.                                                 /sizeof(__apszMixDesc[0]));
  104.  
  105.  
  106. tCIDLib::CH* __apszPatDesc[] =  {
  107.                                       "Default"
  108.                                       , "Dense1"
  109.                                       , "Dense2"
  110.                                       , "Dense3"
  111.                                       , "Dense4"
  112.                                       , "Dense5"
  113.                                       , "Dense6"
  114.                                       , "Dense7"
  115.                                       , "Dense8"
  116.                                       , "Vert"
  117.                                       , "Horiz"
  118.                                       , "Diag1"
  119.                                       , "Diag2"
  120.                                       , "Diag3"
  121.                                       , "Diag4"
  122.                                       , "NoShade"
  123.                                       , "Solid"
  124.                                       , "Halftone"
  125.                                       , "Hatch"
  126.                                       , "DiagHatch"
  127.                                 };
  128. const tCIDLib::CARD4 c4PatMax   = (sizeof(__apszPatDesc)
  129.                                                 /sizeof(__apszPatDesc[0]));
  130.  
  131.  
  132.  
  133.  
  134. // -----------------------------------------------------------------------------
  135. //  Global functions
  136. // -----------------------------------------------------------------------------
  137.  
  138. //
  139. // FUNCTION/METHOD NAME: operator<<(strbDest, eMix)
  140. //
  141. // DESCRIPTION:
  142. //
  143. //  This method will format the passed mix mode to the passed string.
  144. // ---------------------------------------
  145. //   INPUT: eMix is the mix mode to use
  146. //
  147. //  OUTPUT: strbDest is the destination string to format to
  148. //
  149. //  RETURN: A reference to the string
  150. //
  151. STRGBUF& PROCEXP operator<<(STRGBUF& strbDest, tCIDGui::eMIXMODES eMix)
  152. {
  153.     if (eMix > c4MixMax)
  154.     {
  155.         facCIDGui.LogErr(   __FILE__
  156.                             , "operator<<"
  157.                             , __LINE__
  158.                             , GUIERR_GEN_NOT_VALID_VALUE
  159.                             , tCIDLib::eSEV_PROCESS_FATAL
  160.                             , tCIDLib::eCLASS_BADPARMS
  161.                             , CARDINAL(eMix)
  162.                             , STRG16("Mix Mode"));
  163.     }
  164.     strbDest << __apszMixDesc[eMix];
  165.     return strbDest;
  166. }
  167.  
  168. OTXTFILE& PROCEXP operator<<(OTXTFILE& otfDest, tCIDGui::eMIXMODES eMix)
  169. {
  170.     STRG64  strTmp;
  171.     strTmp << eMix;
  172.     otfDest << strTmp;
  173.     return otfDest;
  174. }
  175.  
  176.  
  177. //
  178. // FUNCTION/METHOD NAME: operator<<(strbDest, eLineStyle)
  179. //
  180. // DESCRIPTION:
  181. //
  182. //  This method will format the passed line style into the string buffer
  183. // ---------------------------------------
  184. //   INPUT: eLineStyle is the line style to format
  185. //
  186. //  OUTPUT: strbDest is the buffer to format into
  187. //
  188. //  RETURN: A reference to the string buffer
  189. //
  190. STRGBUF& PROCEXP operator<<(STRGBUF&                strbDest
  191.                             , tCIDGui::eLINESTYLES  eLineStyle)
  192. {
  193.     // Check for valid ranges
  194.     if (eLineStyle > c4LineMax)
  195.     {
  196.         facCIDGui.LogErr(   __FILE__
  197.                             , "operator<<"
  198.                             , __LINE__
  199.                             , GUIERR_GEN_NOT_VALID_VALUE
  200.                             , tCIDLib::eSEV_PROCESS_FATAL
  201.                             , tCIDLib::eCLASS_BADPARMS
  202.                             , INTEGER(eLineStyle)
  203.                             , STRG16("Line Style"));
  204.     }
  205.  
  206.     strbDest << __apszLineDesc[eLineStyle];
  207.     return strbDest;
  208. }
  209.  
  210. OTXTFILE& PROCEXP operator<<(   OTXTFILE&               otfDest
  211.                                 , tCIDGui::eLINESTYLES  eLineStyle)
  212. {
  213.     STRG64  strTmp;
  214.     strTmp << eLineStyle;
  215.     otfDest << strTmp;
  216.     return otfDest;
  217. }
  218.  
  219.  
  220. //
  221. // FUNCTION/METHOD NAME: operator<<(strbDest, ePattern)
  222. //
  223. // DESCRIPTION:
  224. //
  225. //  This method will format the passed pattern to the passed string buffer
  226. //  object.
  227. // ---------------------------------------
  228. //   INPUT: ePattern is the pattern to format
  229. //
  230. //  OUTPUT: strbDest is the destination string.
  231. //
  232. //  RETURN: A reference to the string
  233. //
  234. STRGBUF& PROCEXP operator<<(STRGBUF& strbDest, tCIDGui::ePATTERNS ePattern)
  235. {
  236.     // Check for valid ranges
  237.     if (ePattern > c4PatMax)
  238.     {
  239.         facCIDGui.LogErr(   __FILE__
  240.                             , "operator<<"
  241.                             , __LINE__
  242.                             , GUIERR_GEN_NOT_VALID_VALUE
  243.                             , tCIDLib::eSEV_PROCESS_FATAL
  244.                             , tCIDLib::eCLASS_BADPARMS
  245.                             , INTEGER(ePattern)
  246.                             , STRG16("Pattern"));
  247.     }
  248.  
  249.     strbDest << __apszPatDesc[ePattern];
  250.     return strbDest;
  251. }
  252.  
  253. OTXTFILE& PROCEXP operator<<(OTXTFILE& otfDest, tCIDGui::ePATTERNS ePattern)
  254. {
  255.     STRG64  strTmp;
  256.     strTmp << ePattern;
  257.     otfDest << strTmp;
  258.     return otfDest;
  259. }
  260.  
  261.  
  262.  
  263.  
  264. // -----------------------------------------------------------------------------
  265. //   CLASS: FONT
  266. //  PREFIX: fnt
  267. //
  268. //  This class is just for local use. Objects of this class are used as the
  269. //  nodes of the PAINTBRUSH class' list of active fonts.
  270. // -----------------------------------------------------------------------------
  271. class               FONT : public CIDOBJECT
  272. {
  273.     public          :
  274.         // ---------------------------------------------------------------------
  275.         //  Constructors and Destructors.
  276.         //
  277.         //  FONT
  278.         //      The constructor just saves away the font name, font id, PS, and
  279.         //      the font metrics. The name must be unique for this window and
  280.         //      would ideally be unique for the process.
  281.         //
  282.         //  ~FONT
  283.         //      The destructor destroys the logical font.
  284.         // ---------------------------------------------------------------------
  285.         FONT                            (
  286.                                             const   STRG16&             strName
  287.                                             , const FONTINFO&           finfInfo
  288.                                             ,       HPS                 hpsWnd
  289.                                             ,       tCIDLib::INT4       i4FontId
  290.                                         );
  291.  
  292.         ~FONT                           ();
  293.  
  294.  
  295.         // ---------------------------------------------------------------------
  296.         //  Public, inherited methods
  297.         //
  298.         //  FormatToStr
  299.         //      Formats some debug info about this window to the string buffer.
  300.         // ---------------------------------------------------------------------
  301.         STDVPUBMETHODS(FONT,CIDOBJECT,tCIDLib::eFALSE);
  302.  
  303.         virtual tCIDLib::VOID FormatToStr
  304.                                         (
  305.                                                     STRGBUF&            strbDest
  306.                                         )   const;
  307.  
  308.  
  309.     protected       :
  310.         // ---------------------------------------------------------------------
  311.         //  Declare our friends
  312.         //
  313.         //  PAINTBRUSH
  314.         //      We let PAINTBRUSH access our data members directly since we
  315.         //      exist only for his benefit and he can use all the speed he can
  316.         //      get.
  317.         // ---------------------------------------------------------------------
  318.         friend  class                   PAINTBRUSH;
  319.  
  320.  
  321.         // ---------------------------------------------------------------------
  322.         //  Protected data members
  323.         //
  324.         //  _hpsWnd
  325.         //      This is the PS of the window we belong to, which is needed in
  326.         //      order to destroy the font.
  327.         //
  328.         //  _i4FontId
  329.         //      The logical font id of this font
  330.         //
  331.         //  _finfInfo
  332.         //      The FONTINFO object for this font.
  333.         //
  334.         //  _strName
  335.         //      This holds the name of this font, which is given by the caller
  336.         //      when the font is created. It must be unique.
  337.         // ---------------------------------------------------------------------
  338.         HPS                             _hpsWnd;
  339.         tCIDLib::INT4                   _i4FontId;
  340.         FONTINFO                        _finfInfo;
  341.         STRG16                          _strName;
  342. };
  343.  
  344. // -----------------------------------------------------------------------------
  345. //  FONT: Constructors and Destructors
  346. // -----------------------------------------------------------------------------
  347.  
  348. //
  349. // FUNCTION/METHOD NAME: FONT(strName, finfInfo, hpsWnd, i4FontId)
  350. //
  351. // DESCRIPTION:
  352. //
  353. //  This constructor just needs to store away the passed info.
  354. // ---------------------------------------
  355. //   INPUT: strName is the name that the caller gave to the font
  356. //          finfInfo is the FONTINFO object for the font. This makes it easy
  357. //              to provide font info about a font quickly.
  358. //          hpsWnd is the presentation space of the window.
  359. //          i4FontId is the logical font id of the font.
  360. //
  361. //  OUTPUT: None
  362. //
  363. //  RETURN: None
  364. //
  365. FONT::FONT( const   STRG16&             strName
  366.             , const FONTINFO&           finfInfo
  367.             ,       HPS                 hpsWnd
  368.             ,       tCIDLib::INT4       i4FontId) :
  369.     _i4FontId(i4FontId)
  370.     , _finfInfo(finfInfo)
  371.     , _hpsWnd(hpsWnd)
  372.     , _strName(strName)
  373. {
  374.     // Bump up the font id count in the core metrics
  375.     _pmtrGUICore->OffsetCard(tCIDGui_::eCOREMETRIC_FNTIDCOUNT, 1);
  376. }
  377.  
  378.  
  379. //
  380. // FUNCTION/METHOD NAME: ~FONT()
  381. //
  382. // DESCRIPTION:
  383. //
  384. //  This destructor will delete the logical font. The PAINTBRUSH object needs
  385. //  to have reset the PS to the default font.
  386. // ---------------------------------------
  387. //   INPUT: None
  388. //
  389. //  OUTPUT: None
  390. //
  391. //  RETURN: None
  392. //
  393. FONT::~FONT()
  394. {
  395.     _DeleteFontId(_hpsWnd, _i4FontId, _strName);
  396.  
  397.     // Bump down the font id count in the core metrics
  398.     _pmtrGUICore->OffsetCard(tCIDGui_::eCOREMETRIC_FNTIDCOUNT, -1);
  399. }
  400.  
  401.  
  402. // -----------------------------------------------------------------------------
  403. //  FONT: Public, inherited methods
  404. // -----------------------------------------------------------------------------
  405.  
  406. //
  407. // FUNCTION/METHOD NAME: FormatToStr(strbDest) const
  408. //
  409. // DESCRIPTION:
  410. //
  411. //  This method will format the data members into the passed string buffer
  412. // ---------------------------------------
  413. //   INPUT: None
  414. //
  415. //  OUTPUT: strbDest is the buffer to format into
  416. //
  417. //  RETURN: None
  418. //
  419. tCIDLib::VOID PROCEXP FONT::FormatToStr(STRGBUF& strbDest) const
  420. {
  421.     // Format the info
  422.     strbDest << _finfInfo << ", ID=" << _i4FontId << ", Name=" << _strName;
  423. }
  424.  
  425.  
  426.  
  427.  
  428. // -----------------------------------------------------------------------------
  429. //   CLASS: PAINTBRUSH
  430. //  PREFIX: ptb
  431. // -----------------------------------------------------------------------------
  432.  
  433. // -----------------------------------------------------------------------------
  434. //  PAINTBRUSH: Constructors/Destructors
  435. // -----------------------------------------------------------------------------
  436.  
  437. //
  438. // FUNCTION/METHOD NAME: PAINTBRUSH(wndTarget)
  439. //
  440. // DESCRIPTION:
  441. //
  442. //  This constructor is the only public constructor for PAINTBRUSH objects. It
  443. //  just stores away the window handle and creates a PS. The PS is put into
  444. //  RGB mode.
  445. // ---------------------------------------
  446. //   INPUT: wndTarget is the target window that we are paint into.
  447. //
  448. //  OUTPUT: None
  449. //
  450. //  RETURN: None
  451. //
  452. PROCEXP PAINTBRUSH::PAINTBRUSH(WINDOW& wndTarget) :
  453.  
  454.     __eType(ePS_TEMPORARY)
  455.     , __hPS(0)
  456.     , __llstFonts(tCIDGui::i4MaxFontIds, tCIDLib::eDEL_DELETE)
  457.     , __wndTarget(wndTarget)
  458. {
  459.     // Get a PS from the target window
  460.     __hPS = WinGetPS(wndTarget);
  461.  
  462.     if (!__hPS)
  463.     {
  464.         facCIDGui.LogLastSysErr(__FILE__
  465.                                 , "PAINTBRUSH"
  466.                                 , __LINE__
  467.                                 , "WinGetPS failed"
  468.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  469.     }
  470.  
  471.     // Set the PS to RGB mode
  472.     if (!GpiCreateLogColorTable(__hPS, 0, LCOLF_RGB, 0, 0, 0))
  473.     {
  474.         facCIDGui.LogLastSysErr(__FILE__
  475.                                 , "PAINTBRUSH"
  476.                                 , __LINE__
  477.                                 , "GpiCreateLogColorTable failed"
  478.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  479.     }
  480.  
  481.     // Bump up the count of paint brushes in the metrics
  482.     _pmtrGUICore->OffsetCard(tCIDGui_::eCOREMETRIC_PBRUSHCOUNT, 1);
  483. }
  484.  
  485.  
  486. //
  487. // FUNCTION/METHOD NAME: PAINTBRUSH(hPS, wndTarget, eType)
  488. //
  489. // DESCRIPTION:
  490. //
  491. //  This is a special, protected constructor that is provided for our
  492. //  friends who need to create PAINTBRUSH objects after the fact for
  493. //  existing PSs.
  494. //
  495. //  NOTE: This guy is protected!!!
  496. // ---------------------------------------
  497. //   INPUT: hPS is the PS that already exists
  498. //          wndTarget is the target window that we are drawing to
  499. //          eType indicates what type of PS. For this call it will almost
  500. //              always be ePS_PAINT or ePS_PERSISTENT
  501. //
  502. //  OUTPUT: None
  503. //
  504. //  RETURN: None
  505. //
  506. PROCEXP PAINTBRUSH::PAINTBRUSH(HPS hPS, WINDOW& wndTarget, ePSTYPE eType) :
  507.  
  508.     __eType(eType)
  509.     , __hPS(hPS)
  510.     , __llstFonts(tCIDGui::i4MaxFontIds, tCIDLib::eDEL_DELETE)
  511.     , __wndTarget(wndTarget)
  512. {
  513.     // Set the PS to RGB mode
  514.     if (!GpiCreateLogColorTable(__hPS, 0, LCOLF_RGB, 0, 0, 0))
  515.     {
  516.         facCIDGui.LogLastSysErr(__FILE__
  517.                                 , "PAINTBRUSH"
  518.                                 , __LINE__
  519.                                 , "GpiCreateLogColorTable failed"
  520.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  521.     }
  522.  
  523.     // Bump up the count of paint brushes in the metrics
  524.     _pmtrGUICore->OffsetCard(tCIDGui_::eCOREMETRIC_PBRUSHCOUNT, 1);
  525. }
  526.  
  527.  
  528. //
  529. // FUNCTION/METHOD NAME: PAINTBRUSH()
  530. //
  531. // DESCRIPTION:
  532. //
  533. //  This guy aborts if it is called. We have to use bogus info to create
  534. //  some members because they must be created.
  535. // ---------------------------------------
  536. //   INPUT: None
  537. //
  538. //  OUTPUT: None
  539. //
  540. //  RETURN: None
  541. //
  542. PROCEXP PAINTBRUSH::PAINTBRUSH() :
  543.  
  544.     __llstFonts(1, tCIDLib::eDEL_DELETE)
  545.     , __wndTarget(NUL_WINDOW)
  546. {
  547.     facCIDGui.LogMsg(   __FILE__
  548.                         , "PAINTBRUSH"
  549.                         , __LINE__
  550.                         , "PAINTBRUSH default constructor cannot be called"
  551.                         , tCIDLib::eSEV_PROCESS_FATAL);
  552. }
  553.  
  554.  
  555. //
  556. // FUNCTION/METHOD NAME: ~PAINTBRUSH()
  557. //
  558. // DESCRIPTION:
  559. //
  560. //  This guy will destroy the PS according to what type it is and whether
  561. //  it ever got created.
  562. // ---------------------------------------
  563. //   INPUT: None
  564. //
  565. //  OUTPUT: None
  566. //
  567. //  RETURN: None
  568. //
  569. PROCEXP PAINTBRUSH::~PAINTBRUSH()
  570. {
  571.     // Clean up the PS
  572.     if (__hPS)
  573.     {
  574.         // Make sure that we go back to the default font
  575.         if (!GpiSetCharSet(__hPS, LCID_DEFAULT))
  576.         {
  577.             facCIDGui.LogLastSysErr(__FILE__
  578.                                     , "~PAINTBRUSH"
  579.                                     , __LINE__
  580.                                     , "GpiSetCharSet failed"
  581.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  582.         }
  583.  
  584.         //
  585.         //  Flush the font list. It is in delete mode so it will delete the
  586.         //  FONT objects, which will delete their associated logical font
  587.         //  ids.
  588.         //
  589.         __llstFonts.Flush();
  590.  
  591.         // According to what type of PS, destroy it
  592.         if (__eType == ePS_PAINT)
  593.         {
  594.             if (!WinEndPaint(__hPS))
  595.             {
  596.                 facCIDGui.LogLastSysErr(__FILE__
  597.                                         , "~PAINTBRUSH"
  598.                                         , __LINE__
  599.                                         , "WinEndPaint failed"
  600.                                         , tCIDLib::eSEV_PROCESS_FATAL);
  601.             }
  602.         }
  603.          else if (__eType == ePS_TEMPORARY)
  604.         {
  605.             if (!WinReleasePS(__hPS))
  606.             {
  607.                 facCIDGui.LogLastSysErr(__FILE__
  608.                                         , "~PAINTBRUSH"
  609.                                         , __LINE__
  610.                                         , "WinReleasePS failed"
  611.                                         , tCIDLib::eSEV_PROCESS_FATAL);
  612.             }
  613.         }
  614.          else if (__eType == ePS_PERSISTENT)
  615.         {
  616.             if (!GpiDestroyPS(__hPS))
  617.             {
  618.                 facCIDGui.LogLastSysErr(__FILE__
  619.                                         , "~PAINTBRUSH"
  620.                                         , __LINE__
  621.                                         , "GpiDestroyPS failed"
  622.                                         , tCIDLib::eSEV_PROCESS_FATAL);
  623.             }
  624.         }
  625.         __hPS = 0;
  626.     }
  627.  
  628.     // Bump down the count of paint brushes in the metrics
  629.     _pmtrGUICore->OffsetCard(tCIDGui_::eCOREMETRIC_PBRUSHCOUNT, -1);
  630. }
  631.  
  632.  
  633. // -----------------------------------------------------------------------------
  634. //  PAINTBRUSH: Public, inherited methods
  635. // -----------------------------------------------------------------------------
  636.  
  637. //
  638. // FUNCTION/METHOD NAME: FormatToStr(strbDest) const
  639. //
  640. // DESCRIPTION:
  641. //
  642. //  This method will format the data members into the passed string buffer
  643. // ---------------------------------------
  644. //   INPUT: None
  645. //
  646. //  OUTPUT: strbDest is the buffer to format into
  647. //
  648. //  RETURN: None
  649. //
  650. tCIDLib::VOID PROCEXP PAINTBRUSH::FormatToStr(STRGBUF& strbDest) const
  651. {
  652.     // Format our PS info into the string
  653.     strbDest << "PS=" << CARDINAL(__hPS, tCIDLib::eRADIX_HEX);
  654. }
  655.  
  656.  
  657.  
  658. // -----------------------------------------------------------------------------
  659. //  PAINTBRUSH: Public, non-virtual methods
  660. // -----------------------------------------------------------------------------
  661.  
  662. //
  663. // FUNCTION/METHOD NAME: areaString(strbText, c4Start, c4End)
  664. //
  665. // DESCRIPTION:
  666. //
  667. //  This method will return a 0 based area that will contain the indicated
  668. //  substring of the passed string using the current font and character
  669. //  attributes. There is another version that just does the whole string,
  670. //  which calls this version with the whole string length.
  671. // ---------------------------------------
  672. //   INPUT: strbText is the text to measure
  673. //          c4Start is the starting index of the substring to get the area for
  674. //          c4End is the ending index of the substring to get the area for.
  675. //
  676. //  OUTPUT: None
  677. //
  678. //  RETURN: An AREA object that contains the text
  679. //
  680. AREA PROCEXP PAINTBRUSH::areaString(const STRGBUF& strbText) const
  681. {
  682.     return areaString(strbText, 0, strbText.c4Length()-1);
  683. }
  684.  
  685. AREA PROCEXP PAINTBRUSH::areaString(const   STRGBUF&        strbText
  686.                                     ,       tCIDLib::CARD4  c4Start
  687.                                     ,       tCIDLib::CARD4  c4End) const
  688. {
  689.     POINTL  aptlBox[TXTBOX_COUNT];
  690.     STRING  strTmp("", strbText.c4Length());
  691.  
  692.     // Pull out the indicated substring
  693.     strTmp.CopySubStr(strbText, c4Start, c4End);
  694.  
  695.     if (!GpiQueryTextBox(   __hPS
  696.                             , strTmp.c4Length()
  697.                             , strTmp.pSZ()
  698.                             , TXTBOX_COUNT
  699.                             , aptlBox))
  700.     {
  701.         facCIDGui.LogLastSysErr(__FILE__
  702.                                 , "PAINTBRUSH::areaString"
  703.                                 , __LINE__
  704.                                 , "GpiQueryTextBox failed"
  705.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  706.     }
  707.  
  708.     //
  709.     //  This guy returns points that take into account where the baseline will
  710.     //  be written, but we don't want that. So we need to adjust the y of both
  711.     //  corners by the y of the lower left corner.
  712.     //
  713.     aptlBox[TXTBOX_TOPRIGHT].x -= aptlBox[TXTBOX_BOTTOMLEFT].x;
  714.     aptlBox[TXTBOX_TOPRIGHT].y -= aptlBox[TXTBOX_BOTTOMLEFT].y;
  715.     aptlBox[TXTBOX_BOTTOMLEFT].x = 0;
  716.     aptlBox[TXTBOX_BOTTOMLEFT].y = 0;
  717.  
  718.     return AREA(aptlBox[TXTBOX_BOTTOMLEFT], aptlBox[TXTBOX_TOPRIGHT]);
  719. }
  720.  
  721.  
  722.  
  723. //
  724. // FUNCTION/METHOD NAME: Box(pntTo, c4Rounding)
  725. //                       Box(pntFrom, pntTo, c4Rounding)
  726. //                       Box(areaBox, c4Rounding)
  727. //
  728. // DESCRIPTION:
  729. //
  730. //  There are three versions that:
  731. //
  732. //  1) Draw from the current position to the pntTo
  733. //  2) From from the pntFrom to the pntTo
  734. //  3) Draw a box that covers the passed area
  735. //
  736. //  The foreground color is used for the fill.
  737. // ---------------------------------------
  738. //   INPUT: pntFrom is the point to draw from
  739. //          pntTo is the point to draw to
  740. //          areaBox is the area to draw the box over
  741. //          c4Rounding is the amount of rounding to apply
  742. //
  743. //  OUTPUT: None
  744. //
  745. //  RETURN: None
  746. //
  747. tCIDLib::VOID PROCEXP PAINTBRUSH::Box(  const POINT&        pntTo
  748.                                         , tCIDLib::CARD4    c4Rounding)
  749. {
  750.     if (GpiBox( __hPS
  751.                 , DRO_FILL
  752.                 , pntTo
  753.                 , c4Rounding
  754.                 , c4Rounding) == GPI_ERROR)
  755.     {
  756.         facCIDGui.LogLastSysErr(__FILE__
  757.                                 , "PAINTBRUSH::Box"
  758.                                 , __LINE__
  759.                                 , "GpiBox failed"
  760.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  761.     }
  762. }
  763.  
  764. tCIDLib::VOID PROCEXP PAINTBRUSH::Box(  const   POINT&          pntFrom
  765.                                         , const POINT&          pntTo
  766.                                         ,       tCIDLib::CARD4  c4Rounding)
  767. {
  768.     if (!GpiMove(__hPS, pntFrom))
  769.     {
  770.         facCIDGui.LogLastSysErr(__FILE__
  771.                                 , "PAINTBRUSH::Box"
  772.                                 , __LINE__
  773.                                 , "GpiMove failed"
  774.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  775.     }
  776.  
  777.     if (GpiBox( __hPS
  778.                 , DRO_FILL
  779.                 , pntTo
  780.                 , c4Rounding
  781.                 , c4Rounding) == GPI_ERROR)
  782.     {
  783.         facCIDGui.LogLastSysErr(__FILE__
  784.                                 , "PAINTBRUSH::Box"
  785.                                 , __LINE__
  786.                                 , "GpiBox failed"
  787.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  788.     }
  789. }
  790.  
  791. tCIDLib::VOID PROCEXP PAINTBRUSH::Box(  const   AREA&           areaBox
  792.                                         ,       tCIDLib::CARD4  c4Rounding)
  793. {
  794.     POINTL  ptlFrom, ptlTo;
  795.  
  796.     // Covert the area to 2 pointls
  797.     areaBox.ToPtls(ptlFrom, ptlTo);
  798.  
  799.     if (!GpiMove(__hPS, &ptlFrom))
  800.     {
  801.         facCIDGui.LogLastSysErr(__FILE__
  802.                                 , "PAINTBRUSH::Box"
  803.                                 , __LINE__
  804.                                 , "GpiMove failed"
  805.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  806.     }
  807.  
  808.     if (GpiBox( __hPS
  809.                 , DRO_FILL
  810.                 , &ptlTo
  811.                 , c4Rounding
  812.                 , c4Rounding) == GPI_ERROR)
  813.     {
  814.         facCIDGui.LogLastSysErr(__FILE__
  815.                                 , "PAINTBRUSH::Box"
  816.                                 , __LINE__
  817.                                 , "GpiBox failed"
  818.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  819.     }
  820. }
  821.  
  822.  
  823. //
  824. // FUNCTION/METHOD NAME: c4EnumFonts(   strbFaceName, eFlags, eSignificant
  825. //                                      , llstTarget)
  826. //
  827. // DESCRIPTION:
  828. //
  829. //  This method will return a linked list of FONTINFO objects for all of the
  830. //  available fonts that match the passed criteria.
  831. // ---------------------------------------
  832. //   INPUT: strbFaceName is the face name to look for. If it is "", then all
  833. //              face names are accepted.
  834. //          eFlags is a set of selection criteria to find fonts that match
  835. //              a particular format.
  836. //          eSignificant is a bit mask that indicates which flags in the
  837. //              eFlags parm are valid.
  838. //
  839. //  OUTPUT: llstTarget is the target linked list that will be filled in with
  840. //              the matching fonts. It is flushed before the new fonts are
  841. //              added.
  842. //
  843. //  RETURN: The number of fonts found
  844. //
  845. tCIDLib::CARD4
  846.     PROCEXP PAINTBRUSH::c4EnumFonts(const   STRGBUF&            strbFaceName
  847.                                     ,       tCIDGui::eFONTFLAGS eSelection
  848.                                     ,       tCIDGui::eFONTFLAGS eSelSignificant
  849.                                     ,       LINKLIST&           llstTarget)
  850. {
  851.     return _c4EnumFonts(__hPS
  852.                         , strbFaceName
  853.                         , eSelection
  854.                         , eSelSignificant
  855.                         , llstTarget);
  856. }
  857.  
  858.  
  859. //
  860. // FUNCTION/METHOD NAME: CreateFont(finfNew, eFAttrs, strName)
  861. //
  862. // DESCRIPTION:
  863. //
  864. //  This method will create a font for this window. The font will be given the
  865. //  passed name for future reference.
  866. // ---------------------------------------
  867. //   INPUT: finfNew is the FONTINFO object that contains the info on the type
  868. //              of font to create.
  869. //          eFAttrs are the font creation attributes to use
  870. //          strName is the name to give to the font. It must be unique for this
  871. //              window, and preferably for the process. This name is how the
  872. //              client accesses the font hereafter.
  873. //
  874. //  OUTPUT: None
  875. //
  876. //  RETURN: None
  877. //
  878. tCIDLib::VOID PROCEXP
  879.             PAINTBRUSH::CreateFont( const   FONTINFO&           finfNew
  880.                                     ,       tCIDGui::eFATTRS    eFAttrs
  881.                                     , const STRG16&             strName)
  882. {
  883.     //
  884.     //  The first thing to do is to see if the PS is valid at this time. If
  885.     //  not then abort.
  886.     //
  887.     if (!__hPS)
  888.     {
  889.         facCIDGui.LogErr(   __FILE__
  890.                             , "PAINTBRUSH::CreateFont"
  891.                             , __LINE__
  892.                             , GUIERR_GEN_REQUIRES_VALID_PS
  893.                             , strName
  894.                             , tCIDLib::eSEV_PROCESS_FATAL
  895.                             , tCIDLib::eCLASS_BADPARMS);
  896.     }
  897.  
  898.     // Make sure that the font name is unique for this window.
  899.     if (_plnodFindFnt(strName))
  900.     {
  901.         facCIDGui.LogErr(   __FILE__
  902.                             , "PAINTBRUSH::CreateFont"
  903.                             , __LINE__
  904.                             , GUIERR_FONT_NAME_NOT_UNIQUE
  905.                             , tCIDLib::eSEV_PROCESS_FATAL
  906.                             , tCIDLib::eCLASS_BADPARMS
  907.                             , strName);
  908.     }
  909.  
  910.     // Create a logical font id using the passed font info
  911.     tCIDLib::INT4 i4FontId = _i4CreateLogFont(__hPS, eFAttrs, finfNew);
  912.  
  913.     //
  914.     //  Create a FONT object using the info we have and put it into the list
  915.     //  for this window.
  916.     //
  917.     __llstFonts.plnodAppendNode(new FONT(strName, finfNew, __hPS, i4FontId));
  918. }
  919.  
  920.  
  921. //
  922. // FUNCTION/METHOD NAME: DisplayText(strbText)
  923. //
  924. // DESCRIPTION:
  925. //
  926. //  This method will display the passed text string at the current location
  927. //  using the currently set attributes.
  928. // ---------------------------------------
  929. //   INPUT: strbText is the string to display
  930. //
  931. //  OUTPUT: None
  932. //
  933. //  RETURN: None
  934. //
  935. tCIDLib::VOID PROCEXP PAINTBRUSH::DisplayText(const STRGBUF& strbText)
  936. {
  937.     if (GpiCharString(  __hPS
  938.                         , strbText.c4Length()
  939.                         , strbText.pSZ()) == GPI_ERROR)
  940.     {
  941.         // It failed, so we need to log a message and abort
  942.         facCIDGui.LogLastSysErr(__FILE__
  943.                                 , "PAINTBRUSH::DisplayText"
  944.                                 , __LINE__
  945.                                 , "GpiCharString failed"
  946.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  947.     }
  948. }
  949.  
  950.  
  951. //
  952. // FUNCTION/METHOD NAME: DisplayText(strbText, pntPos)
  953. //
  954. // DESCRIPTION:
  955. //
  956. //  This method will display the passed text string at the indicated location
  957. //  using the currently set attributes.
  958. // ---------------------------------------
  959. //   INPUT: strbText is the string to display
  960. //          pntPos is the position to display the text. This is the baseline
  961. //              position!
  962. //
  963. //  OUTPUT: None
  964. //
  965. //  RETURN: None
  966. //
  967. tCIDLib::VOID PROCEXP PAINTBRUSH::DisplayText(  const   STRGBUF&    strbText
  968.                                                 , const POINT&      pntPos)
  969. {
  970.     if (GpiCharStringAt(__hPS
  971.                         , pntPos
  972.                         , strbText.c4Length()
  973.                         , strbText.pSZ()) == GPI_ERROR)
  974.     {
  975.         facCIDGui.LogLastSysErr(__FILE__
  976.                                 , "PAINTBRUSH::DisplayText"
  977.                                 , __LINE__
  978.                                 , "GpiCharStringAt failed"
  979.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  980.     }
  981. }
  982.  
  983.  
  984. //
  985. // FUNCTION/METHOD NAME: DisplayText(   strbText, areaClip, eHJustify
  986. //                                      , eVJustify, eFlags)
  987. //
  988. // DESCRIPTION:
  989. //
  990. //  This method will display the passed text string using the current attributes
  991. //  and clipped and justified to the passed area.
  992. // ---------------------------------------
  993. //   INPUT: strbText is the string to display
  994. //          areaClip is the area to clipp the output to
  995. //          eHJustify is the horizontal justification
  996. //          eVJustify is the verical justification
  997. //          eFlags is a set of flags that control the display options.
  998. //
  999. //  OUTPUT: None
  1000. //
  1001. //  RETURN: None
  1002. //
  1003. tCIDLib::VOID
  1004.     PROCEXP PAINTBRUSH::DisplayText(const   STRGBUF&        strbText
  1005.                                     , const AREA&           areaClip
  1006.                                     , tCIDLib::eHJUSTIFY    eHJustify
  1007.                                     , tCIDLib::eVJUSTIFY    eVJustify
  1008.                                     , tCIDGui::eTEXTFLAGS   eFlags)
  1009. {
  1010.     RECTL   rectlClip;
  1011.     ULONG   ulFlags = eFlags;
  1012.  
  1013.     if (eHJustify == tCIDLib::eHJUSTIFY_RIGHT)
  1014.         ulFlags = DT_RIGHT;
  1015.     else if (eHJustify == tCIDLib::eHJUSTIFY_CENTER)
  1016.         ulFlags = DT_CENTER;
  1017.  
  1018.     if (eVJustify == tCIDLib::eVJUSTIFY_BOTTOM)
  1019.         ulFlags |= DT_BOTTOM;
  1020.     else if (eVJustify == tCIDLib::eHJUSTIFY_CENTER)
  1021.         ulFlags |= DT_CENTER;
  1022.  
  1023.     // Use colors in PS
  1024.     ulFlags |= DT_TEXTATTRS;
  1025.  
  1026.     areaClip.ToRectl(rectlClip, tCIDGui::eRECTL_NONINCLUSIVE);
  1027.     WinDrawText(__hPS
  1028.                 , -1
  1029.                 , strbText.pSZ()
  1030.                 , &rectlClip
  1031.                 , 0, 0
  1032.                 , ulFlags);
  1033. }
  1034.  
  1035.  
  1036. //
  1037. // FUNCTION/METHOD NAME: DrawBorder(eBorder, areaPos, c4Width)
  1038. //
  1039. // DESCRIPTION:
  1040. //
  1041. //  This method will draw the indicated border type into the area passed,
  1042. //  using the current drawing attributes
  1043. //
  1044. //  NOTE: This guy is based on other calls that all save and restore the
  1045. //        graphical attributes of the paintbrush so we don't need to save
  1046. //        and restore anything other than the colors.
  1047. // ---------------------------------------
  1048. //   INPUT: eBorder is the border type to draw
  1049. //          areaPos is the position
  1050. //          c4Width is the width of the border
  1051. //
  1052. //  OUTPUT: None
  1053. //
  1054. //  RETURN: None
  1055. //
  1056. tCIDLib::VOID
  1057.     PROCEXP PAINTBRUSH::DrawBorder(         tCIDGui::eBORDERS   eBorder
  1058.                                     , const  AREA&              areaPos
  1059.                                     ,        tCIDLib::CARD4     c4Width)
  1060. {
  1061.     tCIDLib::INT4   i4Tmp;
  1062.  
  1063.     if ((!c4Width) || (c4Width > 512))
  1064.     {
  1065.         facCIDGui.LogMsg(   __FILE__
  1066.                             , "PAINTBRUSH::DrawBorder"
  1067.                             , __LINE__
  1068.                             , "Border width was 0 or > 512"
  1069.                             , tCIDLib::eSEV_WARNING);
  1070.         return;
  1071.     }
  1072.  
  1073.     // Get the current foreground/background colors
  1074.     RGBCLR  rgbFgn(rgbFgnColor());
  1075.     RGBCLR  rgbBgn(rgbBgnColor());
  1076.  
  1077.     // Get a copy of the area we can modify
  1078.     AREA    areaDraw(areaPos);
  1079.  
  1080.     switch(eBorder)
  1081.     {
  1082.         case tCIDGui::eBORDER_DIALOG    :
  1083.         case tCIDGui::eBORDER_SOLID     :
  1084.             //
  1085.             //  This one is easy, we just need to draw a solid border around
  1086.             //  the passed area.
  1087.             //
  1088.             Stroke(areaPos, c4Width);
  1089.             break;
  1090.  
  1091.         case tCIDGui::eBORDER_SIZING    :
  1092.             break;
  1093.  
  1094.         case tCIDGui::eBORDER_3D        :
  1095.             //
  1096.             //  This one is a raised border followed by a sunken border. Each
  1097.             //  one is half the width, with the raised side getting the odd
  1098.             //  pel if there is one.
  1099.             //
  1100.             if (c4Width < 2)
  1101.                 c4Width = 2;
  1102.  
  1103.             // Get half the width, plus any odd pel
  1104.             i4Tmp = tCIDLib::INT4(c4Width >> 1);
  1105.             if (c4Width & 1)
  1106.                 i4Tmp++;
  1107.  
  1108.             //
  1109.             //  Draw the raised and sunken borders. The call bumps in the
  1110.             //  passed area by the size of the border, so we just call again
  1111.             //  to draw inside it.
  1112.             //
  1113.             _Draw3DBorder(tCIDLib::eTRUE, areaDraw, i4Tmp, rgbBgn, rgbFgn);
  1114.             i4Tmp = tCIDLib::INT4(c4Width >> 1);
  1115.             _Draw3DBorder(tCIDLib::eFALSE, areaDraw, i4Tmp, rgbBgn, rgbFgn);
  1116.             break;
  1117.  
  1118.         case tCIDGui::eBORDER_RAISED    :
  1119.         case tCIDGui::eBORDER_SUNKEN    :
  1120.             //
  1121.             //  Draw either a raised or sunken border.
  1122.             //
  1123.             _Draw3DBorder(  eBorder == tCIDGui::eBORDER_RAISED ?
  1124.                                             tCIDLib::eTRUE : tCIDLib::eFALSE
  1125.                             , areaDraw
  1126.                             , c4Width
  1127.                             , rgbBgn
  1128.                             , rgbFgn);
  1129.             break;
  1130.  
  1131.         case tCIDGui::eBORDER_NONE      :
  1132.         default                         :
  1133.             break;
  1134.     }
  1135.  
  1136.     // Restore the old colors
  1137.     SetFgnColor(rgbFgn);
  1138.     SetBgnColor(rgbBgn);
  1139. }
  1140.  
  1141.  
  1142. //
  1143. // FUNCTION/METHOD NAME: eBgnMixMode() const
  1144. //                       eBgnMixMode(eNewMode)
  1145. //
  1146. // DESCRIPTION:
  1147. //
  1148. //  This method will get/set the background mix mode of the window. The
  1149. //  window must be in paint mode.
  1150. // ---------------------------------------
  1151. //   INPUT: eNewMode is the mode to set, when setting
  1152. //
  1153. //  OUTPUT: None
  1154. //
  1155. //  RETURN: The new or current background mix mode.
  1156. //
  1157. tCIDGui::eMIXMODES PROCEXP PAINTBRUSH::eBgnMixMode() const
  1158. {
  1159.     tCIDLib::INT4 i4Mix = GpiQueryBackMix(__hPS);
  1160.  
  1161.     if (i4Mix == BM_ERROR)
  1162.     {
  1163.         facCIDGui.LogLastSysErr(__FILE__
  1164.                                 , "PAINTBRUSH::eBgnMixMode"
  1165.                                 , __LINE__
  1166.                                 , "GpiQueryBackMix failed"
  1167.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1168.     }
  1169.     return tCIDGui::eMIXMODES(i4Mix);
  1170. }
  1171.  
  1172. tCIDGui::eMIXMODES
  1173.     PROCEXP PAINTBRUSH::eBgnMixMode(tCIDGui::eMIXMODES eNewMixMode)
  1174. {
  1175.     if (!GpiSetBackMix(__hPS, eNewMixMode))
  1176.     {
  1177.         facCIDGui.LogLastSysErr(__FILE__
  1178.                                 , "PAINTBRUSH::eBgnMixMode"
  1179.                                 , __LINE__
  1180.                                 , "GpiSetBackMix failed"
  1181.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1182.     }
  1183.     return eNewMixMode;
  1184. }
  1185.  
  1186.  
  1187. //
  1188. // FUNCTION/METHOD NAME: eFgnMixMode() const
  1189. //                       eFgnMixMode(eNewMode)
  1190. //
  1191. // DESCRIPTION:
  1192. //
  1193. //  This method will get/set the foreground mix mode of the window. The
  1194. //  window must be in paint mode.
  1195. // ---------------------------------------
  1196. //   INPUT: eNewMode is the mode to set, when setting
  1197. //
  1198. //  OUTPUT: None
  1199. //
  1200. //  RETURN: The new or current foreground mix mode.
  1201. //
  1202. tCIDGui::eMIXMODES PROCEXP PAINTBRUSH::eFgnMixMode() const
  1203. {
  1204.     tCIDLib::INT4 i4Mix = GpiQueryMix(__hPS);
  1205.  
  1206.     if (i4Mix == FM_ERROR)
  1207.     {
  1208.         facCIDGui.LogLastSysErr(__FILE__
  1209.                                 , "PAINTBRUSH::eFgnMixMode"
  1210.                                 , __LINE__
  1211.                                 , "GpiQueryMix failed"
  1212.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1213.     }
  1214.     return tCIDGui::eMIXMODES(i4Mix);
  1215. }
  1216.  
  1217. tCIDGui::eMIXMODES
  1218.     PROCEXP PAINTBRUSH::eFgnMixMode(tCIDGui::eMIXMODES eNewMixMode)
  1219. {
  1220.     if (!GpiSetMix(__hPS, eNewMixMode))
  1221.     {
  1222.         facCIDGui.LogLastSysErr(__FILE__
  1223.                                 , "PAINTBRUSH::eFgnMixMode"
  1224.                                 , __LINE__
  1225.                                 , "GpiSetMix failed"
  1226.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1227.     }
  1228.     return eNewMixMode;
  1229. }
  1230.  
  1231.  
  1232. //
  1233. // FUNCTION/METHOD NAME: eLineStyle()
  1234. //                       eLineStyle(eLineStyle)
  1235. //
  1236. // DESCRIPTION:
  1237. //
  1238. //  This method will set/get the current line style
  1239. // ---------------------------------------
  1240. //   INPUT: eLineType is the new line style to set.
  1241. //
  1242. //  OUTPUT: None
  1243. //
  1244. //  RETURN: The current or new line style
  1245. //
  1246. tCIDGui::eLINESTYLES PROCEXP PAINTBRUSH::eLineStyle() const
  1247. {
  1248.     LONG lType = GpiQueryLineType(__hPS);
  1249.  
  1250.     if (lType == LINETYPE_ERROR)
  1251.     {
  1252.         facCIDGui.LogLastSysErr(__FILE__
  1253.                                 , "PAINTBRUSH::eLineStyle"
  1254.                                 , __LINE__
  1255.                                 , "GpiQueryLineType failed"
  1256.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1257.     }
  1258.     return tCIDGui::eLINESTYLES(lType);
  1259. }
  1260.  
  1261. tCIDGui::eLINESTYLES PROCEXP
  1262.             PAINTBRUSH::eLineStyle(tCIDGui::eLINESTYLES eNewStyle) const
  1263. {
  1264.     if (!GpiSetLineType(__hPS, eNewStyle))
  1265.     {
  1266.         facCIDGui.LogLastSysErr(__FILE__
  1267.                                 , "PAINTBRUSH::eLineStyle"
  1268.                                 , __LINE__
  1269.                                 , "GpiSetLineType failed"
  1270.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1271.     }
  1272.     return eNewStyle;
  1273. }
  1274.  
  1275.  
  1276. //
  1277. // FUNCTION/METHOD NAME: Ellipse(pntCenter, c4Radius)
  1278. //                       Ellipse(areaCircle)
  1279. //
  1280. // DESCRIPTION:
  1281. //
  1282. //  This method will draw an ellipse using either a center point and radius or
  1283. //  an area.
  1284. // ---------------------------------------
  1285. //   INPUT: pntCenter is the center point to draw from
  1286. //          c4Radius is the radius of the ellipse from the center point
  1287. //          areaCircle is the area to fit the circle into.
  1288. //
  1289. //  OUTPUT: None
  1290. //
  1291. //  RETURN: None
  1292. //
  1293. tCIDLib::VOID PROCEXP PAINTBRUSH::Ellipse(  const   POINT&          pntCenter
  1294.                                             ,       tCIDLib::CARD4  c4Radius)
  1295. {
  1296.     ARCPARAMS       rArcParams;
  1297.     FIXED           Fixed;
  1298.  
  1299.     // Make sure that the arc params get reset
  1300.     GRAPHATTR(*this, tCIDGui::eGATTRSET_ARCPARAMS);
  1301.  
  1302.     SetMemory(&rArcParams, 0, sizeof(ARCPARAMS));
  1303.     rArcParams.lP = c4Radius;
  1304.     rArcParams.lQ = c4Radius;
  1305.     if (!GpiSetArcParams(__hPS, &rArcParams))
  1306.     {
  1307.         facCIDGui.LogLastSysErr(__FILE__
  1308.                                 , "PAINTBRUSH::Ellipse"
  1309.                                 , __LINE__
  1310.                                 , "GpiSetArcParams failed"
  1311.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1312.     }
  1313.  
  1314.     // Init the scaling data to not do any
  1315.     Fixed = MAKEFIXED(1, 0);
  1316.  
  1317.     // Set the position to the center point
  1318.     GpiMove(__hPS, pntCenter);
  1319.  
  1320.     // And draw the arc
  1321.     if (GpiFullArc(__hPS, DRO_OUTLINEFILL, Fixed) == GPI_ERROR)
  1322.     {
  1323.         // It failed, so we need to log a message and abort
  1324.         facCIDGui.LogLastSysErr(__FILE__
  1325.                                 , "PAINTBRUSH::Ellipse"
  1326.                                 , __LINE__
  1327.                                 , "GpiFullArc failed"
  1328.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1329.     }
  1330. }
  1331.  
  1332. tCIDLib::VOID PROCEXP PAINTBRUSH::Ellipse(const AREA& areaCircle)
  1333. {
  1334.     ARCPARAMS       rArcParams;
  1335.     FIXED           Fixed;
  1336.     POINTL          ptlTmp;
  1337.  
  1338.     // Make sure that the arc params get reset
  1339.     GRAPHATTR(*this, tCIDGui::eGATTRSET_ARCPARAMS);
  1340.  
  1341.     SetMemory(&rArcParams, 0, sizeof(ARCPARAMS));
  1342.     rArcParams.lP = areaCircle.c4CX() >> 1;
  1343.     rArcParams.lQ = areaCircle.c4CY() >> 1;
  1344.     if (!GpiSetArcParams(__hPS, &rArcParams))
  1345.     {
  1346.         facCIDGui.LogLastSysErr(__FILE__
  1347.                                 , "PAINTBRUSH::Ellipse"
  1348.                                 , __LINE__
  1349.                                 , "GpiSetArcParams failed"
  1350.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1351.     }
  1352.  
  1353.     // Init the scaling data to not do any
  1354.     Fixed = MAKEFIXED(1, 0);
  1355.  
  1356.     //
  1357.     //  Set the current position to the center of the area
  1358.     //
  1359.     areaCircle.pntCenter().ToPtl(ptlTmp);
  1360.     GpiMove(__hPS, &ptlTmp);
  1361.  
  1362.     // And draw the arc
  1363.     if (GpiFullArc(__hPS, DRO_OUTLINEFILL, Fixed) == GPI_ERROR)
  1364.     {
  1365.         facCIDGui.LogLastSysErr(__FILE__
  1366.                                 , "PAINTBRUSH::Ellipse"
  1367.                                 , __LINE__
  1368.                                 , "GpiFullArc failed"
  1369.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1370.     }
  1371. }
  1372.  
  1373.  
  1374. //
  1375. // FUNCTION/METHOD NAME: ePattern() const
  1376. //                       ePattern(ePattern)
  1377. //
  1378. // DESCRIPTION:
  1379. //
  1380. //  This method will get/set the current pattern
  1381. // ---------------------------------------
  1382. //   INPUT: None
  1383. //
  1384. //  OUTPUT: None
  1385. //
  1386. //  RETURN: The current or new pattern
  1387. //
  1388. tCIDGui::ePATTERNS PROCEXP PAINTBRUSH::ePattern() const
  1389. {
  1390.     LONG liTmp = GpiQueryPattern(__hPS);
  1391.  
  1392.     if (liTmp == PATSYM_ERROR)
  1393.     {
  1394.         facCIDGui.LogLastSysErr(__FILE__
  1395.                                 , "PAINTBRUSH::ePattern"
  1396.                                 , __LINE__
  1397.                                 , "GpiQueryPattern failed"
  1398.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1399.     }
  1400.     return tCIDGui::ePATTERNS(liTmp);
  1401. }
  1402.  
  1403. tCIDGui::ePATTERNS PROCEXP PAINTBRUSH::ePattern(tCIDGui::ePATTERNS ePattern)
  1404. {
  1405.     if (!GpiSetPattern(__hPS, ePattern))
  1406.     {
  1407.         facCIDGui.LogLastSysErr(__FILE__
  1408.                                 , "PAINTBRUSH::ePattern"
  1409.                                 , __LINE__
  1410.                                 , "GpiSetPattern failed"
  1411.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1412.     }
  1413.     return ePattern;
  1414. }
  1415.  
  1416.  
  1417. //
  1418. // FUNCTION/METHOD NAME: FillCurPath(eFill)
  1419. //                       FillCurPath(rgbFillClr. eFill)
  1420. //
  1421. // DESCRIPTION:
  1422. //
  1423. //  This method will fill the current path using either the passed color or
  1424. //  the current foreground color. The first version is inline, and just calls
  1425. //  this one with the current foreground color.
  1426. // ---------------------------------------
  1427. //   INPUT: rgbFillClr is the optional color parm
  1428. //          eFill is the fill type to use
  1429. //
  1430. //  OUTPUT: None
  1431. //
  1432. //  RETURN: None
  1433. //
  1434. tCIDLib::VOID PROCEXP
  1435.             PAINTBRUSH::FillCurPath(const RGBCLR&               rgbFillClr
  1436.                                     ,     tCIDGui::ePATHFILL    eFill)
  1437. {
  1438.     tCIDLib::INT4   i4Save = GpiQueryColor(__hPS);
  1439.  
  1440.     GpiSetColor(__hPS, rgbFillClr);
  1441.     SetFgnColor(rgbFillClr);
  1442.     if (!GpiFillPath(__hPS, 1, eFill))
  1443.     {
  1444.         facCIDGui.LogLastSysErr(__FILE__
  1445.                                 , "PAINTBRUSH::FillCurPath"
  1446.                                 , __LINE__
  1447.                                 , "GpiFillPath failed"
  1448.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1449.     }
  1450.     GpiSetColor(__hPS, i4Save);
  1451. }
  1452.  
  1453.  
  1454. //
  1455. // FUNCTION/METHOD NAME: finfCurrent() const
  1456. //
  1457. // DESCRIPTION:
  1458. //
  1459. //  This method will return a FONTINFO object with info on the currently
  1460. //  installed font, i.e. the one that is being used to draw with.
  1461. // ---------------------------------------
  1462. //   INPUT: None
  1463. //
  1464. //  OUTPUT: None
  1465. //
  1466. //  RETURN: A font info object
  1467. //
  1468. FONTINFO PROCEXP PAINTBRUSH::finfCurrent() const
  1469. {
  1470.     return _finfCurFont(__hPS);
  1471. }
  1472.  
  1473.  
  1474. //
  1475. // FUNCTION/METHOD NAME: Line(pntTo)
  1476. //
  1477. // DESCRIPTION:
  1478. //
  1479. //  This method will draw a line from the current position to the indicated
  1480. //  point, using the currently set drawing attributes. The current position
  1481. //  will be left at pntTo.
  1482. // ---------------------------------------
  1483. //   INPUT: pntTo is the destination point of the line.
  1484. //
  1485. //  OUTPUT: None
  1486. //
  1487. //  RETURN: None
  1488. //
  1489. tCIDLib::VOID PROCEXP PAINTBRUSH::Line(const POINT& pntTo)
  1490. {
  1491.     if (!GpiLine(__hPS, pntTo))
  1492.     {
  1493.         // It failed, so we need to log a message and abort
  1494.         facCIDGui.LogLastSysErr(__FILE__
  1495.                                 , "PAINTBRUSH::Line"
  1496.                                 , __LINE__
  1497.                                 , "GpiLine failed"
  1498.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1499.     }
  1500. }
  1501.  
  1502.  
  1503.  
  1504. //
  1505. // FUNCTION/METHOD NAME: Line(pntFrom, pntTo)
  1506. //
  1507. // DESCRIPTION:
  1508. //
  1509. //  This method will draw a line from the indicated from position to the
  1510. //  indicated to position, using the currently set drawing attributes. The
  1511. //  current position will be left at pntTo.
  1512. // ---------------------------------------
  1513. //   INPUT: pntTo is the destination point of the line.
  1514. //
  1515. //  OUTPUT: None
  1516. //
  1517. //  RETURN: None
  1518. //
  1519. tCIDLib::VOID PROCEXP PAINTBRUSH::Line( const POINT&    pntFrom
  1520.                                         , const POINT&  pntTo)
  1521. {
  1522.     if (!GpiMove(__hPS, pntFrom))
  1523.     {
  1524.         facCIDGui.LogLastSysErr(__FILE__
  1525.                                 , "PAINTBRUSH::Line"
  1526.                                 , __LINE__
  1527.                                 , "GpiMove failed"
  1528.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1529.     }
  1530.  
  1531.     if (!GpiLine(__hPS, pntTo))
  1532.     {
  1533.         facCIDGui.LogLastSysErr(__FILE__
  1534.                                 , "PAINTBRUSH::Line"
  1535.                                 , __LINE__
  1536.                                 , "GpiLine failed"
  1537.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1538.     }
  1539. }
  1540.  
  1541.  
  1542. //
  1543. // FUNCTION/METHOD NAME: pntCurPos()
  1544. //
  1545. // DESCRIPTION:
  1546. //
  1547. //  This method will get the current position.
  1548. // ---------------------------------------
  1549. //   INPUT: None
  1550. //
  1551. //  OUTPUT: None
  1552. //
  1553. //  RETURN: The current position
  1554. //
  1555. POINT PROCEXP PAINTBRUSH::pntCurPos() const
  1556. {
  1557.     POINTL  ptlPos;
  1558.  
  1559.     if (!GpiQueryCurrentPosition(__hPS, &ptlPos))
  1560.     {
  1561.         facCIDGui.LogLastSysErr(__FILE__
  1562.                                 , "PAINTBRUSH::pntCurPos"
  1563.                                 , __LINE__
  1564.                                 , "GpiQueryCurrentPosition failed"
  1565.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1566.     }
  1567.     return POINT(ptlPos.x, ptlPos.y);
  1568. }
  1569.  
  1570.  
  1571. //
  1572. // FUNCTION/METHOD NAME: pntRelativePos(i4XOfs, i4YOfs)
  1573. //
  1574. // DESCRIPTION:
  1575. //
  1576. //  This method will move the current position by the relative offsets given.
  1577. // ---------------------------------------
  1578. //   INPUT: i4XOfs, i4YOfs are the offsets to apply to the current position
  1579. //
  1580. //  OUTPUT: None
  1581. //
  1582. //  RETURN: A POINT object that contains the new position.
  1583. //
  1584. POINT PROCEXP PAINTBRUSH::pntRelativePos(   tCIDLib::INT4   i4XOfs
  1585.                                             , tCIDLib::INT4 i4YOfs)
  1586. {
  1587.     POINTL  ptlPos;
  1588.  
  1589.     // Query the current position
  1590.     if (!GpiQueryCurrentPosition(__hPS, &ptlPos))
  1591.     {
  1592.         facCIDGui.LogLastSysErr(__FILE__
  1593.                                 , "PAINTBRUSH::pntRelativePos"
  1594.                                 , __LINE__
  1595.                                 , "GpiQueryCurrentPosition failed"
  1596.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1597.     }
  1598.  
  1599.     // Adjust the result
  1600.     ptlPos.x += i4XOfs;
  1601.     ptlPos.y += i4YOfs;
  1602.  
  1603.     // And move to the new position
  1604.     if (!GpiMove(__hPS, &ptlPos))
  1605.     {
  1606.         facCIDGui.LogLastSysErr(__FILE__
  1607.                                 , "PAINTBRUSH::pntCurPos"
  1608.                                 , __LINE__
  1609.                                 , "GpiMove failed"
  1610.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1611.     }
  1612.  
  1613.     return POINT(ptlPos.x, ptlPos.y);
  1614. }
  1615.  
  1616.  
  1617. //
  1618. // FUNCTION/METHOD NAME: PolyLine(apntList, c4Pnts)
  1619. //
  1620. // DESCRIPTION:
  1621. //
  1622. //  This method will draw a line composed of c4Pnts. The first point is drawn
  1623. //  to from the current position.
  1624. // ---------------------------------------
  1625. //   INPUT: apntList is an array of POINT objects
  1626. //          c4Pnts is the number of points in the array.
  1627. //
  1628. //  OUTPUT: None
  1629. //
  1630. //  RETURN: None
  1631. //
  1632. tCIDLib::VOID PROCEXP PAINTBRUSH::PolyLine( POINT*              apntList
  1633.                                             , tCIDLib::CARD4    c4Pnts)
  1634. {
  1635.     //
  1636.     //  Allocate a buffer of POINTL structures to hold the points. Then
  1637.     //  convert the passed points to the POINTLs.
  1638.     //
  1639.     POINTL*     aptlTmp = new POINTL[c4Pnts];
  1640.  
  1641.     for (tCIDLib::CARD4 c4Ind = 0; c4Ind < c4Pnts; c4Ind++)
  1642.         apntList[c4Ind].ToPtl(aptlTmp[c4Ind]);
  1643.  
  1644.     // Ask PM to draw the lines
  1645.     if (GpiPolyLine(__hPS, c4Pnts, aptlTmp) == GPI_ERROR)
  1646.     {
  1647.         facCIDGui.LogLastSysErr(__FILE__
  1648.                                 , "PAINTBRUSH::PolyLine"
  1649.                                 , __LINE__
  1650.                                 , "GpiPolyLine failed"
  1651.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1652.     }
  1653.  
  1654.     // Get rid of the temp array
  1655.     delete aptlTmp;
  1656. }
  1657.  
  1658.  
  1659. //
  1660. // FUNCTION/METHOD NAME: PolyLineDisjoint(apntList, c4Pnts)
  1661. //
  1662. // DESCRIPTION:
  1663. //
  1664. //  This method will draw a set of line segments. The passed array of POINT
  1665. //  objects is looked at as pairs of end points. The c4Points value is the
  1666. //  number of pairs, so it should be the number of points.
  1667. // ---------------------------------------
  1668. //   INPUT: apntList is the list of end points.
  1669. //          c4Pnts is the number of end point pairs.
  1670. //
  1671. //  OUTPUT: None
  1672. //
  1673. //  RETURN: None
  1674. //
  1675. tCIDLib::VOID
  1676.     PROCEXP PAINTBRUSH::PolyLineDisjoint(   POINT*              apntList
  1677.                                             , tCIDLib::CARD4    c4Pnts)
  1678. {
  1679.     //
  1680.     //  Allocate a buffer of POINTL structures to hold the points. Then
  1681.     //  convert the passed points to the POINTLs.
  1682.     //
  1683.     POINTL*     aptlTmp = new POINTL[c4Pnts];
  1684.  
  1685.     for (tCIDLib::CARD4 c4Ind = 0; c4Ind < c4Pnts; c4Ind++)
  1686.         apntList[c4Ind].ToPtl(aptlTmp[c4Ind]);
  1687.  
  1688.     // Ask PM to draw the lines
  1689.     if (GpiPolyLineDisjoint(__hPS, c4Pnts, aptlTmp) == GPI_ERROR)
  1690.     {
  1691.         facCIDGui.LogLastSysErr(__FILE__
  1692.                                 , "PAINTBRUSH::PolyLineDisjoint"
  1693.                                 , __LINE__
  1694.                                 , "GpiPolyLineDisjoint failed"
  1695.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1696.     }
  1697.  
  1698.     // Get rid of the temp array
  1699.     delete aptlTmp;
  1700. }
  1701.  
  1702.  
  1703. //
  1704. // FUNCTION/METHOD NAME: ResetAttrs()
  1705. //
  1706. // DESCRIPTION:
  1707. //
  1708. //  This method will reset the graphical attributes of this window
  1709. // ---------------------------------------
  1710. //   INPUT: None
  1711. //
  1712. //  OUTPUT: None
  1713. //
  1714. //  RETURN: None
  1715. //
  1716. tCIDLib::VOID PROCEXP PAINTBRUSH::ResetAttrs()
  1717. {
  1718.     if (!GpiResetPS(__hPS, GRES_ATTRS))
  1719.     {
  1720.         facCIDGui.LogLastSysErr(__FILE__
  1721.                                 , "PAINTBRUSH::ResetAttrs"
  1722.                                 , __LINE__
  1723.                                 , "GpiResetPS failed"
  1724.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1725.     }
  1726. }
  1727.  
  1728.  
  1729. //
  1730. // FUNCTION/METHOD NAME: ResetClipPath()
  1731. //
  1732. // DESCRIPTION:
  1733. //
  1734. //  This method will reset the clip path to infinity.
  1735. // ---------------------------------------
  1736. //   INPUT: None
  1737. //
  1738. //  OUTPUT: None
  1739. //
  1740. //  RETURN: None
  1741. //
  1742. tCIDLib::VOID PROCEXP PAINTBRUSH::ResetClipPath()
  1743. {
  1744.     // Reset the clip path to infinite
  1745.     if (!GpiSetClipPath(__hPS, 0, SCP_RESET))
  1746.     {
  1747.         facCIDGui.LogLastSysErr(__FILE__
  1748.                                 , "PAINTBRUSH::ResetClipPath"
  1749.                                 , __LINE__
  1750.                                 , "GpiSetClipPath failed"
  1751.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1752.     }
  1753. }
  1754.  
  1755.  
  1756. //
  1757. // FUNCTION/METHOD NAME: rgbBgnColor()
  1758. //                       rgbFgnColor()
  1759. //
  1760. // DESCRIPTION:
  1761. //
  1762. //  These methods will get the color that will be used for background or
  1763. //  or foreground output.
  1764. // ---------------------------------------
  1765. //   INPUT: rgbNew is the new background color.
  1766. //
  1767. //  OUTPUT: None
  1768. //
  1769. //  RETURN: None
  1770. //
  1771. RGBCLR PROCEXP PAINTBRUSH::rgbBgnColor() const
  1772. {
  1773.     LONG    liClr   = GpiQueryBackColor(__hPS);
  1774.  
  1775.     return RGBCLR(liClr);
  1776. }
  1777.  
  1778. RGBCLR PROCEXP PAINTBRUSH::rgbFgnColor() const
  1779. {
  1780.     LONG    liClr   = GpiQueryColor(__hPS);
  1781.  
  1782.     return RGBCLR(liClr);
  1783. }
  1784.  
  1785.  
  1786. //
  1787. // FUNCTION/METHOD NAME: SetBgnColor(rgbNew)
  1788. //                       SetFgnColor(rgbNew)
  1789. //
  1790. // DESCRIPTION:
  1791. //
  1792. //  These methods will set the foreground and background colors.
  1793. // ---------------------------------------
  1794. //   INPUT: rgbNew is the new color to set
  1795. //
  1796. //  OUTPUT: None
  1797. //
  1798. //  RETURN: None
  1799. //
  1800. tCIDLib::VOID PROCEXP PAINTBRUSH::SetBgnColor(const RGBCLR& rgbNew)
  1801. {
  1802.     if (!GpiSetBackColor(__hPS, rgbNew))
  1803.     {
  1804.         facCIDGui.LogLastSysErr(__FILE__
  1805.                                 , "PAINTBRUSH::SetBgnColor"
  1806.                                 , __LINE__
  1807.                                 , "GpiSetBackColor"
  1808.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1809.     }
  1810. }
  1811.  
  1812. tCIDLib::VOID PROCEXP PAINTBRUSH::SetFgnColor(const RGBCLR& rgbNew)
  1813. {
  1814.     if (!GpiSetColor(__hPS, rgbNew))
  1815.     {
  1816.         facCIDGui.LogLastSysErr(__FILE__
  1817.                                 , "PAINTBRUSH::SetFgnColor"
  1818.                                 , __LINE__
  1819.                                 , "GpiSetColor failed"
  1820.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1821.     }
  1822. }
  1823.  
  1824.  
  1825. //
  1826. // FUNCTION/METHOD NAME: SetCurPos(pntNew)
  1827. //                       SetCurPos(i4XPos, i4YPos)
  1828. //
  1829. // DESCRIPTION:
  1830. //
  1831. //  These methods will set the current output position.
  1832. // ---------------------------------------
  1833. //   INPUT: pntNew is the new point to set
  1834. //          i4XPos, i4YPos are the new x,y position to set
  1835. //
  1836. //  OUTPUT: None
  1837. //
  1838. //  RETURN: None
  1839. //
  1840. tCIDLib::VOID PROCEXP PAINTBRUSH::SetCurPos(const POINT& pntNew)
  1841. {
  1842.     if (!GpiMove(__hPS, pntNew))
  1843.     {
  1844.         facCIDGui.LogLastSysErr(__FILE__
  1845.                                 , "PAINTBRUSH::SetCurPos"
  1846.                                 , __LINE__
  1847.                                 , "GpiMove failed"
  1848.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1849.     }
  1850. }
  1851.  
  1852. tCIDLib::VOID PROCEXP PAINTBRUSH::SetCurPos(tCIDLib::INT4   i4XPos
  1853.                                             , tCIDLib::INT4 i4YPos)
  1854. {
  1855.     POINTL  ptlTmp;
  1856.  
  1857.     ptlTmp.x    = i4XPos;
  1858.     ptlTmp.y    = i4YPos;
  1859.     if (!GpiMove(__hPS, &ptlTmp))
  1860.     {
  1861.         facCIDGui.LogLastSysErr(__FILE__
  1862.                                 , "PAINTBRUSH::SetCurPos"
  1863.                                 , __LINE__
  1864.                                 , "GpiMove failed"
  1865.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1866.     }
  1867. }
  1868.  
  1869.  
  1870. //
  1871. // FUNCTION/METHOD NAME: SetClipPath(eFillType, eClipOpts)
  1872. //                       SetClipPath(areaToClip, eFillType, eClipOpts)
  1873. //                       SetClipPath(pntFrom, pntTo, eFillType, eClipOpts)
  1874. //
  1875. // DESCRIPTION:
  1876. //
  1877. //  This method will create a new path using the passed area. The path options
  1878. //  control how this clip path is mixed with existing clip paths. The path can
  1879. //  be described as an AREA, two POINTs, or the existing path can be used.
  1880. // ---------------------------------------
  1881. //   INPUT: areaToClip is the area to use for the path.
  1882. //          pntFrom, pntTo are another means of indicating the path, via two
  1883. //              points that indicate the corners of an area.
  1884. //          eFillType is the fill type to use
  1885. //          eClipOpts are the path control option flags.
  1886. //
  1887. //  OUTPUT: None
  1888. //
  1889. //  RETURN: None
  1890. //
  1891. tCIDLib::VOID PROCEXP
  1892.             PAINTBRUSH::SetClipPath(tCIDGui::ePATHFILL      eFillType
  1893.                                     , tCIDGui::eCLIPOPTS    eClipOpts)
  1894. {
  1895.     // Set the path as the clip path. This implicitly closes the path
  1896.     if (!GpiSetClipPath(__hPS, 1, tCIDLib::CARD4(eClipOpts | eFillType)))
  1897.     {
  1898.         // It failed, so we need to log a message and abort
  1899.         facCIDGui.LogLastSysErr(__FILE__
  1900.                                 , "PAINTBRUSH::SetClipPath"
  1901.                                 , __LINE__
  1902.                                 , "GpiSetClipPath failed"
  1903.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1904.     }
  1905. }
  1906.  
  1907. tCIDLib::VOID
  1908.         PROCEXP PAINTBRUSH::SetClipPath(const   POINT&              pntFrom
  1909.                                         , const POINT&              pntTo
  1910.                                         ,       tCIDGui::ePATHFILL  eFillType
  1911.                                         ,       tCIDGui::eCLIPOPTS  eClipOpts)
  1912. {
  1913.     // Just make an area and call the other versin
  1914.     AREA    areaClip(pntFrom, pntTo);
  1915.  
  1916.     SetClipPath(areaClip, eFillType, eClipOpts);
  1917. }
  1918.  
  1919. tCIDLib::VOID PROCEXP
  1920.         PAINTBRUSH::SetClipPath(    const   AREA&               areaToClip
  1921.                                     ,       tCIDGui::ePATHFILL  eFillType
  1922.                                     ,       tCIDGui::eCLIPOPTS  eClipOpts)
  1923. {
  1924.     POINTL          ptl1, ptl2;
  1925.     POINTL          aptlBox[3];
  1926.  
  1927.     // Get POINTLs from the area
  1928.     areaToClip.ToPtls(ptl1, ptl2);
  1929.  
  1930.     if (!GpiMove(__hPS, &ptl1))
  1931.     {
  1932.         // It failed, so we need to log a message and abort
  1933.         facCIDGui.LogLastSysErr(__FILE__
  1934.                                 , "PAINTBRUSH::SetClipPath"
  1935.                                 , __LINE__
  1936.                                 , "GpiMove failed"
  1937.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1938.     }
  1939.  
  1940.     if (!GpiBeginPath(__hPS, 1))
  1941.     {
  1942.         // It failed, so we need to log a message and abort
  1943.         facCIDGui.LogLastSysErr(__FILE__
  1944.                                 , "PAINTBRUSH::SetClipPath"
  1945.                                 , __LINE__
  1946.                                 , "GpiBeginPath failed"
  1947.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1948.     }
  1949.  
  1950.     // Create a list of points to draw the clip box
  1951.     aptlBox[0].x = ptl1.x;
  1952.     aptlBox[0].y = ptl2.y;
  1953.     aptlBox[1].x = ptl2.x;
  1954.     aptlBox[1].y = ptl2.y;
  1955.     aptlBox[2].x = ptl2.x;
  1956.     aptlBox[2].y = ptl1.y;
  1957.  
  1958.     if (GpiPolyLine(__hPS, 3, aptlBox) == GPI_ERROR)
  1959.     {
  1960.         // It failed, so we need to log a message and abort
  1961.         facCIDGui.LogLastSysErr(__FILE__
  1962.                                 , "PAINTBRUSH::SetClipPath"
  1963.                                 , __LINE__
  1964.                                 , "GpiPolyLine failed"
  1965.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1966.     }
  1967.  
  1968.     // End the path to close it off
  1969.     if (!GpiEndPath(__hPS))
  1970.     {
  1971.         // It failed, so we need to log a message and abort
  1972.         facCIDGui.LogLastSysErr(__FILE__
  1973.                                 , "PAINTBRUSH::SetClipPath"
  1974.                                 , __LINE__
  1975.                                 , "GpiEndPath failed"
  1976.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1977.     }
  1978.  
  1979.     // Set the path as the clip path. This implicitly closes the path
  1980.     if (!GpiSetClipPath(__hPS, 1, tCIDLib::CARD4(eClipOpts | eFillType)))
  1981.     {
  1982.         // It failed, so we need to log a message and abort
  1983.         facCIDGui.LogLastSysErr(__FILE__
  1984.                                 , "PAINTBRUSH::SetClipPath"
  1985.                                 , __LINE__
  1986.                                 , "GpiSetClipPath failed"
  1987.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1988.     }
  1989. }
  1990.  
  1991.  
  1992. //
  1993. // FUNCTION/METHOD NAME: SetCurFont(strName)
  1994. //
  1995. // DESCRIPTION:
  1996. //
  1997. //  This method will set the indicated font as the current font for this
  1998. //  window object.
  1999. // ---------------------------------------
  2000. //   INPUT: strName is the name that was given to the font when the CreateFont
  2001. //              method was called.
  2002. //
  2003. //  OUTPUT: None
  2004. //
  2005. //  RETURN: None
  2006. //
  2007. tCIDLib::VOID PROCEXP PAINTBRUSH::SetCurFont(const STRG16& strName)
  2008. {
  2009.     // Try to find a font with this name
  2010.     LLSTNODE*   plnodFont = _plnodFindFnt(strName);
  2011.  
  2012.     if (!plnodFont)
  2013.     {
  2014.         facCIDGui.LogErr(   __FILE__
  2015.                             , "PAINTBRUSH::SetCurFont"
  2016.                             , __LINE__
  2017.                             , GUIERR_FONT_NAME_NOT_FOUND
  2018.                             , tCIDLib::eSEV_PROCESS_FATAL
  2019.                             , tCIDLib::eCLASS_BADPARMS
  2020.                             , strName);
  2021.     }
  2022.  
  2023.     // Get the font object out of it
  2024.     FONT* pfntTmp = (FONT*)plnodFont->pobjData();
  2025.  
  2026.     //  Set our font as the current one.
  2027.     if (!GpiSetCharSet(__hPS, pfntTmp->_i4FontId))
  2028.     {
  2029.         facCIDGui.LogLastSysErr(__FILE__
  2030.                                 , "PAINTBRUSH::SetCurFont"
  2031.                                 , __LINE__
  2032.                                 , strName
  2033.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2034.     }
  2035. }
  2036.  
  2037.  
  2038. //
  2039. // FUNCTION/METHOD NAME: SetDefaultFont()
  2040. //
  2041. // DESCRIPTION:
  2042. //
  2043. //  This method will reset the font to the default
  2044. // ---------------------------------------
  2045. //   INPUT: None
  2046. //
  2047. //  OUTPUT: None
  2048. //
  2049. //  RETURN: None
  2050. //
  2051. tCIDLib::VOID PROCEXP PAINTBRUSH::SetDefaultFont()
  2052. {
  2053.     if (!GpiSetCharSet(__hPS, LCID_DEFAULT))
  2054.     {
  2055.         facCIDGui.LogLastSysErr(__FILE__
  2056.                                 , "PAINTBRUSH::SetDefaultFont"
  2057.                                 , __LINE__
  2058.                                 , "GpiSetCharSet failed"
  2059.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2060.     }
  2061. }
  2062.  
  2063.  
  2064. //
  2065. // FUNCTION/METHOD NAME: SetPath(areaToClip)
  2066. //
  2067. // DESCRIPTION:
  2068. //
  2069. //  This method will create a new path using the passed area.
  2070. // ---------------------------------------
  2071. //   INPUT: areaToClip is the area to use for the path.
  2072. //
  2073. //  OUTPUT: None
  2074. //
  2075. //  RETURN: None
  2076. //
  2077. tCIDLib::VOID PROCEXP PAINTBRUSH::SetPath(const AREA& areaToClip)
  2078. {
  2079.     POINTL          ptl1, ptl2;
  2080.     POINTL          aptlBox[3];
  2081.  
  2082.     // Get POINTLs from the area
  2083.     areaToClip.ToPtls(ptl1, ptl2);
  2084.  
  2085.     if (!GpiMove(__hPS, &ptl1))
  2086.     {
  2087.         // It failed, so we need to log a message and abort
  2088.         facCIDGui.LogLastSysErr(__FILE__
  2089.                                 , "PAINTBRUSH::SetPath"
  2090.                                 , __LINE__
  2091.                                 , "GpiMove failed"
  2092.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2093.     }
  2094.  
  2095.     if (!GpiBeginPath(__hPS, 1))
  2096.     {
  2097.         // It failed, so we need to log a message and abort
  2098.         facCIDGui.LogLastSysErr(__FILE__
  2099.                                 , "PAINTBRUSH::SetPath"
  2100.                                 , __LINE__
  2101.                                 , "GpiBeginPath failed"
  2102.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2103.     }
  2104.  
  2105.     // Create a list of points to draw the clip box
  2106.     aptlBox[0].x = ptl1.x;
  2107.     aptlBox[0].y = ptl2.y;
  2108.     aptlBox[1].x = ptl2.x;
  2109.     aptlBox[1].y = ptl2.y;
  2110.     aptlBox[2].x = ptl2.x;
  2111.     aptlBox[2].y = ptl1.y;
  2112.  
  2113.     if (GpiPolyLine(__hPS, 3, aptlBox) == GPI_ERROR)
  2114.     {
  2115.         // It failed, so we need to log a message and abort
  2116.         facCIDGui.LogLastSysErr(__FILE__
  2117.                                 , "PAINTBRUSH::SetPath"
  2118.                                 , __LINE__
  2119.                                 , "GpiPolyLine failed"
  2120.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2121.     }
  2122.  
  2123.     // End the path to close it off
  2124.     if (!GpiEndPath(__hPS))
  2125.     {
  2126.         // It failed, so we need to log a message and abort
  2127.         facCIDGui.LogLastSysErr(__FILE__
  2128.                                 , "PAINTBRUSH::SetPath"
  2129.                                 , __LINE__
  2130.                                 , "GpiEndPath failed"
  2131.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2132.     }
  2133. }
  2134.  
  2135.  
  2136. //
  2137. // FUNCTION/METHOD NAME: SetPel(i4XPos, i4YPos, rgbClr)
  2138. //                       SetPel(pntPos, rgbClr)
  2139. //
  2140. // DESCRIPTION:
  2141. //
  2142. //  This method will set the indicated pel to the passed color
  2143. // ---------------------------------------
  2144. //   INPUT: i4XPos, i4YPos is the position to plot
  2145. //          pntPos is the position to plot
  2146. //          rgbClr is the color to plot
  2147. //
  2148. //  OUTPUT: None
  2149. //
  2150. //  RETURN: None
  2151. //
  2152. tCIDLib::VOID
  2153.     PROCEXP PAINTBRUSH::SetPel( tCIDLib::INT4           i4XPos
  2154.                                 ,       tCIDLib::INT4   i4YPos
  2155.                                 , const RGBCLR&         rgbClr)
  2156. {
  2157.     RGBCLR  rgbSave(rgbFgnColor());
  2158.     SetFgnColor(rgbClr);
  2159.     POINTL  ptlTmp;
  2160.     ptlTmp.x = i4XPos;
  2161.     ptlTmp.y = i4YPos;
  2162.     GpiSetPel(__hPS, &ptlTmp);
  2163.     SetFgnColor(rgbSave);
  2164. }
  2165.  
  2166. tCIDLib::VOID PROCEXP PAINTBRUSH::SetPel(   const   POINT&  pntPos
  2167.                                             , const RGBCLR& rgbClr)
  2168. {
  2169.     RGBCLR  rgbSave(rgbFgnColor());
  2170.     SetFgnColor(rgbClr);
  2171.     POINTL  ptlTmp;
  2172.     pntPos.ToPtl(ptlTmp);
  2173.     GpiSetPel(__hPS, &ptlTmp);
  2174.     SetFgnColor(rgbSave);
  2175. }
  2176.  
  2177.  
  2178. //
  2179. // FUNCTION/METHOD NAME: StringCharOfs(strbText, c4Ind, i4XStart, i4XEnd)
  2180. //
  2181. // DESCRIPTION:
  2182. //
  2183. //  This method will calculate the start and end x offset of a particuar char
  2184. //  of the passed string, using the current drawing attributes. The position
  2185. //  is from the start of the string, so the returned values are usually added
  2186. //  to the position where the string was drawn.
  2187. // ---------------------------------------
  2188. //   INPUT: strbText is the string whose char is being calculated
  2189. //          c4Ind is the index of the char to get
  2190. //
  2191. //  OUTPUT: i4XStart, i4XEnd are filled in with the x offsets of the character
  2192. //
  2193. //  RETURN: None
  2194. //
  2195. tCIDLib::VOID PAINTBRUSH::StringCharOfs(const   STRGBUF&        strbText
  2196.                                         ,       tCIDLib::CARD4  c4Ind
  2197.                                         ,       tCIDLib::INT4&  i4XStart
  2198.                                         ,       tCIDLib::INT4&  i4XEnd)
  2199. {
  2200.     // Probe the string to catch any indexing errors
  2201.     strbText[c4Ind];
  2202.  
  2203.     // Array for the text box call
  2204.     POINTL  aptlBox[TXTBOX_COUNT];
  2205.  
  2206.     // Make a string that we can mangle
  2207.     STRING  strTmp(strbText);
  2208.  
  2209.     //
  2210.     //  Make a small asciiz string that holds just the character at c4Ind
  2211.     //
  2212.     tCIDLib::CH szChar[2];
  2213.     szChar[0] = strTmp[c4Ind];
  2214.     szChar[1] = 0;
  2215.  
  2216.     //
  2217.     //  Cap the string at the passed index and get the length of that. This
  2218.     //  will be the starting offset
  2219.     //
  2220.     strTmp[c4Ind] = 0;
  2221.  
  2222.     // Get the size of this portion of the string
  2223.     if (!GpiQueryTextBox(   __hPS
  2224.                             , strTmp.c4Length()
  2225.                             , strTmp.pSZ()
  2226.                             , TXTBOX_COUNT
  2227.                             , aptlBox))
  2228.     {
  2229.         facCIDGui.LogLastSysErr(__FILE__
  2230.                                 , "PAINTBRUSH::areaString"
  2231.                                 , __LINE__
  2232.                                 , "GpiQueryTextBox failed"
  2233.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2234.     }
  2235.  
  2236.     // Store away the left x as the starting x
  2237.     i4XStart = aptlBox[TXTBOX_BOTTOMRIGHT].x;
  2238.  
  2239.     //
  2240.     //  Now get the size of the 1 char string that we saved away before
  2241.     //  capping of the temp string object.
  2242.     //
  2243.     if (!GpiQueryTextBox(   __hPS
  2244.                             , 1
  2245.                             , szChar
  2246.                             , TXTBOX_COUNT
  2247.                             , aptlBox))
  2248.     {
  2249.         facCIDGui.LogLastSysErr(__FILE__
  2250.                                 , "PAINTBRUSH::areaString"
  2251.                                 , __LINE__
  2252.                                 , "GpiQueryTextBox failed"
  2253.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2254.     }
  2255.  
  2256.     // The ending x is the starting x plus the size of the 1 char
  2257.     i4XEnd = i4XStart + (aptlBox[TXTBOX_TOPRIGHT].x-aptlBox[TXTBOX_TOPLEFT].x);
  2258. }
  2259.  
  2260.  
  2261. //
  2262. // FUNCTION/METHOD NAME: Stroke(areaTarget, c4Width, c4Rounding)
  2263. //
  2264. // DESCRIPTION:
  2265. //
  2266. //  This method will stroke a line around the target area using the current
  2267. //  drawing attributes. The line will be c4Width pixels wide, with its outer
  2268. //  most pixel lying on the area border.
  2269. // ---------------------------------------
  2270. //   INPUT: areaTarget is the area to stroke
  2271. //          c4Width is the width of the line to draw.
  2272. //          c4Rounding controls how deeply rounded the corners are
  2273. //
  2274. //  OUTPUT: None
  2275. //
  2276. //  RETURN: None
  2277. //
  2278. tCIDLib::VOID PROCEXP PAINTBRUSH::Stroke(   const AREA&         areaTarget
  2279.                                             , tCIDLib::CARD4    c4Width
  2280.                                             , tCIDLib::CARD4    c4Rounding)
  2281. {
  2282.     if (!c4Width)
  2283.     {
  2284.         facCIDGui.LogMsg(   __FILE__
  2285.                             , "PAINTBRUSH::Stroke"
  2286.                             , __LINE__
  2287.                             , "0 width stroked"
  2288.                             , tCIDLib::eSEV_WARNING);
  2289.         return;
  2290.     }
  2291.  
  2292.     AREA            areaTmp(areaTarget);
  2293.     POINTL          ptl1, ptl2;
  2294.     tCIDLib::INT4   i4Tmp;
  2295.  
  2296.     // Save the attributes that we will change
  2297.     tCIDLib::INT4   i4GeomWidth = GpiQueryLineWidthGeom(__hPS);
  2298.  
  2299.     //
  2300.     //  Watch for a width of 1 and handle it in a more efficient manner by
  2301.     //  just doing an outline box.
  2302.     //
  2303.     if (c4Width == 1)
  2304.     {
  2305.         // Set the geometric line width
  2306.         GpiSetLineWidthGeom(__hPS, 1);
  2307.  
  2308.         // Convert the passed area to two POINTLs
  2309.         areaTmp.ToPtls(ptl1, ptl2);
  2310.  
  2311.         // Move to the first position
  2312.         if (!GpiMove(__hPS, &ptl1))
  2313.         {
  2314.             facCIDGui.LogLastSysErr(__FILE__
  2315.                                     , "PAINTBRUSH::Stroke"
  2316.                                     , __LINE__
  2317.                                     , "GpiMove failed"
  2318.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2319.         }
  2320.  
  2321.         if (GpiBox( __hPS
  2322.                     , DRO_OUTLINE
  2323.                     , &ptl2
  2324.                     , c4Rounding
  2325.                     , c4Rounding) == GPI_ERROR)
  2326.         {
  2327.             facCIDGui.LogLastSysErr(__FILE__
  2328.                                     , "PAINTBRUSH::Stroke"
  2329.                                     , __LINE__
  2330.                                     , "GpiBox failed"
  2331.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2332.         }
  2333.         return;
  2334.     }
  2335.  
  2336.     //
  2337.     //  We need to play with the area so that the geometric line that we draw
  2338.     //  will not go outside of the area. When we stroke the path, the line is
  2339.     //  centered on the actual path, so subtract half of the width from each
  2340.     //  side. If it is an odd value, subtract another one.
  2341.     //
  2342.     i4Tmp = c4Width >> 1;
  2343.  
  2344.     if (c4Width & 1)
  2345.         i4Tmp++;
  2346.     areaTmp.AdjustSides(-i4Tmp, -i4Tmp);
  2347.  
  2348.     // Convert the passed area to two POINTLs
  2349.     areaTmp.ToPtls(ptl1, ptl2);
  2350.  
  2351.     // Move to the first position
  2352.     if (!GpiMove(__hPS, &ptl1))
  2353.     {
  2354.         facCIDGui.LogLastSysErr(__FILE__
  2355.                                 , "PAINTBRUSH::Stroke"
  2356.                                 , __LINE__
  2357.                                 , "GpiMove failed"
  2358.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2359.     }
  2360.  
  2361.     // Start the path bracket and do a box to create the path
  2362.     if (!GpiBeginPath(__hPS, 1))
  2363.     {
  2364.         facCIDGui.LogLastSysErr(__FILE__
  2365.                                 , "PAINTBRUSH::Stroke"
  2366.                                 , __LINE__
  2367.                                 , "GpiBeginPath failed"
  2368.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2369.     }
  2370.  
  2371.     if (GpiBox(__hPS, DRO_OUTLINE, &ptl2, c4Rounding, c4Rounding) == GPI_ERROR)
  2372.     {
  2373.         facCIDGui.LogLastSysErr(__FILE__
  2374.                                 , "PAINTBRUSH::Stroke"
  2375.                                 , __LINE__
  2376.                                 , "GpiBox failed"
  2377.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2378.     }
  2379.  
  2380.     // Close the path
  2381.     GpiEndPath(__hPS);
  2382.  
  2383.     // Set the geometric line width
  2384.     if (!GpiSetLineWidthGeom(__hPS, LONG(c4Width)))
  2385.     {
  2386.         facCIDGui.LogLastSysErr(__FILE__
  2387.                                 , "PAINTBRUSH::Stroke"
  2388.                                 , __LINE__
  2389.                                 , "GpiSetLineWidthGeom failed"
  2390.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2391.     }
  2392.  
  2393.     if (GpiStrokePath(__hPS, 1, 0) == GPI_ERROR)
  2394.     {
  2395.         facCIDGui.LogLastSysErr(__FILE__
  2396.                                 , "PAINTBRUSH::Stroke"
  2397.                                 , __LINE__
  2398.                                 , "GpiStrokePath failed"
  2399.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2400.     }
  2401.  
  2402.     GpiSetLineWidthGeom(__hPS, i4GeomWidth);
  2403. }
  2404.  
  2405.  
  2406. //
  2407. // FUNCTION/METHOD NAME: Stroke(pntOrg, c4Width, c4XRadius, c4YRadius)
  2408. //
  2409. // DESCRIPTION:
  2410. //
  2411. //  This method will stroke an elliptical line of the indicated width, starting
  2412. //  at the given origin and using the passed x and y radii.
  2413. // ---------------------------------------
  2414. //   INPUT: pntOrg is the center point of the ellipse
  2415. //
  2416. //  OUTPUT: None
  2417. //
  2418. //  RETURN: None
  2419. //
  2420. tCIDLib::VOID PROCEXP PAINTBRUSH::Stroke(   const   POINT&          pntOrg
  2421.                                             ,       tCIDLib::CARD4  c4Width
  2422.                                             ,       tCIDLib::CARD4  c4XRadius
  2423.                                             ,       tCIDLib::CARD4  c4YRadius)
  2424. {
  2425.     if (!c4Width)
  2426.     {
  2427.         facCIDGui.LogMsg(   __FILE__
  2428.                             , "PAINTBRUSH::Stroke"
  2429.                             , __LINE__
  2430.                             , "0 width stroked"
  2431.                             , tCIDLib::eSEV_WARNING);
  2432.         return;
  2433.     }
  2434.  
  2435.     ARCPARAMS       rArcParams;
  2436.     FIXED           Fixed;
  2437.     tCIDLib::INT4   i4Tmp;
  2438.  
  2439.     // Make sure that the arc and line params get reset
  2440.     GRAPHATTR gattrSaveArc(*this, tCIDGui::eGATTRSET_ARCPARAMS);
  2441.     GRAPHATTR gattrSaveLine(*this, tCIDGui::eGATTRSET_ARCPARAMS);
  2442.  
  2443.     // Set up new arc params
  2444.     SetMemory(&rArcParams, 0, sizeof(ARCPARAMS));
  2445.     rArcParams.lP = c4XRadius;
  2446.     rArcParams.lQ = c4YRadius;
  2447.  
  2448.     // Init the scaling data to not do any
  2449.     Fixed = MAKEFIXED(1, 0);
  2450.  
  2451.     // Set the position to the center point
  2452.     GpiMove(__hPS, pntOrg);
  2453.  
  2454.     //
  2455.     //  If the width is 1, we can do things a lot faster by just doing a
  2456.     //  regular ellipse, without any geometric lines.
  2457.     //
  2458.     if (c4Width == 1)
  2459.     {
  2460.         GpiSetArcParams(__hPS, &rArcParams);
  2461.  
  2462.         // And draw the arc
  2463.         if (GpiFullArc(__hPS, DRO_OUTLINE, Fixed) == GPI_ERROR)
  2464.         {
  2465.             // It failed, so we need to log a message and abort
  2466.             facCIDGui.LogLastSysErr(__FILE__
  2467.                                     , "PAINTBRUSH::Stroke"
  2468.                                     , __LINE__
  2469.                                     , "GpiFullArc failed"
  2470.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2471.         }
  2472.         return;
  2473.     }
  2474.     //
  2475.     //  We need to play with the area so that the geometric line that we
  2476.     //  draw will not go outside of the area. When we stroke the path, the
  2477.     //  line is centered on the actual path, so subtract half of the width
  2478.     //  from each side. If it is an odd value, subtract another one.
  2479.     //
  2480.     i4Tmp = c4Width >> 1;
  2481.     if (c4Width & 1)
  2482.         i4Tmp++;
  2483.  
  2484.     rArcParams.lP = c4XRadius - i4Tmp;
  2485.     rArcParams.lQ = c4YRadius - i4Tmp;
  2486.     GpiSetArcParams(__hPS, &rArcParams);
  2487.  
  2488.     // Start the path bracket and do a full arc
  2489.     if (!GpiBeginPath(__hPS, 1))
  2490.     {
  2491.         facCIDGui.LogLastSysErr(__FILE__
  2492.                                 , "PAINTBRUSH::Stroke"
  2493.                                 , __LINE__
  2494.                                 , "GpiBeginPath failed"
  2495.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2496.     }
  2497.  
  2498.     // And draw the arc
  2499.     if (GpiFullArc(__hPS, DRO_OUTLINE, Fixed) == GPI_ERROR)
  2500.     {
  2501.         // It failed, so we need to log a message and abort
  2502.         facCIDGui.LogLastSysErr(__FILE__
  2503.                                 , "PAINTBRUSH::Stroke"
  2504.                                 , __LINE__
  2505.                                 , "GpiFullArc failed"
  2506.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2507.     }
  2508.  
  2509.     // Close the path
  2510.     GpiEndPath(__hPS);
  2511.  
  2512.     // Set the geometric line width
  2513.     if (!GpiSetLineWidthGeom(__hPS, LONG(c4Width)))
  2514.     {
  2515.         facCIDGui.LogLastSysErr(__FILE__
  2516.                                 , "PAINTBRUSH::Stroke"
  2517.                                 , __LINE__
  2518.                                 , "GpiSetLineWidthGeom failed"
  2519.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2520.     }
  2521.  
  2522.     if (GpiStrokePath(__hPS, 1, 0) == GPI_ERROR)
  2523.     {
  2524.         facCIDGui.LogLastSysErr(__FILE__
  2525.                                 , "PAINTBRUSH::Stroke"
  2526.                                 , __LINE__
  2527.                                 , "GpiStrokePath failed"
  2528.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  2529.     }
  2530. }
  2531.  
  2532.  
  2533. // -----------------------------------------------------------------------------
  2534. //  PAINTBRUSH: Protected, non-virtual methods
  2535. // -----------------------------------------------------------------------------
  2536.  
  2537. //
  2538. // FUNCTION/METHOD NAME: _Draw3DBorder( bRaised, areaPos, i4Width, rgbBgn
  2539. //                                      , rgbFgn)
  2540. //
  2541. // DESCRIPTION:
  2542. //
  2543. //  This method is for local use and is a low level function for drawing 3D
  2544. //  borders very quickly. This is done a lot so it is worth being very
  2545. //  efficient. It also helps the public DrawBorders() function which has a
  2546. //  need to draw both raised and sunken borders on the same call.
  2547. // ---------------------------------------
  2548. //   INPUT: bRaised indicates whether the border should be raised or sunken.
  2549. //          areaPos is the area around which the border should go.
  2550. //          i4Width is the width of the border
  2551. //          rgbBgn, rgbFgn are the colors to use
  2552. //
  2553. //  OUTPUT: areaPos is deflated to account for the border drawn. This is
  2554. //              because the caller might want to call again immediately to
  2555. //              draw another border inside this one.
  2556. //
  2557. //  RETURN: None
  2558. //
  2559. tCIDLib::VOID
  2560.     PROCEXP PAINTBRUSH::_Draw3DBorder(          tCIDLib::eBOOL  bRaised
  2561.                                         ,       AREA&           areaPos
  2562.                                         ,       tCIDLib::INT4   i4Width
  2563.                                         , const RGBCLR&         rgbBgn
  2564.                                         , const RGBCLR&         rgbFgn)
  2565. {
  2566.     POINTL  aptlPath[6], aptlPathSave[6];
  2567.  
  2568.     // Get the area to an array of POINTLs.
  2569.     areaPos.ToPtlArray(aptlPath);
  2570.  
  2571.     // Copy the path list to a backup
  2572.     CopyMemory(aptlPathSave, aptlPath, sizeof(aptlPath));
  2573.  
  2574.     // Make sure that the changed attributes get restored
  2575.     tCIDLib::INT4   i4OldBClr   = GpiQueryColor(__hPS);
  2576.     tCIDLib::INT4   i4OldFClr   = GpiQueryColor(__hPS);
  2577.  
  2578.     // Get quick access to new colors
  2579.     tCIDLib::INT4   i4BgnClr    = rgbBgn;
  2580.     tCIDLib::INT4   i4FgnClr    = rgbFgn;
  2581.  
  2582.     //
  2583.     //  Handle the special cases of widths of 1 or 2 which are not thick
  2584.     //  enough to deal with via the normal code. We just do the left and
  2585.     //  upper sides as a line and the right and bottom sides as a line
  2586.     //  for a width of 1. If 2, then we just do the same thing inward
  2587.     //  one more pel.
  2588.     //
  2589.     tCIDLib::INT4   i4Cnt = i4Width;
  2590.     if (i4Cnt < 3)
  2591.     {
  2592.         while (i4Cnt)
  2593.         {
  2594.             if (bRaised)
  2595.                 GpiSetColor(__hPS, i4FgnClr);
  2596.              else
  2597.                 GpiSetColor(__hPS, i4BgnClr);
  2598.  
  2599.             GpiMove(__hPS, &aptlPath[0]);
  2600.             if (!GpiPolyLine(__hPS, 2, &aptlPath[1]))
  2601.             {
  2602.             }
  2603.  
  2604.             if (bRaised)
  2605.                 GpiSetColor(__hPS, i4BgnClr);
  2606.              else
  2607.                 GpiSetColor(__hPS, i4FgnClr);
  2608.  
  2609.             if (!GpiPolyLine(__hPS, 2, &aptlPath[3]))
  2610.             {
  2611.             }
  2612.  
  2613.             aptlPath[0].x++;
  2614.             aptlPath[0].y++;
  2615.             aptlPath[1].x++;
  2616.             aptlPath[1].y--;
  2617.             aptlPath[2].x--;
  2618.             aptlPath[2].y--;
  2619.             aptlPath[3].x--;
  2620.             aptlPath[3].y++;
  2621.             aptlPath[4].x++;
  2622.             aptlPath[4].y++;
  2623.  
  2624.             i4Cnt--;
  2625.         }
  2626.     }
  2627.      else
  2628.     {
  2629.         //
  2630.         //  For speed we drop into raw PM here. We need to do this as
  2631.         //  two filled paths. We start by building up a path for the
  2632.         //  upper and left sides. The first 3 are already ok.
  2633.         //
  2634.         aptlPath[3].x = aptlPath[2].x-(i4Width-1);
  2635.         aptlPath[3].y = aptlPath[2].y-(i4Width-1);
  2636.         aptlPath[4].x = aptlPath[1].x+(i4Width-1);
  2637.         aptlPath[4].y = aptlPath[1].y-(i4Width-1);
  2638.         aptlPath[5].x = aptlPath[0].x+(i4Width-1);
  2639.         aptlPath[5].y = aptlPath[0].y+(i4Width-1);
  2640.  
  2641.         //
  2642.         //  Set the color according to the border type.
  2643.         //
  2644.         if (bRaised)
  2645.             GpiSetColor(__hPS, i4FgnClr);
  2646.          else
  2647.             GpiSetColor(__hPS, i4BgnClr);
  2648.  
  2649.         // Start off in the lower left corner
  2650.         GpiMove(__hPS, &aptlPath[0]);
  2651.  
  2652.         // Start the path bracket and do a polyline to create the path
  2653.         if (!GpiBeginPath(__hPS, 1))
  2654.         {
  2655.             facCIDGui.LogLastSysErr(__FILE__
  2656.                                     , "PAINTBRUSH::DrawBorder"
  2657.                                     , __LINE__
  2658.                                     , "GpiBeginPath failed"
  2659.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2660.         }
  2661.  
  2662.         if (GpiPolyLine(__hPS, 5, &aptlPath[1]) == GPI_ERROR)
  2663.         {
  2664.             facCIDGui.LogLastSysErr(__FILE__
  2665.                                     , "PAINTBRUSH::DrawBorder"
  2666.                                     , __LINE__
  2667.                                     , "GpiPolyLine failed"
  2668.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2669.         }
  2670.         GpiEndPath(__hPS);
  2671.  
  2672.         // Fill and outline the path using the set colors
  2673.         if (GpiFillPath(__hPS, 1, FPATH_ALTERNATE) == GPI_ERROR)
  2674.         {
  2675.             facCIDGui.LogLastSysErr(__FILE__
  2676.                                     , "PAINTBRUSH::DrawBorder"
  2677.                                     , __LINE__
  2678.                                     , "GpiFillPath failed"
  2679.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2680.         }
  2681.  
  2682.  
  2683.         // Set up the line segments for the left and bottom sides
  2684.         aptlPath[0].x = aptlPathSave[3].x;
  2685.         aptlPath[0].y = aptlPathSave[3].y;
  2686.         aptlPath[1].x = aptlPathSave[0].x;
  2687.         aptlPath[1].y = aptlPathSave[0].y;
  2688.         aptlPath[2].x = aptlPathSave[0].x+(i4Width-1);
  2689.         aptlPath[2].y = aptlPathSave[0].y+(i4Width-1);
  2690.         aptlPath[3].x = aptlPathSave[3].x-(i4Width-1);
  2691.         aptlPath[3].y = aptlPathSave[3].y+(i4Width-1);
  2692.         aptlPath[4].x = aptlPathSave[2].x-(i4Width-1);
  2693.         aptlPath[4].y = aptlPathSave[2].y-(i4Width-1);
  2694.  
  2695.         if (bRaised)
  2696.             GpiSetColor(__hPS, i4BgnClr);
  2697.          else
  2698.             GpiSetColor(__hPS, i4FgnClr);
  2699.  
  2700.         // Start at the upper right corner
  2701.         GpiMove(__hPS, &aptlPathSave[2]);
  2702.  
  2703.         //
  2704.         //  Start the path bracket and do a polyline to create the path. Note
  2705.         //  that the current position
  2706.         //
  2707.         if (!GpiBeginPath(__hPS, 1))
  2708.         {
  2709.             facCIDGui.LogLastSysErr(__FILE__
  2710.                                     , "PAINTBRUSH::DrawBorder"
  2711.                                     , __LINE__
  2712.                                     , "GpiBeginPath failed"
  2713.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2714.         }
  2715.  
  2716.         if (GpiPolyLine(__hPS, 5, aptlPath) == GPI_ERROR)
  2717.         {
  2718.             facCIDGui.LogLastSysErr(__FILE__
  2719.                                     , "PAINTBRUSH::DrawBorder"
  2720.                                     , __LINE__
  2721.                                     , "GpiPolyLine failed"
  2722.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2723.         }
  2724.         GpiEndPath(__hPS);
  2725.  
  2726.         // Fill and outline the path using the set colors
  2727.         if (GpiFillPath(__hPS, 1, FPATH_ALTERNATE) == GPI_ERROR)
  2728.         {
  2729.             facCIDGui.LogLastSysErr(__FILE__
  2730.                                     , "PAINTBRUSH::DrawBorder"
  2731.                                     , __LINE__
  2732.                                     , "GpiFillPath failed"
  2733.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  2734.         }
  2735.     }
  2736.  
  2737.     // Bump in the area
  2738.     areaPos.AdjustSides(-i4Width, -i4Width);
  2739.  
  2740.     // Put back the old colors
  2741.     GpiSetColor(__hPS, i4OldFClr);
  2742.     GpiSetBackColor(__hPS, i4OldBClr);
  2743. }
  2744.  
  2745.  
  2746. //
  2747. // FUNCTION/METHOD NAME: _plnodFindFnt(strName)
  2748. //                       _plnodFindFnt(i4FontId)
  2749. //
  2750. // DESCRIPTION:
  2751. //
  2752. //  This method will look for the font with the passed name or id and return
  2753. //  the linked list node if found, else 0.
  2754. //
  2755. //  NOTE:   This guy does not need to be exported.
  2756. // ---------------------------------------
  2757. //   INPUT: strName is the name to look for.
  2758. //          i4FontId is the font id to look for.
  2759. //
  2760. //  OUTPUT: None
  2761. //
  2762. //  RETURN: A ponter to the linked list node or 0
  2763. //
  2764. LLSTNODE* PAINTBRUSH::_plnodFindFnt(const STRG16& strName)
  2765. {
  2766.     FONT*       pfntTmp;
  2767.     LLSTNODE*   plnodTmp = __llstFonts.plnodHead();
  2768.  
  2769.     while (plnodTmp)
  2770.     {
  2771.         pfntTmp = (FONT*)plnodTmp->pobjData();
  2772.  
  2773.         if (pfntTmp->_strName == strName)
  2774.             return plnodTmp;
  2775.  
  2776.         plnodTmp = plnodTmp->plnodNext();
  2777.     }
  2778.     return 0;
  2779. }
  2780.  
  2781. LLSTNODE* PAINTBRUSH::_plnodFindFnt(tCIDLib::INT4 i4FontId)
  2782. {
  2783.     FONT*       pfntTmp;
  2784.     LLSTNODE*   plnodTmp = __llstFonts.plnodHead();
  2785.  
  2786.     while (plnodTmp)
  2787.     {
  2788.         pfntTmp = (FONT*)plnodTmp->pobjData();
  2789.  
  2790.         if (pfntTmp->_i4FontId == i4FontId)
  2791.             return plnodTmp;
  2792.  
  2793.         plnodTmp = plnodTmp->plnodNext();
  2794.     }
  2795.     return 0;
  2796. }
  2797.