CGGradientRef Gradient::platformGradient() { if (m_gradient) return m_gradient; sortStopsIfNecessary(); const int cReservedStops = 3; Vector<CGFloat, 4 * cReservedStops> colorComponents; colorComponents.reserveInitialCapacity(m_stops.size() * 4); // RGBA components per stop Vector<CGFloat, cReservedStops> locations; locations.reserveInitialCapacity(m_stops.size()); for (size_t i = 0; i < m_stops.size(); ++i) { colorComponents.uncheckedAppend(m_stops[i].red); colorComponents.uncheckedAppend(m_stops[i].green); colorComponents.uncheckedAppend(m_stops[i].blue); colorComponents.uncheckedAppend(m_stops[i].alpha); locations.uncheckedAppend(m_stops[i].stop); } m_gradient = CGGradientCreateWithColorComponents(deviceRGBColorSpaceRef(), colorComponents.data(), locations.data(), m_stops.size()); return m_gradient; }
CGGradientRef Gradient::platformGradient() { if (m_gradient) return m_gradient; sortStopsIfNecessary(); // FIXME: ExtendedColor - we should generate CGColorRefs here, so that // we can handle color spaces. const int cReservedStops = 3; Vector<CGFloat, 4 * cReservedStops> colorComponents; colorComponents.reserveInitialCapacity(m_stops.size() * 4); // RGBA components per stop Vector<CGFloat, cReservedStops> locations; locations.reserveInitialCapacity(m_stops.size()); for (size_t i = 0; i < m_stops.size(); ++i) { colorComponents.uncheckedAppend(m_stops[i].red); colorComponents.uncheckedAppend(m_stops[i].green); colorComponents.uncheckedAppend(m_stops[i].blue); colorComponents.uncheckedAppend(m_stops[i].alpha); locations.uncheckedAppend(m_stops[i].stop); } // FIXME: ExtendedColor - use CGGradientCreateWithColors so that we can have stops in different color spaces. m_gradient = CGGradientCreateWithColorComponents(sRGBColorSpaceRef(), colorComponents.data(), locations.data(), m_stops.size()); return m_gradient; }
BlackBerry::Platform::Graphics::Gradient* Gradient::platformGradient() { if (m_gradient) return m_gradient; if (m_radial) m_gradient = BlackBerry::Platform::Graphics::Gradient::createRadialGradient(m_p0, m_p1, m_r0, m_r1, m_aspectRatio, (BlackBerry::Platform::Graphics::Gradient::SpreadMethod)m_spreadMethod); else m_gradient = BlackBerry::Platform::Graphics::Gradient::createLinearGradient(m_p0, m_p1, (BlackBerry::Platform::Graphics::Gradient::SpreadMethod)m_spreadMethod); sortStopsIfNecessary(); ASSERT(m_stopsSorted); size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); ASSERT(countUsed >= 2); ASSERT(countUsed >= m_stops.size()); Vector<float> pos(countUsed); Vector<unsigned> colors(countUsed); fillStops(m_stops.data(), m_stops.size(), pos.data(), colors.data()); m_gradient->setColorStops(pos.data(), colors.data(), countUsed); if (!m_gradientSpaceTransformation.isIdentity()) m_gradient->setLocalMatrix(reinterpret_cast<const double*>(&m_gradientSpaceTransformation)); return m_gradient; }
SkShader* Gradient::platformGradient() { if (m_gradient) return m_gradient; sortStopsIfNecessary(); ASSERT(m_stopsSorted); size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); ASSERT(countUsed >= 2); ASSERT(countUsed >= m_stops.size()); // FIXME: Why is all this manual pointer math needed?! SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar))); SkColor* colors = (SkColor*)storage.get(); SkScalar* pos = (SkScalar*)(colors + countUsed); fillStops(m_stops.data(), m_stops.size(), pos, colors); SkShader::TileMode tile = SkShader::kClamp_TileMode; switch (m_spreadMethod) { case SpreadMethodReflect: tile = SkShader::kMirror_TileMode; break; case SpreadMethodRepeat: tile = SkShader::kRepeat_TileMode; break; case SpreadMethodPad: tile = SkShader::kClamp_TileMode; break; } if (m_radial) { // Since the two-point radial gradient is slower than the plain radial, // only use it if we have to. if (m_p0 == m_p1 && m_r0 <= 0.0f) { // The radius we give to Skia must be positive (and non-zero). If // we're given a zero radius, just ask for a very small radius so // Skia will still return an object. SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : WebCoreFloatToSkScalar(FLT_EPSILON); m_gradient = SkGradientShader::CreateRadial(m_p1, radius, colors, pos, static_cast<int>(countUsed), tile); } else { // The radii we give to Skia must be positive. If we're given a // negative radius, ask for zero instead. SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; m_gradient = SkGradientShader::CreateTwoPointRadial(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile); } if (aspectRatio() != 1) { // CSS3 elliptical gradients: apply the elliptical scaling at the // gradient center point. m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); ASSERT(m_p0 == m_p1); } } else { SkPoint pts[2] = { m_p0, m_p1 }; m_gradient = SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile); } ASSERT(m_gradient); SkMatrix matrix = m_gradientSpaceTransformation; m_gradient->setLocalMatrix(matrix); return m_gradient; }
sk_sp<SkShader> Gradient::createShader() { sortStopsIfNecessary(); ASSERT(m_stopsSorted); size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); ASSERT(countUsed >= 2); ASSERT(countUsed >= m_stops.size()); ColorStopOffsetVector pos(countUsed); ColorStopColorVector colors(countUsed); fillStops(m_stops.data(), m_stops.size(), pos, colors); SkShader::TileMode tile = SkShader::kClamp_TileMode; switch (m_spreadMethod) { case SpreadMethodReflect: tile = SkShader::kMirror_TileMode; break; case SpreadMethodRepeat: tile = SkShader::kRepeat_TileMode; break; case SpreadMethodPad: tile = SkShader::kClamp_TileMode; break; } sk_sp<SkShader> shader; uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0; if (m_radial) { if (aspectRatio() != 1) { // CSS3 elliptical gradients: apply the elliptical scaling at the // gradient center point. m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); ASSERT(m_p0 == m_p1); } SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation); // Since the two-point radial gradient is slower than the plain radial, // only use it if we have to. if (m_p0 == m_p1 && m_r0 <= 0.0f) { shader = SkGradientShader::MakeRadial(m_p1.data(), m_r1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix); } else { // The radii we give to Skia must be positive. If we're given a // negative radius, ask for zero instead. SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; shader = SkGradientShader::MakeTwoPointConical(m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix); } } else { SkPoint pts[2] = { m_p0.data(), m_p1.data() }; SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation); shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix); } if (!shader) { // use last color, since our "geometry" was degenerate (e.g. radius==0) shader = SkShader::MakeColorShader(colors[countUsed - 1]); } return shader; }
SkShader* Gradient::shader() { if (m_gradient) return m_gradient.get(); sortStopsIfNecessary(); ASSERT(m_stopsSorted); size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); ASSERT(countUsed >= 2); ASSERT(countUsed >= m_stops.size()); // FIXME: Why is all this manual pointer math needed?! SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar))); SkColor* colors = (SkColor*)storage.get(); SkScalar* pos = (SkScalar*)(colors + countUsed); fillStops(m_stops.data(), m_stops.size(), pos, colors); SkShader::TileMode tile = SkShader::kClamp_TileMode; switch (m_spreadMethod) { case SpreadMethodReflect: tile = SkShader::kMirror_TileMode; break; case SpreadMethodRepeat: tile = SkShader::kRepeat_TileMode; break; case SpreadMethodPad: tile = SkShader::kClamp_TileMode; break; } uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0; if (m_radial) { // Since the two-point radial gradient is slower than the plain radial, // only use it if we have to. if (m_p0 == m_p1 && m_r0 <= 0.0f) { m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); } else { // The radii we give to Skia must be positive. If we're given a // negative radius, ask for zero instead. SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); } if (aspectRatio() != 1) { // CSS3 elliptical gradients: apply the elliptical scaling at the // gradient center point. m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); ASSERT(m_p0 == m_p1); } } else { SkPoint pts[2] = { m_p0, m_p1 }; m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); } if (!m_gradient) { // use last color, since our "geometry" was degenerate (e.g. radius==0) m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1])); } else { m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation)); } return m_gradient.get(); }