示例#1
0
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Insert :before and :after content before/after the RenderRubyRun(s)
    if (child->isBeforeContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderInline::addChild(child, firstChild());
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* beforeBlock = rubyBeforeBlock(this);
            if (!beforeBlock) {
                beforeBlock = createAnonymousRubyInlineBlock(*this);
                RenderInline::addChild(beforeBlock, firstChild());
            }
            beforeBlock->addChild(child);
        }
        return;
    }
    if (child->isAfterContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderInline::addChild(child);
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* afterBlock = rubyAfterBlock(this);
            if (!afterBlock) {
                afterBlock = createAnonymousRubyInlineBlock(*this);
                RenderInline::addChild(afterBlock);
            }
            afterBlock->addChild(child);
        }
        return;
    }

    // If the child is a ruby run, just add it normally.
    if (child->isRubyRun()) {
        RenderInline::addChild(child, beforeChild);
        return;
    }

    if (beforeChild && !isAfterContent(beforeChild)) {
        // insert child into run
        ASSERT(!beforeChild->isRubyRun());
        RenderElement* run = beforeChild->parent();
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
        // Emergency fallback: fall through and just append.
    }

    // If the new child would be appended, try to add the child to the previous run
    // if possible, or create a new run otherwise.
    // (The RenderRubyRun object will handle the details)
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderInline::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, GraphicsContext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*)
{
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    FilterData* filterData = m_filter.get(&renderer);
    if (!filterData)
        return;

    switch (filterData->state) {
    case FilterData::MarkedForRemoval:
        m_filter.remove(&renderer);
        return;

    case FilterData::CycleDetected:
    case FilterData::Applying:
        // We have a cycle if we are already applying the data.
        // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
        // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
        // will continue correctly.
        filterData->state = FilterData::PaintingSource;
        return;

    case FilterData::PaintingSource:
        if (!filterData->savedContext) {
            removeClientFromCache(renderer);
            return;
        }

        context = filterData->savedContext;
        filterData->savedContext = 0;
        break;

    case FilterData::Built: { } // Empty
    }

    FilterEffect* lastEffect = filterData->builder->lastEffect();

    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
        // This is the real filtering of the object. It just needs to be called on the
        // initial filtering process. We just take the stored filter result on a
        // second drawing.
        if (filterData->state != FilterData::Built)
            filterData->filter->setSourceImage(WTF::move(filterData->sourceGraphicBuffer));

        // Always true if filterData is just built (filterData->state == FilterData::Built).
        if (!lastEffect->hasResult()) {
            filterData->state = FilterData::Applying;
            lastEffect->applyAll();
            lastEffect->correctFilterResultIfNeeded();
            lastEffect->transformResultColorSpace(ColorSpaceDeviceRGB);
        }
        filterData->state = FilterData::Built;

        ImageBuffer* resultImage = lastEffect->asImageBuffer();
        if (resultImage) {
            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());

            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
            context->drawImageBuffer(*resultImage, renderer.style().colorSpace(), lastEffect->absolutePaintRect());
            context->scale(filterData->filter->filterResolution());

            context->concatCTM(filterData->shearFreeAbsoluteTransform);
        }
    }
    filterData->sourceGraphicBuffer.reset();
}
bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    if (m_filter.contains(&renderer)) {
        FilterData* filterData = m_filter.get(&renderer);
        if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
            filterData->state = FilterData::CycleDetected;
        return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
    }

    auto filterData = std::make_unique<FilterData>();
    FloatRect targetBoundingBox = renderer.objectBoundingBox();

    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(&filterElement(), filterElement().filterUnits(), targetBoundingBox);
    if (filterData->boundaries.isEmpty())
        return false;

    // Determine absolute transformation matrix for filter. 
    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
    if (!absoluteTransform.isInvertible())
        return false;

    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);

    // Determine absolute boundaries of the filter and the drawing region.
    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
    filterData->drawingRegion = renderer.strokeBoundingBox();
    filterData->drawingRegion.intersect(filterData->boundaries);
    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion);

    // Create the SVGFilter object.
    bool primitiveBoundingBoxMode = filterElement().primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);

    // Create all relevant filter primitives.
    filterData->builder = buildPrimitives(*filterData->filter);
    if (!filterData->builder)
        return false;

    // Calculate the scale factor for the use of filterRes.
    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
    FloatSize scale(1, 1);
    if (filterElement().hasAttribute(SVGNames::filterResAttr)) {
        scale.setWidth(filterElement().filterResX() / absoluteFilterBoundaries.width());
        scale.setHeight(filterElement().filterResY() / absoluteFilterBoundaries.height());
    }

    if (scale.isEmpty())
        return false;

    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
    FloatRect tempSourceRect = absoluteDrawingRegion;
    ImageBuffer::sizeNeedsClamping(tempSourceRect.size(), scale);
    tempSourceRect.scale(scale.width(), scale.height());

    // Set the scale level in SVGFilter.
    filterData->filter->setFilterResolution(scale);

    static const unsigned maxTotalOfEffectInputs = 100;
    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect || lastEffect->totalNumberOfEffectInputs() > maxTotalOfEffectInputs)
        return false;

    RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
    FloatRect subRegion = lastEffect->maxEffectRect();
    // At least one FilterEffect has a too big image size,
    // recalculate the effect sizes with new scale factors.
    if (ImageBuffer::sizeNeedsClamping(subRegion.size(), scale)) {
        filterData->filter->setFilterResolution(scale);
        RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
    }

    // If the drawingRegion is empty, we have something like <g filter=".."/>.
    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
    if (filterData->drawingRegion.isEmpty()) {
        ASSERT(!m_filter.contains(&renderer));
        filterData->savedContext = context;
        m_filter.set(&renderer, WTF::move(filterData));
        return false;
    }

    // Change the coordinate transformation applied to the filtered element to reflect the resolution of the filter.
    AffineTransform effectiveTransform;
    effectiveTransform.scale(scale.width(), scale.height());
    effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);

    RenderingMode renderingMode = renderer.frame().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;

    auto sourceGraphic = SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, ColorSpaceLinearRGB, renderingMode);
    if (!sourceGraphic) {
        ASSERT(!m_filter.contains(&renderer));
        filterData->savedContext = context;
        m_filter.set(&renderer, WTF::move(filterData));
        return false;
    }
    
    // Set the rendering mode from the page's settings.
    filterData->filter->setRenderingMode(renderingMode);

    GraphicsContext& sourceGraphicContext = sourceGraphic->context();
  
    filterData->sourceGraphicBuffer = WTF::move(sourceGraphic);
    filterData->savedContext = context;

    context = &sourceGraphicContext;

    ASSERT(!m_filter.contains(&renderer));
    m_filter.set(&renderer, WTF::move(filterData));

    return true;
}
示例#4
0
void RendererOpenGL::RenderPrimitives( const RenderElement& _Primitives )
#endif
{
    PROFILING( "Render Primitives" );

#ifdef MULTIPLE_RENDER_ELEMENTS  
    RenderElementPrimitives::Type eType = _spPrimitives->GetType();
    const CFoundation::Color& color = _spPrimitives->GetColor();
    Float16 f16Thickness = _spPrimitives->GetThickness();
    const RenderElementPrimitives::PointVec& avPoints = _spPrimitives->GetPoints();
#else
    RenderElement::Type eType = _Primitives.GetType();
    const CFoundation::Color& color = _Primitives.GetColor();
    Float16 f16Thickness = _Primitives.GetThickness();
    const RenderElement::PointVec& avPoints = _Primitives.GetPoints();
#endif

    // Get opengl type
    Unsigned32 u32Type = 0;
    switch ( eType )
    {
#ifdef MULTIPLE_RENDER_ELEMENTS 
    case RenderElementPrimitives::TYPE_POINTS:
#else
    case RenderElement::TYPE_POINTS:
#endif
        {
            u32Type = GL_POINTS;
        }
        break;
#ifdef MULTIPLE_RENDER_ELEMENTS 
    case RenderElementPrimitives::TYPE_LINES:
#else
    case RenderElement::TYPE_LINES:
#endif
        {
            u32Type = GL_LINES;
        }
        break;
#ifdef MULTIPLE_RENDER_ELEMENTS 
    case RenderElementPrimitives::TYPE_TRIANGLES:
#else
    case RenderElement::TYPE_TRIANGLES:
#endif
        {
            u32Type = GL_TRIANGLES;
        }
        break;
#ifdef MULTIPLE_RENDER_ELEMENTS 
    case RenderElementPrimitives::TYPE_QUADS:
#else
    case RenderElement::TYPE_QUADS:
#endif
        {
            u32Type = GL_QUADS;
        }
        break;
    }

    // Set color
    Float16 f16R, f16G, f16B, f16A;
    color.ToRGBA( f16R, f16G, f16B, f16A );
    glColor4f( f16R, f16G, f16B, f16A );

    // Set line thickness
    glLineWidth( f16Thickness );

    // Render primitives
    glLoadIdentity();
    glDisable( GL_TEXTURE_2D );

	glBegin( u32Type );

    Unsigned32 u32NumPoints = avPoints.size();
    for ( Unsigned32 u32Idx = 0; u32Idx < u32NumPoints; ++u32Idx )
    {
        const CFoundation::Vector2Df& vPoint = avPoints[ u32Idx ];
        glVertex3d( vPoint.GetX(),  vPoint.GetY(), 0 );
    }

	glEnd();
}
示例#5
0
void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, int& ascent, int& descent,
                                           bool& affectsAscent, bool& affectsDescent) const
{
    bool ascentDescentSet = false;

    // Replaced boxes will return 0 for the line-height if line-box-contain says they are
    // not to be included.
    if (box->renderer().isReplaced()) {
        if (lineStyle().lineBoxContain() & LineBoxContainReplaced) {
            ascent = box->baselinePosition(baselineType());
            descent = box->lineHeight() - ascent;
            
            // Replaced elements always affect both the ascent and descent.
            affectsAscent = true;
            affectsDescent = true;
        }
        return;
    }

    Vector<const SimpleFontData*>* usedFonts = 0;
    GlyphOverflow* glyphOverflow = 0;
    if (box->isInlineTextBox()) {
        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(toInlineTextBox(box));
        usedFonts = it == textBoxDataMap.end() ? 0 : &it->value.first;
        glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
    }
        
    bool includeLeading = includeLeadingForBox(box);
    bool includeFont = includeFontForBox(box);
    
    bool setUsedFont = false;
    bool setUsedFontWithLeading = false;

    const RenderStyle& boxLineStyle = box->lineStyle();
#if PLATFORM(IOS)
    if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading)) && !box->renderer().document().settings()->alwaysUseBaselineOfPrimaryFont()) {
#else
    if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading))) {
#endif
        usedFonts->append(boxLineStyle.font().primaryFont());
        for (size_t i = 0; i < usedFonts->size(); ++i) {
            const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics();
            int usedFontAscent = fontMetrics.ascent(baselineType());
            int usedFontDescent = fontMetrics.descent(baselineType());
            int halfLeading = (fontMetrics.lineSpacing() - fontMetrics.height()) / 2;
            int usedFontAscentAndLeading = usedFontAscent + halfLeading;
            int usedFontDescentAndLeading = fontMetrics.lineSpacing() - usedFontAscentAndLeading;
            if (includeFont) {
                setAscentAndDescent(ascent, descent, usedFontAscent, usedFontDescent, ascentDescentSet);
                setUsedFont = true;
            }
            if (includeLeading) {
                setAscentAndDescent(ascent, descent, usedFontAscentAndLeading, usedFontDescentAndLeading, ascentDescentSet);
                setUsedFontWithLeading = true;
            }
            if (!affectsAscent)
                affectsAscent = usedFontAscent - box->logicalTop() > 0;
            if (!affectsDescent)
                affectsDescent = usedFontDescent + box->logicalTop() > 0;
        }
    }

    // If leading is included for the box, then we compute that box.
    if (includeLeading && !setUsedFontWithLeading) {
        int ascentWithLeading = box->baselinePosition(baselineType());
        int descentWithLeading = box->lineHeight() - ascentWithLeading;
        setAscentAndDescent(ascent, descent, ascentWithLeading, descentWithLeading, ascentDescentSet);
        
        // Examine the font box for inline flows and text boxes to see if any part of it is above the baseline.
        // If the top of our font box relative to the root box baseline is above the root box baseline, then
        // we are contributing to the maxAscent value. Descent is similar. If any part of our font box is below
        // the root box's baseline, then we contribute to the maxDescent value.
        affectsAscent = ascentWithLeading - box->logicalTop() > 0;
        affectsDescent = descentWithLeading + box->logicalTop() > 0; 
    }
    
    if (includeFontForBox(box) && !setUsedFont) {
        int fontAscent = boxLineStyle.fontMetrics().ascent(baselineType());
        int fontDescent = boxLineStyle.fontMetrics().descent(baselineType());
        setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
        affectsAscent = fontAscent - box->logicalTop() > 0;
        affectsDescent = fontDescent + box->logicalTop() > 0; 
    }

    if (includeGlyphsForBox(box) && glyphOverflow && glyphOverflow->computeBounds) {
        setAscentAndDescent(ascent, descent, glyphOverflow->top, glyphOverflow->bottom, ascentDescentSet);
        affectsAscent = glyphOverflow->top - box->logicalTop() > 0;
        affectsDescent = glyphOverflow->bottom + box->logicalTop() > 0; 
        glyphOverflow->top = std::min(glyphOverflow->top, std::max(0, glyphOverflow->top - boxLineStyle.fontMetrics().ascent(baselineType())));
        glyphOverflow->bottom = std::min(glyphOverflow->bottom, std::max(0, glyphOverflow->bottom - boxLineStyle.fontMetrics().descent(baselineType())));
    }

    if (includeMarginForBox(box)) {
        LayoutUnit ascentWithMargin = boxLineStyle.fontMetrics().ascent(baselineType());
        LayoutUnit descentWithMargin = boxLineStyle.fontMetrics().descent(baselineType());
        if (box->parent() && !box->renderer().isTextOrLineBreak()) {
            ascentWithMargin += box->boxModelObject()->borderAndPaddingBefore() + box->boxModelObject()->marginBefore();
            descentWithMargin += box->boxModelObject()->borderAndPaddingAfter() + box->boxModelObject()->marginAfter();
        }
        setAscentAndDescent(ascent, descent, ascentWithMargin, descentWithMargin, ascentDescentSet);
        
        // Treat like a replaced element, since we're using the margin box.
        affectsAscent = true;
        affectsDescent = true;
    }
}

LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositionCache& verticalPositionCache)
{
    if (box->renderer().isTextOrLineBreak())
        return box->parent()->logicalTop();
    
    RenderBoxModelObject* renderer = box->boxModelObject();
    ASSERT(renderer->isInline());
    if (!renderer->isInline())
        return 0;

    // This method determines the vertical position for inline elements.
    bool firstLine = isFirstLine();
    if (firstLine && !renderer->document().styleSheetCollection().usesFirstLineRules())
        firstLine = false;

    // Check the cache.
    bool isRenderInline = renderer->isRenderInline();
    if (isRenderInline && !firstLine) {
        LayoutUnit verticalPosition = verticalPositionCache.get(renderer, baselineType());
        if (verticalPosition != PositionUndefined)
            return verticalPosition;
    }

    LayoutUnit verticalPosition = 0;
    EVerticalAlign verticalAlign = renderer->style().verticalAlign();
    if (verticalAlign == TOP || verticalAlign == BOTTOM)
        return 0;
   
    RenderElement* parent = renderer->parent();
    if (parent->isRenderInline() && parent->style().verticalAlign() != TOP && parent->style().verticalAlign() != BOTTOM)
        verticalPosition = box->parent()->logicalTop();
    
    if (verticalAlign != BASELINE) {
        const RenderStyle& parentLineStyle = firstLine ? parent->firstLineStyle() : parent->style();
        const Font& font = parentLineStyle.font();
        const FontMetrics& fontMetrics = font.fontMetrics();
        int fontSize = font.pixelSize();

        LineDirectionMode lineDirection = parent->isHorizontalWritingMode() ? HorizontalLine : VerticalLine;

        if (verticalAlign == SUB)
            verticalPosition += fontSize / 5 + 1;
        else if (verticalAlign == SUPER)
            verticalPosition -= fontSize / 3 + 1;
        else if (verticalAlign == TEXT_TOP)
            verticalPosition += renderer->baselinePosition(baselineType(), firstLine, lineDirection) - fontMetrics.ascent(baselineType());
        else if (verticalAlign == MIDDLE)
            verticalPosition = (verticalPosition - LayoutUnit(fontMetrics.xHeight() / 2) - renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection)).round();
        else if (verticalAlign == TEXT_BOTTOM) {
            verticalPosition += fontMetrics.descent(baselineType());
            // lineHeight - baselinePosition is always 0 for replaced elements (except inline blocks), so don't bother wasting time in that case.
            if (!renderer->isReplaced() || renderer->isInlineBlockOrInlineTable())
                verticalPosition -= (renderer->lineHeight(firstLine, lineDirection) - renderer->baselinePosition(baselineType(), firstLine, lineDirection));
        } else if (verticalAlign == BASELINE_MIDDLE)
            verticalPosition += -renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection);
        else if (verticalAlign == LENGTH) {
            LayoutUnit lineHeight;
            //Per http://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align: 'Percentages: refer to the 'line-height' of the element itself'.
            if (renderer->style().verticalAlignLength().isPercent())
                lineHeight = renderer->style().computedLineHeight();
            else
                lineHeight = renderer->lineHeight(firstLine, lineDirection);
            verticalPosition -= valueForLength(renderer->style().verticalAlignLength(), lineHeight);
        }
    }

    // Store the cached value.
    if (isRenderInline && !firstLine)
        verticalPositionCache.set(renderer, baselineType(), verticalPosition);

    return verticalPosition;
}

