예제 #1
0
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const
{
    AffineTransform viewBoxTransform;
    if (attributes()->getAttributeItem(SVGNames::viewBoxAttr))
        viewBoxTransform = viewBoxToViewTransform(width().value(this), height().value(this));

    AffineTransform transform;
    if (!isOutermostSVG())
        transform.translate(x().value(this), y().value(this));
    else if (mode == SVGLocatable::ScreenScope) {
        if (RenderObject* renderer = this->renderer()) {
            // Translate in our CSS parent coordinate space
            // FIXME: This doesn't work correctly with CSS transforms.
            FloatPoint location = renderer->localToAbsolute(FloatPoint(), false, true);

            // Be careful here! localToAbsolute() includes the x/y offset coming from the viewBoxToViewTransform(), because
            // RenderSVGRoot::localToBorderBoxTransform() (called through mapLocalToContainer(), called from localToAbsolute())
            // also takes the viewBoxToViewTransform() into account, so we have to subtract it here (original cause of bug #27183)
            transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f());

            // Respect scroll offset.
            if (FrameView* view = document()->view()) {
                IntSize scrollOffset = view->scrollOffset();
                transform.translate(-scrollOffset.width(), -scrollOffset.height());
            }
        }
    }

    return transform.multLeft(viewBoxTransform);
}
void SVGAnimateMotionElement::applyResultsToTarget()
{
    // We accumulate to the target element transform list so there is not much to do here.
    SVGElement* targetElement = this->targetElement();
    if (!targetElement)
        return;

    if (RenderObject* renderer = targetElement->renderer())
        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);

    AffineTransform* t = targetElement->supplementalTransform();
    if (!t)
        return;

    // ...except in case where we have additional instances in <use> trees.
    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
        SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
        ASSERT(shadowTreeElement);
        AffineTransform* transform = shadowTreeElement->supplementalTransform();
        if (!transform)
            continue;
        transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f());
        if (RenderObject* renderer = shadowTreeElement->renderer()) {
            renderer->setNeedsTransformUpdate();
            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
        }
    }
}
AffineTransform SVGGraphicsElement::animatedLocalTransform() const
{
    AffineTransform matrix;
    RenderStyle* style = renderer() ? &renderer()->style() : nullptr;

    // If CSS property was set, use that, otherwise fallback to attribute (if set).
    if (style && style->hasTransform()) {
        // Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath.
        // See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/
        TransformationMatrix transform;
        style->applyTransform(transform, renderer()->objectBoundingBox());

        // Flatten any 3D transform.
        matrix = transform.toAffineTransform();
        // CSS bakes the zoom factor into lengths, including translation components.
        // In order to align CSS & SVG transforms, we need to invert this operation.
        float zoom = style->effectiveZoom();
        if (zoom != 1) {
            matrix.setE(matrix.e() / zoom);
            matrix.setF(matrix.f() / zoom);
        }

    } else
        transform().concatenate(matrix);

    if (m_supplementalTransform)
        return *m_supplementalTransform * matrix;
    return matrix;
}
예제 #4
0
static void drawDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement)
{
    SkiaImageFilterBuilder builder(context);
    SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName()));
    ASSERT(sourceGraphic);
    builder.setSourceGraphic(sourceGraphic);
    RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB);
    FloatRect boundaries = filterData->boundaries;
    context->save();

    FloatSize deviceSize = context->getCTM().mapSize(boundaries.size());
    float scaledArea = deviceSize.width() * deviceSize.height();

    // If area of scaled size is bigger than the upper limit, adjust the scale
    // to fit. Note that this only really matters in the non-impl-side painting
    // case, since the impl-side case never allocates a full-sized backing
    // store, only tile-sized.
    // FIXME: remove this once all platforms are using impl-side painting.
    // crbug.com/169282.
    if (scaledArea > FilterEffect::maxFilterArea()) {
        float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea);
        context->scale(scale, scale);
    }
    // Clip drawing of filtered image to the minimum required paint rect.
    FilterEffect* lastEffect = filterData->builder->lastEffect();
    context->clipRect(lastEffect->determineAbsolutePaintRect(lastEffect->maxEffectRect()));
    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
        // Get boundaries in device coords.
        // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device
        // zoom or High DPI adjustments?
        FloatSize size = context->getCTM().mapSize(boundaries.size());
        // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels.
        float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width();
        float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height();
        // Scale the CTM so the primitive is drawn to filterRes.
        context->scale(filterResScaleX, filterResScaleY);
        // Create a resize filter with the inverse scale.
        AffineTransform resizeMatrix;
        resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY);
        imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get());
    }
    // If the CTM contains rotation or shearing, apply the filter to
    // the unsheared/unrotated matrix, and do the shearing/rotation
    // as a final pass.
    AffineTransform ctm = context->getCTM();
    if (ctm.b() || ctm.c()) {
        AffineTransform scaleAndTranslate;
        scaleAndTranslate.translate(ctm.e(), ctm.f());
        scaleAndTranslate.scale(ctm.xScale(), ctm.yScale());
        ASSERT(scaleAndTranslate.isInvertible());
        AffineTransform shearAndRotate = scaleAndTranslate.inverse();
        shearAndRotate.multiply(ctm);
        context->setCTM(scaleAndTranslate);
        imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get());
    }
    context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get());
    context->endLayer();
    context->restore();
}
예제 #5
0
static v8::Handle<v8::Value> fAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.AffineTransform.f._get");
    V8SVGPODTypeWrapper<AffineTransform>* impWrapper = V8SVGPODTypeWrapper<AffineTransform>::toNative(info.Holder());
    AffineTransform impInstance = *impWrapper;
    AffineTransform* imp = &impInstance;
    return v8::Number::New(imp->f());
}
예제 #6
0
파일: Shader.cpp 프로젝트: dslab-epfl/warr
// static
void Shader::affineTo3x3(const AffineTransform& transform, float mat[9])
{
    mat[0] = transform.a();
    mat[1] = transform.b();
    mat[2] = 0.0f;
    mat[3] = transform.c();
    mat[4] = transform.d();
    mat[5] = 0.0f;
    mat[6] = transform.e();
    mat[7] = transform.f();
    mat[8] = 1.0f;
}
예제 #7
0
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(
    SVGElement::CTMScope mode) const {
  AffineTransform viewBoxTransform;
  if (!hasEmptyViewBox()) {
    FloatSize size = currentViewportSize();
    viewBoxTransform = viewBoxToViewTransform(size.width(), size.height());
  }

  AffineTransform transform;
  if (!isOutermostSVGSVGElement()) {
    SVGLengthContext lengthContext(this);
    transform.translate(m_x->currentValue()->value(lengthContext),
                        m_y->currentValue()->value(lengthContext));
  } else if (mode == SVGElement::ScreenScope) {
    if (LayoutObject* layoutObject = this->layoutObject()) {
      FloatPoint location;
      float zoomFactor = 1;

      // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the
      // localToBorderBoxTransform to map an element from SVG viewport
      // coordinates to CSS box coordinates.  LayoutSVGRoot's localToAbsolute
      // method expects CSS box coordinates.  We also need to adjust for the
      // zoom level factored into CSS coordinates (bug #96361).
      if (layoutObject->isSVGRoot()) {
        location = toLayoutSVGRoot(layoutObject)
                       ->localToBorderBoxTransform()
                       .mapPoint(location);
        zoomFactor = 1 / layoutObject->style()->effectiveZoom();
      }

      // Translate in our CSS parent coordinate space
      // FIXME: This doesn't work correctly with CSS transforms.
      location = layoutObject->localToAbsolute(location, UseTransforms);
      location.scale(zoomFactor, zoomFactor);

      // Be careful here! localToBorderBoxTransform() included the x/y offset
      // coming from the viewBoxToViewTransform(), so we have to subtract it
      // here (original cause of bug #27183)
      transform.translate(location.x() - viewBoxTransform.e(),
                          location.y() - viewBoxTransform.f());

      // Respect scroll offset.
      if (FrameView* view = document().view()) {
        LayoutSize scrollOffset(view->getScrollOffset());
        scrollOffset.scale(zoomFactor);
        transform.translate(-scrollOffset.width(), -scrollOffset.height());
      }
    }
  }

  return transform.multiply(viewBoxTransform);
}
예제 #8
0
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const
{
    AffineTransform viewBoxTransform;
    if (!hasEmptyViewBox()) {
        FloatSize size = currentViewportSize();
        viewBoxTransform = viewBoxToViewTransform(size.width(), size.height());
    }

    AffineTransform transform;
    if (!isOutermostSVGSVGElement()) {
        SVGLengthContext lengthContext(this);
        transform.translate(x().value(lengthContext), y().value(lengthContext));
    } else if (mode == SVGLocatable::ScreenScope) {
        if (auto* renderer = this->renderer()) {
            FloatPoint location;
            float zoomFactor = 1;

            // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform 
            // to map an element from SVG viewport coordinates to CSS box coordinates.
            // RenderSVGRoot's localToAbsolute method expects CSS box coordinates.
            // We also need to adjust for the zoom level factored into CSS coordinates (bug #96361).
            if (is<RenderSVGRoot>(*renderer)) {
                location = downcast<RenderSVGRoot>(*renderer).localToBorderBoxTransform().mapPoint(location);
                zoomFactor = 1 / renderer->style().effectiveZoom();
            }

            // Translate in our CSS parent coordinate space
            // FIXME: This doesn't work correctly with CSS transforms.
            location = renderer->localToAbsolute(location, UseTransforms);
            location.scale(zoomFactor);

            // Be careful here! localToBorderBoxTransform() included the x/y offset coming from the viewBoxToViewTransform(),
            // so we have to subtract it here (original cause of bug #27183)
            transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f());

            // Respect scroll offset.
            if (FrameView* view = document().view()) {
                LayoutPoint scrollPosition = view->scrollPosition();
                scrollPosition.scale(zoomFactor);
                transform.translate(-scrollPosition.x(), -scrollPosition.y());
            }
        }
    }

    return transform.multiply(viewBoxTransform);
}
예제 #9
0
SkMatrix affineTransformToSkMatrix(const AffineTransform& source)
{
    SkMatrix result;

    result.setScaleX(WebCoreDoubleToSkScalar(source.a()));
    result.setSkewX(WebCoreDoubleToSkScalar(source.c()));
    result.setTranslateX(WebCoreDoubleToSkScalar(source.e()));

    result.setScaleY(WebCoreDoubleToSkScalar(source.d()));
    result.setSkewY(WebCoreDoubleToSkScalar(source.b()));
    result.setTranslateY(WebCoreDoubleToSkScalar(source.f()));

    // FIXME: Set perspective properly.
    result.setPerspX(0);
    result.setPerspY(0);
    result.set(SkMatrix::kMPersp2, SK_Scalar1);

    return result;
}
예제 #10
0
static void paintFilteredContent(const LayoutObject& object, GraphicsContext& context, FilterData* filterData)
{
    ASSERT(filterData->m_state == FilterData::ReadyToPaint);
    ASSERT(filterData->filter->sourceGraphic());

    filterData->m_state = FilterData::PaintingFilter;

    SkiaImageFilterBuilder builder;
    RefPtr<SkImageFilter> imageFilter = builder.build(filterData->filter->lastEffect(), ColorSpaceDeviceRGB);
    FloatRect boundaries = filterData->filter->filterRegion();
    context.save();

    // Clip drawing of filtered image to the minimum required paint rect.
    FilterEffect* lastEffect = filterData->filter->lastEffect();
    context.clipRect(lastEffect->determineAbsolutePaintRect(lastEffect->maxEffectRect()));

#ifdef CHECK_CTM_FOR_TRANSFORMED_IMAGEFILTER
    // TODO: Remove this workaround once skew/rotation support is added in Skia
    // (https://code.google.com/p/skia/issues/detail?id=3288, crbug.com/446935).
    // If the CTM contains rotation or shearing, apply the filter to
    // the unsheared/unrotated matrix, and do the shearing/rotation
    // as a final pass.
    AffineTransform ctm = SVGLayoutSupport::deprecatedCalculateTransformToLayer(&object);
    if (ctm.b() || ctm.c()) {
        AffineTransform scaleAndTranslate;
        scaleAndTranslate.translate(ctm.e(), ctm.f());
        scaleAndTranslate.scale(ctm.xScale(), ctm.yScale());
        ASSERT(scaleAndTranslate.isInvertible());
        AffineTransform shearAndRotate = scaleAndTranslate.inverse();
        shearAndRotate.multiply(ctm);
        context.concatCTM(shearAndRotate.inverse());
        imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get());
    }
