bool SkDrawColor::setProperty(int index, SkScriptValue& value) { SkASSERT(value.fType == SkType_Float); SkScalar scalar = value.fOperand.fScalar; switch (index) { case SK_PROPERTY(alpha): uint8_t alpha; #ifdef SK_SCALAR_IS_FLOAT alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256)); #else alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8); #endif color = SkColorSetARGB(alpha, SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(blue): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkToU8((U8CPU) scalar)); break; case SK_PROPERTY(green): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkToU8((U8CPU) scalar), SkColorGetB(color)); break; case SK_PROPERTY(hue): fHue = scalar;//RGB_to_HSV(color, kGetHue); fDirty = true; break; case SK_PROPERTY(red): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(saturation): fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation); fDirty = true; break; case SK_PROPERTY(value): fValue = scalar;//RGB_to_HSV(color, kGetValue); fDirty = true; break; default: SkASSERT(0); return false; } return true; }
inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPMColor c1, SkPMColor c2, SkPMColor c3) { SkScalar t2 = t * t, t3 = t2 * t; SkScalar cc[4]; // FIXME: For the fractx case, this should be refactored out of this function. cc[0] = c[0] + SkScalarMul(c[1], t) + SkScalarMul(c[2], t2) + SkScalarMul(c[3], t3); cc[1] = c[4] + SkScalarMul(c[5], t) + SkScalarMul(c[6], t2) + SkScalarMul(c[7], t3); cc[2] = c[8] + SkScalarMul(c[9], t) + SkScalarMul(c[10], t2) + SkScalarMul(c[11], t3); cc[3] = c[12] + SkScalarMul(c[13], t) + SkScalarMul(c[14], t2) + SkScalarMul(c[15], t3); SkScalar a = SkScalarClampMax(SkScalarMul(cc[0], SkGetPackedA32(c0)) + SkScalarMul(cc[1], SkGetPackedA32(c1)) + SkScalarMul(cc[2], SkGetPackedA32(c2)) + SkScalarMul(cc[3], SkGetPackedA32(c3)), 255); SkScalar r = SkScalarMul(cc[0], SkGetPackedR32(c0)) + SkScalarMul(cc[1], SkGetPackedR32(c1)) + SkScalarMul(cc[2], SkGetPackedR32(c2)) + SkScalarMul(cc[3], SkGetPackedR32(c3)); SkScalar g = SkScalarMul(cc[0], SkGetPackedG32(c0)) + SkScalarMul(cc[1], SkGetPackedG32(c1)) + SkScalarMul(cc[2], SkGetPackedG32(c2)) + SkScalarMul(cc[3], SkGetPackedG32(c3)); SkScalar b = SkScalarMul(cc[0], SkGetPackedB32(c0)) + SkScalarMul(cc[1], SkGetPackedB32(c1)) + SkScalarMul(cc[2], SkGetPackedB32(c2)) + SkScalarMul(cc[3], SkGetPackedB32(c3)); return SkPackARGB32(SkScalarRoundToInt(a), SkScalarRoundToInt(SkScalarClampMax(r, a)), SkScalarRoundToInt(SkScalarClampMax(g, a)), SkScalarRoundToInt(SkScalarClampMax(b, a))); }
bool SkPatchUtils::getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], int lodX, int lodY) { if (lodX < 1 || lodY < 1 || NULL == cubics || NULL == data) { return false; } // check for overflow in multiplication const int64_t lodX64 = (lodX + 1), lodY64 = (lodY + 1), mult64 = lodX64 * lodY64; if (mult64 > SK_MaxS32) { return false; } data->fVertexCount = SkToS32(mult64); // it is recommended to generate draw calls of no more than 65536 indices, so we never generate // more than 60000 indices. To accomplish that we resize the LOD and vertex count if (data->fVertexCount > 10000 || lodX > 200 || lodY > 200) { SkScalar weightX = static_cast<SkScalar>(lodX) / (lodX + lodY); SkScalar weightY = static_cast<SkScalar>(lodY) / (lodX + lodY); // 200 comes from the 100 * 2 which is the max value of vertices because of the limit of // 60000 indices ( sqrt(60000 / 6) that comes from data->fIndexCount = lodX * lodY * 6) lodX = static_cast<int>(weightX * 200); lodY = static_cast<int>(weightY * 200); data->fVertexCount = (lodX + 1) * (lodY + 1); } data->fIndexCount = lodX * lodY * 6; data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount); data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount); // if colors is not null then create array for colors SkPMColor colorsPM[kNumCorners]; if (NULL != colors) { // premultiply colors to avoid color bleeding. for (int i = 0; i < kNumCorners; i++) { colorsPM[i] = SkPreMultiplyColor(colors[i]); } data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount); } // if texture coordinates are not null then create array for them if (NULL != texCoords) { data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount); } SkPoint pts[kNumPtsCubic]; SkPatchUtils::getBottomCubic(cubics, pts); FwDCubicEvaluator fBottom(pts); SkPatchUtils::getTopCubic(cubics, pts); FwDCubicEvaluator fTop(pts); SkPatchUtils::getLeftCubic(cubics, pts); FwDCubicEvaluator fLeft(pts); SkPatchUtils::getRightCubic(cubics, pts); FwDCubicEvaluator fRight(pts); fBottom.restart(lodX); fTop.restart(lodX); SkScalar u = 0.0f; int stride = lodY + 1; for (int x = 0; x <= lodX; x++) { SkPoint bottom = fBottom.next(), top = fTop.next(); fLeft.restart(lodY); fRight.restart(lodY); SkScalar v = 0.f; for (int y = 0; y <= lodY; y++) { int dataIndex = x * (lodY + 1) + y; SkPoint left = fLeft.next(), right = fRight.next(); SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(), (1.0f - v) * top.y() + v * bottom.y()); SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(), (1.0f - u) * left.y() + u * right.y()); SkPoint s2 = SkPoint::Make( (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x() + u * fTop.getCtrlPoints()[3].x()) + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x() + u * fBottom.getCtrlPoints()[3].x()), (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y() + u * fTop.getCtrlPoints()[3].y()) + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y() + u * fBottom.getCtrlPoints()[3].y())); data->fPoints[dataIndex] = s0 + s1 - s2; if (NULL != colors) { uint8_t a = uint8_t(bilerp(u, v, SkScalar(SkColorGetA(colorsPM[kTopLeft_Corner])), SkScalar(SkColorGetA(colorsPM[kTopRight_Corner])), SkScalar(SkColorGetA(colorsPM[kBottomLeft_Corner])), SkScalar(SkColorGetA(colorsPM[kBottomRight_Corner])))); uint8_t r = uint8_t(bilerp(u, v, SkScalar(SkColorGetR(colorsPM[kTopLeft_Corner])), SkScalar(SkColorGetR(colorsPM[kTopRight_Corner])), SkScalar(SkColorGetR(colorsPM[kBottomLeft_Corner])), SkScalar(SkColorGetR(colorsPM[kBottomRight_Corner])))); uint8_t g = uint8_t(bilerp(u, v, SkScalar(SkColorGetG(colorsPM[kTopLeft_Corner])), SkScalar(SkColorGetG(colorsPM[kTopRight_Corner])), SkScalar(SkColorGetG(colorsPM[kBottomLeft_Corner])), SkScalar(SkColorGetG(colorsPM[kBottomRight_Corner])))); uint8_t b = uint8_t(bilerp(u, v, SkScalar(SkColorGetB(colorsPM[kTopLeft_Corner])), SkScalar(SkColorGetB(colorsPM[kTopRight_Corner])), SkScalar(SkColorGetB(colorsPM[kBottomLeft_Corner])), SkScalar(SkColorGetB(colorsPM[kBottomRight_Corner])))); data->fColors[dataIndex] = SkPackARGB32(a,r,g,b); } if (NULL != texCoords) { data->fTexCoords[dataIndex] = SkPoint::Make( bilerp(u, v, texCoords[kTopLeft_Corner].x(), texCoords[kTopRight_Corner].x(), texCoords[kBottomLeft_Corner].x(), texCoords[kBottomRight_Corner].x()), bilerp(u, v, texCoords[kTopLeft_Corner].y(), texCoords[kTopRight_Corner].y(), texCoords[kBottomLeft_Corner].y(), texCoords[kBottomRight_Corner].y())); } if(x < lodX && y < lodY) { int i = 6 * (x * lodY + y); data->fIndices[i] = x * stride + y; data->fIndices[i + 1] = x * stride + 1 + y; data->fIndices[i + 2] = (x + 1) * stride + 1 + y; data->fIndices[i + 3] = data->fIndices[i]; data->fIndices[i + 4] = data->fIndices[i + 2]; data->fIndices[i + 5] = (x + 1) * stride + y; } v = SkScalarClampMax(v + 1.f / lodY, 1); } u = SkScalarClampMax(u + 1.f / lodX, 1); } return true; }