Esempio n. 1
0
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op)
{    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), op);
        return;
    }

    FloatSize intrinsicTileSize = size();
    if (hasRelativeWidth())
        intrinsicTileSize.setWidth(scaledTileSize.width());
    if (hasRelativeHeight())
        intrinsicTileSize.setHeight(scaledTileSize.height());

    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
                    scaledTileSize.height() / intrinsicTileSize.height());
    AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());

    FloatRect oneTileRect;
    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
    oneTileRect.setSize(scaledTileSize);
    
    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.    
    if (oneTileRect.contains(destRect)) {
        FloatRect visibleSrcRect;
        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
        visibleSrcRect.setWidth(destRect.width() / scale.width());
        visibleSrcRect.setHeight(destRect.height() / scale.height());
        draw(ctxt, destRect, visibleSrcRect, op);
        return;
    }

    FloatRect tileRect(FloatPoint(), intrinsicTileSize);    
    drawPatternCounter.startCounting();
    drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect);
    drawPatternCounter.stopCounting();
    
    startAnimation();
}
Esempio n. 2
0
// Drawing Routines
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
                       const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
    QRectF normalizedDst = dst.normalized();
    QRectF normalizedSrc = src.normalized();

    startAnimation();

    if (normalizedSrc.isEmpty() || normalizedDst.isEmpty())
        return;

    QPixmap* image = nativeImageForCurrentFrame();
    if (!image)
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, normalizedDst, solidColor(), styleColorSpace, op);
        return;
    }

    CompositeOperator previousOperator = ctxt->compositeOperation();
    ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);

    ContextShadow* shadow = ctxt->contextShadow();
    if (shadow->m_type != ContextShadow::NoShadow) {
        QPainter* shadowPainter = shadow->beginShadowLayer(ctxt, normalizedDst);
        if (shadowPainter) {
            shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
            shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc);
            shadow->endShadowLayer(ctxt);
        }
    }

    ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc);

    ctxt->setCompositeOperation(previousOperator);

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 3
0
// Drawing Routines
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
    if (!m_source.initialized())
        return;

    // Spin the animation to the correct frame before we try to draw it, so we
    // don't draw an old frame and then immediately need to draw a newer one,
    // causing flicker and wasting CPU.
    startAnimation();

    BBitmap* image = nativeImageForCurrentFrame();
    if (!image || !image->IsValid()) // If the image hasn't fully loaded.
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
        return;
    }

    ctxt->save();
    ctxt->setCompositeOperation(op);

    BRect srcRect(src);
    BRect dstRect(dst);

    // Test using example site at
    // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
    ctxt->platformContext()->SetDrawingMode(B_OP_ALPHA);
    uint32 options = 0;
    if (ctxt->imageInterpolationQuality() == InterpolationDefault
        || ctxt->imageInterpolationQuality() > InterpolationLow) {
        options |= B_FILTER_BITMAP_BILINEAR;
    }
    ctxt->platformContext()->DrawBitmapAsync(image, srcRect, dstRect, options);
    ctxt->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 4
