Example #1
0
FloatRect AffineTransform::mapRect(const FloatRect& rect) const
{
    if (isIdentityOrTranslation()) {
        FloatRect mappedRect(rect);
        mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
        return mappedRect;
    }

    FloatQuad result;
    result.setP1(mapPoint(rect.location()));
    result.setP2(mapPoint(FloatPoint(rect.right(), rect.y())));
    result.setP3(mapPoint(FloatPoint(rect.right(), rect.bottom())));
    result.setP4(mapPoint(FloatPoint(rect.x(), rect.bottom())));
    return result.boundingBox();
}
bool FloatRect::intersects(const FloatRect& other) const
{
    // Checking emptiness handles negative widths as well as zero.
    return !isEmpty() && !other.isEmpty()
        && x() < other.right() && other.x() < right()
        && y() < other.bottom() && other.y() < bottom();
}
static inline FloatRect normalizeRect(const FloatRect& rect)
{
    return FloatRect(min(rect.x(), rect.right()),
        min(rect.y(), rect.bottom()),
        max(rect.width(), -rect.width()),
        max(rect.height(), -rect.height()));
}
IntRect enclosingIntRect(const FloatRect& rect)
{
    int l = static_cast<int>(floorf(rect.x()));
    int t = static_cast<int>(floorf(rect.y()));
    int r = static_cast<int>(ceilf(rect.right()));
    int b = static_cast<int>(ceilf(rect.bottom()));
    return IntRect(l, t, r - l, b - t);
}
IntRect enclosingIntRect(const FloatRect& rect)
{
    int l = static_cast<int>(rect.x());
    int t = static_cast<int>(rect.y());
    // FIXME: These two need to be a "ceiling" operation, not rounding.
    // We changed them to do "+ 0.5f" to compile on Win32 where there's
    // no ceilf, but they should be changed back to "ceiling" at some point
    // and we should provide an implementation of ceilf for Win32.
    int r = static_cast<int>(rect.right() + 0.5f);
    int b = static_cast<int>(rect.bottom() + 0.5f);
    return IntRect(l, t, r - l, b - t);
}
Example #6
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp)
{
    CGImageRef image = frameAtIndex(m_currentFrame);
    if (!image) // If it's too early we won't have an image yet.
        return;
    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp);
        return;
    }

    CGContextRef context = ctxt->platformContext();
    ctxt->save();

    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
    // and then set a clip to the portion that we want to display.
    CGSize selfSize = size();
    FloatRect adjustedDestRect = destRect;
    if (srcRect.width() != selfSize.width || srcRect.height() != selfSize.height) {
        // A subportion of the image is drawing.  Adjust the destination rect to
        // account for this.
        float xScale = srcRect.width() / destRect.width();
        float yScale = srcRect.height() / destRect.height();
        
        adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
        adjustedDestRect.setSize(FloatSize(size().width() / xScale, size().height() / yScale));
        
        CGContextClipToRect(context, destRect);
    }

    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    float currHeight = CGImageGetHeight(image);
    if (currHeight < selfSize.height)
        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height);

    // Flip the coords.
    ctxt->setCompositeOperation(compositeOp);
    CGContextTranslateCTM(context, adjustedDestRect.x(), adjustedDestRect.bottom());
    CGContextScaleCTM(context, 1, -1);
    adjustedDestRect.setLocation(FloatPoint());

    // Draw the image.
    CGContextDrawImage(context, adjustedDestRect, image);
        
    ctxt->restore();
    
    startAnimation();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Example #7