#endif

    context.beginLayer(1, SkXfermode::kSrcOver_Mode, &boundaries, ColorFilterNone, imageFilter.get());
    context.endLayer();
    context.restore();

    filterData->m_state = FilterData::ReadyToPaint;
}
예제 #11
0
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const
{
    AffineTransform viewBoxTransform;
    if (hasAttribute(SVGNames::viewBoxAttr)) {
        FloatSize size = currentViewportSize();
        viewBoxTransform = viewBoxToViewTransform(size.width(), size.height());
    }

    AffineTransform transform;
    if (!isOutermostSVGSVGElement()) {
        SVGLengthContext lengthContext(this);
        transform.translate(x().value(lengthContext), y().value(lengthContext));
    } else if (mode == SVGLocatable::ScreenScope) {
        if (RenderObject* renderer = this->renderer()) {
            FloatPoint location;
            
            // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform 
            // to map an element from SVG viewport coordinates to CSS box coordinates.
            // RenderSVGRoot's localToAbsolute method expects CSS box coordinates.
            if (renderer->isSVGRoot())
                location = toRenderSVGRoot(renderer)->localToBorderBoxTransform().mapPoint(location);
            
            // Translate in our CSS parent coordinate space
            // FIXME: This doesn't work correctly with CSS transforms.
            location = renderer->localToAbsolute(location, false, true);

            // Be careful here! localToBorderBoxTransform() included the x/y offset coming from the viewBoxToViewTransform(),
            // so we have to subtract it here (original cause of bug #27183)
            transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f());

            // Respect scroll offset.
            if (FrameView* view = document()->view()) {
                LayoutSize scrollOffset = view->scrollOffset();
                transform.translate(-scrollOffset.width(), -scrollOffset.height());
            }
        }
    }

    return transform.multiply(viewBoxTransform);
}
예제 #12
0
static inline void normalizeTransform(AffineTransform& transform)
{
    // Obtain consistent numerical results for the AffineTransform on both 32/64bit platforms.
    // Tested with SnowLeopard on Core Duo vs. Core 2 Duo.
    static const float s_floatEpsilon = std::numeric_limits<float>::epsilon();

    if (fabs(transform.a() - 1) <= s_floatEpsilon)
        transform.setA(1);
    else if (fabs(transform.a() + 1) <= s_floatEpsilon)
        transform.setA(-1);

    if (fabs(transform.d() - 1) <= s_floatEpsilon)
        transform.setD(1);
    else if (fabs(transform.d() + 1) <= s_floatEpsilon)
        transform.setD(-1);

    if (fabs(transform.e()) <= s_floatEpsilon)
        transform.setE(0);

    if (fabs(transform.f()) <= s_floatEpsilon)
        transform.setF(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) {
        AffineTransform 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();
}
예제 #14
0
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
#ifndef NDEBUG
    ASSERT(resourceMode == ApplyToDefaultMode);
#else
    UNUSED_PARAM(resourceMode);
#endif

    // Returning false here, to avoid drawings onto the context. We just want to
    // draw the stored filter output, not the unfiltered object as well.
    if (m_filter.contains(object)) {
        FilterData* filterData = m_filter.get(object);
        if (filterData->builded)
            return false;

        delete m_filter.take(object); // Oops, have to rebuild, go through normal code path
    }

    OwnPtr<FilterData> filterData(new FilterData);
    FloatRect targetBoundingBox = object->objectBoundingBox();

    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
    filterData->boundaries = filterElement->filterBoundingBox(targetBoundingBox);
    if (filterData->boundaries.isEmpty())
        return false;

    // Determine absolute transformation matrix for filter. 
    AffineTransform absoluteTransform;
    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
    if (!absoluteTransform.isInvertible())
        return false;

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

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

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

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

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

    if (scale.isEmpty())
        return false;

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

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

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect)
        return false;

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

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

    absoluteDrawingRegion.scale(scale.width(), scale.height());

    OwnPtr<ImageBuffer> sourceGraphic;
    if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) {
        ASSERT(!m_filter.contains(object));
        filterData->savedContext = context;
        m_filter.set(object, filterData.leakPtr());
        return false;
    }
    
    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
    ASSERT(sourceGraphicContext);
  
    sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y());
    if (scale.width() != 1 || scale.height() != 1)
        sourceGraphicContext->scale(scale);

    sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform);
    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size()));
    filterData->sourceGraphicBuffer = sourceGraphic.release();
    filterData->savedContext = context;

    context = sourceGraphicContext;

    ASSERT(!m_filter.contains(object));
    m_filter.set(object, filterData.leakPtr());

    return true;
}
예제 #15
0
IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
{
    IntRect rect;

    RenderBlock* cb = containingBlock();
    if (!cb || !cb->container())
        return rect;

    RenderSVGRoot* root = findSVGRootObject(parent());
    if (!root)
        return rect;

    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
        rect.unite(box->selectionRect(0, 0, startPos, endPos));

    // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
    int x, y;
    cb->container()->absolutePosition(x, y);

    // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
    // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
    AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();

    FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
    return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
}
예제 #16
0
void GraphicsContext::concatCTM(const AffineTransform& affine)
{
	if (paintingDisabled())
		return;
	//platformContext()->canvas()->concat(affine);
	nvgTransform(platformContext()->canvas(), affine.a(), affine.b(), affine.c(), affine.d(), affine.e(), affine.f());
}
예제 #17
0
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
    const FontPlatformData& fontPlatformData = primaryFont()->platformData();
    const float scaleFactor = fontPlatformData.scaleFactor();
    Olympia::Platform::Text::Font* font = fontPlatformData.font(); // FIXME: use fallback fonts as well?
    Olympia::Platform::Text::DrawParam drawParam;

    String sanitized = setupTextDrawing(this, run, &drawParam);
    adjustOffsetsForTextDrawing(run, from, to);

    SurfaceOpenVG* surface = context->platformContext();
    surface->makeCurrent();

    // Before passing control to Text API, make sure we're ok ourselves.
    ASSERT_VG_NO_ERROR();

    PainterOpenVG* painter = surface->activePainter();
    painter->save();
    painter->setStateModified(PainterOpenVG::AllStateCategories);

    Olympia::Platform::Text::GraphicsContext* textContext = FontPlatformData::textGraphicsContext();