bool RootInlineBox::includeLeadingForBox(InlineBox* box) const
{
    if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText()))
        return false;

    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    return (lineBoxContain & LineBoxContainInline) || (box == this && (lineBoxContain & LineBoxContainBlock));
}

bool RootInlineBox::includeFontForBox(InlineBox* box) const
{
    if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText()))
        return false;
    
    if (!box->behavesLikeText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
        return false;

    // For now map "glyphs" to "font" in vertical text mode until the bounds returned by glyphs aren't garbage.
    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    return (lineBoxContain & LineBoxContainFont) || (!isHorizontal() && (lineBoxContain & LineBoxContainGlyphs));
}

bool RootInlineBox::includeGlyphsForBox(InlineBox* box) const
{
    if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText()))
        return false;
    
    if (!box->behavesLikeText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
        return false;

    // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
}

bool RootInlineBox::includeMarginForBox(InlineBox* box) const
{
    if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText()))
        return false;

    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    return lineBoxContain & LineBoxContainInlineBox;
}


bool RootInlineBox::fitsToGlyphs() const
{
    // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
}
示例#6
0
void SVGRenderSupport::styleChanged(RenderElement& renderer)
{
    auto parent = renderer.parent();
    SVGRenderSupport::setRendererHasSVGShadow(renderer, (parent && SVGRenderSupport::rendererHasSVGShadow(*parent)) || renderer.style().svgStyle().shadow());
}
示例#7
0
void RendererOpenGL::RenderTexturedRect( const RenderElement& _TexturedRect )
#endif
{
    PROFILING( "Render Texture" );
    
    // Get settings
#ifdef MULTIPLE_RENDER_ELEMENTS
    const CFoundation::Vector2Di& vPosition = _spTexturedRect->GetPosition();
    const Texture& mask = _spTexturedRect->GetMask();
    const Texture& texture = _spTexturedRect->GetTexture();
    const CFoundation::RectF16& rectTexture = _spTexturedRect->GetRelativeTextureRect();
    const CFoundation::Vector2Du& vSize = _spTexturedRect->GetSize();
    bool bBgVisible = _spTexturedRect->IsBgVisible();
    const CFoundation::Color& bgColor = _spTexturedRect->GetBgColor();
    Float16 f16Angle = _spTexturedRect->GetAngle();
#else
    const CFoundation::Vector2Di& vPosition = _TexturedRect.GetPosition();
    const Texture& mask = _TexturedRect.GetMask();
    const Texture& texture = _TexturedRect.GetTexture();
    const CFoundation::RectF16& rectTexture = _TexturedRect.GetRelativeTextureRect();
    const CFoundation::Vector2Du& vSize = _TexturedRect.GetSize();
    bool bBgVisible = _TexturedRect.IsBgVisible();
    const CFoundation::Color& bgColor = _TexturedRect.GetBgColor();
    Float16 f16Angle = _TexturedRect.GetAngle();
#endif

    // Compute size
    Float16 f16HalfWidth = vSize.GetX() * 0.5f;
    Float16 f16HalfHeight = vSize.GetY() * 0.5f;
    Unsigned32 u32Width = vSize.GetX();
	Unsigned32 u32Height = vSize.GetY();

    // Render mask
    if ( mask.IsValid() )
    {
        // Enable stencil buffer
	    glClear( GL_STENCIL_BUFFER_BIT );
	    glEnable( GL_STENCIL_TEST );
	    glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); 
	    glStencilFunc( GL_ALWAYS, 1, 1 );

        // Enable mask
	    glEnable( GL_TEXTURE_2D );
	    glBindTexture( GL_TEXTURE_2D, mask.GetID() );

        // Draw only non-transparent pixels into the stencil buffer
	    glEnable( GL_ALPHA_TEST );
	    glAlphaFunc( GL_GREATER, 0.01f );
        
        // Draw nothing on the screen
	    glColorMask( 0, 0, 0, 0 );

        // Move to right position
	    glLoadIdentity();
	    glTranslated( vPosition.GetX(), vPosition.GetY(), 0 );   

        // Draw mask into stencil buffer
	    glBegin( GL_QUADS );

		    glTexCoord2f( rectTexture.GetLeft(), rectTexture.GetBottom() );     glVertex3d( 0, 0, 0 );
		    glTexCoord2f( rectTexture.GetRight(), rectTexture.GetBottom() );    glVertex3d( u32Width, 0, 0 );
		    glTexCoord2f( rectTexture.GetRight(), rectTexture.GetTop() );       glVertex3d( u32Width, u32Height, 0 );
		    glTexCoord2f( rectTexture.GetLeft(), rectTexture.GetTop() );        glVertex3d( 0, u32Height, 0 );

	    glEnd();

        // Draw again on the screen
	    glColorMask( 1, 1, 1, 1 );

        // Setup stencil test for background/texture
	    glStencilFunc( GL_EQUAL, 1, 1 );
	    glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
    }

    // Render background
    if ( bBgVisible )
    {
        glLoadIdentity();
        glDisable( GL_TEXTURE_2D );
        Drawer::GetInstance().DrawSolidRect( CFoundation::RectI32( vPosition, vSize ), bgColor, f16Angle );
    }

    // Render texture	
	glLoadIdentity();
    glEnable( GL_TEXTURE_2D );
	glBindTexture( GL_TEXTURE_2D, texture.GetID() );

    // Set color
    Float16 f16R, f16G, f16B, f16A;
    bgColor.ToRGBA( f16R, f16G, f16B, f16A );
    glColor4f( f16R, f16G, f16B, f16A );
	
    // Translation
    //glTranslated( vPosition.GetX(), vPosition.GetY(), 0.0f );
    glTranslatef( vPosition.GetX() + f16HalfWidth, vPosition.GetY() + f16HalfHeight, 0.0f );

    // Rotate
    glRotatef( f16Angle, 0.0f, 0.0f, 1.0f );

    // Render texture
	glBegin( GL_QUADS );

		glTexCoord2f( rectTexture.GetLeft(), rectTexture.GetBottom() );     glVertex3f( -f16HalfWidth,  -f16HalfHeight, 0 );
		glTexCoord2f( rectTexture.GetRight(), rectTexture.GetBottom() );    glVertex3f(  f16HalfWidth,  -f16HalfHeight, 0 );
		glTexCoord2f( rectTexture.GetRight(), rectTexture.GetTop() );       glVertex3f(  f16HalfWidth,   f16HalfHeight, 0 );
		glTexCoord2f( rectTexture.GetLeft(), rectTexture.GetTop() );        glVertex3f( -f16HalfWidth,   f16HalfHeight, 0 );

	glEnd();
    
    if ( mask.IsValid() )
    {
	    glClear( GL_STENCIL_BUFFER_BIT );
	    glDisable( GL_STENCIL_TEST );	
    }
}
示例#8
0
void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout)
{
    bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
    bool transformChanged = transformToRootChanged(&start);
    bool hasSVGShadow = rendererHasSVGShadow(start);
    bool needsBoundariesUpdate = start.needsBoundariesUpdate();
    HashSet<RenderObject*> notlayoutedObjects;

    for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) {
        bool needsLayout = selfNeedsLayout;
        bool childEverHadLayout = child->everHadLayout();

        if (needsBoundariesUpdate && hasSVGShadow) {
            // If we have a shadow, our shadow is baked into our children's cached boundaries,
            // so they need to update.
            child->setNeedsBoundariesUpdate();
            needsLayout = true;
        }

        if (transformChanged) {
            // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
            if (child->isSVGText())
                toRenderSVGText(child)->setNeedsTextMetricsUpdate();
            needsLayout = true;
        }

        if (layoutSizeChanged) {
            // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
            if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
                if (element->hasRelativeLengths()) {
                    // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
                    if (child->isSVGShape())
                        toRenderSVGShape(child)->setNeedsShapeUpdate();
                    else if (child->isSVGText()) {
                        toRenderSVGText(child)->setNeedsTextMetricsUpdate();
                        toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
                    }

                    needsLayout = true;
                }
            }
        }

        if (needsLayout)
            child->setNeedsLayout(MarkOnlyThis);

        if (child->needsLayout()) {
            toRenderElement(child)->layout();
            // Renderers are responsible for repainting themselves when changing, except
            // for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds.
            // We could handle this in the individual objects, but for now it's easier to have
            // parent containers call repaint().  (RenderBlock::layout* has similar logic.)
            if (!childEverHadLayout)
                child->repaint();
        } else if (layoutSizeChanged)
            notlayoutedObjects.add(child);

        ASSERT(!child->needsLayout());
    }

    if (!layoutSizeChanged) {
        ASSERT(notlayoutedObjects.isEmpty());
        return;
    }

    // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
    HashSet<RenderObject*>::iterator end = notlayoutedObjects.end();
    for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it != end; ++it)
        invalidateResourcesOfChildren(*it);
}
示例#9
0
bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
{
    return renderer.isCSSAnimating() && m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, runningState);
}
示例#10
0
std::unique_ptr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderElement& renderer)
{
    if (!renderer.isCSSAnimating())
        return RenderStyle::clonePtr(renderer.style());
    return m_data->getAnimatedStyleForRenderer(renderer);
}
示例#11
0
static inline bool hasVisibleTextArea(RenderElement& textControl, TextControlInnerTextElement* innerText)
{
    return textControl.style()->visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height();
}
示例#12
0
bool TextAutoSizingValue::adjustNodeSizes()
{
    bool objectsRemoved = false;
    
    // Remove stale nodes.  Nodes may have had their renderers detached.  We'll
    // also need to remove the style from the documents m_textAutoSizedNodes
    // collection.  Return true indicates we need to do that removal.
    Vector<RefPtr<Node> > nodesForRemoval;
    HashSet<RefPtr<Node> >::iterator end = m_autoSizedNodes.end();
    for (HashSet<RefPtr<Node> >::iterator i = m_autoSizedNodes.begin(); i != end; ++i) {
        RefPtr<Node> autoSizingNode = *i;
        RenderText* text = static_cast<RenderText*>(autoSizingNode->renderer());
        if (!text || !text->style().textSizeAdjust().isAuto() || !text->candidateComputedTextSize()) {
            // remove node.
            nodesForRemoval.append(autoSizingNode);
            objectsRemoved = true;
        }
    }
    
    unsigned count = nodesForRemoval.size();
    for (unsigned i = 0; i < count; i++)
        m_autoSizedNodes.remove(nodesForRemoval[i]);
    
    // If we only have one piece of text with the style on the page don't
    // adjust it's size.
    if (m_autoSizedNodes.size() <= 1)
        return objectsRemoved;
    
    // Compute average size
    float cumulativeSize = 0;
    end = m_autoSizedNodes.end();
    for (HashSet<RefPtr<Node> >::iterator i = m_autoSizedNodes.begin(); i != end; ++i) {
        RefPtr<Node> autoSizingNode = *i;
        RenderText* renderText = static_cast<RenderText*>(autoSizingNode->renderer());
        cumulativeSize += renderText->candidateComputedTextSize();
    }
    
    float averageSize = roundf(cumulativeSize / m_autoSizedNodes.size());
    
    // Adjust sizes
    bool firstPass = true;
    end = m_autoSizedNodes.end();
    for (HashSet<RefPtr<Node> >::iterator i = m_autoSizedNodes.begin(); i != end; ++i) {
        const RefPtr<Node>& autoSizingNode = *i;
        RenderText* text = static_cast<RenderText*>(autoSizingNode->renderer());
        if (text && text->style().fontDescription().computedSize() != averageSize) {
            float specifiedSize = text->style().fontDescription().specifiedSize();
            float scaleChange = averageSize / specifiedSize;
            if (scaleChange > MAX_SCALE_INCREASE && firstPass) {
                firstPass = false;
                averageSize = roundf(specifiedSize * MAX_SCALE_INCREASE);
                scaleChange = averageSize / specifiedSize;
            }
            
            RefPtr<RenderStyle> style = cloneRenderStyleWithState(text->style());
            FontDescription fontDescription = style->fontDescription();
            fontDescription.setComputedSize(averageSize);
            style->setFontDescription(fontDescription);
            style->font().update(autoSizingNode->document().ensureStyleResolver().fontSelector());
            text->parent()->setStyle(style.releaseNonNull());
            
            RenderElement* parentRenderer = text->parent();
            if (parentRenderer->isAnonymousBlock())
                parentRenderer = parentRenderer->parent();
            
            // If we have a list we should resize ListMarkers separately.
            RenderObject* listMarkerRenderer = parentRenderer->firstChild();
            if (listMarkerRenderer->isListMarker()) {
                RefPtr<RenderStyle> style = cloneRenderStyleWithState(listMarkerRenderer->style());
                style->setFontDescription(fontDescription);
                style->font().update(autoSizingNode->document().ensureStyleResolver().fontSelector());
                toRenderListMarker(*listMarkerRenderer).setStyle(style.releaseNonNull());
            }
            
            // Resize the line height of the parent.
            const RenderStyle& parentStyle = parentRenderer->style();
            Length lineHeightLength = parentStyle.specifiedLineHeight();
            
            int specifiedLineHeight = 0;
            if (lineHeightLength.isPercent())
                specifiedLineHeight = minimumValueForLength(lineHeightLength, fontDescription.specifiedSize());
            else
                specifiedLineHeight = lineHeightLength.value();
            
            int lineHeight = specifiedLineHeight * scaleChange;
            if (!lineHeightLength.isFixed() || lineHeightLength.value() != lineHeight) {
                RefPtr<RenderStyle> newParentStyle = cloneRenderStyleWithState(parentStyle);
                newParentStyle->setLineHeight(Length(lineHeight, Fixed));
                newParentStyle->setSpecifiedLineHeight(lineHeightLength);
                newParentStyle->setFontDescription(fontDescription);
                newParentStyle->font().update(autoSizingNode->document().ensureStyleResolver().fontSelector());
                parentRenderer->setStyle(newParentStyle.releaseNonNull());
            }
        }
    }
    
    return objectsRemoved;
}