0
WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
    : widthSet(true)
    , heightSet(true)
    , menuBarVisible(false)
    , toolBarVisible(false)
    , locationBarVisible(false)
    , fullscreen(false)
    , dialog(true)
{
    DialogFeaturesMap features;
    parseDialogFeatures(dialogFeaturesString, features);

    const bool trusted = false;

    // The following features from Microsoft's documentation are not implemented:
    // - default font settings
    // - width, height, left, and top specified in units other than "px"
    // - edge (sunken or raised, default is raised)
    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
    // - unadorned: trusted && boolFeature(features, "unadorned");

    width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
    height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE

    x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.right() - width, -1);
    xSet = x > 0;
    y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.bottom() - height, -1);
    ySet = y > 0;

    if (boolFeature(features, "center", true)) {
        if (!xSet) {
            x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
            xSet = true;
        }
        if (!ySet) {
            y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
            ySet = true;
        }
    }

    resizable = boolFeature(features, "resizable");
    scrollbarsVisible = boolFeature(features, "scroll", true);
    statusBarVisible = boolFeature(features, "status", !trusted);
}
void FloatRect::unite(const FloatRect& other)
{
    // Handle empty special cases first.
    if (other.isEmpty())
        return;
    if (isEmpty()) {
        *this = other;
        return;
    }

    float l = min(x(), other.x());
    float t = min(y(), other.y());
    float r = max(right(), other.right());
    float b = max(bottom(), other.bottom());

    m_location.setX(l);
    m_location.setY(t);
    m_size.setWidth(r - l);
    m_size.setHeight(b - t);
}
void FloatRect::intersect(const FloatRect& other)
{
    float l = max(x(), other.x());
    float t = max(y(), other.y());
    float r = min(right(), other.right());
    float b = min(bottom(), other.bottom());

    // Return a clean empty rectangle for non-intersecting cases.
    if (l >= r || t >= b) {
        l = 0;
        t = 0;
        r = 0;
        b = 0;
    }

    m_location.setX(l);
    m_location.setY(t);
    m_size.setWidth(r - l);
    m_size.setHeight(b - t);
}
Example #10
0
IntRect TiledImageOpenVG::tilesInRect(const FloatRect& rect) const
{
    int leftIndex = static_cast<int>(rect.x()) / m_maxTileSize.width();
    int topIndex = static_cast<int>(rect.y()) / m_maxTileSize.height();

    if (leftIndex < 0)
        leftIndex = 0;
    if (topIndex < 0)
        topIndex = 0;

    // Round rect edges up to get the outer pixel boundaries.
    int rightIndex = (static_cast<int>(ceil(rect.right())) - 1) / m_maxTileSize.width();
    int bottomIndex = (static_cast<int>(ceil(rect.bottom())) - 1) / m_maxTileSize.height();
    int columns = (rightIndex - leftIndex) + 1;
    int rows = (bottomIndex - topIndex) + 1;

    return IntRect(leftIndex, topIndex,
        (columns <= m_numColumns) ? columns : m_numColumns,
        (rows <= (m_tiles.size() / m_numColumns)) ? rows : (m_tiles.size() / m_numColumns));
}
Example #11
0
void SVGRenderStyle::inflateForShadow(FloatRect& repaintRect) const
{
    ShadowData* svgShadow = shadow();
    if (!svgShadow)
        return;

    int shadowTop;
    int shadowRight;
    int shadowBottom;
    int shadowLeft;
    getSVGShadowExtent(svgShadow, shadowTop, shadowRight, shadowBottom, shadowLeft);

    int overflowLeft = repaintRect.x() + shadowLeft;
    int overflowRight = repaintRect.right() + shadowRight;
    int overflowTop = repaintRect.y() + shadowTop;
    int overflowBottom = repaintRect.bottom() + shadowBottom;

    repaintRect.setX(overflowLeft);
    repaintRect.setY(overflowTop);
    repaintRect.setWidth(overflowRight - overflowLeft);
    repaintRect.setHeight(overflowBottom - overflowTop);
}
void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect)
{
    if (!m_hdc)
        return;
    IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom());
}
bool FloatRect::contains(const FloatRect& other) const
{
    return x() <= other.x() && right() >= other.right()
        && y() <= other.y() && bottom() >= other.bottom();
}
Example #14
0
void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
{
    if (offset > m_end)
        offset = m_end;

    int currentCharacter = m_currentCharacter;
    const UChar* cp = m_run.data(currentCharacter);

    bool rtl = m_run.rtl();
    bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_padding) && !m_run.spacingDisabled();

    float widthSinceLastRounding = m_runWidthSoFar;
    m_runWidthSoFar = floorf(m_runWidthSoFar);
    widthSinceLastRounding -= m_runWidthSoFar;

    float lastRoundingWidth = m_finalRoundingWidth;
    FloatRect bounds;

    const SimpleFontData* primaryFont = m_font->primaryFont();
    const SimpleFontData* lastFontData = primaryFont;

    while (currentCharacter < offset) {
        UChar32 c = *cp;
        unsigned clusterLength = 1;
        if (c >= 0x3041) {
            if (c <= 0x30FE) {
                // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
                // Normalize into composed form, and then look for glyph with base + combined mark.
                // Check above for character range to minimize performance impact.
                UChar32 normalized = normalizeVoicingMarks(currentCharacter);
                if (normalized) {
                    c = normalized;
                    clusterLength = 2;
                }
            } else if (U16_IS_SURROGATE(c)) {
                if (!U16_IS_SURROGATE_LEAD(c))
                    break;

                // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
                // code point before glyph lookup.
                // Make sure we have another character and it's a low surrogate.
                if (currentCharacter + 1 >= m_run.length())
                    break;
                UChar low = cp[1];
                if (!U16_IS_TRAIL(low))
                    break;
                c = U16_GET_SUPPLEMENTARY(c, low);
                clusterLength = 2;
            }
        }

        const GlyphData& glyphData = m_font->glyphDataForCharacter(c, rtl);
        Glyph glyph = glyphData.glyph;
        const SimpleFontData* fontData = glyphData.fontData;

        ASSERT(fontData);

        // Now that we have a glyph and font data, get its width.
        float width;
        if (c == '\t' && m_run.allowTabs()) {
            float tabWidth = m_font->tabWidth(*fontData);
            width = tabWidth - fmodf(m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding, tabWidth);
        } else {
            width = fontData->widthForGlyph(glyph);

#if ENABLE(SVG)
            // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text.
            width *= m_run.horizontalGlyphStretch();
#endif

            // We special case spaces in two ways when applying word rounding.
            // First, we round spaces to an adjusted width in all fonts.
            // Second, in fixed-pitch fonts we ensure that all characters that
            // match the width of the space character have the same width as the space character.
            if (width == fontData->spaceWidth() && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
                width = fontData->adjustedSpaceWidth();
        }

        if (fontData != lastFontData && width) {
            lastFontData = fontData;
            if (m_fallbackFonts && fontData != primaryFont) {
                // FIXME: This does a little extra work that could be avoided if
                // glyphDataForCharacter() returned whether it chose to use a small caps font.
                if (!m_font->isSmallCaps() || c == toUpper(c))
                    m_fallbackFonts->add(fontData);
                else {
                    const GlyphData& uppercaseGlyphData = m_font->glyphDataForCharacter(toUpper(c), rtl);
                    if (uppercaseGlyphData.fontData != primaryFont)
                        m_fallbackFonts->add(uppercaseGlyphData.fontData);
                }
            }
        }

        if (hasExtraSpacing) {
            // Account for letter-spacing.
            if (width && m_font->letterSpacing())
                width += m_font->letterSpacing();

            if (Font::treatAsSpace(c)) {
                // Account for padding. WebCore uses space padding to justify text.
                // We distribute the specified padding over the available spaces in the run.
                if (m_padding) {
                    // Use left over padding if not evenly divisible by number of spaces.
                    if (m_padding < m_padPerSpace) {
                        width += m_padding;
                        m_padding = 0;
                    } else {
                        float previousPadding = m_padding;
                        m_padding -= m_padPerSpace;
                        width += roundf(previousPadding) - roundf(m_padding);
                    }
                }

                // Account for word spacing.
                // We apply additional space between "words" by adding width to the space character.
                if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
                    width += m_font->wordSpacing();
            }
        }

        if (m_accountForGlyphBounds) {
            bounds = fontData->boundsForGlyph(glyph);
            if (!currentCharacter)
                m_firstGlyphOverflow = max<float>(0, -bounds.x());
        }

        if (m_forTextEmphasis && !Font::canReceiveTextEmphasis(c))
            glyph = 0;

        // Advance past the character we just dealt with.
        cp += clusterLength;
        currentCharacter += clusterLength;

        // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters 
        // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
        // We adjust the width of the last character of a "word" to ensure an integer width.
        // If we move KHTML to floats we can remove this (and related) hacks.

        float oldWidth = width;

        // Force characters that are used to determine word boundaries for the rounding hack
        // to be integer width, so following words will start on an integer boundary.
        if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c)) {
            width = ceilf(width);

            // Since widthSinceLastRounding can lose precision if we include measurements for
            // preceding whitespace, we bypass it here.
            m_runWidthSoFar += width;

            // Since this is a rounding hack character, we should have reset this sum on the previous
            // iteration.
            ASSERT(!widthSinceLastRounding);
        } else {
            // Check to see if the next character is a "rounding hack character", if so, adjust
            // width so that the total run width will be on an integer boundary.
            if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
                    || (m_run.applyRunRounding() && currentCharacter >= m_end)) {
                float totalWidth = widthSinceLastRounding + width;
                widthSinceLastRounding = ceilf(totalWidth);
                width += widthSinceLastRounding - totalWidth;
                m_runWidthSoFar += widthSinceLastRounding;
                widthSinceLastRounding = 0;
            } else
                widthSinceLastRounding += width;
        }

        if (glyphBuffer)
            glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));

        lastRoundingWidth = width - oldWidth;

        if (m_accountForGlyphBounds) {
            m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.bottom());
            m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y());
            m_lastGlyphOverflow = max<float>(0, bounds.right() - width);
        }
    }

    m_currentCharacter = currentCharacter;
    m_runWidthSoFar += widthSinceLastRounding;
    m_finalRoundingWidth = lastRoundingWidth;
}
Example #15
0
// Sets the scissor region to the given rectangle. The coordinate system for the
// scissorRect has its origin at the top left corner of the current visible rect.
void LayerRendererChromium::scissorToRect(const FloatRect& scissorRect)
{
    // Compute the lower left corner of the scissor rect.
    float bottom = std::max((float)m_rootVisibleRect.height() - scissorRect.bottom(), 0.f);
    GLC(glScissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height()));
}
Example #16
0
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect)
{
#if USE(WXGC)
    wxGCDC* context = (wxGCDC*)ctxt->platformContext();
    wxGraphicsBitmap* bitmap = nativeImageForCurrentFrame();
#else
    wxDC* context = ctxt->platformContext();
    wxBitmap* bitmap = nativeImageForCurrentFrame();
#endif

    if (!bitmap) // If it's too early we won't have an image yet.
        return;

    ctxt->save();
    ctxt->clip(IntRect(dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height()));
    
    float currentW = 0;
    float currentH = 0;
    
#if USE(WXGC)
    wxGraphicsContext* gc = context->GetGraphicsContext();

    float adjustedX = phase.x() + srcRect.x() *
                      narrowPrecisionToFloat(patternTransform.a());
    float adjustedY = phase.y() + srcRect.y() *
                      narrowPrecisionToFloat(patternTransform.d());
                      
    gc->ConcatTransform(patternTransform);
#else
    float adjustedX = phase.x();
    float adjustedY = phase.y();
    wxMemoryDC mydc;
    mydc.SelectObject(*bitmap);

    ctxt->concatCTM(patternTransform);
#endif

    //wxPoint origin(context->GetDeviceOrigin());
    AffineTransform mat(ctxt->getCTM());
    wxPoint origin(mat.mapPoint(IntPoint(0, 0)));
    wxSize clientSize(context->GetSize());

    wxCoord w = srcRect.width();
    wxCoord h = srcRect.height();
    wxCoord srcx = srcRect.x();
    wxCoord srcy = srcRect.y();

    while (currentW < dstRect.right() - phase.x() && origin.x + adjustedX + currentW < clientSize.x) {
        while (currentH < dstRect.bottom() - phase.y() && origin.y + adjustedY + currentH < clientSize.y) {
#if USE(WXGC)
#if wxCHECK_VERSION(2,9,0)
            gc->DrawBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height());
#else
            gc->DrawGraphicsBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height());
#endif
#else
            context->Blit(adjustedX + currentW, adjustedY + currentH,
                          w, h, &mydc, srcx, srcy, wxCOPY, true);
#endif
            currentH += srcRect.height();
        }
        currentW += srcRect.width();
        currentH = 0;
    }
    ctxt->restore();