#if PLATFORM(EGL)
    textContext->setDisplay(static_cast<Olympia::Platform::Text::NativeGraphicsDisplay>(surface->eglDisplay()));
    textContext->setSurface(static_cast<Olympia::Platform::Text::NativeGraphicsSurface>(surface->eglSurface()));
    textContext->setContext(static_cast<Olympia::Platform::Text::NativeGraphicsContext>(surface->eglContext()));
    ASSERT_EGL_NO_ERROR();
#endif

    if (painter->textDrawingMode() & cTextClip)
        return; // unsupported for every port except CG at the time of writing
    if (!(painter->textDrawingMode() & cTextFill))
        painter->setFillColor(Color::transparent);
    if (!(painter->textDrawingMode() & cTextStroke))
        painter->setStrokeStyle(NoStroke);

    if (from > 0 || to < sanitized.length()) {
        // Clip to the from-to region. We need to draw the full text
        // (and clip) because characters might change appearance when
        // connected to other characters.
        double fromX;
        FontPlatformData::engine()->textPosToX(from, fromX, *font,
            sanitized.characters(), sanitized.length(), drawParam);
        ASSERT_VG_NO_ERROR();
        fromX *= scaleFactor;

        double toX;
        FontPlatformData::engine()->textPosToX(to, toX, *font,
            sanitized.characters(), sanitized.length(), drawParam);
        ASSERT_VG_NO_ERROR();
        toX *= scaleFactor;

        // FIXME: Some glyphs can be higher than primary font's height.
        // We multiply ascent and descent by 4 so the clip rect will be high
        // enough for all glyphs we know. This is safe because we only apply
        // the clip rect when drawing partial strings, and we are only interested
        // in horizontal clip range.
        const float y = point.y() - primaryFont()->ascent() * 4;
        const float height = (primaryFont()->ascent() + primaryFont()->descent()) * 4;
        FloatRect clipRect = (toX > fromX)
            ? FloatRect(point.x() + fromX, y, toX - fromX, height)
            : FloatRect(point.x() + toX, y, fromX - toX, height);

        painter->clipRect(clipRect, PainterOpenVG::IntersectClip);
    }

    AffineTransform transformation = painter->transformation();
    transformation.translate(point.x(), point.y());
    FloatPoint currentTranslation(transformation.e(), transformation.f());
    transformation.setE(0);
    transformation.setF(0);
    transformation.scale(scaleFactor);
    transformation.setE(roundf(currentTranslation.x()));
    transformation.setF(roundf(currentTranslation.y()));
    painter->setTransformation(transformation);

    if (painter->shadowEnabled()) {
        painter->beginDrawShadow();
        FontPlatformData::engine()->drawText(textContext, *font,
            sanitized.characters(), sanitized.length(), 0, 0,
            0 /* no wrap */, &drawParam, 0 /* returned metrics */);
        painter->endDrawShadow();
    }

    FontPlatformData::engine()->drawText(textContext, *font,
        sanitized.characters(), sanitized.length(), 0, 0,
        0 /* no wrap */, &drawParam, 0 /* returned metrics */);

#if PLATFORM(EGL)
    SurfaceOpenVG* sharedSurface = surface->sharedSurface();
    textContext->setDisplay(static_cast<Olympia::Platform::Text::NativeGraphicsDisplay>(sharedSurface->eglDisplay()));
    textContext->setSurface(static_cast<Olympia::Platform::Text::NativeGraphicsSurface>(sharedSurface->eglSurface()));
    textContext->setContext(static_cast<Olympia::Platform::Text::NativeGraphicsContext>(sharedSurface->eglContext()));
    ASSERT_EGL_NO_ERROR();
#endif

    // Let's make sure Text API didn't cause any troubles.
    ASSERT_VG_NO_ERROR();
    painter->restore();
}
예제 #18
0
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
{
    RenderSVGRoot* root = findSVGRootObject(parent());
    if (!root)
        return;

    int x, y;
    absolutePosition(x, y);

    AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
 
    // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
    // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
            FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
            boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
            rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
        }
    }
}