void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; #if ENABLE(CSS_SHAPES) // When floats with shape outside are stacked, the floats are positioned based on the margin box of the float, // not the shape's contour. Since we computed the width based on the shape contour when we added the float, // when we add a subsequent float on the same line, we need to undo the shape delta in order to position // based on the margin box. In order to do this, we need to walk back through the floating object list to find // the first previous float that is on the same side as our newFloat. ShapeOutsideInfo* previousShapeOutsideInfo = 0; const FloatingObjectSet& floatingObjectSet = m_block.m_floatingObjects->set(); auto it = floatingObjectSet.end(); auto begin = floatingObjectSet.begin(); LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); for (--it; it != begin; --it) { FloatingObject* previousFloat = it->get(); if (previousFloat != newFloat && previousFloat->type() == newFloat->type()) { previousShapeOutsideInfo = previousFloat->renderer().shapeOutsideInfo(); if (previousShapeOutsideInfo) previousShapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, previousFloat, m_block.logicalHeight(), lineHeight); break; } } ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer().shapeOutsideInfo(); if (shapeOutsideInfo) shapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, newFloat, m_block.logicalHeight(), lineHeight); #endif if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat); #if ENABLE(CSS_SHAPES) if (previousShapeOutsideInfo) newLeft -= previousShapeOutsideInfo->rightMarginBoxDelta(); if (shapeOutsideInfo) newLeft += shapeOutsideInfo->rightMarginBoxDelta(); #endif if (shouldIndentText() && m_block.style()->isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat); #if ENABLE(CSS_SHAPES) if (previousShapeOutsideInfo) newRight -= previousShapeOutsideInfo->leftMarginBoxDelta(); if (shapeOutsideInfo) newRight += shapeOutsideInfo->leftMarginBoxDelta(); #endif if (shouldIndentText() && !m_block.style()->isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
Spectrum MIPMap::getValue(Float u, Float v, Float dudx, Float dudy, Float dvdx, Float dvdy) const { if (m_filterType == ETrilinear) { ++mipmapLookups; /* Conservatively estimate a square lookup region */ Float width = 2.0f * std::max( std::max(std::abs(dudx), std::abs(dudy)), std::max(std::abs(dvdx), std::abs(dvdy))); Float mipmapLevel = m_levels - 1 + log2(std::max(width, (Float) 1e-8f)); if (mipmapLevel < 0) { /* The lookup is smaller than one pixel */ return triangle(0, u, v); } else if (mipmapLevel >= m_levels - 1) { /* The lookup is larger than the whole texture */ return getTexel(m_levels - 1, 0, 0); } else { /* Tri-linear interpolation */ int level = (int) mipmapLevel; Float delta = mipmapLevel - level; return triangle(level, u, v) * (1.0f - delta) + triangle(level, u, v) * delta; } } else if (m_filterType == EEWA) { if (dudx*dudx + dudy*dudy < dvdx*dvdx + dvdy*dvdy) { std::swap(dudx, dvdx); std::swap(dudy, dvdy); } Float majorLength = std::sqrt(dudx * dudx + dudy * dudy); Float minorLength = std::sqrt(dvdx * dvdx + dvdy * dvdy); if (minorLength * m_maxAnisotropy < majorLength && minorLength > 0.0f) { Float scale = majorLength / (minorLength * m_maxAnisotropy); dvdx *= scale; dvdy *= scale; minorLength *= scale; } if (minorLength == 0) return triangle(0, u, v); // The min() below avoids overflow in the int conversion when lod=inf Float lod = std::min(std::max((Float) 0, m_levels - 1 + log2(minorLength)), (Float) (m_levels-1)); int ilod = floorToInt(lod); Float d = lod - ilod; return EWA(u, v, dudx, dudy, dvdx, dvdy, ilod) * (1-d) + EWA(u, v, dudx, dudy, dvdx, dvdy, ilod+1) * d; } else { int xPos = floorToInt(u*m_levelWidth[0]), yPos = floorToInt(v*m_levelHeight[0]); return getTexel(0, xPos, yPos); } }
void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded( const FloatingObject& newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; ShapeOutsideDeltas shapeDeltas; if (ShapeOutsideInfo* shapeOutsideInfo = newFloat.layoutObject()->shapeOutsideInfo()) { LayoutUnit lineHeight = m_block.lineHeight( m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeDeltas = shapeOutsideInfo->computeDeltasForContainingBlockLine( m_block, newFloat, m_block.logicalHeight(), lineHeight); } if (newFloat.getType() == FloatingObject::FloatLeft) { LayoutUnit newLeft = m_block.logicalRightForFloat(newFloat); if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) { newLeft += shapeDeltas.rightMarginBoxDelta(); } else { // Per the CSS Shapes spec, If the line doesn't overlap the shape, then // ignore this shape for this line. newLeft = m_left; } } if (indentText() == IndentText && m_block.style()->isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); m_left = std::max(m_left, newLeft); } else { LayoutUnit newRight = m_block.logicalLeftForFloat(newFloat); if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) { newRight += shapeDeltas.leftMarginBoxDelta(); } else { // Per the CSS Shapes spec, If the line doesn't overlap the shape, then // ignore this shape for this line. newRight = m_right; } } if (indentText() == IndentText && !m_block.style()->isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); m_right = std::min(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
inline Spectrum getValue(const Point2 &uv) const { Float x = uv.x - floorToInt(uv.x); Float y = uv.y - floorToInt(uv.y); if (x > .5) x -= 1; if (y > .5) y -= 1; if (std::abs(x) < m_lineWidth || std::abs(y) < m_lineWidth) return m_color1; else return m_color0; }
Spectrum MIPMap::triangle(int level, Float x, Float y) const { if (m_filterType == ENone) { int xPos = floorToInt(x*m_levelWidth[0]), yPos = floorToInt(y*m_levelHeight[0]); return getTexel(0, xPos, yPos); } else { level = clamp(level, 0, m_levels - 1); x = x * m_levelWidth[level] - 0.5f; y = y * m_levelHeight[level] - 0.5f; int xPos = floorToInt(x), yPos = floorToInt(y); Float dx = x - xPos, dy = y - yPos; return getTexel(level, xPos, yPos) * (1.0f - dx) * (1.0f - dy) + getTexel(level, xPos, yPos + 1) * (1.0f - dx) * dy + getTexel(level, xPos + 1, yPos) * dx * (1.0f - dy) + getTexel(level, xPos + 1, yPos + 1) * dx * dy; } }
void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; #if ENABLE(CSS_SHAPES) ShapeOutsideDeltas shapeDeltas; if (ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer().shapeOutsideInfo()) { LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeDeltas = shapeOutsideInfo->computeDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight); } #endif if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat); if (shouldIndentText() && m_block.style().isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); #if ENABLE(CSS_SHAPES) if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) newLeft += shapeDeltas.rightMarginBoxDelta(); else // If the line doesn't overlap the shape, then we need to act as if this float didn't exist. newLeft = m_left; } #endif m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat); if (shouldIndentText() && !m_block.style().isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); #if ENABLE(CSS_SHAPES) if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) newRight += shapeDeltas.leftMarginBoxDelta(); else // If the line doesn't overlap the shape, then we need to act as if this float didn't exist. newRight = m_right; } #endif m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo(); if (shapeOutsideInfo) { LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeOutsideInfo->updateDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight); } if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat).toFloat(); if (shapeOutsideInfo) { if (shapeOutsideInfo->lineOverlapsShape()) newLeft += shapeOutsideInfo->rightMarginBoxDelta(); else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. newLeft = m_left; } if (shouldIndentText() && m_block.style()->isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat).toFloat(); if (shapeOutsideInfo) { if (shapeOutsideInfo->lineOverlapsShape()) newRight += shapeOutsideInfo->leftMarginBoxDelta(); else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. newRight = m_right; } if (shouldIndentText() && !m_block.style()->isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
Float Noise::perlinNoise(const Point &p) { // Compute noise cell coordinates and offsets int ix = floorToInt(p.x), iy = floorToInt(p.y), iz = floorToInt(p.z); Float dx = p.x - ix, dy = p.y - iy, dz = p.z - iz; // Compute gradient weights ix &= (NOISE_PERM_SIZE-1); iy &= (NOISE_PERM_SIZE-1); iz &= (NOISE_PERM_SIZE-1); Float w000 = grad(ix, iy, iz, dx, dy, dz); Float w100 = grad(ix+1, iy, iz, dx-1, dy, dz); Float w010 = grad(ix, iy+1, iz, dx, dy-1, dz); Float w110 = grad(ix+1, iy+1, iz, dx-1, dy-1, dz); Float w001 = grad(ix, iy, iz+1, dx, dy, dz-1); Float w101 = grad(ix+1, iy, iz+1, dx-1, dy, dz-1); Float w011 = grad(ix, iy+1, iz+1, dx, dy-1, dz-1); Float w111 = grad(ix+1, iy+1, iz+1, dx-1, dy-1, dz-1); // Compute trilinear interpolation of weights Float wx = noiseWeight(dx), wy = noiseWeight(dy), wz = noiseWeight(dz); Float x00 = lerp(wx, w000, w100), x10 = lerp(wx, w010, w110), x01 = lerp(wx, w001, w101), x11 = lerp(wx, w011, w111), y0 = lerp(wy, x00, x10), y1 = lerp(wy, x01, x11); return lerp(wz, y0, y1); }
MIPMap::ResampleWeight *MIPMap::resampleWeights(int oldRes, int newRes) const { /* Resample using a Lanczos windowed sinc reconstruction filter */ Assert(newRes >= oldRes); Float filterWidth = 2.0f; ResampleWeight *weights = new ResampleWeight[newRes]; for (int i=0; i<newRes; i++) { Float center = (i + .5f) * oldRes / newRes; weights[i].firstTexel = floorToInt(center - filterWidth + (Float) 0.5f); Float weightSum = 0; for (int j=0; j<4; j++) { Float pos = weights[i].firstTexel + j + .5f; Float weight = lanczosSinc((pos - center) / filterWidth); weightSum += weight; weights[i].weight[j] = weight; } /* Normalize */ Float invWeights = 1.0f / weightSum; for (int j=0; j<4; j++) weights[i].weight[j] *= invWeights; } return weights; }