void LayerCompositingThread::setDrawTransform(double scale, const TransformationMatrix& matrix, const TransformationMatrix& projectionMatrix) { m_drawTransform = projectionMatrix * matrix; FloatRect boundsRect(-origin(), bounds()); if (sizeIsScaleInvariant()) boundsRect.scale(1 / scale); m_centerW = 0; m_transformedBounds.clear(); m_ws.clear(); m_textureCoordinates.clear(); if (matrix.hasPerspective() && !m_layerRendererSurface) { // Perform processing according to http://www.w3.org/TR/css3-transforms 6.2 // If w < 0 for all four corners of the transformed box, the box is not rendered. // If w < 0 for one to three corners of the transformed box, the box // must be replaced by a polygon that has any parts with w < 0 cut out. // If w = 0, (x′, y′, z′) = (x ⋅ n, y ⋅ n, z ⋅ n) // We implement this by intersecting with the image plane, i.e. the last row of the column-major matrix. // To avoid problems with w close to 0, we use w = epsilon as the near plane by subtracting epsilon from matrix.m44(). const float epsilon = 1e-3; Vector<FloatPoint3D, 4> quad = toVector<FloatPoint3D, 4>(boundsRect); Vector<FloatPoint3D, 4> polygon = intersect(quad, LayerClipPlane(FloatPoint3D(matrix.m14(), matrix.m24(), matrix.m34()), matrix.m44() - epsilon)); // Compute the clipped texture coordinates. if (polygon != quad) { for (size_t i = 0; i < polygon.size(); ++i) { FloatPoint3D& p = polygon[i]; m_textureCoordinates.append(FloatPoint(p.x() / boundsRect.width() + 0.5f, p.y() / boundsRect.height() + 0.5f)); } } // If w > 0, (x′, y′, z′) = (x/w, y/w, z/w) for (size_t i = 0; i < polygon.size(); ++i) { float w; FloatPoint3D p = multVecMatrix(matrix, polygon[i], w); if (w != 1) { p.setX(p.x() / w); p.setY(p.y() / w); p.setZ(p.z() / w); } FloatPoint3D q = projectionMatrix.mapPoint(p); m_transformedBounds.append(FloatPoint(q.x(), q.y())); m_ws.append(w); } m_centerW = matrix.m44(); } else m_transformedBounds = toVector<FloatPoint, 4>(m_drawTransform.mapQuad(boundsRect)); m_boundingBox = WebCore::boundingBox(m_transformedBounds); }
inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector) { m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale); float lightStrength; if (!normal2DVector.x() && !normal2DVector.y()) { // Normal vector is (0, 0, 1). This is a quite frequent case. if (m_lightingType == FELighting::DiffuseLighting) { lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength; } else { FloatPoint3D halfwayVector = paintingData.lightVector; halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); float halfwayVectorLength = halfwayVector.length(); if (m_specularExponent == 1) lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength; else lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent); } } else { FloatPoint3D normalVector; normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale); normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale); normalVector.setZ(1); float normalVectorLength = normalVector.length(); if (m_lightingType == FELighting::DiffuseLighting) { lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength); } else { FloatPoint3D halfwayVector = paintingData.lightVector; halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); float halfwayVectorLength = halfwayVector.length(); if (m_specularExponent == 1) lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength); else lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent); } } if (lightStrength > 1) lightStrength = 1; if (lightStrength < 0) lightStrength = 0; data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x())); data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y())); data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z())); }