0
void quarterHour(uint8_t hour, uint8_t minute, uint16_t wait) {
  uint8_t no_rows;
  uint8_t y;
  uint8_t x;
  int16_t j;
  // light number of rows depending on the hour quarter (floored to be safe)
  no_rows = floor(minute / 15) * height;
  // one hour indicator is actually 0 but we want full display
  no_rows = (no_rows == 0) ? (4 * height) : no_rows;

  solidColor(0,0,0); // turn them all off
  show();

  if ((hour == 12 || hour == 0 ) && minute == 0) {
    rainbowCycle(25); // special edition hour for midday
  } else { // fade columns in and out
    for (j = 0; j <= 255; j += 5) {
      for (y = 0; y < no_rows; y++) {
        for (x = 0; x < PIXEL_ROW; x++) {
        setPixel(pixelMap[x][y],1,Color(0,0,j));
        }
      }
      show();
      usleep(10*1000);
    }
    usleep(wait*1000); // show for 10s
    for (j = 255; j >= 0; j -= 5) {
      for (y = 0; y < no_rows; y++) {
        for (x = 0; x < PIXEL_ROW; x++) {
        setPixel(pixelMap[x][y],1,Color(0,0,j));
        }
      }
      show();
      usleep(10*1000);
    }
  }
}
Esempio n. 5
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation)
{
    startAnimation();

    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;
    }

    FloatSize selfSize = currentFrameSize();
    ImageOrientation orientation = DefaultImageOrientation;

    if (shouldRespectImageOrientation == RespectImageOrientation)
        orientation = frameOrientationAtIndex(m_currentFrame);

    ctxt->drawNativeImage(image, selfSize, styleColorSpace, destRect, srcRect, compositeOp, blendMode, orientation);

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 6
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRectIn, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
    if (!m_source.initialized())
        return;

    if (mayFillWithSolidColor())
        fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, compositeOp);
    else {
        IntRect intSrcRect(srcRectIn);
        RefPtr<SharedBitmap> bmp = frameAtIndex(m_currentFrame);

        if (bmp->width() != m_source.size().width()) {
            double scaleFactor = static_cast<double>(bmp->width()) / m_source.size().width();

            intSrcRect.setX(stableRound(srcRectIn.x() * scaleFactor));
            intSrcRect.setWidth(stableRound(srcRectIn.width() * scaleFactor));
            intSrcRect.setY(stableRound(srcRectIn.y() * scaleFactor));
            intSrcRect.setHeight(stableRound(srcRectIn.height() * scaleFactor));
        }
        bmp->draw(ctxt, enclosingIntRect(dstRect), intSrcRect, styleColorSpace, compositeOp);
    }

    startAnimation();
}
Esempio n. 7
0
void Image::drawPattern(GraphicsContext* context, const FloatRect& src,
                        const AffineTransform& patternTransformation,
                        const FloatPoint& phase, ColorSpace styleColorSpace,
                        CompositeOperator op, const FloatRect& dst)
{
    if (dst.isEmpty() || src.isEmpty())
        return;

    NativeImagePtr image = nativeImageForCurrentFrame();
    if (!image)
        return;

    startAnimation();

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op);
        return;
    }

    notImplemented();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 8
0
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
    if (dst.isEmpty() || src.isEmpty())
        return;

    NativeImagePtr image = nativeImageForCurrentFrame();
    if (!image)
        return;

    startAnimation();

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op);
        return;
    }

    context->save();

    // Set the compositing operation.
    if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
        context->setCompositeOperation(CompositeCopy);
    else
        context->setCompositeOperation(op);

#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    FloatRect srcRectLocal = adjustSourceRectForDownSampling(src, image->size());
#else
    FloatRect srcRectLocal(src);
#endif

    context->platformContext()->activePainter()->drawImage(image, dst, srcRectLocal);
    context->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 9
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
{
    if (!m_source.initialized())
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, dst, solidColor(), op);
        return;
    }

#if USE(WXGC)
    wxGCDC* context = (wxGCDC*)ctxt->platformContext();
    wxGraphicsContext* gc = context->GetGraphicsContext();
#else
    wxWindowDC* context = ctxt->platformContext();
#endif

    startAnimation();

    wxBitmap* bitmap = frameAtIndex(m_currentFrame);
    if (!bitmap) // If it's too early we won't have an image yet.
        return;
    
    // If we're drawing a sub portion of the image or scaling then create
    // a pattern transformation on the image and draw the transformed pattern.
    // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
    // FIXME: NYI
   
    ctxt->save();

    // Set the compositing operation.
    ctxt->setCompositeOperation(op);
    
#if USE(WXGC)
    float scaleX = src.width() / dst.width();
    float scaleY = src.height() / dst.height();

    FloatRect adjustedDestRect = dst;
    FloatSize selfSize = currentFrameSize();
    
    if (src.size() != selfSize) {
        adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY));
        adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY));
    }
    
    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    int currHeight = bitmap->GetHeight(); 
    if (currHeight < selfSize.height())
        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());

    gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
#else
    IntRect srcIntRect(src);
    IntRect dstIntRect(dst);
    bool rescaling = false;
    if ((dstIntRect.width() != srcIntRect.width()) || (dstIntRect.height() != srcIntRect.height()))
    {
        rescaling = true;
        wxImage img = bitmap->ConvertToImage();
        img.Rescale(dstIntRect.width(), dstIntRect.height());
        bitmap = new wxBitmap(img);
    } 
    
    wxMemoryDC mydc; 
    ASSERT(bitmap->GetRefData());
    mydc.SelectObject(*bitmap); 
    
    context->Blit((wxCoord)dstIntRect.x(),(wxCoord)dstIntRect.y(), (wxCoord)dstIntRect.width(), (wxCoord)dstIntRect.height(), &mydc, 
                    (wxCoord)srcIntRect.x(), (wxCoord)srcIntRect.y(), wxCOPY, true); 
    mydc.SelectObject(wxNullBitmap);
    
    // 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;
    if (rescaling)
    {
        delete bitmap;
        bitmap = NULL;
    }
#endif

    ctxt->restore();
}
Esempio n. 10
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);
}
void GraphicsLayerTextureMapper::commitLayerChanges()
{
    if (m_changeMask == NoChanges)
        return;

    if (m_changeMask & ChildrenChange) {
        Vector<TextureMapperLayer*> textureMapperLayerChildren;
        toTextureMapperLayerVector(children(), textureMapperLayerChildren);
        m_layer->setChildren(textureMapperLayerChildren);
    }

    if (m_changeMask & MaskLayerChange)
        m_layer->setMaskLayer(toTextureMapperLayer(maskLayer()));

    if (m_changeMask & ReplicaLayerChange)
        m_layer->setReplicaLayer(toTextureMapperLayer(replicaLayer()));

    if (m_changeMask & PositionChange)
        m_layer->setPosition(position());

    if (m_changeMask & AnchorPointChange)
        m_layer->setAnchorPoint(anchorPoint());

    if (m_changeMask & SizeChange)
        m_layer->setSize(size());

    if (m_changeMask & TransformChange)
        m_layer->setTransform(transform());

    if (m_changeMask & ChildrenTransformChange)
        m_layer->setChildrenTransform(childrenTransform());

    if (m_changeMask & Preserves3DChange)
        m_layer->setPreserves3D(preserves3D());

    if (m_changeMask & ContentsRectChange)
        m_layer->setContentsRect(contentsRect());

    if (m_changeMask & MasksToBoundsChange)
        m_layer->setMasksToBounds(masksToBounds());

    if (m_changeMask & DrawsContentChange)
        m_layer->setDrawsContent(drawsContent());

    if (m_changeMask & ContentsVisibleChange)
        m_layer->setContentsVisible(contentsAreVisible());

    if (m_changeMask & ContentsOpaqueChange)
        m_layer->setContentsOpaque(contentsOpaque());

    if (m_changeMask & BackfaceVisibilityChange)
        m_layer->setBackfaceVisibility(backfaceVisibility());

    if (m_changeMask & OpacityChange)
        m_layer->setOpacity(opacity());

    if (m_changeMask & BackgroundColorChange)
        m_layer->setSolidColor(solidColor());

#if ENABLE(CSS_FILTERS)
    if (m_changeMask & FilterChange)
        m_layer->setFilters(filters());
#endif

    if (m_changeMask & BackingStoreChange)
        m_layer->setBackingStore(m_backingStore);

    if (m_changeMask & DebugVisualsChange)
        m_layer->setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());

    if (m_changeMask & RepaintCountChange)
        m_layer->setRepaintCount(repaintCount());

    if (m_changeMask & ContentChange)
        m_layer->setContentsLayer(platformLayer());

    if (m_changeMask & AnimationChange)
        m_layer->setAnimations(m_animations);

    if (m_changeMask & AnimationStarted)
        client()->notifyAnimationStarted(this, m_animationStartTime);

    if (m_changeMask & FixedToViewporChange)
        m_layer->setFixedToViewport(fixedToViewport());

    if (m_changeMask & IsScrollableChange)
        m_layer->setIsScrollable(isScrollable());

    if (m_changeMask & CommittedScrollOffsetChange)
        m_layer->didCommitScrollOffset(m_committedScrollOffset);

    m_changeMask = NoChanges;
}
Esempio n. 12
0
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
    const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
{    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, dstRect, solidColor(), op);
        return;
    }
    
    FloatSize tileScale = tileScaleFactor;
    FloatSize spacing;
    
    // FIXME: These rules follow CSS border-image rules, but they should not be down here in Image.
    bool centerOnGapHorizonally = false;
    bool centerOnGapVertically = false;
    switch (hRule) {
    case RoundTile: {
        int numItems = std::max<int>(floorf(dstRect.width() / srcRect.width()), 1);
        tileScale.setWidth(dstRect.width() / (srcRect.width() * numItems));
        break;
    }
    case SpaceTile: {
        int numItems = floorf(dstRect.width() / srcRect.width());
        if (!numItems)
            return;
        spacing.setWidth((dstRect.width() - srcRect.width() * numItems) / (numItems + 1));
        tileScale.setWidth(1);
        centerOnGapHorizonally = !(numItems & 1);
        break;
    }
    case StretchTile:
    case RepeatTile:
        break;
    }

    switch (vRule) {
    case RoundTile: {
        int numItems = std::max<int>(floorf(dstRect.height() / srcRect.height()), 1);
        tileScale.setHeight(dstRect.height() / (srcRect.height() * numItems));
        break;
        }
    case SpaceTile: {
        int numItems = floorf(dstRect.height() / srcRect.height());
        if (!numItems)
            return;
        spacing.setHeight((dstRect.height() - srcRect.height() * numItems) / (numItems + 1));
        tileScale.setHeight(1);
        centerOnGapVertically = !(numItems & 1);
        break;
    }
    case StretchTile:
    case RepeatTile:
        break;
    }

    AffineTransform patternTransform = AffineTransform().scaleNonUniform(tileScale.width(), tileScale.height());

    // We want to construct the phase such that the pattern is centered (when stretch is not
    // set for a particular rule).
    float hPhase = tileScale.width() * srcRect.x();
    float vPhase = tileScale.height() * srcRect.y();
    float scaledTileWidth = tileScale.width() * srcRect.width();
    float scaledTileHeight = tileScale.height() * srcRect.height();

    if (centerOnGapHorizonally)
        hPhase -= spacing.width();
    else if (hRule == Image::RepeatTile || hRule == Image::SpaceTile)
        hPhase -= (dstRect.width() - scaledTileWidth) / 2;

    if (centerOnGapVertically)
        vPhase -= spacing.height();
    else if (vRule == Image::RepeatTile || vRule == Image::SpaceTile)
        vPhase -= (dstRect.height() - scaledTileHeight) / 2;

    FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
    drawPattern(ctxt, srcRect, patternTransform, patternPhase, spacing, op, dstRect);

#if PLATFORM(IOS)
    startAnimation(DoNotCatchUp);
#else
    startAnimation();
#endif
}
Esempio n. 13
0
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
    FloatRect srcRect(src);
    FloatRect dstRect(dst);

    if (dstRect.width() == 0.0f || dstRect.height() == 0.0f ||
        srcRect.width() == 0.0f || srcRect.height() == 0.0f)
        return;

    startAnimation();

    cairo_surface_t* image = frameAtIndex(m_currentFrame);
    if (!image) // If it's too early we won't have an image yet.
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op);
        return;
    }

    IntSize selfSize = size();

    cairo_t* cr = context->platformContext();
    context->save();

    // Set the compositing operation.
    if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
        context->setCompositeOperation(CompositeCopy);
    else
        context->setCompositeOperation(op);

    // If we're drawing a sub portion of the image or scaling then create
    // a pattern transformation on the image and draw the transformed pattern.
    // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);

    cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);

    float scaleX = srcRect.width() / dstRect.width();
    float scaleY = srcRect.height() / dstRect.height();
    cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
    cairo_pattern_set_matrix(pattern, &matrix);

    // Draw the shadow
#if ENABLE(FILTERS)
    FloatSize shadowOffset;
    float shadowBlur;
    Color shadowColor;
    if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) {
        IntSize shadowBufferSize;
        FloatRect shadowRect;
        float radius = 0;
        context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur);
        shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() *  context->getAlpha()) / 255.f);

        //draw shadow into a new ImageBuffer
        OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
        cairo_t* shadowContext = shadowBuffer->context()->platformContext();
        cairo_set_source(shadowContext, pattern);
        cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
        cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
        cairo_fill(shadowContext);

        context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
    }
#endif

    // Draw the image.
    cairo_translate(cr, dstRect.x(), dstRect.y());
    cairo_set_source(cr, pattern);
    cairo_pattern_destroy(pattern);
    cairo_rectangle(cr, 0, 0, dstRect.width(), dstRect.height());
    cairo_clip(cr);
    cairo_paint_with_alpha(cr, context->getAlpha());

    context->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 14
0
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
{    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), op);
        return;
    }

    ASSERT(!isBitmapImage() || notSolidColor());

#if PLATFORM(IOS)
    FloatSize intrinsicTileSize = originalSize();
#else
    FloatSize intrinsicTileSize = size();
#endif
    if (hasRelativeWidth())
        intrinsicTileSize.setWidth(scaledTileSize.width());
    if (hasRelativeHeight())
        intrinsicTileSize.setHeight(scaledTileSize.height());

    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
                    scaledTileSize.height() / intrinsicTileSize.height());

    FloatRect oneTileRect;
    FloatSize actualTileSize(scaledTileSize.width() + spacing.width(), scaledTileSize.height() + spacing.height());
    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
    oneTileRect.setSize(scaledTileSize);
    
    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.
    if (oneTileRect.contains(destRect) && !ctxt.drawLuminanceMask()) {
        FloatRect visibleSrcRect;
        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
        visibleSrcRect.setWidth(destRect.width() / scale.width());
        visibleSrcRect.setHeight(destRect.height() / scale.height());
        draw(ctxt, destRect, visibleSrcRect, op, blendMode, ImageOrientationDescription());
        return;
    }

#if PLATFORM(IOS)
    // When using accelerated drawing on iOS, it's faster to stretch an image than to tile it.
    if (ctxt.isAcceleratedContext()) {
        if (size().width() == 1 && intersection(oneTileRect, destRect).height() == destRect.height()) {
            FloatRect visibleSrcRect;
            visibleSrcRect.setX(0);
            visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
            visibleSrcRect.setWidth(1);
            visibleSrcRect.setHeight(destRect.height() / scale.height());
            draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription());
            return;
        }
        if (size().height() == 1 && intersection(oneTileRect, destRect).width() == destRect.width()) {
            FloatRect visibleSrcRect;
            visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
            visibleSrcRect.setY(0);
            visibleSrcRect.setWidth(destRect.width() / scale.width());
            visibleSrcRect.setHeight(1);
            draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription());
            return;
        }
    }
#endif

    // Patterned images and gradients can use lots of memory for caching when the
    // tile size is large (<rdar://problem/4691859>, <rdar://problem/6239505>).
    // Memory consumption depends on the transformed tile size which can get
    // larger than the original tile if user zooms in enough.
#if PLATFORM(IOS)
    const float maxPatternTilePixels = 512 * 512;
#else
    const float maxPatternTilePixels = 2048 * 2048;
#endif
    FloatRect transformedTileSize = ctxt.getCTM().mapRect(FloatRect(FloatPoint(), scaledTileSize));
    float transformedTileSizePixels = transformedTileSize.width() * transformedTileSize.height();
    FloatRect currentTileRect = oneTileRect;
    if (transformedTileSizePixels > maxPatternTilePixels) {
        GraphicsContextStateSaver stateSaver(ctxt);
        ctxt.clip(destRect);

        currentTileRect.shiftYEdgeTo(destRect.y());
        float toY = currentTileRect.y();
        while (toY < destRect.maxY()) {
            currentTileRect.shiftXEdgeTo(destRect.x());
            float toX = currentTileRect.x();
            while (toX < destRect.maxX()) {
                FloatRect toRect(toX, toY, currentTileRect.width(), currentTileRect.height());
                FloatRect fromRect(toFloatPoint(currentTileRect.location() - oneTileRect.location()), currentTileRect.size());
                fromRect.scale(1 / scale.width(), 1 / scale.height());

                draw(ctxt, toRect, fromRect, op, BlendModeNormal, ImageOrientationDescription());
                toX += currentTileRect.width();
                currentTileRect.shiftXEdgeTo(oneTileRect.x());
            }
            toY += currentTileRect.height();
            currentTileRect.shiftYEdgeTo(oneTileRect.y());
        }
        return;
    }

    AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height());
    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
    drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), spacing, op, destRect, blendMode);

#if PLATFORM(IOS)
    startAnimation(DoNotCatchUp);
#else
    startAnimation();
#endif
}
Esempio n. 15
0
void App::onGraphics3D(RenderDevice* rd, Array<shared_ptr<Surface> >& allSurfaces) {
    // This implementation is equivalent to the default GApp's. It is repeated here to make it
    // easy to modify rendering. If you don't require custom rendering, just delete this
    // method from your application and rely on the base class.

    if (!scene()) {
        if ((submitToDisplayMode() == SubmitToDisplayMode::MAXIMIZE_THROUGHPUT) && (!rd->swapBuffersAutomatically())) {
            swapBuffers();
        }
        rd->clear();
        rd->pushState(); {
            rd->setProjectionAndCameraMatrix(activeCamera()->projection(), activeCamera()->frame());
            drawDebugShapes();
        } rd->popState();
        return;
    }

    updateAudioData();

    if (System::time() - m_lastInterestingEventTime > 10.0) {
        if (Random::common().uniform() < 0.001f) {
            if (m_sonicSculpturePieces.size() > 0) {
                int index = Random::common().integer(0, m_sonicSculpturePieces.size() - 1);
                generatePlayPulse(m_sonicSculpturePieces[index]);
                m_lastInterestingEventTime = System::time();
            }
        }
    }
    handlePlayPulses();

    GBuffer::Specification gbufferSpec = m_gbufferSpecification;
    extendGBufferSpecification(gbufferSpec);
    m_gbuffer->setSpecification(gbufferSpec);
    m_gbuffer->resize(m_framebuffer->width(), m_framebuffer->height());
    m_gbuffer->prepare(rd, activeCamera(), 0, -(float)previousSimTimeStep(), m_settings.depthGuardBandThickness, m_settings.colorGuardBandThickness);

    m_renderer->render(rd, m_framebuffer, m_depthPeelFramebuffer, scene()->lightingEnvironment(), m_gbuffer, allSurfaces);

    // Debug visualizations and post-process effects
    rd->pushState(m_framebuffer); {
        // Call to make the App show the output of debugDraw(...)
        rd->setProjectionAndCameraMatrix(activeCamera()->projection(), activeCamera()->frame());

        for (auto& piece : m_sonicSculpturePieces) {
            piece->render(rd, scene()->lightingEnvironment());
        }
        if (notNull(m_currentSonicSculpturePiece)) {
            m_currentSonicSculpturePiece->render(rd, scene()->lightingEnvironment());
        }
        for (int i = m_playPlanes.size() - 1; i >= 0; --i) {
	        const PlayPlane& pp = m_playPlanes[i];
	        if (pp.endWindowIndex < g_sampleWindowIndex) {
	            m_playPlanes.remove(i);
	        }

	        Point3 point = pp.origin + (pp.direction * METERS_PER_SAMPLE_WINDOW * (g_sampleWindowIndex-pp.beginWindowIndex));

	        Color4 solidColor(1.0f, .02f, .03f, .15f);
	        //	  Plane plane(point, pp.direction);
	        //	  Draw::plane(plane, rd, solidColor, Color4::clear());

	        CFrame planeFrame = pp.frame;
	        planeFrame.translation = point;
            Vector3 minP(finf(), finf(), finf());
            Vector3 maxP(-finf(), -finf(), -finf());
            for (auto& piece : m_sonicSculpturePieces) {
                piece->minMaxValue(planeFrame, minP, maxP);
            }
            Box b(Vector3(minP.xy()-Vector2(3,3), 0.0f), Vector3(maxP.xy() + Vector2(3, 3), 0.1f), planeFrame);

            Draw::box(b, rd, solidColor, Color4::clear());
        }


        drawDebugShapes();
        const shared_ptr<Entity>& selectedEntity = (notNull(developerWindow) && notNull(developerWindow->sceneEditorWindow)) ? developerWindow->sceneEditorWindow->selectedEntity() : shared_ptr<Entity>();
        scene()->visualize(rd, selectedEntity, allSurfaces, sceneVisualizationSettings(), activeCamera());

        // Post-process special effects
        m_depthOfField->apply(rd, m_framebuffer->texture(0), m_framebuffer->texture(Framebuffer::DEPTH), activeCamera(), m_settings.depthGuardBandThickness - m_settings.colorGuardBandThickness);

        m_motionBlur->apply(rd, m_framebuffer->texture(0), m_gbuffer->texture(GBuffer::Field::SS_EXPRESSIVE_MOTION),
            m_framebuffer->texture(Framebuffer::DEPTH), activeCamera(),
            m_settings.depthGuardBandThickness - m_settings.colorGuardBandThickness);
    } rd->popState();

    rd->push2D(m_framebuffer); {
        rd->setBlendFunc(RenderDevice::BLEND_SRC_ALPHA, RenderDevice::BLEND_ONE_MINUS_SRC_ALPHA);
        Array<SoundInstance> soundInstances;
        Synthesizer::global->getSoundInstances(soundInstances);
        int xOffset = 10;
        Vector2 dim(256,100);
        for (int i = 0; i < soundInstances.size(); ++i) {
            int yOffset = rd->height() - 120 - (120 * i);
            Draw::rect2D(Rect2D::xywh(Point2(xOffset, yOffset), dim), rd, Color3::white(), soundInstances[i].displayTexture());
            float playheadAlpha = ((float)soundInstances[i].currentPosition) / soundInstances[i].audioSample->buffer.size();
            float playheadX = xOffset + (playheadAlpha * dim.x);
            Draw::rect2D(Rect2D::xywh(Point2(playheadX, yOffset), Vector2(1, dim.y)), rd, Color3::yellow());
        }


	
	static shared_ptr<GFont> font = GFont::fromFile(System::findDataFile("arial.fnt"));
	float time = System::time() - m_initialTime;
	if (time < 10.0f) {
	  float fontAlpha = time < 9.0f ? 1.0f : 10.0f - time;
	  font->draw2D(rd, "Press Space to Sculpt", Vector2(rd->width()/2, rd->height()-100.0f), 30.0f, Color4(Color3::black(), fontAlpha), Color4(Color3::white()*0.6f, fontAlpha), GFont::XALIGN_CENTER);
	}
    } rd->pop2D();

    if ((submitToDisplayMode() == SubmitToDisplayMode::MAXIMIZE_THROUGHPUT) && (!renderDevice->swapBuffersAutomatically())) {
        // We're about to render to the actual back buffer, so swap the buffers now.
        // This call also allows the screenshot and video recording to capture the
        // previous frame just before it is displayed.
        swapBuffers();
    }

    // Clear the entire screen (needed even though we'll render over it, since
    // AFR uses clear() to detect that the buffer is not re-used.)
    rd->clear();

    // Perform gamma correction, bloom, and SSAA, and write to the native window frame buffer
    m_film->exposeAndRender(rd, activeCamera()->filmSettings(), m_framebuffer->texture(0));
}
Esempio n. 16
0
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
{
    SDL_Surface* image = frameAtIndex(m_currentFrame);
    if (!image) // If it's too early we won't have an image yet.
        return;

    FloatRect sourceRect(src);
    FloatRect destRect(dst);

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(context, destRect, solidColor(), op);
        return;
    }

    // Set the compositing operation.
    if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
        context->setCompositeOperation(CompositeCopy);
    else
        context->setCompositeOperation(op);

    SDL_Surface* cr = context->platformContext();

    float scaleX = destRect.width() / sourceRect.width();
    float scaleY = destRect.height() / sourceRect.height();

    // Draw the image.
    SDL_Rect srcRect, dstRect;

    srcRect.x = static_cast<Sint16>(src.x());
    srcRect.y = static_cast<Sint16>(src.y());
    if (0 == sourceRect.width())
        srcRect.w = image->w;
    else
        srcRect.w = static_cast<Uint16>(sourceRect.width());
    if (0 == sourceRect.height())
        srcRect.h = image->h;
    else
        srcRect.h = static_cast<Uint16>(sourceRect.height());


    dstRect.x = static_cast<Sint16>(destRect.x() + context->origin().x());
    dstRect.y = static_cast<Sint16>(destRect.y() + context->origin().y());
    dstRect.w = static_cast<Sint16>(destRect.width());
    dstRect.h = static_cast<Sint16>(destRect.height());

    if ((scaleX != 1.0)||(scaleY != 1.0)) {
        srcRect.x = static_cast<Sint16>(src.x() * scaleX);
        srcRect.y = static_cast<Sint16>(src.y() * scaleY);
        srcRect.w = dstRect.w;
        srcRect.h = dstRect.h;
    }


    if (sourceRect != destRect) {
        if (context->transparencyLayer() == 1.0) {
            if ((scaleX != 1.0) || (scaleY != 1.0)) {
                SDL_Surface *surface = zoomSurface(image, scaleX, scaleY, SMOOTHING_OFF);
                SDL_BlitSurface(surface, &srcRect, cr, &dstRect);
                SDL_FreeSurface(surface);
            } else
                SDL_BlitSurface(image, &srcRect, cr, &dstRect);
        }
        else {
            SDL_Surface *surfaceWithAlpha = applyTransparency(image, static_cast<int> (context->transparencyLayer() * 255));
            if ((scaleX != 1.0) || (scaleY != 1.0)) {
                SDL_Surface *surface = zoomSurface(surfaceWithAlpha, scaleX, scaleY, SMOOTHING_OFF);
                SDL_BlitSurface(surface, &srcRect, cr, &dstRect);
                SDL_FreeSurface(surface);
            } else
                SDL_BlitSurface(surfaceWithAlpha, &srcRect, cr, &dstRect);

            SDL_FreeSurface(surfaceWithAlpha);
        }
    } else if (context->transparencyLayer() == 1.0)
        SDL_BlitSurface(image, &srcRect, cr, &dstRect);
    else {
        SDL_Surface *surfaceWithAlpha = applyTransparency(image, static_cast<int> (context->transparencyLayer() * 255));
        SDL_BlitSurface(surfaceWithAlpha, &srcRect, cr, &dstRect);
        SDL_FreeSurface(surfaceWithAlpha);
    }

    startAnimation();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 17
0
void BitmapImage::readyWRATHWidgets(PaintedWidgetsOfWRATHHandleT<Image>& handle, ContextOfWRATH *ctx,
                                    const FloatRect& dst, const FloatRect& src,
                                    ColorSpace styleColorSpace, CompositeOperator op)
{
    BitmapImage_readyWRATHWidgets *d(BitmapImage_readyWRATHWidgets::object(this, handle));

    ContextOfWRATH::AutoPushNode autoPushRoot(ctx, d->m_root_node);

    d->m_solid_color.visible(false);
    if (d->m_image_rect_item.widget())
        d->m_image_rect_item.widget()->visible(false);

    FloatRect normalizedDst = dst.normalized();
    FloatRect normalizedSrc = src.normalized();

    startAnimation();

    if (normalizedSrc.isEmpty() || normalizedDst.isEmpty())
        return;

    NativeImagePtr nativeImage = nativeImageForCurrentFrame();
    if (!nativeImage)
        return;

    // "Hardcode" the requirement for the underlying wrath image type to WRATHImage.
    // The reason is support for setting texture coordinates, which isn't possible for WRATHCompoundImage
    WRATHImage* image = nativeImage->getWrathImage();
    if (!image)
        return;

    if (mayFillWithSolidColor()) {
        d->m_solid_color.visible(true);
        readyWRATHWidgetSolidColor(d->m_solid_color, ctx, this, normalizedDst, solidColor(), styleColorSpace, op);
        return;
    }

    // ImageRectOfWRATH methods handle changing the op with respect to composite operator
    /*
    CompositeOperator previousOperator = ctxt->compositeOperation();
    ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
    */
    if(!nativeImage->hasAlpha() && op == CompositeSourceOver)
      {
        op=CompositeCopy;
      }
    
    /*
      [WRATH-DANGER]: No shadows

    ContextShadow* shadow = ctxt->contextShadow();
    if (shadow->m_type != ContextShadow::NoShadow) {
        QPainter* shadowPainter = shadow->beginShadowLayer(ctxt, normalizedDst);
        if (shadowPainter) {
            shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
            shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc);
            shadow->endShadowLayer(ctxt);
        }
    }
    */

    /*
      [WRATH-DANGER]: Possible rounding errors from converting to IntRect
     */
    d->m_image_rect_item.update(ctx, nativeImage,
                                normalizedDst, IntRect(normalizedSrc),
                                op);
    if (d->m_image_rect_item.widget())
      d->m_image_rect_item.widget()->visible(true);

    /*
      ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc);
    */

    /*
    ctxt->setCompositeOperation(previousOperator);
    */

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Esempio n. 18
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
    if (!m_source.initialized())
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
        return;
    }