#if !USE(WXGC)
    mydc.SelectObject(wxNullBitmap);
#endif    
    
    // NB: delete is causing crashes during page load, but not during the deletion
    // itself. It occurs later on when a valid bitmap created in frameAtIndex
    // suddenly becomes invalid after returning. It's possible these errors deal
    // with reentrancy and threding problems.
    //delete bitmap;

    startAnimation();

    if (ImageObserver* observer = imageObserver())
        observer->didDraw(this);
}
Example #17
0
void BackingStoreScrollbar::repaint(const WebCore::IntRect& hotRect, bool vertical)
{
    SurfaceOpenVG* surface = SurfacePool::globalSurfacePool()->tileRenderingSurface();
    const IntSize surfaceSize(surface->width(), surface->height());
    PainterOpenVG painter(surface);

    // If the rendering surface is smaller than the scrollbar
    // (e.g. when the screen is rotated), paint it multiple times.
    int lastXTile = (m_size.width() - 1) / surfaceSize.width();
    int lastYTile = (m_size.height() - 1) / surfaceSize.height();

    FloatRect innerRect = hotRect;
    innerRect.move(0.5, 0.5); // draw it pixel-perfect with a 1.0 wide stroke
    int radius = vertical ? hotRect.width() / 2 : hotRect.height() / 2;
    if (vertical)
        innerRect.inflateY(-radius);
    else
        innerRect.inflateX(-radius);

    Path path;

    if (vertical) {
        path.moveTo(FloatPoint(innerRect.x(), innerRect.y()));
        path.addArc(FloatPoint(innerRect.x() + radius, innerRect.y()), radius, piFloat, 0, false);
        path.addLineTo(FloatPoint(innerRect.right(), innerRect.bottom()));
        path.addArc(FloatPoint(innerRect.x() + radius, innerRect.bottom()), radius, 0, piFloat, false);
        path.closeSubpath();
    } else {
        path.moveTo(FloatPoint(innerRect.right(), innerRect.y()));
        path.addArc(FloatPoint(innerRect.right(), innerRect.y() + radius), radius, piFloat + piFloat / 2, piFloat / 2, false);
        path.addLineTo(FloatPoint(innerRect.x(), innerRect.bottom()));
        path.addArc(FloatPoint(innerRect.x(), innerRect.y() + radius), radius, piFloat / 2, piFloat + piFloat / 2, false);
        path.closeSubpath();
    }

    for (int i = 0; i <= lastXTile; ++i) {
        for (int j = 0; j <= lastYTile; ++j) {
            const int dstX = i * surfaceSize.width();
            const int dstY = j * surfaceSize.height();
            const int dstRight = (i == lastXTile) ? m_size.width() : (i + 1) * surfaceSize.width();
            const int dstBottom = (j == lastYTile) ? m_size.height() : (j + 1) * surfaceSize.height();

            painter.translate(rect().x(), rect().y());

            if (dstX || dstY)
                painter.translate(-dstX, -dstY);

            // Paint the actual scrollbar.
            painter.setFillColor(Color(255, 255, 255));
            painter.drawRect(IntRect(IntPoint(0, 0), rect().size()), VG_FILL_PATH);
            painter.setFillColor(Color(173, 176, 178));
            painter.drawPath(path, VG_FILL_PATH, WebCore::RULE_NONZERO);

            surface->makeCurrent();
            unsigned char* dstBufferStart = m_image + (dstY * imageStride()) + (dstX * imageBytesPerPixel());
            vgReadPixels(dstBufferStart, imageStride(), VG_sRGB_565,
                0, 0, dstRight - dstX, dstBottom - dstY);
            ASSERT_VG_NO_ERROR();

            // Paint the alpha channel for the actual scrollbar.
            painter.setCompositeOperation(CompositeClear);
            painter.setFillColor(Color(0, 0, 0));
            painter.drawRect(IntRect(IntPoint(0, 0), rect().size()), VG_FILL_PATH);
            painter.setCompositeOperation(CompositeSourceOver);
            painter.setFillColor(Color(255, 255, 255));
            painter.drawPath(path, VG_FILL_PATH, WebCore::RULE_NONZERO);

            surface->makeCurrent();
            // FIXME: We need VG_A_4 until proper alpha blending is available.
            //   When we get 8-bit formats, make sure to adapt both the format
            //   and remove the division by two when determining the dstAlphaBufferStart.
            unsigned char* dstAlphaBufferStart = m_alphaImage + (dstY * alphaImageStride()) + dstX / 2;
            vgReadPixels(dstAlphaBufferStart, alphaImageStride(), VG_A_4,
                0, 0, dstRight - dstX, dstBottom - dstY);
            ASSERT_VG_NO_ERROR();

            if (dstX || dstY)
                painter.translate(dstX, dstY);
        }
    }
}
Example #18
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
    startAnimation();

    RetainPtr<CGImageRef> image = frameAtIndex(m_currentFrame);
    if (!image) // If it's too early we won't have an image yet.
        return;
    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
        return;
    }

    float currHeight = CGImageGetHeight(image.get());
    if (currHeight <= srcRect.y())
        return;

    CGContextRef context = ctxt->platformContext();
    ctxt->save();

    bool shouldUseSubimage = false;

    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
    // and then set a clip to the portion that we want to display.
    FloatRect adjustedDestRect = destRect;
    FloatSize selfSize = currentFrameSize();
    if (srcRect.size() != selfSize) {
        CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
        // When the image is scaled using high-quality interpolation, we create a temporary CGImage
        // containing only the portion we want to display. We need to do this because high-quality
        // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
        // into the destination rect. See <rdar://problem/6112909>.
        shouldUseSubimage = (interpolationQuality == kCGInterpolationHigh || interpolationQuality == kCGInterpolationDefault) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
        float xScale = srcRect.width() / destRect.width();
        float yScale = srcRect.height() / destRect.height();
        if (shouldUseSubimage) {
            FloatRect subimageRect = srcRect;
            float leftPadding = srcRect.x() - floorf(srcRect.x());
            float topPadding = srcRect.y() - floorf(srcRect.y());

            subimageRect.move(-leftPadding, -topPadding);
            adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);

            subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
            adjustedDestRect.setWidth(subimageRect.width() / xScale);

            subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
            adjustedDestRect.setHeight(subimageRect.height() / yScale);

            image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
            if (currHeight < srcRect.bottom()) {
                ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
                adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
            }
        } else {
            adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
            adjustedDestRect.setSize(FloatSize(selfSize.width() / xScale, selfSize.height() / yScale));
        }

        CGContextClipToRect(context, destRect);
    }

    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    if (!shouldUseSubimage && currHeight < selfSize.height())
        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());

    ctxt->setCompositeOperation(compositeOp);

    // Flip the coords.
    CGContextScaleCTM(context, 1, -1);
    adjustedDestRect.setY(-adjustedDestRect.bottom());

    // Adjust the color space.
    image = imageWithColorSpace(image.get(), styleColorSpace);

    // Draw the image.
    CGContextDrawImage(context, adjustedDestRect, image.get());

    ctxt->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
