void HitRectSur::Ellipse2(const float centerx, const float centery, const int radius) { if (m_fFailedAlready) { return; } const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int circleleft = ix - radius; const int circletop = iy - radius; const int circleright = ix + radius; const int circlebottom = iy + radius; const int left = SCALEXf(m_rcRect.left); const int top = SCALEYf(m_rcRect.top); const int right = SCALEXf(m_rcRect.right); const int bottom = SCALEYf(m_rcRect.bottom); if (circleleft < left || circletop < top || circleright > right || circlebottom > bottom) { FailObject(); } }
void HitSur::Rectangle(const float x, const float y, const float x2, float y2) { if (m_pcur == NULL) return; int ix = SCALEXf(x); int iy = SCALEYf(y); int ix2 = SCALEXf(x2); int iy2 = SCALEYf(y2); if (ix > ix2) { const int temp = ix; ix = ix2; ix2 = temp; } if (iy > iy2) { const int temp = iy; iy = iy2; iy2 = temp; } if (m_hitx >= ix && m_hitx <= ix2 && m_hity >= iy && m_hity <= iy2) { m_pselected = m_pcur; } }
void ShadowSur::Image(const float x, const float y, const float x2, const float y2, HDC hdcSrc, const int width, const int height) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); StretchBlt(m_hdc, ix, iy, ix2-ix, iy2-iy, hdcSrc, 0, 0, width, height, SRCCOPY); }
void ShadowSur::Rectangle(const float x, const float y, const float x2, float y2) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); ::Rectangle(m_hdc, ix, iy, ix2, iy2); }
void PaintSur::Image(const float x, const float y, const float x2, const float y2, HDC hdcSrc, const int width, const int height) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); SetStretchBltMode(m_hdc, HALFTONE); // somehow enables filtering StretchBlt(m_hdc, ix, iy, ix2 - ix, iy2 - iy, hdcSrc, 0, 0, width, height, SRCCOPY); }
void PaintSur::Rectangle(const float x, const float y, const float x2, float y2) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); SelectObject(m_hdc, m_hbr); SelectObject(m_hdc, m_hpnOutline); ::Rectangle(m_hdc, ix, iy, ix2, iy2); }
void ShadowSur::Line(const float x, const float y, const float x2, const float y2) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); SelectObject(m_hdc, m_hpnLine); ::MoveToEx(m_hdc, ix, iy, NULL); ::LineTo(m_hdc, ix2, iy2); }
void PaintSur::Line(const float x, const float y, const float x2, const float y2) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ix2 = SCALEXf(x2); const int iy2 = SCALEYf(y2); SelectObject(m_hdc, m_hpnLine); ::MoveToEx(m_hdc, ix, iy, NULL); ::LineTo(m_hdc, ix2, iy2); ::LineTo(m_hdc, ix, iy); // To get the last pixel drawn //!! meh }
// copy-pasted from above void HitSur::Polygon(const std::vector<RenderVertex> &rgv) { if (m_pcur == NULL) return; int x1 = SCALEXf(rgv[rgv.size()-1].x); int y1 = SCALEYf(rgv[rgv.size()-1].y); bool hx1 = (m_hitx >= x1); bool hy1 = (m_hity > y1); int crosscount=0; // count of lines which the hit point is to the left of for (unsigned i=0;i<rgv.size();++i) { const int x2 = x1; const int y2 = y1; const bool hx2 = hx1; const bool hy2 = hy1; x1 = SCALEXf(rgv[i].x); y1 = SCALEYf(rgv[i].y); hx1 = (m_hitx >= x1); hy1 = (m_hity > y1); if ((y1==y2) || (!hy1 && !hy2) || (hy1 && hy2) || // if out of y range, forget about this segment (hx1 && hx2)) // Hit point is on the right of the line continue; if (!hx1 && !hx2) { crosscount^=1; continue; } if (x2 == x1) { if (!hx2) crosscount^=1; continue; } // Now the hard part - the hit point is in the line bounding box if (x2 - (y2 - m_hity)*(x1 - x2)/(y1 - y2) > m_hitx) crosscount^=1; } if (crosscount & 1) { m_pselected = m_pcur; } }
void ShadowSur::Arc(const float x, const float y, const float radius, const float pt1x, const float pt1y, const float pt2x, const float pt2y) { const int ix = SCALEXf(x); const int iy = SCALEYf(y); const int ir = SCALEDf(radius); const int x1 = SCALEXf(pt1x); const int y1 = SCALEYf(pt1y); const int x2 = SCALEXf(pt2x); const int y2 = SCALEYf(pt2y); SelectObject(m_hdc, m_hpnLine); ::Arc(m_hdc, ix-ir, iy-ir, ix+ir, iy+ir, x1, y1, x2, y2); }
void HitSur::Line(const float x, const float y, const float x2, const float y2) { if (m_pcur == NULL) return; const int x_1 = SCALEXf(x); const int y_1 = SCALEYf(y); const int x_2 = SCALEXf(x2); const int y_2 = SCALEYf(y2); if (abs(x_2-x_1) > abs(y_2-y_1)) { int lineY = m_hity+4; if (x_1>x_2) { if (m_hitx>=x_2 && m_hitx<=x_1) lineY = ((y_1-y_2)*(m_hitx-x_2))/(x_1-x_2) + y_2; } else if (m_hitx>=x_1 && m_hitx<=x_2) lineY = ((y_2-y_1)*(m_hitx-x_1))/(x_2-x_1) + y_1; if (m_hity+4>lineY && m_hity<lineY+4) { m_pselected = m_pcur; return; } } else if (abs(x_2-x_1) < abs(y_2-y_1)) { int lineX = m_hitx+4; if (y_1>y_2) { if (m_hity>=y_2 && m_hity<=y_1) lineX = ((x_1-x_2)*(m_hity-y_2))/(y_1-y_2) + x_2; } else if (m_hity>=y_1 && m_hity<=y_2) lineX = ((x_2-x_1)*(m_hity-y_1))/(y_2-y_1) + x_1; if (m_hitx+4>lineX && m_hitx<lineX+4) { m_pselected = m_pcur; return; } } }
void ShadowSur::PolygonSkew(const Vector<RenderVertex> &rgv, const float z1, const float z2) const { const int basepixel = SCALEXf(m_z); const int top = SCALEXf(z2) - basepixel; if (top <= 0) return; //This entire polygon is underneath this shadow level int bottom = SCALEXf(z1) - basepixel; if (bottom < 0) bottom = 0; // Polygon crosses shadow level const int count = rgv.Size(); POINT * const rgpt = new POINT[count]; for (int i=0;i<count;i++) { rgpt[i].x = SCALEXf(rgv.ElementAt(i)->x); rgpt[i].y = SCALEYf(rgv.ElementAt(i)->y); } SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); for (int i=bottom;i<top;i++) { //SetViewportOrgEx(m_hdc, i, -i, NULL); SetViewportOrgEx(m_hdc, (int)((float)i*m_shadowDirX), (int)((float)i*m_shadowDirY), NULL); ::Polygon(m_hdc, rgpt, count); } delete [] rgpt; SetViewportOrgEx(m_hdc, 0, 0, NULL); }
// copy-pasted from above void PaintSur::Polygon(const std::vector<RenderVertex> &rgv) { std::vector<POINT> rgpt(rgv.size()); for (size_t i = 0; i < rgv.size(); i++) { rgpt[i].x = SCALEXf(rgv[i].x); rgpt[i].y = SCALEYf(rgv[i].y); } SelectObject(m_hdc, m_hbr); SelectObject(m_hdc, m_hpnOutline); ::Polygon(m_hdc, rgpt.data(), (int)rgv.size()); if (rgv.size() == 4) { POINT pnt; ::MoveToEx(m_hdc, rgpt[0].x, rgpt[0].y, &pnt); ::LineTo(m_hdc, rgpt[2].x, rgpt[2].y); ::MoveToEx(m_hdc, rgpt[1].x, rgpt[1].y, NULL); ::LineTo(m_hdc, rgpt[3].x, rgpt[3].y); ::MoveToEx(m_hdc, pnt.x, pnt.y, NULL); } }
void ShadowSur::EllipseSkew(const float centerx, const float centery, const float radius, const float z1, const float z2) const { const int basepixel = SCALEXf(m_z); const int top = SCALEXf(z2) - basepixel; if (top <= 0) return; //This entire polygon is underneath this shadow level int bottom = SCALEXf(z1) - basepixel; if (bottom < 0) bottom = 0; // Polygon crosses shadow level const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = SCALEDf(radius); SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); for (int i=bottom;i<top;i++) { //SetViewportOrgEx(m_hdc, i, -i, NULL); SetViewportOrgEx(m_hdc, (int)((float)i*m_shadowDirX), (int)((float)i*m_shadowDirY), NULL); ::Ellipse(m_hdc, ix - ir, iy - ir, ix + ir, iy + ir); } SetViewportOrgEx(m_hdc, 0, 0, NULL); }
void ShadowSur::PolylineSkew(const Vertex2D * const rgv, const int count, const float * const rgz, const float z1, const float z2) const { //const int basepixel = SCALEXf(m_z); //const int bottom = SCALEX(z1) - basepixel; //const int top = SCALEX(z2) - basepixel; POINT * const rgpt = new POINT[count]; int cpoints = 0; // points above the shadow level if (rgz) for (int i=0;i<count;++i) if (rgz[i] > m_z) { rgpt[cpoints].x = SCALEXf(rgv[cpoints].x + rgz[cpoints]); rgpt[cpoints].y = SCALEYf(rgv[cpoints].y - rgz[cpoints]); ++cpoints; } SelectObject(m_hdc, m_hpnLine); for (int i=0;i<1;++i) { //SetViewportOrgEx(m_hdc, i, -i, NULL); SetViewportOrgEx(m_hdc, (int)((float)i*m_shadowDirX), (int)((float)i*m_shadowDirY), NULL); ::Polyline(m_hdc, rgpt, cpoints); } delete [] rgpt; SetViewportOrgEx(m_hdc, 0, 0, NULL); }
void PaintSur::PolygonImage(const std::vector<RenderVertex> &rgv, HBITMAP hbm, const float left, const float top, const float right, const float bottom, const int bitmapwidth, const int bitmapheight) { const int ix = SCALEXf(left); const int iy = SCALEYf(top); const int ix2 = SCALEXf(right); const int iy2 = SCALEYf(bottom); const HDC hdcNew = CreateCompatibleDC(m_hdc); const HBITMAP hbmOld = (HBITMAP)SelectObject(hdcNew, hbm); std::vector<POINT> rgpt(rgv.size()); for (size_t i = 0; i < rgv.size(); i++) { rgpt[i].x = SCALEXf(rgv[i].x); rgpt[i].y = SCALEYf(rgv[i].y); } if (GetWinVersion() >= 2600) // For everything newer than Windows XP: use the alpha in the bitmap (RGB needs to be premultiplied with alpha, too, then! see CopyTo_ConvertAlpha()) { const HRGN hrgn = CreatePolygonRgn(rgpt.data(), (int)rgv.size(), WINDING); SelectClipRgn(m_hdc, hrgn); const BLENDFUNCTION blendf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; AlphaBlend(m_hdc, ix, iy, ix2 - ix, iy2 - iy, hdcNew, 0, 0, bitmapwidth, bitmapheight, blendf); SelectClipRgn(m_hdc, NULL); DeleteObject(hrgn); } else // do XOR trick for masking (draw image, draw black polygon, draw image again, and the XOR will do an implicit mask op) { SetStretchBltMode(m_hdc, HALFTONE); // somehow enables filtering StretchBlt(m_hdc, ix, iy, ix2 - ix, iy2 - iy, hdcNew, 0, 0, bitmapwidth, bitmapheight, SRCINVERT); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); SelectObject(m_hdc, GetStockObject(NULL_PEN)); ::Polygon(m_hdc, rgpt.data(), (int)rgv.size()); SetStretchBltMode(m_hdc, HALFTONE); // somehow enables filtering StretchBlt(m_hdc, ix, iy, ix2 - ix, iy2 - iy, hdcNew, 0, 0, bitmapwidth, bitmapheight, SRCINVERT); } SelectObject(hdcNew, hbmOld); DeleteDC(hdcNew); }
void ShadowSur::Ellipse2(const float centerx, const float centery, const int radius) { const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); ::Ellipse(m_hdc, ix - radius, iy - radius, ix + radius + 1, iy + radius + 1); }
void PaintSur::Ellipse(float centerx, float centery, float radius) { const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = SCALEDf(radius); SelectObject(m_hdc, m_hbr); SelectObject(m_hdc, m_hpnOutline); ::Ellipse(m_hdc, ix - ir, iy - ir, ix + ir, iy + ir); }
void ShadowSur::Ellipse(const float centerx, const float centery, const float radius) { const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = SCALEDf(radius); SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); ::Ellipse(m_hdc, ix - ir, iy - ir, ix + ir, iy + ir); }
void PaintSur::Ellipse2(const float centerx, const float centery, const int radius) { const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = radius; SelectObject(m_hdc, m_hbr); SelectObject(m_hdc, m_hpnOutline); ::Ellipse(m_hdc, ix - ir, iy - ir, ix + ir + 1, iy + ir + 1); }
void ShadowSur::EllipseImage(const float centerx, const float centery, const float radius, HBITMAP hbm, const float left, const float top, const float right, const float bottom, const int bitmapwidth, const int bitmapheight) { const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = SCALEDf(radius); SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); ::Ellipse(m_hdc, ix - ir, iy - ir, ix + ir, iy + ir); }
void PaintSur::Polygon(const Vertex2D * const rgv, const int count) { std::vector<POINT> rgpt(count); for (int i = 0; i < count; i++) { rgpt[i].x = SCALEXf(rgv[i].x); rgpt[i].y = SCALEYf(rgv[i].y); } SelectObject(m_hdc, m_hbr); SelectObject(m_hdc, m_hpnOutline); ::Polygon(m_hdc, rgpt.data(), count); }
void ShadowSur::Polyline(const Vertex2D * const rgv, const int count) { POINT * const rgpt = new POINT[count]; for (int i=0;i<count;++i) { rgpt[i].x = SCALEXf(rgv[i].x); rgpt[i].y = SCALEYf(rgv[i].y); } SelectObject(m_hdc, m_hpnLine); ::Polyline(m_hdc, rgpt, count); delete [] rgpt; }
void ShadowSur::Polygon(const Vertex2D * const rgv, const int count) { POINT * const rgpt = new POINT[count]; for (int i=0;i<count;i++) { rgpt[i].x = SCALEXf(rgv[i].x); rgpt[i].y = SCALEYf(rgv[i].y); } SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); ::Polygon(m_hdc, rgpt, count); delete [] rgpt; }
// copy-pasted from above void ShadowSur::Polygon(const Vector<RenderVertex> &rgv) { POINT * const rgpt = new POINT[rgv.Size()]; for (int i=0;i<rgv.Size();i++) { rgpt[i].x = SCALEXf(rgv.ElementAt(i)->x); rgpt[i].y = SCALEYf(rgv.ElementAt(i)->y); } SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); ::Polygon(m_hdc, rgpt, rgv.Size()); delete [] rgpt; }
void HitSur::Ellipse(const float centerx, const float centery, const float radius) { if (m_pcur == NULL) return; const int ix = SCALEXf(centerx); const int iy = SCALEYf(centery); const int ir = SCALEDf(radius); const int dx = m_hitx - ix; const int dy = m_hity - iy; const int dist = dx*dx + dy*dy; if (dist <= ir*ir) { m_pselected = m_pcur; } }
void ShadowSur::PolygonSkew(const Vertex2D * const rgv, const int count, const float * const rgz) const { POINT * const rgpt = new POINT[count]; for (int i=0;i<count;i++) { rgpt[i].x = SCALEXf(rgv[i].x + rgz[i]); rgpt[i].y = SCALEYf(rgv[i].y - rgz[i]); } SelectObject(m_hdc, GetStockObject(BLACK_PEN)); SelectObject(m_hdc, GetStockObject(BLACK_BRUSH)); SetViewportOrgEx(m_hdc, 0, 0, NULL); ::Polygon(m_hdc, rgpt, count); delete [] rgpt; SetViewportOrgEx(m_hdc, 0, 0, NULL); }
void PaintSur::Polyline(const Vertex2D * const rgv, const int count) { SelectObject(m_hdc, m_hpnLine); /* * There seems to be a known GDI bug where drawing very large polylines in one * call freezes the system shortly, so we batch them into groups of MAX_SUR_PT_CACHE. */ //m_ptCache.resize(min(count,MAX_SUR_PT_CACHE+1)); for (int i = 0; i < count; i += MAX_SUR_PT_CACHE) { const int batchSize = std::min(count - i, MAX_SUR_PT_CACHE + 1); for (int i2 = 0; i2 < batchSize; i2++) { m_ptCache[i2].x = SCALEXf(rgv[i + i2].x); m_ptCache[i2].y = SCALEYf(rgv[i + i2].y); } ::Polyline(m_hdc, m_ptCache, batchSize); } }