本文整理汇总了C++中AffineTransform::translate方法的典型用法代码示例。如果您正苦于以下问题:C++ AffineTransform::translate方法的具体用法?C++ AffineTransform::translate怎么用?C++ AffineTransform::translate使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类AffineTransform
的用法示例。
在下文中一共展示了AffineTransform::translate方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: drawContentIntoMaskImage
bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, ColorSpace colorSpace, const SVGMaskElement* maskElement, RenderObject* object)
{
GraphicsContext* maskImageContext = maskerData->maskImage->context();
ASSERT(maskImageContext);
// Eventually adjust the mask image context according to the target objectBoundingBox.
AffineTransform maskContentTransformation;
if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
FloatRect objectBoundingBox = object->objectBoundingBox();
maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y());
maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
maskImageContext->concatCTM(maskContentTransformation);
}
// Draw the content into the ImageBuffer.
for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) {
RenderObject* renderer = node->renderer();
if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer)
continue;
if (renderer->needsLayout())
return false;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
SVGImageBufferTools::renderSubtreeToImageBuffer(maskerData->maskImage.get(), renderer, maskContentTransformation);
}
#if !USE(CG)
maskerData->maskImage->transformColorSpace(ColorSpaceDeviceRGB, colorSpace);
#else
UNUSED_PARAM(colorSpace);
#endif
// Create the luminance mask.
maskerData->maskImage->convertToLuminanceMask();
return true;
}
示例2: getAspectRatio
AffineTransform RenderSVGContainer::getAspectRatio(const FloatRect& logical, const FloatRect& physical) const
{
AffineTransform temp;
float logicX = logical.x();
float logicY = logical.y();
float logicWidth = logical.width();
float logicHeight = logical.height();
float physWidth = physical.width();
float physHeight = physical.height();
float vpar = logicWidth / logicHeight;
float svgar = physWidth / physHeight;
if (align() == ALIGN_NONE) {
temp.scale(physWidth / logicWidth, physHeight / logicHeight);
temp.translate(-logicX, -logicY);
} else if ((vpar < svgar && !slice()) || (vpar >= svgar && slice())) {
temp.scale(physHeight / logicHeight, physHeight / logicHeight);
if (align() == ALIGN_XMINYMIN || align() == ALIGN_XMINYMID || align() == ALIGN_XMINYMAX)
temp.translate(-logicX, -logicY);
else if (align() == ALIGN_XMIDYMIN || align() == ALIGN_XMIDYMID || align() == ALIGN_XMIDYMAX)
temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY);
else
temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY);
} else {
temp.scale(physWidth / logicWidth, physWidth / logicWidth);
if (align() == ALIGN_XMINYMIN || align() == ALIGN_XMIDYMIN || align() == ALIGN_XMAXYMIN)
temp.translate(-logicX, -logicY);
else if (align() == ALIGN_XMINYMID || align() == ALIGN_XMIDYMID || align() == ALIGN_XMAXYMID)
temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2);
else
temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth));
}
return temp;
}
示例3: prepareFilterEffect
bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
{
ASSERT(m_haveFilterEffect && renderLayer->filterRenderer());
m_renderLayer = renderLayer;
m_paintInvalidationRect = dirtyRect;
// Prepare a transformation that brings the coordinates into the space
// filter coordinates are defined in.
AffineTransform absoluteTransform;
// FIXME: Should these really be upconverted to doubles and not rounded? crbug.com/350474
absoluteTransform.translate(filterBoxRect.x().toDouble(), filterBoxRect.y().toDouble());
FilterEffectRenderer* filter = renderLayer->filterRenderer();
filter->setAbsoluteTransform(absoluteTransform);
IntRect filterSourceRect = pixelSnappedIntRect(filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect));
if (filterSourceRect.isEmpty()) {
// The dirty rect is not in view, just bail out.
m_haveFilterEffect = false;
return false;
}
m_filterBoxRect = filterBoxRect;
filter->setFilterRegion(filter->mapAbsoluteRectToLocalRect(filterSourceRect));
filter->lastEffect()->determineFilterPrimitiveSubregion(MapRectForward);
bool hasUpdatedBackingStore = filter->updateBackingStoreRect(filterSourceRect);
if (filter->hasFilterThatMovesPixels()) {
if (hasUpdatedBackingStore)
m_paintInvalidationRect = filterSourceRect;
else
m_paintInvalidationRect.intersect(filterSourceRect);
}
return true;
}
示例4: getCTM
AffineTransform SVGPreserveAspectRatio::getCTM(double logicX, double logicY,
double logicWidth, double logicHeight,
double /*physX*/, double /*physY*/,
double physWidth, double physHeight)
{
AffineTransform temp;
if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN)
return temp;
double vpar = logicWidth / logicHeight;
double svgar = physWidth / physHeight;
if (align() == SVG_PRESERVEASPECTRATIO_NONE) {
temp.scale(physWidth / logicWidth, physHeight / logicHeight);
temp.translate(-logicX, -logicY);
} else if (vpar < svgar && (meetOrSlice() == SVG_MEETORSLICE_MEET) || vpar >= svgar && (meetOrSlice() == SVG_MEETORSLICE_SLICE)) {
temp.scale(physHeight / logicHeight, physHeight / logicHeight);
if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX)
temp.translate(-logicX, -logicY);
else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX)
temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY);
else
temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY);
} else {
temp.scale(physWidth / logicWidth, physWidth / logicWidth);
if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN)
temp.translate(-logicX, -logicY);
else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID)
temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2);
else
temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth));
}
return temp;
}
示例5: createMaskImage
void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object)
{
FloatRect objectBoundingBox = object->objectBoundingBox();
// Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present.
maskerData->maskRect = object->repaintRectInLocalCoordinates();
if (maskerData->maskRect.isEmpty()) {
maskerData->emptyMask = true;
return;
}
if (m_maskBoundaries.isEmpty())
calculateMaskContentRepaintRect();
FloatRect repaintRect = m_maskBoundaries;
AffineTransform contextTransform;
// We need to scale repaintRect for objectBoundingBox to get the drawing area.
if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
FloatPoint contextAdjustment = repaintRect.location();
repaintRect = contextTransform.mapRect(repaintRect);
repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y());
contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y());
}
repaintRect.intersect(maskerData->maskRect);
maskerData->maskRect = repaintRect;
IntRect maskImageRect = enclosingIntRect(maskerData->maskRect);
maskImageRect.setLocation(IntPoint());
// Don't create ImageBuffers with image size of 0
if (maskImageRect.isEmpty()) {
maskerData->emptyMask = true;
return;
}
// FIXME: This changes color space to linearRGB, the default color space
// for masking operations in SVG. We need a switch for the other color-space
// attribute values sRGB, inherit and auto.
maskerData->maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB);
if (!maskerData->maskImage)
return;
GraphicsContext* maskImageContext = maskerData->maskImage->context();
ASSERT(maskImageContext);
maskImageContext->save();
if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
maskImageContext->translate(-maskerData->maskRect.x(), -maskerData->maskRect.y());
maskImageContext->concatCTM(contextTransform);
// draw the content into the ImageBuffer
for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) {
RenderObject* renderer = node->renderer();
if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer)
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
renderSubtreeToImage(maskerData->maskImage.get(), renderer);
}
maskImageContext->restore();
// create the luminance mask
RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect));
CanvasPixelArray* srcPixelArray(imageData->data());
for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
unsigned char a = srcPixelArray->get(pixelOffset + 3);
if (!a)
continue;
unsigned char r = srcPixelArray->get(pixelOffset);
unsigned char g = srcPixelArray->get(pixelOffset + 1);
unsigned char b = srcPixelArray->get(pixelOffset + 2);
double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
srcPixelArray->set(pixelOffset + 3, luma);
}
maskerData->maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint());
}
示例6: drawSVGGlyphs
void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const TextRun& run, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
SVGFontElement* fontElement = 0;
SVGFontFaceElement* fontFaceElement = 0;
const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
if (!fontElement || !fontFaceElement)
return;
// We can only paint SVGFonts if a context is available.
RenderSVGResource* activePaintingResource = activePaintingResourceFromRun(run);
RenderObject* renderObject = renderObjectFromRun(run);
RenderObject* parentRenderObject = firstParentRendererForNonTextNode(renderObject);
RenderStyle* parentRenderObjectStyle = 0;
ASSERT(renderObject);
if (!activePaintingResource) {
// TODO: We're only supporting simple filled HTML text so far.
RenderSVGResourceSolidColor* solidPaintingResource = RenderSVGResource::sharedSolidPaintingResource();
solidPaintingResource->setColor(context->fillColor());
activePaintingResource = solidPaintingResource;
}
bool isVerticalText = false;
if (parentRenderObject) {
parentRenderObjectStyle = parentRenderObject->style();
ASSERT(parentRenderObjectStyle);
isVerticalText = parentRenderObjectStyle->svgStyle()->isVerticalWritingMode();
}
float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm());
ASSERT(activePaintingResource);
FloatPoint glyphOrigin;
glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
FloatPoint currentPoint = point;
RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
for (int i = 0; i < numGlyphs; ++i) {
Glyph glyph = glyphBuffer.glyphAt(from + i);
if (!glyph)
continue;
float advance = glyphBuffer.advanceAt(from + i);
SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
ASSERT(!svgGlyph.isPartOfLigature);
ASSERT(svgGlyph.tableEntry == glyph);
SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
// FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
if (svgGlyph.pathData.isEmpty()) {
if (isVerticalText)
currentPoint.move(0, advance);
else
currentPoint.move(advance, 0);
continue;
}
context->save();
if (isVerticalText) {
glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
}
AffineTransform glyphPathTransform;
glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
glyphPathTransform.scale(scale, -scale);
Path glyphPath = svgGlyph.pathData;
glyphPath.transform(glyphPathTransform);
if (activePaintingResource->applyResource(parentRenderObject, parentRenderObjectStyle, context, resourceMode)) {
if (renderObject && renderObject->isSVGInlineText()) {
const RenderSVGInlineText* textRenderer = toRenderSVGInlineText(renderObject);
context->setStrokeThickness(context->strokeThickness() * textRenderer->scalingFactor());
}
activePaintingResource->postApplyResource(parentRenderObject, context, resourceMode, &glyphPath, 0);
}
context->restore();
if (isVerticalText)
currentPoint.move(0, advance);
else
currentPoint.move(advance, 0);
}
}
示例7: applyResource
bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(object);
ASSERT(style);
ASSERT(context);
ASSERT(resourceMode != ApplyToDefaultMode);
// Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further.
// Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
// synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our
// GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node());
if (!gradientElement)
return false;
gradientElement->updateAnimatedSVGAttribute(anyQName());
if (!m_gradient.contains(object))
m_gradient.set(object, new GradientData);
GradientData* gradientData = m_gradient.get(object);
// Create gradient object
if (!gradientData->gradient)
buildGradient(gradientData, gradientElement);
if (!gradientData->gradient)
return false;
// Draw gradient
context->save();
bool isPaintingText = resourceMode & ApplyToTextMode;
if (isPaintingText) {
#if PLATFORM(CG)
if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) {
context->restore();
return false;
}
#endif
context->setTextDrawingMode(resourceMode & ApplyToFillMode ? cTextFill : cTextStroke);
}
AffineTransform transform;
// CG platforms will handle the gradient space transform for text after applying the
// resource, so don't apply it here. For non-CG platforms, we want the text bounding
// box applied to the gradient space transform now, so the gradient shader can use it.
#if PLATFORM(CG)
if (gradientData->boundingBoxMode && !isPaintingText) {
#else
if (gradientData->boundingBoxMode) {
#endif
FloatRect objectBoundingBox = object->objectBoundingBox();
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
}
transform.multiply(gradientData->transform);
gradientData->gradient->setGradientSpaceTransform(transform);
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
if (resourceMode & ApplyToFillMode) {
context->setAlpha(svgStyle->fillOpacity());
context->setFillGradient(gradientData->gradient);
context->setFillRule(svgStyle->fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
context->setAlpha(svgStyle->strokeOpacity());
context->setStrokeGradient(gradientData->gradient);
applyStrokeStyleToContext(context, style, object);
}
return true;
}
void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(context);
ASSERT(resourceMode != ApplyToDefaultMode);
if (resourceMode & ApplyToTextMode) {
#if PLATFORM(CG)
// CG requires special handling for gradient on text
if (m_savedContext && m_gradient.contains(object)) {
GradientData* gradientData = m_gradient.get(object);
// Restore on-screen drawing context
context = m_savedContext;
m_savedContext = 0;
gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, object, gradientData));
context->setFillGradient(gradientData->gradient);
const RenderObject* textRootBlock = findTextRootObject(object);
context->fillRect(textRootBlock->repaintRectInLocalCoordinates());
m_imageBuffer.clear();
//.........这里部分代码省略.........
示例8: contentTransformScope
PassRefPtr<const SkPicture> LayoutSVGResourceClipper::createContentPicture(AffineTransform& contentTransformation, const FloatRect& targetBoundingBox,
GraphicsContext& context)
{
ASSERT(frame());
if (clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
}
if (m_clipContentPicture)
return m_clipContentPicture;
SubtreeContentTransformScope contentTransformScope(contentTransformation);
// Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
// with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
// userSpaceOnUse units (http://crbug.com/294900).
FloatRect bounds = strokeBoundingBox();
SkPictureBuilder pictureBuilder(bounds, nullptr, &context);
for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
LayoutObject* layoutObject = childElement->layoutObject();
if (!layoutObject)
continue;
const ComputedStyle* style = layoutObject->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
bool isUseElement = isSVGUseElement(*childElement);
if (isUseElement) {
const SVGGraphicsElement* clippingElement = toSVGUseElement(*childElement).targetGraphicsElementForClipping();
if (!clippingElement)
continue;
layoutObject = clippingElement->layoutObject();
if (!layoutObject)
continue;
}
// Only shapes, paths and texts are allowed for clipping.
if (!layoutObject->isSVGShape() && !layoutObject->isSVGText())
continue;
if (isUseElement)
layoutObject = childElement->layoutObject();
// Switch to a paint behavior where all children of this <clipPath> will be laid out using special constraints:
// - fill-opacity/stroke-opacity/opacity set to 1
// - masker/filter not applied when laying out the children
// - fill is set to the initial fill paint server (solid, black)
// - stroke is set to the initial stroke paint server (none)
PaintInfo info(pictureBuilder.context(), LayoutRect::infiniteIntRect(), PaintPhaseForeground, GlobalPaintNormalPhase, PaintLayerPaintingRenderingClipPathAsMask);
layoutObject->paint(info, IntPoint());
}
m_clipContentPicture = pictureBuilder.endRecording();
return m_clipContentPicture;
}
示例9: drawSVGGlyphs
void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const TextRun& run, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
SVGFontElement* fontElement = 0;
SVGFontFaceElement* fontFaceElement = 0;
const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
if (!fontElement || !fontFaceElement)
return;
// We can only paint SVGFonts if a context is available.
RenderObject* renderObject = renderObjectFromRun(run);
ASSERT(renderObject);
bool isVerticalText = false;
if (RenderObject* parentRenderObject = firstParentRendererForNonTextNode(renderObject)) {
RenderStyle* parentRenderObjectStyle = parentRenderObject->style();
ASSERT(parentRenderObjectStyle);
isVerticalText = parentRenderObjectStyle->svgStyle().isVerticalWritingMode();
}
float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm());
FloatPoint glyphOrigin;
glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
unsigned short resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
FloatPoint currentPoint = point;
for (int i = 0; i < numGlyphs; ++i) {
Glyph glyph = glyphBuffer.glyphAt(from + i);
if (!glyph)
continue;
float advance = glyphBuffer.advanceAt(from + i);
SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
ASSERT(!svgGlyph.isPartOfLigature);
ASSERT(svgGlyph.tableEntry == glyph);
SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
// FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
if (svgGlyph.pathData.isEmpty()) {
if (isVerticalText)
currentPoint.move(0, advance);
else
currentPoint.move(advance, 0);
continue;
}
if (isVerticalText) {
glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
}
AffineTransform glyphPathTransform;
glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
glyphPathTransform.scale(scale, -scale);
Path glyphPath = svgGlyph.pathData;
glyphPath.transform(glyphPathTransform);
SVGRenderSupport::fillOrStrokePath(context, resourceMode, glyphPath);
if (isVerticalText)
currentPoint.move(0, advance);
else
currentPoint.move(advance, 0);
}
}
示例10: translate
void Path::translate(const FloatSize& size)
{
AffineTransform transformation;
transformation.translate(size.width(), size.height());
transform(transformation);
}
示例11: prepareEffect
bool SVGClipPainter::prepareEffect(const LayoutObject& target,
const FloatRect& targetBoundingBox,
const FloatRect& paintInvalidationRect,
const FloatPoint& layerPositionOffset,
GraphicsContext& context,
ClipperState& clipperState) {
DCHECK_EQ(clipperState, ClipperState::NotApplied);
SECURITY_DCHECK(!m_clip.needsLayout());
m_clip.clearInvalidationMask();
if (paintInvalidationRect.isEmpty() || m_clip.hasCycle())
return false;
SVGClipExpansionCycleHelper inClipExpansionChange(m_clip);
AffineTransform animatedLocalTransform =
toSVGClipPathElement(m_clip.element())->calculateAnimatedLocalTransform();
// When drawing a clip for non-SVG elements, the CTM does not include the zoom
// factor. In this case, we need to apply the zoom scale explicitly - but
// only for clips with userSpaceOnUse units (the zoom is accounted for
// objectBoundingBox-resolved lengths).
if (!target.isSVG() &&
m_clip.clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
DCHECK(m_clip.style());
animatedLocalTransform.scale(m_clip.style()->effectiveZoom());
}
// First, try to apply the clip as a clipPath.
Path clipPath;
if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) {
AffineTransform positionTransform;
positionTransform.translate(layerPositionOffset.x(),
layerPositionOffset.y());
clipPath.transform(positionTransform);
clipperState = ClipperState::AppliedPath;
context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(
target, clipPath);
return true;
}
// Fall back to masking.
clipperState = ClipperState::AppliedMask;
// Begin compositing the clip mask.
CompositingRecorder::beginCompositing(
context, target, SkXfermode::kSrcOver_Mode, 1, &paintInvalidationRect);
{
if (!drawClipAsMask(context, target, targetBoundingBox,
paintInvalidationRect, animatedLocalTransform,
layerPositionOffset)) {
// End the clip mask's compositor.
CompositingRecorder::endCompositing(context, target);
return false;
}
}
// Masked content layer start.
CompositingRecorder::beginCompositing(
context, target, SkXfermode::kSrcIn_Mode, 1, &paintInvalidationRect);
return true;
}
示例12: tryPathOnlyClipping
bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox) {
// If the current clip-path gets clipped itself, we have to fallback to masking.
if (!style()->svgStyle().clipperResource().isEmpty())
return false;
WindRule clipRule = RULE_NONZERO;
Path clipPath = Path();
for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
RenderObject* renderer = childElement->renderer();
if (!renderer)
continue;
// Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
if (renderer->isSVGText())
return false;
if (!childElement->isSVGGraphicsElement())
continue;
SVGGraphicsElement* styled = toSVGGraphicsElement(childElement);
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
const SVGRenderStyle& svgStyle = style->svgStyle();
// Current shape in clip-path gets clipped too. Fallback to masking.
if (!svgStyle.clipperResource().isEmpty())
return false;
if (clipPath.isEmpty()) {
// First clip shape.
styled->toClipPath(clipPath);
clipRule = svgStyle.clipRule();
clipPath.setWindRule(clipRule);
continue;
}
if (RuntimeEnabledFeatures::pathOpsSVGClippingEnabled()) {
// Attempt to generate a combined clip path, fall back to masking if not possible.
Path subPath;
styled->toClipPath(subPath);
subPath.setWindRule(svgStyle.clipRule());
if (!clipPath.unionPath(subPath))
return false;
} else {
return false;
}
}
// Only one visible shape/path was found. Directly continue clipping and transform the content to userspace if necessary.
if (clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
clipPath.transform(transform);
}
// Transform path by animatedLocalTransform.
clipPath.transform(animatedLocalTransform);
// The SVG specification wants us to clip everything, if clip-path doesn't have a child.
if (clipPath.isEmpty())
clipPath.addRect(FloatRect());
context->clipPath(clipPath, clipRule);
return true;
}
示例13: paintObject
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && m_layoutBlock.childrenInline() && !paintInfo.context.paintController().skippingCache()) {
if (m_layoutBlock.paintOffsetChanged(paintOffset)) {
LineBoxListPainter(m_layoutBlock.lineBoxes()).invalidateLineBoxPaintOffsets(paintInfo);
paintInfo.context.paintController().invalidatePaintOffset(m_layoutBlock);
}
// Set previousPaintOffset here in case that m_layoutBlock paints nothing and no
// LayoutObjectDrawingRecorder updates its previousPaintOffset.
// TODO(wangxianzhu): Integrate paint offset checking into new paint invalidation.
m_layoutBlock.mutableForPainting().setPreviousPaintOffset(paintOffset);
}
const PaintPhase paintPhase = paintInfo.phase;
if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhaseBlockBackground)
&& m_layoutBlock.style()->visibility() == VISIBLE
&& m_layoutBlock.hasBoxDecorationBackground())
m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset);
if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == VISIBLE) {
m_layoutBlock.paintMask(paintInfo, paintOffset);
return;
}
if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == VISIBLE) {
BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset);
return;
}
// FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872),
// this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase.
if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting())
ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset);
{
Optional<ScrollRecorder> scrollRecorder;
Optional<PaintInfo> scrolledPaintInfo;
if (m_layoutBlock.hasOverflowClip()) {
IntSize scrollOffset = m_layoutBlock.scrolledContentOffset();
if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) {
scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase, scrollOffset);
scrolledPaintInfo.emplace(paintInfo);
AffineTransform transform;
transform.translate(-scrollOffset.width(), -scrollOffset.height());
scrolledPaintInfo->updateCullRect(transform);
}
}
// We're done. We don't bother painting any children.
if (paintPhase == PaintPhaseSelfBlockBackground || paintInfo.paintRootBackgroundOnly())
return;
const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo;
if (paintPhase != PaintPhaseSelfOutline)
paintContents(contentsPaintInfo, paintOffset);
if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting())
m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks.
if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)
m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset);
}
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() == VISIBLE)
ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset);
// If the caret's node's layout object's containing block is this block, and the paint action is PaintPhaseForeground,
// then paint the caret.
if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutBlock, DisplayItem::Caret, paintOffset)) {
LayoutRect bounds = m_layoutBlock.visualOverflowRect();
bounds.moveBy(paintOffset);
LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutBlock, DisplayItem::Caret, bounds, paintOffset);
paintCarets(paintInfo, paintOffset);
}
}
示例14: paintObject
void BlockPainter::paintObject(const PaintInfo& paintInfo,
const LayoutPoint& paintOffset) {
const PaintPhase paintPhase = paintInfo.phase;
if (shouldPaintSelfBlockBackground(paintPhase)) {
if (m_layoutBlock.style()->visibility() == EVisibility::Visible &&
m_layoutBlock.hasBoxDecorationBackground())
m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset);
// We're done. We don't bother painting any children.
if (paintPhase == PaintPhaseSelfBlockBackgroundOnly)
return;
}
if (paintInfo.paintRootBackgroundOnly())
return;
if (paintPhase == PaintPhaseMask &&
m_layoutBlock.style()->visibility() == EVisibility::Visible) {
m_layoutBlock.paintMask(paintInfo, paintOffset);
return;
}
if (paintPhase == PaintPhaseClippingMask &&
m_layoutBlock.style()->visibility() == EVisibility::Visible) {
BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset);
return;
}
if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting())
ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset);
if (paintPhase != PaintPhaseSelfOutlineOnly) {
Optional<ScopedPaintChunkProperties> m_scopedScrollProperty;
Optional<ScrollRecorder> scrollRecorder;
Optional<PaintInfo> scrolledPaintInfo;
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
const auto* objectProperties = m_layoutBlock.paintProperties();
if (auto* scroll =
objectProperties ? objectProperties->scroll() : nullptr) {
PaintChunkProperties properties(paintInfo.context.getPaintController()
.currentPaintChunkProperties());
auto* scrollTranslation = objectProperties->scrollTranslation();
DCHECK(scrollTranslation);
properties.transform = scrollTranslation;
properties.scroll = scroll;
m_scopedScrollProperty.emplace(
paintInfo.context.getPaintController(), m_layoutBlock,
DisplayItem::paintPhaseToDrawingType(paintPhase), properties);
scrolledPaintInfo.emplace(paintInfo);
scrolledPaintInfo->updateCullRect(
scrollTranslation->matrix().toAffineTransform());
}
} else if (m_layoutBlock.hasOverflowClip()) {
IntSize scrollOffset = m_layoutBlock.scrolledContentOffset();
if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) {
scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase,
scrollOffset);
scrolledPaintInfo.emplace(paintInfo);
AffineTransform transform;
transform.translate(-scrollOffset.width(), -scrollOffset.height());
scrolledPaintInfo->updateCullRect(transform);
}
}
const PaintInfo& contentsPaintInfo =
scrolledPaintInfo ? *scrolledPaintInfo : paintInfo;
if (m_layoutBlock.isLayoutBlockFlow()) {
BlockFlowPainter blockFlowPainter(toLayoutBlockFlow(m_layoutBlock));
blockFlowPainter.paintContents(contentsPaintInfo, paintOffset);
if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection ||
paintPhase == PaintPhaseTextClip)
blockFlowPainter.paintFloats(contentsPaintInfo, paintOffset);
} else {
paintContents(contentsPaintInfo, paintOffset);
}
}
if (shouldPaintSelfOutline(paintPhase))
ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset);
// If the caret's node's layout object's containing block is this block, and
// the paint action is PaintPhaseForeground, then paint the caret.
if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret())
paintCarets(paintInfo, paintOffset);
}
示例15: drawComplexText
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();
}