JSValue JSDOMWindow::showModalDialog(ExecState* exec)
{
    String url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
    JSValue dialogArgs = exec->argument(1);
    String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));

    Frame* frame = impl()->frame();
    if (!frame)
        return jsUndefined();
    Frame* lexicalFrame = toLexicalFrame(exec);
    if (!lexicalFrame)
        return jsUndefined();
    Frame* dynamicFrame = toDynamicFrame(exec);
    if (!dynamicFrame)
        return jsUndefined();

    if (!DOMWindow::canShowModalDialogNow(frame) || !domWindowAllowPopUp(dynamicFrame))
        return jsUndefined();

    HashMap<String, String> features;
    DOMWindow::parseModalDialogFeatures(featureArgs, features);

    const bool trusted = false;

    // The following features from Microsoft's documentation are not implemented:
    // - default font settings
    // - width, height, left, and top specified in units other than "px"
    // - edge (sunken or raised, default is raised)
    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
    // - unadorned: trusted && boolFeature(features, "unadorned");

    FloatRect screenRect = screenAvailableRect(frame->view());

    WindowFeatures wargs;
    wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
    wargs.widthSet = true;
    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
    wargs.heightSet = true;

    wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
    wargs.xSet = wargs.x > 0;
    wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
    wargs.ySet = wargs.y > 0;

    if (WindowFeatures::boolFeature(features, "center", true)) {
        if (!wargs.xSet) {
            wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
            wargs.xSet = true;
        }
        if (!wargs.ySet) {
            wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
            wargs.ySet = true;
        }
    }

    wargs.dialog = true;
    wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
    wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
    wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
    wargs.menuBarVisible = false;
    wargs.toolBarVisible = false;
    wargs.locationBarVisible = false;
    wargs.fullscreen = false;

    Frame* dialogFrame = createWindow(exec, lexicalFrame, dynamicFrame, frame, url, "", wargs, dialogArgs);
    if (!dialogFrame)
        return jsUndefined();

    JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec));
    dialogFrame->page()->chrome()->runModal();

    Identifier returnValue(exec, "returnValue");
    if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) {
        PropertySlot slot;
        // This is safe, we have already performed the origin security check and we are
        // not interested in any of the DOM properties of the window.
        if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot))
            return slot.getValue(exec, returnValue);
    }
    return jsUndefined();
}
Example #20
0
static JSValuePtr showModalDialog(ExecState* exec, Frame* frame, const String& url, JSValuePtr dialogArgs, const String& featureArgs)
{
    if (!canShowModalDialogNow(frame) || !allowPopUp(exec))
        return jsUndefined();

    const HashMap<String, String> features = parseModalDialogFeatures(featureArgs);

    const bool trusted = false;

    // The following features from Microsoft's documentation are not implemented:
    // - default font settings
    // - width, height, left, and top specified in units other than "px"
    // - edge (sunken or raised, default is raised)
    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
    // - unadorned: trusted && boolFeature(features, "unadorned");

    if (!frame)
        return jsUndefined();

    FloatRect screenRect = screenAvailableRect(frame->view());

    WindowFeatures wargs;
    wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
    wargs.widthSet = true;
    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
    wargs.heightSet = true;

    wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
    wargs.xSet = wargs.x > 0;
    wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
    wargs.ySet = wargs.y > 0;

    if (WindowFeatures::boolFeature(features, "center", true)) {
        if (!wargs.xSet) {
            wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
            wargs.xSet = true;
        }
        if (!wargs.ySet) {
            wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
            wargs.ySet = true;
        }
    }

    wargs.dialog = true;
    wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
    wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
    wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
    wargs.menuBarVisible = false;
    wargs.toolBarVisible = false;
    wargs.locationBarVisible = false;
    wargs.fullscreen = false;

    Frame* dialogFrame = createWindow(exec, frame, url, "", wargs, dialogArgs);
    if (!dialogFrame)
        return jsUndefined();

    JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame);

    // Get the return value either just before clearing the dialog window's
    // properties (in JSDOMWindowBase::clear), or when on return from runModal.
    JSValuePtr returnValue = noValue();
    dialogWindow->setReturnValueSlot(&returnValue);
    dialogFrame->page()->chrome()->runModal();
    dialogWindow->setReturnValueSlot(0);

    // If we don't have a return value, get it now.
    // Either JSDOMWindowBase::clear was not called yet, or there was no return value,
    // and in that case, there's no harm in trying again (no benefit either).
    if (!returnValue)
        returnValue = dialogWindow->getDirect(Identifier(exec, "returnValue"));

    return returnValue ? returnValue : jsUndefined();
}
Example #21
0
void FindIndicator::draw(GraphicsContext& graphicsContext, const IntRect& dirtyRect)
{
    for (size_t i = 0; i < m_textRects.size(); ++i) {
        FloatRect textRect = m_textRects[i];
        textRect.move(leftBorderThickness, topBorderThickness);

        graphicsContext.save();
        FloatRect outerPathRect = inflateRect(textRect, horizontalOutsetToCenterOfLightBorder, verticalOutsetToCenterOfLightBorder);
        graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, shadowColor(), ColorSpaceSRGB);
        graphicsContext.addPath(pathWithRoundedRect(outerPathRect, cornerRadius));
        graphicsContext.setFillColor(lightBorderColor(), ColorSpaceDeviceRGB);
        graphicsContext.fillPath();
        graphicsContext.restore();

        graphicsContext.save();
        FloatRect innerPathRect = inflateRect(textRect, horizontalPaddingInsideLightBorder, verticalPaddingInsideLightBorder);
        graphicsContext.clip(pathWithRoundedRect(innerPathRect, cornerRadius));
        RefPtr<Gradient> gradient = Gradient::create(FloatPoint(innerPathRect.x(), innerPathRect.y()), FloatPoint(innerPathRect.x(), innerPathRect.bottom()));
        gradient->addColorStop(0, gradientLightColor());
        gradient->addColorStop(1, gradientDarkColor());
        graphicsContext.setFillGradient(gradient);
        graphicsContext.fillRect(outerPathRect);
        graphicsContext.restore();

        graphicsContext.save();
        graphicsContext.translate(FloatSize(roundf(leftBorderThickness), roundf(topBorderThickness) + m_contentImage->bounds().height()));
        graphicsContext.scale(FloatSize(1, -1));
        m_contentImage->paint(&graphicsContext, m_contentImage->bounds());
        graphicsContext.restore();
    }
}