WPainterPath WTransform::map(const WPainterPath& path) const { if (isIdentity()) return path; WPainterPath result; if (isJavaScriptBound() || path.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (!isJavaScriptBound()) o = &path; result.assignBinding(*o, WT_CLASS ".gfxUtils.transform_apply(" + jsRef() + ',' + path.jsRef() + ')'); } const std::vector<WPainterPath::Segment> &sourceSegments = path.segments(); for (std::size_t i = 0; i < sourceSegments.size(); ++i) { double tx, ty; if (sourceSegments[i].type() == WPainterPath::Segment::ArcR || sourceSegments[i].type() == WPainterPath::Segment::ArcAngleSweep) { result.segments_.push_back(sourceSegments[i]); } else { map(sourceSegments[i].x(), sourceSegments[i].y(), &tx, &ty); result.segments_.push_back(WPainterPath::Segment(tx, ty, sourceSegments[i].type())); } } return result; }
WTransform& WTransform::operator*= (const WTransform& Y) { if (isIdentity()) return operator=(Y); if (Y.isIdentity()) return *this; // conceptually: Z = Y * X // our transposed representation: Z = X * Y const WTransform& X = *this; if (isJavaScriptBound() || Y.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (!isJavaScriptBound()) o = &Y; assignBinding(*o, WT_CLASS ".gfxUtils.transform_mult(" + jsRef() + ',' + Y.jsRef() + ')'); } double z11 = X.m_[M11] * Y.m_[M11] + X.m_[M12] * Y.m_[M21] /* + X.m_[M13] * Y.m_[M31]=0*/; double z12 = X.m_[M11] * Y.m_[M12] + X.m_[M12] * Y.m_[M22] /* + X.m_[M13] * Y.m_[M32]=0*/; double z13 = X.m_[M11] * Y.m_[M13] + X.m_[M12] * Y.m_[M23] + X.m_[M13] /* * Y.m_[M33]=1*/; double z21 = X.m_[M21] * Y.m_[M11] + X.m_[M22] * Y.m_[M21] /* + X.m_[M23] * Y.m_[M31]=0*/; double z22 = X.m_[M21] * Y.m_[M12] + X.m_[M22] * Y.m_[M22] /* + X.m_[M23] * Y.m_[M32]=0*/; double z23 = X.m_[M21] * Y.m_[M13] + X.m_[M22] * Y.m_[M23] + X.m_[M23] /* * Y.m_[M33]=1*/; m_[M11] = z11; m_[M12] = z12; m_[M13] = z13; m_[M21] = z21; m_[M22] = z22; m_[M23] = z23; return *this; }
WRectF WTransform::map(const WRectF& rect) const { if (isIdentity()) return rect; double minX, minY, maxX, maxY; WPointF p = map(rect.topLeft()); minX = maxX = p.x(); minY = maxY = p.y(); for (unsigned i = 0; i < 3; ++i) { WPointF p2 = map(i == 0 ? rect.bottomLeft() : i == 1 ? rect.topRight() : rect.bottomRight()); minX = std::min(minX, p2.x()); maxX = std::max(maxX, p2.x()); minY = std::min(minY, p2.y()); maxY = std::max(maxY, p2.y()); } WRectF result(minX, minY, maxX - minX, maxY - minY); if (isJavaScriptBound() || rect.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (rect.isJavaScriptBound()) o = ▭ result.assignBinding(*o, WT_CLASS ".gfxUtils.transform_mult(" + jsRef() + ',' + rect.jsRef() + ')'); } return result; }
bool WTransform::isIdentity() const { return !isJavaScriptBound() && (m_[M11] == 1.0) && (m_[M22] == 1.0) && (m_[M21] == 0.0) && (m_[M12] == 0.0) && (m_[M13] == 0.0) && (m_[M23] == 0.0); }
WTransform& WTransform::translate(const WPointF& p) { std::string refBefore = jsRef(); translate(p.x(), p.y()); if (isJavaScriptBound() || p.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (!isJavaScriptBound()) o = &p; assignBinding(*o, WT_CLASS ".gfxUtils.transform_mult((function(){" "var p=" + p.jsRef() + ";" "return [1,0,0,1,p[0],p[1]];" "})(),(" + refBefore + "))"); } return *this; }
WBrush WBrush::clone() const { WBrush result; if (isJavaScriptBound()) result.assignBinding(*this); result.color_ = color_; result.gradient_ = gradient_; result.style_ = style_; return result; }
WPointF WPointF::swapHV(double width) const { WPointF result(width - y(), x()); if (isJavaScriptBound()) { WStringStream ss; char buf[30]; ss << "((function(p){return ["; ss << Utils::round_js_str(width, 3, buf) << " - p[1],p[0]];})(" << jsRef() + "))"; result.assignBinding(*this, ss.str()); } return result; }
WTransform WTransform::adjoint() const { WTransform res = WTransform(m33() * m22() - m32() * m23(), - (m33() * m12() - m32() * m13()), - (m33() * m21() - m31() * m23()), m33() * m11() - m31() * m13(), m32() * m21() - m31() * m22(), - (m32() * m11() - m31() * m12())); if (isJavaScriptBound()) { res.assignBinding(*this, WT_CLASS ".gfxUtils.transform_adjoint(" + jsRef() + ")"); } return res; }
WPointF WTransform::map(const WPointF& p) const { if (isIdentity()) return p; double x, y; map(p.x(), p.y(), &x, &y); WPointF result(x, y); if (isJavaScriptBound() || p.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (p.isJavaScriptBound()) o = &p; result.assignBinding(*o, WT_CLASS ".gfxUtils.transform_mult(" + jsRef() + ',' + p.jsRef() + ')'); } return result; }
WTransform WTransform::inverted() const { double det = determinant(); if (det != 0) { WTransform adj = adjoint(); WTransform res(adj.m11() / det, adj.m12() / det, adj.m21() / det, adj.m22() / det, adj.m31() / det, adj.m32() / det); if (isJavaScriptBound()) { res.assignBinding(*this, WT_CLASS ".gfxUtils.transform_inverted(" + jsRef() + ")"); } return res; } else { LOG_ERROR("inverted(): oops, determinant == 0"); return *this; } }
void WJavaScriptExposableObject::checkModifiable() { if (isJavaScriptBound()) { throw WException("Trying to modify a JavaScript bound object!"); } }