⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 canvas.cxx

📁 windows mobile phone source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * canvas.cxx
 *
 * Canvas classes implementation
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: canvas.cxx,v $
 * Revision 1.49  1999/02/16 08:08:07  robertj
 * MSVC 6.0 compatibility changes.
 *
 * Revision 1.48  1998/10/15 11:32:53  robertj
 * New memory leak detection system.
 *
 * Revision 1.47  1998/09/24 03:42:31  robertj
 * Added open software license.
 *
 * Revision 1.46  1998/09/22 15:09:58  robertj
 * Added delayed HDC creation in PDrawCanvas.
 *
 * Revision 1.45  1998/09/18 13:59:31  robertj
 * Fixed FillRect leaving small gaps in pattern filled rectangles next to each other.
 *
 * Revision 1.44  1998/09/07 14:03:41  robertj
 * Fixed printing transforms being reset after each page.
 *
 * Revision 1.43  1998/09/04 07:00:10  robertj
 * Fixed double print dialog.
 * Can now print more than one page.
 * Fixed uninitialised variable for win95 StartDoc()
 *
 * Revision 1.42  1998/03/20 03:13:25  robertj
 * Added function to get physical bounds of canvas. Allows to scale drawing.
 *
 * Revision 1.41  1996/10/31 12:39:55  robertj
 * Added RCS keywords.
 *
 */

#include <pwlib.h>

#define new PNEW


PCanvas::PCanvas()
  : _hDC(NULL),
    _hPen((HPEN)GetStockObject(BLACK_PEN)),
    _hBrush((HBRUSH)GetStockObject(HOLLOW_BRUSH)),
    _hFont(NULL)
{
  deviceResX = deviceResY = 1;
  font = realFont;
}


PCanvas::~PCanvas()
{
  if (_hDC != NULL)
    PAssertOS(DeleteDC(_hDC));
  if (_hPen != NULL)
    PAssertOS(DeleteObject(_hPen));
  if (_hBrush != NULL)
    PAssertOS(DeleteObject(_hBrush));
  if (_hFont != NULL)
    PAssertOS(DeleteObject(_hFont));
}


PCanvasState & PCanvas::operator=(const PCanvasState & state)
{
  PCanvasState::operator=(state);
  if (_hDC != NULL)
    SetHDC(_hDC);
  return *this;
}


PObject::Comparison PCanvas::Compare(const PObject & obj) const
{
  PAssert(obj.IsDescendant(PCanvas::Class()), PInvalidCast);
  return _hDC == ((const PCanvas &)obj)._hDC ? EqualTo : GreaterThan;
}


int PEXPORTED PEnumFontFamilyProc(const ENUMLOGFONT FAR * lpelf,
                                 const NEWTEXTMETRIC FAR *,
                                 int fontType,
                                 LPARAM lParam)
{
  PFontFamily * family = new PFontFamily(lpelf->elfLogFont.lfFaceName);
  family->scalable = (fontType & RASTER_FONTTYPE) == 0;
  ((PFontFamilyList *)lParam)->Append(family);
  return TRUE;
}


int PEXPORTED PEnumFontFaceProc(const ENUMLOGFONT FAR * lpelf,
                               const NEWTEXTMETRIC FAR * lpntm,
                               int fontType,
                               LPARAM lParam)
{
  PFontFamily * family = (PFontFamily *)lParam;
  if ((fontType & TRUETYPE_FONTTYPE) != 0) {
    if (family->sizes.GetSize() == 0) {
      WORD sizes[] = {
        8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72
      };
      family->sizes = PWORDArray(sizes, PARRAYSIZE(sizes));
    }
    WORD style = PFont::Regular;
    if ((lpntm->ntmFlags&0x20) != 0)
      style |= PFont::Bold;
    if ((lpntm->ntmFlags&1) != 0)
      style |= PFont::Italic;
    if ((lpntm->ntmFlags&2) != 0)
      style |= PFont::Underline;
    family->styles[family->styles.GetSize()] = style;
    family->styleNames[family->styleNames.GetSize()] =
                                        PString((const char *)lpelf->elfStyle);
  }
  else {
    family->sizes[family->sizes.GetSize()] = (WORD)lpelf->elfLogFont.lfHeight;
    if (family->styles.GetSize() == 0) {
      family->sizes[0] = 0;
      if (lpelf->elfStyle[0] != '\0')
        family->styleNames[0] = PString((const char *)lpelf->elfStyle);
      else
        family->styleNames[0] = "Regular";
    }
  }
  return TRUE;
}


PFontFamilyList PCanvas::GetAvailableFonts() const
{
  PFontFamilyList list;
  EnumFontFamilies(GetHDC(),
                       NULL, (FONTENUMPROC)PEnumFontFamilyProc, (LPARAM)&list);
  for (PINDEX i = 0; i < list.GetSize(); i++)
    EnumFontFamilies(GetHDC(), list[i].GetFacename(),
                            (FONTENUMPROC)PEnumFontFaceProc, (LPARAM)&list[i]);
  return list;
}


