#include "config.h"
#include "SkiaUtils.h"
#include "ImageBuffer.h"
#include "SharedBuffer.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkMatrix.h"
#include "SkRegion.h"
namespace WebCore {
static const struct CompositOpToPorterDuffMode {
uint8_t mCompositOp;
uint8_t mPorterDuffMode;
} gMapCompositOpsToPorterDuffModes[] = {
{ CompositeClear, SkPorterDuff::kClear_Mode },
{ CompositeCopy, SkPorterDuff::kSrcOver_Mode }, { CompositeSourceOver, SkPorterDuff::kSrcOver_Mode },
{ CompositeSourceIn, SkPorterDuff::kSrcIn_Mode },
{ CompositeSourceOut, SkPorterDuff::kSrcOut_Mode },
{ CompositeSourceAtop, SkPorterDuff::kSrcATop_Mode },
{ CompositeDestinationOver, SkPorterDuff::kDstOver_Mode },
{ CompositeDestinationIn, SkPorterDuff::kDstIn_Mode },
{ CompositeDestinationOut, SkPorterDuff::kDstOut_Mode },
{ CompositeDestinationAtop, SkPorterDuff::kDstATop_Mode },
{ CompositeXOR, SkPorterDuff::kXor_Mode },
{ CompositePlusDarker, SkPorterDuff::kDarken_Mode },
{ CompositeHighlight, SkPorterDuff::kSrcOver_Mode }, { CompositePlusLighter, SkPorterDuff::kLighten_Mode }
};
SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op)
{
const CompositOpToPorterDuffMode* table = gMapCompositOpsToPorterDuffModes;
for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToPorterDuffModes); i++) {
if (table[i].mCompositOp == op)
return (SkPorterDuff::Mode)table[i].mPorterDuffMode;
}
SkDEBUGF(("GraphicsContext::setCompositeOperation uknown CompositeOperator %d\n", op));
return SkPorterDuff::kSrcOver_Mode; }
static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
{
SkASSERT(component == (uint8_t)component);
return (component * scale + 0x8000) >> 16;
}
SkColor SkPMColorToColor(SkPMColor pm)
{
if (0 == pm)
return 0;
unsigned a = SkGetPackedA32(pm);
uint32_t scale = (255 << 16) / a;
return SkColorSetARGB(a,
InvScaleByte(SkGetPackedR32(pm), scale),
InvScaleByte(SkGetPackedG32(pm), scale),
InvScaleByte(SkGetPackedB32(pm), scale));
}
Color SkPMColorToWebCoreColor(SkPMColor pm)
{
return SkPMColorToColor(pm);
}
void IntersectRectAndRegion(const SkRegion& region, const SkRect& srcRect, SkRect* destRect) {
SkIRect srcRectRounded;
srcRect.roundOut(&srcRectRounded);
SkRegion::Cliperator cliperator(region, srcRectRounded);
if (cliperator.done()) {
destRect->setEmpty();
return;
}
SkIRect currentVisibleRect = cliperator.rect();
cliperator.next();
while (!cliperator.done()) {
currentVisibleRect.join(cliperator.rect());
cliperator.next();
}
destRect->set(currentVisibleRect);
}
void ClipRectToCanvas(const SkCanvas& canvas, const SkRect& srcRect, SkRect* destRect) {
SkRect transformedSrc;
canvas.getTotalMatrix().mapRect(&transformedSrc, srcRect);
SkRect transformedDest;
IntersectRectAndRegion(canvas.getTotalClip(), transformedSrc, &transformedDest);
SkMatrix inverseTransform;
canvas.getTotalMatrix().invert(&inverseTransform);
inverseTransform.mapRect(destRect, transformedDest);
}
bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::FillType ft)
{
SkRegion rgn;
SkRegion clip;
SkPath::FillType originalFillType = originalPath->getFillType();
const SkPath* path = originalPath;
SkPath scaledPath;
int scale = 1;
SkRect bounds;
#ifdef SK_USE_OLD_255_TO_256
bounds = originalPath->getBounds();
#else
originalPath->computeBounds(&bounds, SkPath::kFast_BoundsType);
#endif
if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())))
return false;
originalPath->setFillType(ft);
const SkScalar kMaxCoordinate = SkIntToScalar(1<<15);
SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
if (biggestCoord > kMaxCoordinate) {
scale = SkScalarCeil(SkScalarDiv(biggestCoord, kMaxCoordinate));
SkMatrix m;
m.setScale(SkScalarInvert(SkIntToScalar(scale)), SkScalarInvert(SkIntToScalar(scale)));
originalPath->transform(m, &scaledPath);
path = &scaledPath;
}
int x = static_cast<int>(floorf(point.x() / scale));
int y = static_cast<int>(floorf(point.y() / scale));
clip.setRect(x, y, x + 1, y + 1);
bool contains = rgn.setPath(*path, clip);
originalPath->setFillType(originalFillType);
return contains;
}
GraphicsContext* scratchContext()
{
static ImageBuffer* scratch = 0;
if (!scratch)
scratch = ImageBuffer::create(IntSize(1, 1), false).release();
return scratch->context();
}
}