void AudioBufferSourceHandler::clampGrainParameters(const AudioBuffer* buffer) { ASSERT(buffer); // We have a buffer so we can clip the offset and duration to lie within the buffer. double bufferDuration = buffer->duration(); m_grainOffset = clampTo(m_grainOffset, 0.0, bufferDuration); // If the duration was not explicitly given, use the buffer duration to set the grain // duration. Otherwise, we want to use the user-specified value, of course. if (!m_isDurationGiven) m_grainDuration = bufferDuration - m_grainOffset; if (m_isDurationGiven && loop()) { // We're looping a grain with a grain duration specified. Schedule the loop to stop after // grainDuration seconds after starting, possibly running the loop multiple times if // grainDuration is larger than the buffer duration. The net effect is as if the user called // stop(when + grainDuration). m_grainDuration = clampTo(m_grainDuration, 0.0, std::numeric_limits<double>::infinity()); m_endTime = m_startTime + m_grainDuration; } else { m_grainDuration = clampTo(m_grainDuration, 0.0, bufferDuration - m_grainOffset); } // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through // linear interpolation at a sub-sample position since it will degrade the quality. When // aligned to the sample-frame the playback will be identical to the PCM data stored in the // buffer. Since playbackRate == 1 is very common, it's worth considering quality. m_virtualReadIndex = AudioUtilities::timeToSampleFrame(m_grainOffset, buffer->sampleRate()); }
AnimatableColorImpl::AnimatableColorImpl(float red, float green, float blue, float alpha) : m_alpha(clampTo(alpha, 0.0f, 1.0f)) , m_red(clampTo(red, 0.0f, 1.0f)) , m_green(clampTo(green, 0.0f, 1.0f)) , m_blue(clampTo(blue, 0.0f, 1.0f)) { }
void StereoPanner::panWithSampleAccurateValues(const AudioBus* inputBus, AudioBus* outputBus, const float* panValues, size_t framesToProcess) { bool isInputSafe = inputBus && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2) && framesToProcess <= inputBus->length(); ASSERT(isInputSafe); if (!isInputSafe) return; unsigned numberOfInputChannels = inputBus->numberOfChannels(); bool isOutputSafe = outputBus && outputBus->numberOfChannels() == 2 && framesToProcess <= outputBus->length(); ASSERT(isOutputSafe); if (!isOutputSafe) return; const float* sourceL = inputBus->channel(0)->data(); const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : sourceL; float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutableData(); float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->mutableData(); if (!sourceL || !sourceR || !destinationL || !destinationR) return; double gainL, gainR, panRadian; int n = framesToProcess; if (numberOfInputChannels == 1) { // For mono source case. while (n--) { float inputL = *sourceL++; m_pan = clampTo(*panValues++, -1.0, 1.0); // Pan from left to right [-1; 1] will be normalized as [0; 1]. panRadian = (m_pan * 0.5 + 0.5) * piOverTwoDouble; gainL = std::cos(panRadian); gainR = std::sin(panRadian); *destinationL++ = static_cast<float>(inputL * gainL); *destinationR++ = static_cast<float>(inputL * gainR); } } else { // For stereo source case. while (n--) { float inputL = *sourceL++; float inputR = *sourceR++; m_pan = clampTo(*panValues++, -1.0, 1.0); // Normalize [-1; 0] to [0; 1]. Do nothing when [0; 1]. panRadian = (m_pan <= 0 ? m_pan + 1 : m_pan) * piOverTwoDouble; gainL = std::cos(panRadian); gainR = std::sin(panRadian); if (m_pan <= 0) { *destinationL++ = static_cast<float>(inputL + inputR * gainL); *destinationR++ = static_cast<float>(inputR * gainR); } else { *destinationL++ = static_cast<float>(inputL * gainL); *destinationR++ = static_cast<float>(inputR + inputL * gainR); } } } }
FloatPoint PageViewportController::clampViewportToContents(const WebCore::FloatPoint& viewportPos, float viewportScale) { const float horizontalRange = std::max(0.f, m_contentsSize.width() - m_viewportSize.width() / viewportScale); const float verticalRange = std::max(0.f, m_contentsSize.height() - m_viewportSize.height() / viewportScale); return FloatPoint(clampTo(viewportPos.x(), 0.f, horizontalRange), clampTo(viewportPos.y(), 0.f, verticalRange)); }
void OcclusionEngine::addOccluders( const Occluder occluderArray[], int numberOfOccluders ) { if( engineMode == NormalRasterization ) { for( int i = 0 ; i < numberOfOccluders ; i++ ) { const Occluder *currentOccluder; currentOccluder = &(occluderArray[i]); int triangleIndexOffset; //Create triangles based on occluder triangle strip. for( int t = 0 ; t < currentOccluder->numberOfPoints - 2 ; t++ ) { triangleIndexOffset = t + 1; //Rasterize every triangle that forms the occluder convex hull. rasterizer->rasterizeTriangle( currentOccluder->points[0].x, currentOccluder->points[0].y, currentOccluder->points[triangleIndexOffset].x, currentOccluder->points[triangleIndexOffset].y, currentOccluder->points[triangleIndexOffset + 1].x, currentOccluder->points[triangleIndexOffset + 1].y, clampTo(currentOccluder->points[0].depth,0.0f,1.0f), //Clamp depth between 0 and 1 inclusive. clampTo(currentOccluder->points[triangleIndexOffset].depth,0.0f,1.0f), clampTo(currentOccluder->points[triangleIndexOffset + 1].depth,0.0f,1.0f) ); } } } if( engineMode == Optimized ) { int totalTilesDefferedFromRasterization = 0; for( int i = 0 ; i < numberOfOccluders ; i++ ) { tiledRasterizer->rasterizeConvexHull(occluderArray[i]); totalTilesDefferedFromRasterization += tiledRasterizer->tilesDefferredFromRasterization; } if( drawAllTiles ) tiledRasterizer->tempRasterFullyCoveredNotRasterized(); //printf("Tiles avoided: %d\n", totalTilesDefferedFromRasterization); } }
JSValue JSWebSocket::close(ExecState* exec) { // FIXME: We should implement [Clamp] for IDL binding code generator, and // remove this custom method. WebSocket* webSocket = static_cast<WebSocket*>(impl()); size_t argumentCount = exec->argumentCount(); int code = WebSocketChannel::CloseEventCodeNotSpecified; String reason = ""; if (argumentCount >= 1) { JSValue v = exec->argument(0); double x = v.toNumber(exec); double maxValue = static_cast<double>(std::numeric_limits<uint16_t>::max()); double minValue = static_cast<double>(std::numeric_limits<uint16_t>::min()); if (isnan(x)) x = 0.0; else x = clampTo(x, minValue, maxValue); code = clampToInteger(x); if (argumentCount >= 2) { reason = ustringToString(exec->argument(1).toString(exec)->value(exec)); if (exec->hadException()) { setDOMException(exec, SYNTAX_ERR); return jsUndefined(); } } } ExceptionCode ec = 0; webSocket->close(code, reason, ec); setDOMException(exec, ec); return jsUndefined(); }
void adjustBoundingBox( Occludee::OccludeeAABB &boundingBox, const int width, const int height ) { boundingBox.xMin = clampTo(boundingBox.xMin, 0, width - 1); boundingBox.yMin = clampTo(boundingBox.yMin, 0, height - 1); boundingBox.xMax = clampTo(boundingBox.xMax, 0, width - 1); boundingBox.yMax = clampTo(boundingBox.yMax, 0, height- 1); if( boundingBox.xMin > boundingBox.xMax) boundingBox.xMin = boundingBox.xMax; if( boundingBox.yMin > boundingBox.yMax) boundingBox.yMin = boundingBox.yMax; }
OcclusionEngine::OcclusionEngine(int pBufferWidth, int pBufferHeight, OcclusionEngineOptions options) { int tileSize = clampTo(options.tileSize, MIN_TILE_SIZE, MAX_TILE_SIZE ); if( tileSize % MIN_TILE_SIZE != 0 ) tileSize = ((int)(tileSize / MIN_TILE_SIZE) + 1) * MIN_TILE_SIZE; drawAllTiles = options.drawAllTiles; engineMode = (EOcclusionEngineMode)options.engineMode; depthBuffer = NULL; tiledDepthBuffer = NULL; bufferWidth = pBufferWidth; bufferHeight = pBufferHeight; if( engineMode == NormalRasterization ) { //Create the depth buffer. depthBuffer = new DepthBuffer(bufferWidth, bufferHeight); //Create a rasterizer. rasterizer = new Rasterizer(depthBuffer); } if( engineMode == Optimized ) { tiledDepthBuffer = new TiledDepthBuffer(bufferWidth, bufferHeight, tileSize); tiledRasterizer = new TiledRasterizer(tiledDepthBuffer); tiledRasterizer->numberOfThreads = options.numberOfThreads; } }
double AudioBufferSourceHandler::computePlaybackRate() { // Incorporate buffer's sample-rate versus AbstractAudioContext's sample-rate. // Normally it's not an issue because buffers are loaded at the // AbstractAudioContext's sample-rate, but we can handle it in any case. double sampleRateFactor = 1.0; if (buffer()) { // Use doubles to compute this to full accuracy. sampleRateFactor = buffer()->sampleRate() / static_cast<double>(sampleRate()); } // Use finalValue() to incorporate changes of AudioParamTimeline and // AudioSummingJunction from m_playbackRate AudioParam. double basePlaybackRate = m_playbackRate->finalValue(); double finalPlaybackRate = sampleRateFactor * basePlaybackRate; // Take the detune value into account for the final playback rate. finalPlaybackRate *= pow(2, m_detune->finalValue() / 1200); // Sanity check the total rate. It's very important that the resampler not // get any bad rate values. finalPlaybackRate = clampTo(finalPlaybackRate, 0.0, MaxRate); bool isPlaybackRateValid = !std::isnan(finalPlaybackRate) && !std::isinf(finalPlaybackRate); ASSERT(isPlaybackRateValid); if (!isPlaybackRateValid) finalPlaybackRate = 1.0; // Record the minimum playback rate for use by handleStoppableSourceNode. m_minPlaybackRate = std::min(finalPlaybackRate, m_minPlaybackRate); return finalPlaybackRate; }
v8::Handle<v8::Value> V8WebSocket::closeCallback(const v8::Arguments& args) { // FIXME: We should implement [Clamp] for IDL binding code generator, and // remove this custom method. WebSocket* webSocket = toNative(args.Holder()); int argumentCount = args.Length(); int code = WebSocketChannel::CloseEventCodeNotSpecified; String reason = ""; if (argumentCount >= 1) { double x = args[0]->NumberValue(); double maxValue = static_cast<double>(std::numeric_limits<uint16_t>::max()); double minValue = static_cast<double>(std::numeric_limits<uint16_t>::min()); if (isnan(x)) x = 0.0; else x = clampTo(x, minValue, maxValue); code = clampToInteger(x); if (argumentCount >= 2) { v8::TryCatch tryCatch; v8::Handle<v8::String> reasonValue = args[1]->ToString(); if (tryCatch.HasCaught()) return throwError(tryCatch.Exception()); reason = toWebCoreString(reasonValue); } } ExceptionCode ec = 0; webSocket->close(code, reason, ec); if (ec) return throwError(ec); return v8::Undefined(); }
static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction) { for (unsigned i = 0; i < 256; ++i) { double val = transferFunction.slope * i + 255 * transferFunction.intercept; val = clampTo(val, 0.0, 255.0); values[i] = static_cast<unsigned char>(val); } }
void GroundAvoidanceAdvisory::updateAltitudeAdvisories(const double descent_velocity) { const double advance_altitude_loss = descent_velocity * 2.0; const double reaction_altitude_loss = descent_velocity * 1.0; // TODO 0.45 in A-G mode const double roll_altitude_loss = descent_velocity * std::abs(b_Roll->value()) / m_RollRate; const double recovery_altitude_loss = b_Velocity->value().length2() * (1.0 - cos(b_Pitch->value())) * m_InverseG; const double predicted_altitude_loss = advance_altitude_loss + reaction_altitude_loss + roll_altitude_loss + recovery_altitude_loss; const double cas_factor = clampTo(375.0 - convert::mps_kts(b_CAS->value()), 0.0, 50.0); const double buffer_factor = cas_factor * (0.125 / 50.0); const double buffer_offset = convert::ft_m(cas_factor * 2.0 + 50.0); const double buffer = buffer_factor * predicted_altitude_loss + buffer_offset; const double alow = convert::ft_m(b_CaraAlow->value()); const double maximum_loss = b_Position->value().z() - b_GroundZ->value() - buffer - alow; const double advance_alert_loss = std::max(maximum_loss - (predicted_altitude_loss - advance_altitude_loss), 0.0); b_AltitudeAdvisory->pushOnChange(maximum_loss < (predicted_altitude_loss - advance_altitude_loss)); b_AdvanceAltitudeAdvisory->value() = maximum_loss < predicted_altitude_loss; b_PullupAnticipation->value() = 1.0 - clampTo(advance_alert_loss / descent_velocity * 0.125, 0.0, 1.000001); }
static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction) { for (unsigned i = 0; i < 256; ++i) { double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset); val = clampTo(val, 0.0, 255.0); values[i] = static_cast<unsigned char>(val); } }
ShadowData ShadowData::blend(const ShadowData& from, double progress, const Color& currentColor) const { ASSERT(style() == from.style()); return ShadowData(blink::blend(from.location(), location(), progress), clampTo(blink::blend(from.blur(), blur(), progress), 0.0f), blink::blend(from.spread(), spread(), progress), style(), blink::blend(from.color().resolve(currentColor), color().resolve(currentColor), progress)); }
void GraphicsLayerBlackBerry::setOpacity(float opacity) { float clampedOpacity = clampTo(opacity, 0.0f, 1.0f); if (m_opacity == clampedOpacity) return; GraphicsLayer::setOpacity(clampedOpacity); primaryLayer()->setOpacity(opacity); }
float OcclusionEngine::getDepthBufferPixel(const int x, const int y) { int clampedX, clampedY; clampedX = clampTo(x, 0, bufferWidth - 1); clampedY = clampTo(y, 0, bufferHeight - 1); if( engineMode == Optimized ) { return tiledDepthBuffer->getValue(clampedX, clampedY); } if( engineMode == NormalRasterization ) { return depthBuffer->getValue(clampedX, clampedY); } return 0; }
float PageViewportController::outerBoundedViewportScale(float viewportScale) const { if (m_allowsUserScaling) { // Bounded by [0.1, 10.0] like the viewport meta code in WebCore. float hardMin = toViewportScale(std::max<float>(0.1, 0.5 * m_minimumScaleToFit)); float hardMax = toViewportScale(std::min<float>(10, 2 * m_rawAttributes.maximumScale)); return clampTo(viewportScale, hardMin, hardMax); } return innerBoundedViewportScale(viewportScale); }
FELighting::FELighting(Filter* filter, LightingType lightingType, const Color& lightingColor, float surfaceScale, float diffuseConstant, float specularConstant, float specularExponent, PassRefPtr<LightSource> lightSource) : FilterEffect(filter) , m_lightingType(lightingType) , m_lightSource(lightSource) , m_lightingColor(lightingColor) , m_surfaceScale(surfaceScale) , m_diffuseConstant(std::max(diffuseConstant, 0.0f)) , m_specularConstant(std::max(specularConstant, 0.0f)) , m_specularExponent(clampTo(specularExponent, 1.0f, 128.0f)) { }
int ScrollbarThemeOverlay::thumbLength(const ScrollbarThemeClient& scrollbar) { int trackLen = trackLength(scrollbar); if (!scrollbar.totalSize()) return trackLen; float proportion = static_cast<float>(scrollbar.visibleSize()) / scrollbar.totalSize(); int length = round(proportion * trackLen); int minLen = std::min(minimumThumbLength(scrollbar), trackLen); length = clampTo(length, minLen, trackLen); return length; }
static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction) { const Vector<float>& tableValues = transferFunction.tableValues; unsigned n = tableValues.size(); if (n < 1) return; for (unsigned i = 0; i < 256; ++i) { unsigned k = static_cast<unsigned>((i * n) / 255.0); k = std::min(k, n - 1); double val = 255 * tableValues[k]; val = clampTo(val, 0.0, 255.0); values[i] = static_cast<unsigned char>(val); } }
void update(double dt) { double v = m_Channel->value(); v += m_Increment * dt * m_Rate; if (m_DecayCount > 0) { m_DecayCount--; if (m_Increment == 0.0) { if (m_DecayCount == 0) { v = 0.0; } else { v *= m_Decay; } } } m_Channel->value() = clampTo(v, m_Minimum, m_Maximum); }
static void table(unsigned char* values, const ComponentTransferFunction& transferFunction) { const Vector<float>& tableValues = transferFunction.tableValues; unsigned n = tableValues.size(); if (n < 1) return; for (unsigned i = 0; i < 256; ++i) { double c = i / 255.0; unsigned k = static_cast<unsigned>(c * (n - 1)); double v1 = tableValues[k]; double v2 = tableValues[std::min((k + 1), (n - 1))]; double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1)); val = clampTo(val, 0.0, 255.0); values[i] = static_cast<unsigned char>(val); } }
double F16FlightModel::calculateYawMoment() const { const double p = -m_AngularVelocityBody.y(); /** * negative since yaw axis (and hence yaw rate) is opposite nasa 1979. */ const double r = -m_AngularVelocityBody.z(); /** * cn_da = dcn,da + dcn,da,lef * (1 - dlef/25) */ double cn_da = m_Cn_da_a_b[m_Alpha][(m_Aileron > 0) ? m_Beta : -m_Beta]; cn_da += m_ScaleLEF * (m_Cn_da_lef_a_b[m_Alpha][(m_Aileron > 0) ? m_Beta : -m_Beta] - cn_da); double cn_p = (m_Cn_p_a[m_Alpha] + m_Cn_p_lef_a[m_Alpha] * m_ScaleLEF) * p; double cn_r = (m_Cn_r_a[m_Alpha] + m_Cn_r_lef_a[m_Alpha] * m_ScaleLEF) * r; double cn_dr = m_Cn_dr_a_b[m_Alpha][(m_Rudder > 0) ? m_Beta : -m_Beta]; /** * XXX hack (testing spin control in deep stall trim) without this "boost" the yaw rate in * a deep stall is about 45 deg/sec, compared with about 20 deg/sec cited in the nasa paper. * this could be due to differences between the nasa data and the data used in the fm. For * convenience, the fm data was taken from the "non-linear f-16 simulation using simulink * and matlab" package in predigitized form. This data should be identical to the nasa data, * but in practice there are small variations. */ cn_dr *= clampTo((toDegrees(m_Alpha) - 40) * 0.8, 1.0, 20.0); cn_dr = -fabs(cn_dr); /** * note that these offsets are in internal body coordinates, not fm coordinates. */ double offset_y = m_CenterOfMassBody.y() - m_CL_x_m[0.0]; /** @todo should this vary with mach? */ double offset_x = m_CenterOfMassBody.x(); double moment = m_Cn_de_a_b[m_Elevator][m_Alpha][m_Beta] + m_Cn_lef_a_b[m_Alpha][m_Beta] * m_ScaleLEF + (cn_p + cn_r) * m_WingSpan * m_Inv2V + cn_da * m_Aileron + cn_dr * m_Rudder + (offset_x * m_CX - offset_y * m_CY) / m_WingSpan; /** * negative since yaw axis (and hence yaw moment) is opposite nasa 1979. */ return -moment * m_qBarS * m_WingSpan; }
double StepsTimingFunction::evaluate(double fraction, double) const { double startOffset = 0; switch (m_stepAtPosition) { case Start: startOffset = 1; break; case Middle: startOffset = 0.5; break; case End: startOffset = 0; break; default: ASSERT_NOT_REACHED(); break; } return clampTo(floor((m_steps * fraction) + startOffset) / m_steps, 0.0, 1.0); }
int HRTFPanner::calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azimuthBlend) { // Convert the azimuth angle from the range -180 -> +180 into the range 0 -> // 360. The azimuth index may then be calculated from this positive value. if (azimuth < 0) azimuth += 360.0; int numberOfAzimuths = HRTFDatabase::numberOfAzimuths(); const double angleBetweenAzimuths = 360.0 / numberOfAzimuths; // Calculate the azimuth index and the blend (0 -> 1) for interpolation. double desiredAzimuthIndexFloat = azimuth / angleBetweenAzimuths; int desiredAzimuthIndex = static_cast<int>(desiredAzimuthIndexFloat); azimuthBlend = desiredAzimuthIndexFloat - static_cast<double>(desiredAzimuthIndex); // We don't immediately start using this azimuth index, but instead approach // this index from the last index we rendered at. This minimizes the clicks // and graininess for moving sources which occur otherwise. desiredAzimuthIndex = clampTo(desiredAzimuthIndex, 0, numberOfAzimuths - 1); return desiredAzimuthIndex; }
void FilterEffectRenderer::build(Document* document, const FilterOperations& operations) { #if !ENABLE(CSS_SHADERS) || !ENABLE(WEBGL) UNUSED_PARAM(document); #else CustomFilterProgramList cachedCustomFilterPrograms; #endif m_effects.clear(); RefPtr<FilterEffect> previousEffect; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::REFERENCE: { // FIXME: Not yet implemented. // https://bugs.webkit.org/show_bug.cgi?id=72443 break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = 1; transferFunction.intercept = narrowPrecisionToFloat(componentTransferOperation->amount()); ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0); effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(), dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1); break; } #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: { #if ENABLE(WEBGL) if (!isCSSCustomFilterEnabled(document)) continue; CustomFilterOperation* customFilterOperation = static_cast<CustomFilterOperation*>(filterOperation); RefPtr<CustomFilterProgram> program = customFilterOperation->program(); cachedCustomFilterPrograms.append(program); program->addClient(this); if (program->isLoaded()) { effect = FECustomFilter::create(this, document, program, customFilterOperation->parameters(), customFilterOperation->meshRows(), customFilterOperation->meshColumns(), customFilterOperation->meshBoxType(), customFilterOperation->meshType()); } #endif break; } #endif default: break; } if (effect) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); if (previousEffect) effect->inputEffects().append(previousEffect); m_effects.append(effect); previousEffect = effect.release(); } } // If we didn't make a real filter, create a null-op (FEMerge with one input). if (!previousEffect) m_effects.append(FEMerge::create(this)); m_effects.first()->inputEffects().append(m_sourceGraphic); setMaxEffectRects(m_sourceDrawingRegion); #if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) removeCustomFilterClients(); m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms); #endif }
bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& operations) { m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); // Inverse zoom the pre-zoomed CSS shorthand filters, so that they are in the same zoom as the unzoomed reference filters. const RenderStyle* style = renderer->style(); float invZoom = style ? 1.0f / style->effectiveZoom() : 1.0f; RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->type()) { case FilterOperation::REFERENCE: { effect = ReferenceFilterBuilder::build(this, renderer, previousEffect.get(), toReferenceFilterOperation(filterOperation)); break; } case FilterOperation::GRAYSCALE: { Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperation(filterOperation)->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperation(filterOperation)->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilterOperation(filterOperation)->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilterOperation(filterOperation)->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = toBasicComponentTransferFilterOperation(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(toBasicComponentTransferFilterOperation(filterOperation)->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = narrowPrecisionToFloat(toBasicComponentTransferFilterOperation(filterOperation)->amount()); transferFunction.intercept = 0; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(toBasicComponentTransferFilterOperation(filterOperation)->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { float stdDeviation = floatValueForLength(toBlurFilterOperation(filterOperation)->stdDeviation(), 0) * invZoom; effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterOperation(filterOperation); float stdDeviation = dropShadowOperation->stdDeviation() * invZoom; float x = dropShadowOperation->x() * invZoom; float y = dropShadowOperation->y() * invZoom; effect = FEDropShadow::create(this, stdDeviation, stdDeviation, x, y, dropShadowOperation->color(), 1); break; } default: break; } if (effect) { if (filterOperation->type() != FilterOperation::REFERENCE) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); effect->setOperatingColorSpace(ColorSpaceDeviceRGB); effect->inputEffects().append(previousEffect); } previousEffect = effect.release(); } } // We need to keep the old effects alive until this point, so that SVG reference filters // can share cached resources across frames. m_lastEffect = previousEffect; // If we didn't make any effects, tell our caller we are not valid if (!m_lastEffect.get()) return false; return true; }
bool FilterEffectRenderer::build(Document* document, const FilterOperations& operations) { #if !ENABLE(CSS_SHADERS) || !USE(3D_GRAPHICS) UNUSED_PARAM(document); #endif #if ENABLE(CSS_SHADERS) m_hasCustomShaderFilter = false; #endif m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); if (m_hasFilterThatMovesPixels) operations.getOutsets(m_topOutset, m_rightOutset, m_bottomOutset, m_leftOutset); // Keep the old effects on the stack until we've created the new effects. // New FECustomFilters can reuse cached resources from old FECustomFilters. FilterEffectList oldEffects; m_effects.swap(oldEffects); RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::REFERENCE: { ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation); effect = buildReferenceFilter(document, previousEffect, referenceOperation); referenceOperation->setFilterEffect(effect); break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = 1; transferFunction.intercept = narrowPrecisionToFloat(componentTransferOperation->amount()); ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0); effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(), dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1); break; } #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) case FilterOperation::CUSTOM: // CUSTOM operations are always converted to VALIDATED_CUSTOM before getting here. // The conversion happens in RenderLayer::computeFilterOperations. ASSERT_NOT_REACHED(); break; case FilterOperation::VALIDATED_CUSTOM: { ValidatedCustomFilterOperation* customFilterOperation = static_cast<ValidatedCustomFilterOperation*>(filterOperation); effect = createCustomFilterEffect(this, document, customFilterOperation); if (effect) m_hasCustomShaderFilter = true; break; } #endif default: break; } if (effect) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); effect->setColorSpace(ColorSpaceDeviceRGB); if (filterOperation->getOperationType() != FilterOperation::REFERENCE) { effect->inputEffects().append(previousEffect); m_effects.append(effect); } previousEffect = effect.release(); } } // If we didn't make any effects, tell our caller we are not valid if (!m_effects.size()) return false; setMaxEffectRects(m_sourceDrawingRegion); return true; }
float PageViewportController::innerBoundedViewportScale(float viewportScale) const { return clampTo(viewportScale, toViewportScale(m_minimumScaleToFit), toViewportScale(m_rawAttributes.maximumScale)); }
bool FilterEffectRenderer::build(RenderElement* renderer, const FilterOperations& operations, FilterConsumer consumer) { m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); if (m_hasFilterThatMovesPixels) m_outsets = operations.outsets(); m_effects.clear(); RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation& filterOperation = *operations.operations().at(i); switch (filterOperation.type()) { case FilterOperation::REFERENCE: { ReferenceFilterOperation& referenceOperation = downcast<ReferenceFilterOperation>(filterOperation); effect = buildReferenceFilter(renderer, previousEffect, &referenceOperation); referenceOperation.setFilterEffect(effect); break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation.amount())); effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation.amount())); effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation.amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation.amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation.amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(*this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation.amount()); transferFunction.intercept = 0; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation.amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation& blurOperation = downcast<BlurFilterOperation>(filterOperation); float stdDeviation = floatValueForLength(blurOperation.stdDeviation(), 0); effect = FEGaussianBlur::create(*this, stdDeviation, stdDeviation, consumer == FilterProperty ? EDGEMODE_NONE : EDGEMODE_DUPLICATE); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation& dropShadowOperation = downcast<DropShadowFilterOperation>(filterOperation); effect = FEDropShadow::create(*this, dropShadowOperation.stdDeviation(), dropShadowOperation.stdDeviation(), dropShadowOperation.x(), dropShadowOperation.y(), dropShadowOperation.color(), 1); break; } default: break; } if (effect) { // Unlike SVG Filters and CSSFilterImages, filter functions on the filter // property applied here should not clip to their primitive subregions. effect->setClipsToBounds(consumer == FilterFunction); effect->setOperatingColorSpace(ColorSpaceSRGB); if (filterOperation.type() != FilterOperation::REFERENCE) { effect->inputEffects().append(previousEffect); m_effects.append(effect); } previousEffect = effect.release(); } } // If we didn't make any effects, tell our caller we are not valid if (!m_effects.size()) return false; setMaxEffectRects(m_sourceDrawingRegion); return true; }