void PCanvas::SetHDC(HDC newDC)
{
  _hDC = PAssertNULL(newDC);
  deviceResX = GetDeviceCaps(_hDC, LOGPIXELSX);
  deviceResY = GetDeviceCaps(_hDC, LOGPIXELSY);

  realFont = PRealFont(*this, font);

  SetMapMode(_hDC, MM_ANISOTROPIC);
  SetTransform();
  MakePen();
  MakeBrush();

#if defined(_WIN32)
  SetBrushOrgEx(GetHDC(), patternOrigin.X(), patternOrigin.Y(), NULL);
#else
  SetBrushOrg(GetHDC(), patternOrigin.X(), patternOrigin.Y());
#endif
  PAssertOS(SelectPalette(_hDC, palette.GetHPALETTE(), TRUE) != NULL);
  ::SetPolyFillMode(_hDC, polyFillMode == Winding ? WINDING : ALTERNATE);
  SetTextAlign(_hDC, TA_LEFT|TA_TOP|TA_NOUPDATECP);
}


BOOL PCanvas::SetPenStyle(PenStyles style)
{
  if (PCanvasState::SetPenStyle(style)) {
    MakePen();
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetPenWidth(int width)
{
  if (PCanvasState::SetPenWidth(width)) {
    MakePen();
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetPenFgColour(const PColour & colour)
{
  if (PCanvasState::SetPenFgColour(colour)) {
    MakePen();
    return TRUE;
  }
  return FALSE;
}


void PCanvas::MakePen()
{
  HPEN oldPen = _hPen;

  if (penFgColour.GetAlpha() == 0)
    _hPen = (HPEN)GetStockObject(NULL_PEN);
  else {
    static int msStyle[] = { PS_SOLID, PS_DOT, PS_DASH, PS_DASHDOT };
    PAssert(penStyle < sizeof(msStyle)/sizeof(msStyle[0]), PInvalidParameter);
    _hPen = CreatePen(msStyle[penStyle],
                          penWidth, penFgColour.ToCOLORREF());
  }
  PAssertNULL(_hPen);

  if (_hDC != NULL)
    PAssertOS(SelectObject(_hDC, _hPen) != NULL);

  if (oldPen != NULL)
    PAssertOS(DeleteObject(oldPen));
}


BOOL PCanvas::SetFillPattern(const PPattern & pattern)
{
  if (PCanvasState::SetFillPattern(pattern)) {
    MakeBrush();
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetPatternOrigin(const PPoint & pt)
{
  if (PCanvasState::SetPatternOrigin(pt)) {
#ifdef WIN32
    SetBrushOrgEx(GetHDC(), pt.X(), pt.Y(), NULL);
#else
    SetBrushOrg(GetHDC(), pt.X(), pt.Y());
#endif
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetFillFgColour(const PColour & colour)
{
  if (PCanvasState::SetFillFgColour(colour)) {
    MakeBrush();
    return TRUE;
  }
  return FALSE;
}


void PCanvas::MakeBrush()
{
  HBRUSH oldBrush = _hBrush;

  if (fillFgColour.GetAlpha() == 0)
    _hBrush = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
  else if (fillPattern.GetHBITMAP() == NULL)
    _hBrush = CreateSolidBrush(fillFgColour.ToCOLORREF());
  else
    _hBrush = CreatePatternBrush(fillPattern.GetHBITMAP());
  PAssertNULL(_hBrush);

  if (_hDC != NULL)
    PAssertOS(SelectObject(_hDC, _hBrush) != NULL);

  if (oldBrush != NULL)
    PAssertOS(DeleteObject(oldBrush));
}


BOOL PCanvas::SetFont(const PFont & newFont)
{
  if (!PCanvasState::SetFont(newFont))
    return FALSE;

  GetHDC();
  realFont = PRealFont(*this, newFont);
  MakeFont();
  return TRUE;
}


void PCanvas::MakeFont()
{
  HFONT oldFont = _hFont;

  _hFont = CreateFont(FromPointsY(realFont.GetHeight()),
                     0, 0, 0,
                     realFont.IsBold() ? FW_BOLD : FW_NORMAL,
                     (BYTE)realFont.IsItalic(),
                     (BYTE)realFont.IsUnderlined(),
                     0, 0, 0, 0, 0, 0,
                     realFont.GetFacename());
  PAssertNULL(_hFont);

  if (_hDC != NULL)
    PAssertOS(SelectObject(_hDC, _hFont) != NULL);

  if (oldFont != NULL)
    PAssertOS(DeleteObject(oldFont));
}


BOOL PCanvas::SetPalette(const PPalette & newPal)
{
  if (PCanvasState::SetPalette(newPal)) {
    if (_hDC != NULL)
      PAssertOS(SelectPalette(_hDC, palette.GetHPALETTE(), TRUE) != NULL);
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetPolyFillMode(PolyFillMode newMode)
{
  if (PCanvasState::SetPolyFillMode(newMode)) {
    if (_hDC != NULL)
      ::SetPolyFillMode(_hDC, polyFillMode == Winding ? WINDING : ALTERNATE);
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetViewportRect(const PRect & rect)
{
  if (PCanvasState::SetViewportRect(rect)) {
    SetTransform();
    return TRUE;
  }
  return FALSE;
}


BOOL PCanvas::SetMappingRect(const PRect & rect)
{
  if (PCanvasState::SetMappingRect(rect)) {
    SetTransform();
    return TRUE;
  }
  return FALSE;
}


void PCanvas::SetTransform()
{
  if (_hDC == NULL)
    return;

  SetViewportOrgEx(_hDC, viewport.Left(), viewport.Top(), NULL);
  SetViewportExtEx(_hDC, viewport.Width(), viewport.Height(), NULL);
  SetWindowOrgEx(_hDC, map.Left(), map.Top(), NULL);
  SetWindowExtEx(_hDC, map.Width(), map.Height(), NULL);
  if (GetPenWidth() != 0)
    MakePen();
  MakeFont();
}


void PCanvas::MoveCurrentPosition(PORDINATE x, PORDINATE y)
{
  POINT p;
  PAssertOS(GetCurrentPositionEx(GetHDC(), &p));
  MoveToEx(_hDC, p.x+x, p.y+y, NULL);
}


PPoint PCanvas::GetCurrentPosition() const
{
  PPoint p;
  PAssertOS(::GetCurrentPositionEx(GetHDC(), p));
  return p;
}


void PCanvas::DrawLine(PORDINATE x, PORDINATE y)
{
  SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  LineTo(GetHDC(), x, y);
}


void PCanvas::DrawLine(PORDINATE x1, PORDINATE y1, PORDINATE x2, PORDINATE y2)
{
  SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  POINT p;
  MoveToEx(GetHDC(), x1, y1, &p);
  LineTo(_hDC, x2, y2);
  MoveToEx(_hDC, (int)p.x, (int)p.y, NULL);
}


void PCanvas::DrawLineRelative(PORDINATE x, PORDINATE y)
{
  SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  POINT p;
  PAssertOS(GetCurrentPositionEx(GetHDC(), &p));
  LineTo(_hDC, p.x+x, p.y+y);
}


void PCanvas::_DrawRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
{
  if (penMode == fillMode) {
    SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
    Rectangle(_hDC, x, y, x+dx, y+dy);
  }
  else {
    HGDIOBJ oldBrush =
           SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
    Rectangle(_hDC, x, y, x+dx, y+dy);
    HGDIOBJ oldPen =
      SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
    Rectangle(_hDC, x, y, x+dx, y+dy);
    SelectObject(_hDC, oldPen);
  }
}


void PCanvas::_FillRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
{
  SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  PRect r(x, y, dx, dy);
  ::FillRect(GetHDC(), r, _hBrush);
}


void PCanvas::DrawRoundRect(const PRect & rect,
                               PDIMENSION cornerWidth, PDIMENSION cornerHeight)
{
  if (penMode == fillMode) {
    SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
    RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
                                                    cornerWidth, cornerHeight);
  }
  else {
    HGDIOBJ oldBrush =
           SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
    RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
                                                    cornerWidth, cornerHeight);
    HGDIOBJ oldPen =
      SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
    RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
                                                    cornerWidth, cornerHeight);
    SelectObject(_hDC, oldPen);
  }
}


void PCanvas::DrawEllipse(const PRect & rect)
{
  if (penMode == fillMode) {
    SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
    Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
  }
  else {
    HGDIOBJ oldBrush =
           SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
    Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
    HGDIOBJ oldPen =
      SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
    Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
    SelectObject(_hDC, oldPen);
  }
}


void PCanvas::DrawArc(const PRect & rect,
                                  const PPoint & startPt, const PPoint & endPt)
{
  SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  Arc(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
                               startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
}


static PPoint PointFromAngle(int angle)
{
  static int sine[] = {
      0,  17,  35,  52,  70,  87, 105, 122, 139, 156, 174,  191,  208,
    225, 242, 259, 276, 292, 309, 326, 342, 358, 375, 391,  407,  423,
    438, 454, 469, 485, 500, 515, 530, 545, 559, 574, 588,  602,  616,
    629, 643, 656, 669, 682, 695, 707, 719, 731, 743, 755,  766,  777,
    788, 799, 809, 819, 829, 839, 848, 857, 866, 875, 883,  891,  899,
    906, 914, 921, 927, 934, 940, 946, 951, 956, 961, 966,  970,  974,
    978, 982, 985, 988, 990, 993, 995, 996, 998, 999, 999, 1000, 1000
  };

  while (angle < 0)
    angle += 360;
  angle %= 360;

  switch (angle/45) {
    default:
    case 0 :
      return PPoint(1000, sine[angle]);

    case 1 :
      return PPoint(sine[90-angle], 1000);

    case 2 :
      return PPoint(sine[angle], -1000);

    case 3 :
      return PPoint(1000, sine[angle]);

    case 4 :
      return PPoint(1000, sine[angle]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -