コード例 #1
0
String SVGTransformList::valueAsString() const
{
    // TODO: We may want to build a real transform string, instead of concatting to a matrix(...).
    SVGTransform transform = concatenate();
    if (transform.type() == SVGTransform::SVG_TRANSFORM_MATRIX) {
        TransformationMatrix matrix = transform.matrix();
        return String::format("matrix(%f %f %f %f %f %f)", matrix.a(), matrix.b(), matrix.c(), matrix.d(), matrix.e(), matrix.f());
    }

    return String();
}
コード例 #2
0
void PrintTo(const AnimatableTransform& animTransform, ::std::ostream* os)
{
    TransformOperations ops = animTransform.transformOperations();

    *os << "AnimatableTransform(";
    // FIXME: TransformOperations should really have it's own pretty-printer
    // then we could just call that.
    // FIXME: Output useful names not just the raw matrixes.
    for (unsigned i = 0; i < ops.size(); i++) {
        const TransformOperation* op = ops.at(i);

        TransformationMatrix matrix;
        op->apply(matrix, FloatSize(1.0, 1.0));

        *os << "[";
        if (matrix.isAffine()) {
            *os << matrix.a();
            *os << " " << matrix.b();
            *os << " " << matrix.c();
            *os << " " << matrix.d();
            *os << " " << matrix.e();
            *os << " " << matrix.f();
        } else {
            *os << matrix.m11();
            *os << " " << matrix.m12();
            *os << " " << matrix.m13();
            *os << " " << matrix.m14();
            *os << " ";
            *os << " " << matrix.m21();
            *os << " " << matrix.m22();
            *os << " " << matrix.m23();
            *os << " " << matrix.m24();
            *os << " ";
            *os << " " << matrix.m31();
            *os << " " << matrix.m32();
            *os << " " << matrix.m33();
            *os << " " << matrix.m34();
            *os << " ";
            *os << " " << matrix.m41();
            *os << " " << matrix.m42();
            *os << " " << matrix.m43();
            *os << " " << matrix.m44();
        }
        *os << "]";
        if (i < ops.size() - 1)
            *os << ", ";
    }
    *os << ")";
}
コード例 #3
0
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
                        const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
    cairo_surface_t* image = nativeImageForCurrentFrame();
    if (!image) // If it's too early we won't have an image yet.
        return;

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

    IntRect imageSize = enclosingIntRect(tileRect);
    OwnPtr<ImageBuffer> imageSurface = ImageBuffer::create(imageSize.size(), false);

    if (!imageSurface)
        return;

    if (tileRect.size() != size()) {
        cairo_t* clippedImageContext = imageSurface->context()->platformContext();
        cairo_set_source_surface(clippedImageContext, image, -tileRect.x(), -tileRect.y());
        cairo_paint(clippedImageContext);
        image = imageSurface->image()->nativeImageForCurrentFrame();
    }

    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
    cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);

    // Workaround to avoid the unwanted gradient effect (#14017)
    cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);

    cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
    cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
    cairo_matrix_t combined;
    cairo_matrix_multiply(&combined, &pattern_matrix, &phase_matrix);
    cairo_matrix_invert(&combined);
    cairo_pattern_set_matrix(pattern, &combined);

    context->setCompositeOperation(op);
    cairo_set_source(cr, pattern);
    cairo_pattern_destroy(pattern);
    cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
    cairo_fill(cr);

    context->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
コード例 #4
0
void Image::drawPattern(GraphicsContext *gc, const FloatRect& srcRect, const AffineTransform& patternTransform,
                        const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& destRect, BlendMode)
{
    JNIEnv* env = WebCore_GetJavaEnv();

    if (!gc || gc->paintingDisabled() || srcRect.isEmpty()) {
        return;
    }

    NativeImagePtr currFrame = nativeImageForCurrentFrame();
    if (!currFrame) {
        return;
    }

    TransformationMatrix tm = patternTransform.toTransformationMatrix();

    static jmethodID mid = env->GetMethodID(PG_GetGraphicsManagerClass(env),
                "createTransform",
                "(DDDDDD)Lcom/sun/webkit/graphics/WCTransform;");
    ASSERT(mid);
    JLObject transform(env->CallObjectMethod(PL_GetGraphicsManager(env), mid,
                tm.a(), tm.b(), tm.c(), tm.d(), tm.e(), tm.f()));
    ASSERT(transform);
    CheckAndClearException(env);

    gc->platformContext()->rq().freeSpace(13 * 4)
    << (jint)com_sun_webkit_graphics_GraphicsDecoder_DRAWPATTERN
    << currFrame
    << srcRect.x() << srcRect.y() << srcRect.width() << srcRect.height()
    << RQRef::create(transform)
    << phase.x() << phase.y()
    << destRect.x() << destRect.y() << destRect.width() << destRect.height();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
コード例 #5
0
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
                        const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
    if (!nativeImageForCurrentFrame())
        return;

    ASSERT(patternTransform.isInvertible());
    if (!patternTransform.isInvertible())
        // Avoid a hang under CGContextDrawTiledImage on release builds.
        return;

    CGContextRef context = ctxt->platformContext();
    ctxt->save();
    CGContextClipToRect(context, destRect);
    ctxt->setCompositeOperation(op);
    CGContextTranslateCTM(context, destRect.x(), destRect.y() + destRect.height());
    CGContextScaleCTM(context, 1, -1);
    
    // Compute the scaled tile size.
    float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d());
    
    // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being
    // the origin).
    float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out.
    float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight);

    CGImageRef tileImage = nativeImageForCurrentFrame();
    float h = CGImageGetHeight(tileImage);

    CGImageRef subImage;
    if (tileRect.size() == size())
        subImage = tileImage;
    else {
        // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen
        // because sub-images are only used for border-image, which only renders when the image is fully decoded.
        ASSERT(h == height());
        subImage = CGImageCreateWithImageInRect(tileImage, tileRect);
    }
    
#ifndef BUILDING_ON_TIGER
    // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
    // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the
    // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
    // FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well.
    // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors.  Snow Leopard is ok.
    float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
    float w = CGImageGetWidth(tileImage);
#ifdef BUILDING_ON_LEOPARD
    if (w == size().width() && h == size().height() && scaledTileWidth == tileRect.width() && scaledTileHeight == tileRect.height())
#else
    if (w == size().width() && h == size().height())
#endif
        CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
    else {
#endif

    // On Leopard, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
    // On Tiger this code runs all the time.  This code is suboptimal because the pattern does not reference the image directly, and the
    // pattern is destroyed before exiting the function.  This means any decoding the pattern does doesn't end up cached anywhere, so we
    // redecode every time we paint.
    static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
    CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
    matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
    // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
    matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
    CGPatternRef pattern = CGPatternCreate(subImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()),
                                           matrix, tileRect.width(), tileRect.height(), 
                                           kCGPatternTilingConstantSpacing, true, &patternCallbacks);
    if (pattern == NULL) {
        if (subImage != tileImage)
            CGImageRelease(subImage);
        ctxt->restore();
        return;
    }

    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
    
    CGFloat alpha = 1;
    CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
    CGContextSetFillColorSpace(context, patternSpace);
    CGColorSpaceRelease(patternSpace);
    CGPatternRelease(pattern);

    // FIXME: Really want a public API for this.  It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
    wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
    CGContextSetPatternPhase(context, CGSizeZero);

    CGContextSetFillColorWithColor(context, color);
    CGContextFillRect(context, CGContextGetClipBoundingBox(context));
    
    CGColorRelease(color);
    
#ifndef BUILDING_ON_TIGER
    }
#endif

    if (subImage != tileImage)
        CGImageRelease(subImage);
    ctxt->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
コード例 #6
0
PassOwnPtr<CCTransformKeyframe> CCTransformKeyframe::clone() const
{
    // We need to do a deep copy the m_value may contain ref pointers to TransformOperation objects.
    TransformOperations operations;
    for (size_t j = 0; j < m_value.size(); ++j) {
        TransformOperation::OperationType operationType = m_value.operations()[j]->getOperationType();
        switch (operationType) {
        case TransformOperation::SCALE_X:
        case TransformOperation::SCALE_Y:
        case TransformOperation::SCALE_Z:
        case TransformOperation::SCALE_3D:
        case TransformOperation::SCALE: {
            ScaleTransformOperation* transform = static_cast<ScaleTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(ScaleTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType));
            break;
        }
        case TransformOperation::TRANSLATE_X:
        case TransformOperation::TRANSLATE_Y:
        case TransformOperation::TRANSLATE_Z:
        case TransformOperation::TRANSLATE_3D:
        case TransformOperation::TRANSLATE: {
            TranslateTransformOperation* transform = static_cast<TranslateTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(TranslateTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType));
            break;
        }
        case TransformOperation::ROTATE_X:
        case TransformOperation::ROTATE_Y:
        case TransformOperation::ROTATE_3D:
        case TransformOperation::ROTATE: {
            RotateTransformOperation* transform = static_cast<RotateTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(RotateTransformOperation::create(transform->x(), transform->y(), transform->z(), transform->angle(), operationType));
            break;
        }
        case TransformOperation::SKEW_X:
        case TransformOperation::SKEW_Y:
        case TransformOperation::SKEW: {
            SkewTransformOperation* transform = static_cast<SkewTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(SkewTransformOperation::create(transform->angleX(), transform->angleY(), operationType));
            break;
        }
        case TransformOperation::MATRIX: {
            MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(m_value.operations()[j].get());
            TransformationMatrix m = transform->matrix();
            operations.operations().append(MatrixTransformOperation::create(m.a(), m.b(), m.c(), m.d(), m.e(), m.f()));
            break;
        }
        case TransformOperation::MATRIX_3D: {
            Matrix3DTransformOperation* transform = static_cast<Matrix3DTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(Matrix3DTransformOperation::create(transform->matrix()));
            break;
        }
        case TransformOperation::PERSPECTIVE: {
            PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(m_value.operations()[j].get());
            operations.operations().append(PerspectiveTransformOperation::create(transform->perspective()));
            break;
        }
        case TransformOperation::IDENTITY: {
            operations.operations().append(IdentityTransformOperation::create());
            break;
        }
        case TransformOperation::NONE:
            // Do nothing.
            break;
        } // switch
    } // for each operation

    return CCTransformKeyframe::create(time(), operations, timingFunction() ? cloneTimingFunction(timingFunction()) : nullptr);
}