Example #1
0
void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
{
    const Font& font = style->font();
    const ShadowData* shadow = style->textShadow();

    FloatPoint textOrigin(fragment.x, fragment.y);
    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - font.fontMetrics().ascent()), FloatSize(fragment.width, fragment.height));

    do {
        if (!prepareGraphicsContextForTextPainting(context, textRun, style))
            break;

        FloatSize extraOffset;
        if (shadow)
            extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */);

        font.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);
        restoreGraphicsContextAfterTextPainting(context, textRun);

        if (!shadow)
            break;

        if (shadow->next())
            context->restore();
        else
            context->clearShadow();

        shadow = shadow->next();
    } while (shadow);
}
void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
{
    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
    ASSERT(textRenderer);

    float scalingFactor = textRenderer->scalingFactor();
    ASSERT(scalingFactor);

    const Font& scaledFont = textRenderer->scaledFont();
    const ShadowData* shadow = style->textShadow();

    FloatPoint textOrigin(fragment.x, fragment.y);
    FloatSize textSize(fragment.width, fragment.height);

    if (scalingFactor != 1) {
        textOrigin.scale(scalingFactor, scalingFactor);
        textSize.scale(scalingFactor);
    }

    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);

    do {
        if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style))
            break;

        FloatSize extraOffset;
        if (shadow)
            extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */);

        AffineTransform originalTransform;
        if (scalingFactor != 1) {
            originalTransform = context->getCTM();

            AffineTransform newTransform = originalTransform;
            newTransform.scale(1 / scalingFactor);
            normalizeTransform(newTransform);

            context->setCTM(newTransform);
        }

        scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);

        if (scalingFactor != 1)
            context->setCTM(originalTransform);

        restoreGraphicsContextAfterTextPainting(context, textRun);

        if (!shadow)
            break;

        if (shadow->next())
            context->restore();
        else
            context->clearShadow();

        shadow = shadow->next();
    } while (shadow);
}
void OverscrollTheme::updateOverhangShadowLayer(GraphicsLayer* shadowLayer, GraphicsLayer* rootContentLayer)
{
    // Note that for the position, the division m_overhangShadow->width() / 2 is an intentional
    // round-down, and that for the width and height, the 1-pixel aperture is being replaced
    // by the root contents layer, hence subtracting 1 and adding the rootContentsLayer size.
    IntRect shadowRect(
        static_cast<int>(rootContentLayer->position().x()) - m_overhangShadow->width() / 2,
        static_cast<int>(rootContentLayer->position().y()) -  m_overhangShadow->height() / 2,
        static_cast<int>(rootContentLayer->size().width()) + m_overhangShadow->width() - 1,
        static_cast<int>(rootContentLayer->size().height()) + m_overhangShadow->height() - 1);
    shadowLayer->setContentsRect(shadowRect);
}
Example #4
0
void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
{
    float scalingFactor = renderer().scalingFactor();
    ASSERT(scalingFactor);

    const Font& scaledFont = renderer().scaledFont();
    const ShadowData* shadow = style->textShadow();

    FloatPoint textOrigin(fragment.x, fragment.y);
    FloatSize textSize(fragment.width, fragment.height);

    if (scalingFactor != 1) {
        textOrigin.scale(scalingFactor, scalingFactor);
        textSize.scale(scalingFactor);
    }

    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);

    do {
        if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style))
            break;

        FloatSize extraOffset;
        bool didSaveContext = false;
        if (shadow)
            extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */, didSaveContext);

        context->save();
        context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));

        scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);

        context->restore();

        if (shadow) {
            if (didSaveContext)
                context->restore();
            else
                context->clearShadow();
        }

        restoreGraphicsContextAfterTextPainting(context, textRun);

        if (!shadow)
            break;

        shadow = shadow->next();
    } while (shadow);
}
Example #5
0
void nsTextBoxFrame::PaintOneShadow(gfxContext*      aCtx,
                                    const nsRect&    aTextRect,
                                    nsCSSShadowItem* aShadowDetails,
                                    const nscolor&   aForegroundColor,
                                    const nsRect&    aDirtyRect) {
  nsPoint shadowOffset(aShadowDetails->mXOffset,
                       aShadowDetails->mYOffset);
  nscoord blurRadius = NS_MAX(aShadowDetails->mRadius, 0);

  nsRect shadowRect(aTextRect);
  shadowRect.MoveBy(shadowOffset);

  nsContextBoxBlur contextBoxBlur;
  gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
                                                  PresContext()->AppUnitsPerDevPixel(),
                                                  aCtx, aDirtyRect, nsnull);

  if (!shadowContext)
    return;

  nscolor shadowColor;
  if (aShadowDetails->mHasColor)
    shadowColor = aShadowDetails->mColor;
  else
    shadowColor = aForegroundColor;

  // Conjure an nsIRenderingContext from a gfxContext for DrawText
  nsCOMPtr<nsIRenderingContext> renderingContext = nsnull;
  nsIDeviceContext* devCtx = PresContext()->DeviceContext();
  devCtx->CreateRenderingContextInstance(*getter_AddRefs(renderingContext));
  if (!renderingContext)
    return;
  renderingContext->Init(devCtx, shadowContext);

  aCtx->Save();
  aCtx->NewPath();
  aCtx->SetColor(gfxRGBA(shadowColor));

  // Draw the text onto our alpha-only surface to capture the alpha values.
  // Remember that the box blur context has a device offset on it, so we don't need to
  // translate any coordinates to fit on the surface.
  DrawText(*renderingContext, shadowRect, &shadowColor);
  contextBoxBlur.DoPaint();
  aCtx->Restore();
}
Example #6
0
void SVGInlineTextBox::paintTextWithShadows(GraphicsContext& context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
{
    float scalingFactor = renderer().scalingFactor();
    ASSERT(scalingFactor);

    const FontCascade& scaledFont = renderer().scaledFont();
    const ShadowData* shadow = style->textShadow();

    FloatPoint textOrigin(fragment.x, fragment.y);
    FloatSize textSize(fragment.width, fragment.height);

    if (scalingFactor != 1) {
        textOrigin.scale(scalingFactor, scalingFactor);
        textSize.scale(scalingFactor);
    }

    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);

    GraphicsContext* usedContext = &context;
    do {
        if (!prepareGraphicsContextForTextPainting(usedContext, scalingFactor, textRun, style))
            break;

        {
            ShadowApplier shadowApplier(*usedContext, shadow, shadowRect);

            if (!shadowApplier.didSaveContext())
                usedContext->save();
            usedContext->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));

            scaledFont.drawText(*usedContext, textRun, textOrigin + shadowApplier.extraOffset(), startPosition, endPosition);

            if (!shadowApplier.didSaveContext())
                usedContext->restore();
        }

        restoreGraphicsContextAfterTextPainting(usedContext, textRun);

        if (!shadow)
            break;

        shadow = shadow->next();
    } while (shadow);
}
Example #7
0
static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked)
{
    do {
        IntSize extraOffset;

        if (shadow) {
            IntSize shadowOffset(shadow->x, shadow->y);
            int shadowBlur = shadow->blur;
            const Color& shadowColor = shadow->color;

            if (shadow->next || stroked) {
                IntRect shadowRect(x, y, w, h);
                shadowRect.inflate(shadowBlur);
                shadowRect.move(shadowOffset);
                context->save();
                context->clip(shadowRect);

                extraOffset = IntSize(0, 2 * h + max(0, shadowOffset.height()) + shadowBlur);
                shadowOffset -= extraOffset;
            }
            context->setShadow(shadowOffset, shadowBlur, shadowColor);
        }

        if (startOffset <= endOffset)
            context->drawText(textRun, textOrigin + extraOffset, startOffset, endOffset);
        else {
            if (endOffset > 0)
                context->drawText(textRun, textOrigin + extraOffset,  0, endOffset);
            if (startOffset < textRun.length())
                context->drawText(textRun, textOrigin + extraOffset, startOffset);
        }

        if (!shadow)
            break;

        if (shadow->next || stroked)
            context->restore();
        else
            context->clearShadow();

        shadow = shadow->next;
    } while (shadow || stroked);
}
Example #8
0
bool RenderThemeGtk::paintTextField(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect)
{
    GtkWidget* widget = gtkEntry();

    bool enabled = isEnabled(renderObject) && !isReadOnlyControl(renderObject);
    GtkStateType backgroundState = enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
    gtk_widget_set_sensitive(widget, enabled);
    gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style().direction()));
    setWidgetHasFocus(widget, isFocused(renderObject));

    WidgetRenderingContext widgetContext(info.context, rect);
    IntRect textFieldRect(IntPoint(), rect.size());

    // The entry background is only painted over the interior part of the GTK+ entry, not
    // the entire frame. This happens in the Mozilla theme drawing code as well.
    IntRect interiorRect(textFieldRect);
    GtkStyle* style = gtk_widget_get_style(widget);
    interiorRect.inflateX(-style->xthickness);
    interiorRect.inflateY(-style->ythickness);
    widgetContext.gtkPaintFlatBox(interiorRect, widget, backgroundState, GTK_SHADOW_NONE, "entry_bg");

    // This is responsible for drawing the actual frame.
    widgetContext.gtkPaintShadow(textFieldRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry");

    gboolean interiorFocus;
    gint focusWidth;
    gtk_widget_style_get(widget,
                         "interior-focus", &interiorFocus,
                         "focus-line-width", &focusWidth,  NULL);
    if (isFocused(renderObject) && !interiorFocus) {
        // When GTK+ paints a text entry with focus, it shrinks the size of the frame area by the
        // focus width and paints over the previously unfocused text entry. We need to emulate that
        // by drawing both the unfocused frame above and the focused frame here.
        IntRect shadowRect(textFieldRect);
        shadowRect.inflate(-focusWidth);
        widgetContext.gtkPaintShadow(shadowRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry");

        widgetContext.gtkPaintFocus(textFieldRect, widget, GTK_STATE_NORMAL, "entry");
    }

    return false;
}
Example #9
0
ShadowApplier::ShadowApplier(GraphicsContext& context, const ShadowData* shadow, const FloatRect& textRect, bool lastShadowIterationShouldDrawText, bool opaque, FontOrientation orientation)
    : m_context(context)
    , m_shadow(shadow)
    , m_onlyDrawsShadow(!isLastShadowIteration() || !lastShadowIterationShouldDrawText)
    , m_avoidDrawingShadow(shadowIsCompletelyCoveredByText(opaque))
    , m_nothingToDraw(shadow && m_avoidDrawingShadow && m_onlyDrawsShadow)
    , m_didSaveContext(false)
{
    if (!shadow || m_nothingToDraw) {
        m_shadow = nullptr;
        return;
    }

    int shadowX = orientation == Horizontal ? shadow->x() : shadow->y();
    int shadowY = orientation == Horizontal ? shadow->y() : -shadow->x();
    FloatSize shadowOffset(shadowX, shadowY);
    int shadowRadius = shadow->radius();
    const Color& shadowColor = shadow->color();

    // When drawing shadows, we usually clip the context to the area the shadow will reside, and then
    // draw the text itself outside the clipped area (so only the shadow shows up). However, we can
    // often draw the *last* shadow and the text itself in a single call.
    if (m_onlyDrawsShadow) {
        FloatRect shadowRect(textRect);
        shadowRect.inflate(shadow->paintingExtent());
        shadowRect.move(shadowOffset);
        context.save();
        context.clip(shadowRect);

        m_didSaveContext = true;
        m_extraOffset = FloatSize(0, 2 * textRect.height() + std::max(0.0f, shadowOffset.height()) + shadowRadius);
        shadowOffset -= m_extraOffset;
    }

    if (!m_avoidDrawingShadow)
        context.setShadow(shadowOffset, shadowRadius, shadowColor, context.fillColorSpace());
}
Example #10
0
void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, int deco, ShadowData* shadow)
{
    tx += m_x;
    ty += m_y;

    if (m_truncation == cFullTruncation)
        return;
    
    int width = (m_truncation == cNoTruncation) ? m_width
        : static_cast<RenderText*>(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
    
    // Get the text decoration colors.
    Color underline, overline, linethrough;
    object()->getTextDecorationColors(deco, underline, overline, linethrough, true);
    
    // Use a special function for underlines to get the positioning exactly right.
    bool isPrinting = textObject()->document()->printing();
    context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.

    bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);

    bool setClip = false;
    int extraOffset = 0;
    if (!linesAreOpaque && shadow && shadow->next) {
        context->save();
        IntRect clipRect(tx, ty, width, m_baseline + 2);
        for (ShadowData* s = shadow; s; s = s->next) {
            IntRect shadowRect(tx, ty, width, m_baseline + 2);
            shadowRect.inflate(s->blur);
            shadowRect.move(s->x, s->y);
            clipRect.unite(shadowRect);
            extraOffset = max(extraOffset, max(0, s->y) + s->blur);
        }
        context->save();
        context->clip(clipRect);
        extraOffset += m_baseline + 2;
        ty += extraOffset;
        setClip = true;
    }

    bool setShadow = false;
    do {
        if (shadow) {
            if (!shadow->next) {
                // The last set of lines paints normally inside the clip.
                ty -= extraOffset;
                extraOffset = 0;
            }
            context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color);
            setShadow = true;
            shadow = shadow->next;
        }

        if (deco & UNDERLINE) {
            context->setStrokeColor(underline);
            // Leave one pixel of white between the baseline and the underline.
            context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), width, isPrinting);
        }
        if (deco & OVERLINE) {
            context->setStrokeColor(overline);
            context->drawLineForText(IntPoint(tx, ty), width, isPrinting);
        }
        if (deco & LINE_THROUGH) {
            context->setStrokeColor(linethrough);
            context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), width, isPrinting);
        }
    } while (shadow);

    if (setClip)
        context->restore();
    else if (setShadow)
        context->clearShadow();
}
Example #11
0
void TextDecorationPainter::paintTextDecoration(const TextRun& textRun, const FloatPoint& textOrigin, const FloatPoint& boxOrigin)
{
#if !ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
    UNUSED_PARAM(textRun);
    UNUSED_PARAM(textOrigin);
#endif
    ASSERT(m_font);
    float textDecorationThickness = textDecorationStrokeThickness(m_lineStyle.fontSize());
    m_context.setStrokeThickness(textDecorationThickness);
    FloatPoint localOrigin = boxOrigin;

    auto paintDecoration = [&](TextDecoration decoration, TextDecorationStyle style, const Color& color, const FloatPoint& start, const FloatPoint& end, int offset) {
        m_context.setStrokeColor(color);

        auto strokeStyle = textDecorationStyleToStrokeStyle(style);

        if (style == TextDecorationStyleWavy)
            strokeWavyTextDecoration(m_context, start, end, textDecorationThickness);
        else if (decoration == TextDecorationUnderline || decoration == TextDecorationOverline) {
#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
            if ((m_lineStyle.textDecorationSkip() == TextDecorationSkipInk || m_lineStyle.textDecorationSkip() == TextDecorationSkipAuto) && m_isHorizontal) {
                if (!m_context.paintingDisabled())
                    drawSkipInkUnderline(m_context, *m_font, textRun, textOrigin, localOrigin, offset, m_width, m_isPrinting, style == TextDecorationStyleDouble, strokeStyle);
            } else
                // FIXME: Need to support text-decoration-skip: none.
#endif
                m_context.drawLineForText(start, m_width, m_isPrinting, style == TextDecorationStyleDouble, strokeStyle);
            
        } else {
            ASSERT(decoration == TextDecorationLineThrough);
            m_context.drawLineForText(start, m_width, m_isPrinting, style == TextDecorationStyleDouble, strokeStyle);
        }
    };

    bool linesAreOpaque = !m_isPrinting
        && (!(m_decoration & TextDecorationUnderline) || m_styles.underlineColor.isOpaque())
        && (!(m_decoration & TextDecorationOverline) || m_styles.overlineColor.isOpaque())
        && (!(m_decoration & TextDecorationLineThrough) || m_styles.linethroughColor.isOpaque());

    int extraOffset = 0;
    bool clipping = !linesAreOpaque && m_shadow && m_shadow->next();
    if (clipping) {
        FloatRect clipRect(localOrigin, FloatSize(m_width, m_baseline + 2));
        for (const ShadowData* shadow = m_shadow; shadow; shadow = shadow->next()) {
            int shadowExtent = shadow->paintingExtent();
            FloatRect shadowRect(localOrigin, FloatSize(m_width, m_baseline + 2));
            shadowRect.inflate(shadowExtent);
            int shadowX = m_isHorizontal ? shadow->x() : shadow->y();
            int shadowY = m_isHorizontal ? shadow->y() : -shadow->x();
            shadowRect.move(shadowX, shadowY);
            clipRect.unite(shadowRect);
            extraOffset = std::max(extraOffset, std::max(0, shadowY) + shadowExtent);
        }
        m_context.save();
        m_context.clip(clipRect);
        extraOffset += m_baseline + 2;
        localOrigin.move(0, extraOffset);
    }

    const ShadowData* shadow = m_shadow;
    do {
        if (shadow) {
            if (!shadow->next()) {
                // The last set of lines paints normally inside the clip.
                localOrigin.move(0, -extraOffset);
                extraOffset = 0;
            }
            int shadowX = m_isHorizontal ? shadow->x() : shadow->y();
            int shadowY = m_isHorizontal ? shadow->y() : -shadow->x();
            m_context.setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow->radius(), shadow->color());
            shadow = shadow->next();
        }
        
        // These decorations should match the visual overflows computed in visualOverflowForDecorations()
        if (m_decoration & TextDecorationUnderline) {
            const int offset = computeUnderlineOffset(m_lineStyle.textUnderlinePosition(), m_lineStyle.fontMetrics(), m_inlineTextBox, textDecorationThickness);
            int wavyOffset = m_styles.underlineStyle == TextDecorationStyleWavy ? m_wavyOffset : 0;
            FloatPoint start = localOrigin + FloatSize(0, offset + wavyOffset);
            FloatPoint end = localOrigin + FloatSize(m_width, offset + wavyOffset);
            paintDecoration(TextDecorationUnderline, m_styles.underlineStyle, m_styles.underlineColor, start, end, offset);
        }
        if (m_decoration & TextDecorationOverline) {
            int wavyOffset = m_styles.overlineStyle == TextDecorationStyleWavy ? m_wavyOffset : 0;
            FloatPoint start = localOrigin - FloatSize(0, wavyOffset);
            FloatPoint end = localOrigin + FloatSize(m_width, -wavyOffset);
            paintDecoration(TextDecorationOverline, m_styles.overlineStyle, m_styles.overlineColor, start, end, 0);
        }
        if (m_decoration & TextDecorationLineThrough) {
            FloatPoint start = localOrigin + FloatSize(0, 2 * m_baseline / 3);
            FloatPoint end = localOrigin + FloatSize(m_width, 2 * m_baseline / 3);
            paintDecoration(TextDecorationLineThrough, m_styles.linethroughStyle, m_styles.linethroughColor, start, end, 0);
        }
    } while (shadow);

    if (clipping)
        m_context.restore();
    else if (m_shadow)
        m_context.clearShadow();
}