#if USE(WXGC)
    wxGCDC* context = (wxGCDC*)ctxt->platformContext();
    wxGraphicsContext* gc = context->GetGraphicsContext();
    wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame);
#else
    wxDC* context = ctxt->platformContext();
    wxBitmap* bitmap = frameAtIndex(m_currentFrame);
#endif

    startAnimation();
    if (!bitmap) // If it's too early we won't have an image yet.
        return;
    
    // If we're drawing a sub portion of the image or scaling then create
    // a pattern transformation on the image and draw the transformed pattern.
    // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
    // FIXME: NYI
   
    ctxt->save();

    // Set the compositing operation.
    ctxt->setCompositeOperation(op);
    
#if USE(WXGC)
    float scaleX = src.width() / dst.width();
    float scaleY = src.height() / dst.height();

    FloatRect adjustedDestRect = dst;
    FloatSize selfSize = currentFrameSize();
    
    if (src.size() != selfSize) {
        adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY));
        adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY));
    }

    gc->Clip(dst.x(), dst.y(), dst.width(), dst.height());
#if wxCHECK_VERSION(2,9,0)
    gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
#else
    gc->DrawGraphicsBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
#endif

#else // USE(WXGC)
    bitmap = getCachedResizedBitmap(bitmap, dst.size(), src);
    context->DrawBitmap(*bitmap, dst.x(), dst.y(), true);
#endif

    ctxt->restore();

    if (ImageObserver* observer = imageObserver())
        observer->didDraw(this);
}