git-svn-id: http://skia.googlecode.com/svn/trunk@409 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-10-28 14:25:34 +00:00
Родитель b577b41c8e
Коммит 2ee7c64015
6 изменённых файлов: 326 добавлений и 174 удалений

Просмотреть файл

@ -1,20 +1,14 @@
#include "SkBoundaryPatch.h"
SkBoundaryPatch::SkBoundaryPatch() {
sk_bzero(fCurve, sizeof(fCurve));
};
SkBoundaryPatch::SkBoundaryPatch() : fBoundary(NULL) {}
SkBoundaryPatch::~SkBoundaryPatch() {
for (int i = 0; i < 4; i++) {
SkSafeUnref(fCurve[i]);
}
SkSafeUnref(fBoundary);
}
SkBoundaryCurve* SkBoundaryPatch::setCurve(Edge e, SkBoundaryCurve* curve) {
SkASSERT((unsigned)e < 4);
SkRefCnt_SafeAssign(fCurve[e], curve);
return curve;
SkBoundary* SkBoundaryPatch::setBoundary(SkBoundary* b) {
SkRefCnt_SafeAssign(fBoundary, b);
return b;
}
static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
@ -28,27 +22,52 @@ static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) {
SkScalarInterp(a.fY, b.fY, t));
}
SkPoint SkBoundaryPatch::evaluate(SkScalar unitU, SkScalar unitV) {
SkPoint u = SkPointInterp(fCurve[kLeft]->evaluate(unitV),
fCurve[kRight]->evaluate(unitV), unitU);
SkPoint v = SkPointInterp(fCurve[kTop]->evaluate(unitU),
fCurve[kBottom]->evaluate(unitU), unitV);
SkPoint SkBoundaryPatch::eval(SkScalar unitU, SkScalar unitV) {
SkBoundary* b = fBoundary;
SkPoint u = SkPointInterp(b->eval(SkBoundary::kLeft, SK_Scalar1 - unitV),
b->eval(SkBoundary::kRight, unitV),
unitU);
SkPoint v = SkPointInterp(b->eval(SkBoundary::kTop, unitU),
b->eval(SkBoundary::kBottom, SK_Scalar1 - unitU),
unitV);
return SkMakePoint(SkScalarAve(u.fX, v.fX),
SkScalarAve(u.fY, v.fY));
}
bool SkBoundaryPatch::evalPatch(SkPoint verts[], int rows, int cols) {
if (rows < 2 || cols < 2) {
return false;
}
const SkScalar invR = SkScalarInvert(SkIntToScalar(rows - 1));
const SkScalar invC = SkScalarInvert(SkIntToScalar(cols - 1));
for (int y = 0; y < cols; y++) {
SkScalar yy = y * invC;
for (int x = 0; x < rows; x++) {
*verts++ = this->eval(x * invR, yy);
}
}
return true;
}
////////////////////////////////////////////////////////////////////////
#include "SkGeometry.h"
SkPoint SkLineBoundaryCurve::evaluate(SkScalar t) {
return SkPointInterp(fPts[0], fPts[1], t);
SkPoint SkLineBoundary::eval(Edge e, SkScalar t) {
SkASSERT((unsigned)e < 4);
return SkPointInterp(fPts[e], fPts[(e + 1) & 3], t);
}
SkPoint SkCubicBoundaryCurve::evaluate(SkScalar t) {
SkPoint SkCubicBoundary::eval(Edge e, SkScalar t) {
SkASSERT((unsigned)e < 4);
// ensure our 4th cubic wraps to the start of the first
fPts[12] = fPts[0];
SkPoint loc;
SkEvalCubicAt(fPts, t, &loc, NULL, NULL);
SkEvalCubicAt(&fPts[e * 3], t, &loc, NULL, NULL);
return loc;
}

Просмотреть файл

@ -4,9 +4,17 @@
#include "SkPoint.h"
#include "SkRefCnt.h"
class SkBoundaryCurve : public SkRefCnt {
class SkBoundary : public SkRefCnt {
public:
virtual SkPoint evaluate(SkScalar unitInterval) = 0;
// These must be 0, 1, 2, 3 for efficiency in the subclass implementations
enum Edge {
kTop = 0,
kRight = 1,
kBottom = 2,
kLeft = 3
};
// Edge index goes clockwise around the boundary, beginning at the "top"
virtual SkPoint eval(Edge, SkScalar unitInterval) = 0;
};
class SkBoundaryPatch {
@ -14,38 +22,33 @@ public:
SkBoundaryPatch();
~SkBoundaryPatch();
enum Edge {
kLeft,
kTop,
kRight,
kBottom
};
SkBoundaryCurve* getCurve(Edge e) const { return fCurve[e]; }
SkBoundaryCurve* setCurve(Edge e, SkBoundaryCurve*);
SkBoundary* getBoundary() const { return fBoundary; }
SkBoundary* setBoundary(SkBoundary*);
SkPoint evaluate(SkScalar unitU, SkScalar unitV);
SkPoint eval(SkScalar unitU, SkScalar unitV);
bool evalPatch(SkPoint verts[], int rows, int cols);
private:
SkBoundaryCurve* fCurve[4];
SkBoundary* fBoundary;
};
////////////////////////////////////////////////////////////////////////
class SkLineBoundaryCurve : public SkBoundaryCurve {
public:
SkPoint fPts[2];
// override
virtual SkPoint evaluate(SkScalar);
};
class SkCubicBoundaryCurve : public SkBoundaryCurve {
class SkLineBoundary : public SkBoundary {
public:
SkPoint fPts[4];
// override
virtual SkPoint evaluate(SkScalar);
virtual SkPoint eval(Edge, SkScalar);
};
class SkCubicBoundary : public SkBoundary {
public:
// the caller sets the first 12 entries. The 13th is used by the impl.
SkPoint fPts[13];
// override
virtual SkPoint eval(Edge, SkScalar);
};
#endif

Просмотреть файл

@ -0,0 +1,43 @@
#ifndef SkMeshUtils_DEFINED
#define SkMeshUtils_DEFINED
#include "SkPoint.h"
#include "SkColor.h"
class SkBitmap;
class SkCanvas;
class SkPaint;
class SkMeshIndices {
public:
SkMeshIndices();
~SkMeshIndices();
bool init(int texW, int texH, int rows, int cols) {
return this->init(NULL, NULL, texW, texH, rows, cols);
}
bool init(SkPoint tex[], uint16_t indices[],
int texW, int texH, int rows, int cols);
size_t indexCount() const { return fIndexCount; }
const uint16_t* indices() const { return fIndices; }
size_t texCount() const { return fTexCount; }
const SkPoint* tex() const { return fTex; }
private:
size_t fIndexCount, fTexCount;
SkPoint* fTex;
uint16_t* fIndices;
void* fStorage; // may be null
};
class SkMeshUtils {
public:
static void Draw(SkCanvas*, const SkBitmap&, int rows, int cols,
const SkPoint verts[], const SkColor colors[],
const SkPaint& paint);
};
#endif

Просмотреть файл

@ -5,6 +5,50 @@
#include "SkAnimator.h"
#include "SkStream.h"
#include "SkColorPriv.h"
static inline void Filter_32_opaque_portable(unsigned x, unsigned y,
SkPMColor a00, SkPMColor a01,
SkPMColor a10, SkPMColor a11,
SkPMColor* dstColor) {
SkASSERT((unsigned)x <= 0xF);
SkASSERT((unsigned)y <= 0xF);
int xy = x * y;
uint32_t mask = gMask_00FF00FF; //0xFF00FF;
int scale = 256 - 16*y - 16*x + xy;
uint32_t lo = (a00 & mask) * scale;
uint32_t hi = ((a00 >> 8) & mask) * scale;
scale = 16*x - xy;
lo += (a01 & mask) * scale;
hi += ((a01 >> 8) & mask) * scale;
scale = 16*y - xy;
lo += (a10 & mask) * scale;
hi += ((a10 >> 8) & mask) * scale;
lo += (a11 & mask) * xy;
hi += ((a11 >> 8) & mask) * xy;
*dstColor = ((lo >> 8) & mask) | (hi & ~mask);
}
static void test_filter() {
for (int r = 0; r <= 0xFF; r++) {
SkPMColor c = SkPackARGB32(0xFF, r, r, r);
for (int y = 0; y <= 0xF; y++) {
for (int x = 0; x <= 0xF; x++) {
SkPMColor dst;
Filter_32_opaque_portable(x, y, c, c, c, c, &dst);
SkASSERT(SkGetPackedA32(dst) == 255);
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
class SkAnimatorView : public SkView {
public:
SkAnimatorView();
@ -30,6 +74,7 @@ private:
};
SkAnimatorView::SkAnimatorView() : fAnimator(NULL) {
test_filter();
}
SkAnimatorView::~SkAnimatorView() {

Просмотреть файл

@ -8,6 +8,8 @@
#include "SkUtils.h"
#include "SkImageDecoder.h"
#include "SkMeshUtils.h"
static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
SkPoint pt;
pt.set(x, y);
@ -21,18 +23,6 @@ static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) {
#include "SkBoundaryPatch.h"
static void set_pts(SkPoint pts[], int R, int C, SkBoundaryPatch* patch) {
SkScalar invR = SkScalarInvert(SkIntToScalar(R - 1));
SkScalar invC = SkScalarInvert(SkIntToScalar(C - 1));
for (int y = 0; y < C; y++) {
SkScalar yy = y * invC;
for (int x = 0; x < R; x++) {
*pts++ = patch->evaluate(x * invR, yy);
}
}
}
static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0,
SkScalar x3, SkScalar y3, SkScalar scale = 1) {
SkPoint tmp, tmp2;
@ -53,82 +43,78 @@ static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0,
pts[2] = tmp + tmp2;
}
static void draw_texture(SkCanvas* canvas, const SkPoint verts[], int R, int C,
const SkBitmap& texture) {
int vertCount = R * C;
const int rows = R - 1;
const int cols = C - 1;
int idxCount = rows * cols * 6;
SkAutoTArray<SkPoint> texStorage(vertCount);
SkPoint* tex = texStorage.get();
SkAutoTArray<uint16_t> idxStorage(idxCount);
uint16_t* idx = idxStorage.get();
const SkScalar dtx = texture.width() / rows;
const SkScalar dty = texture.height() / cols;
int index = 0;
for (int y = 0; y <= cols; y++) {
for (int x = 0; x <= rows; x++) {
tex->set(x*dtx, y*dty);
tex += 1;
if (y < cols && x < rows) {
*idx++ = index;
*idx++ = index + rows + 1;
*idx++ = index + 1;
*idx++ = index + 1;
*idx++ = index + rows + 1;
*idx++ = index + rows + 2;
index += 1;
}
}
index += 1;
}
SkPaint paint;
paint.setShader(SkShader::CreateBitmapShader(texture,
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode))->unref();
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, vertCount, verts,
texStorage.get(), NULL, NULL, idxStorage.get(),
idxCount, paint);
}
static void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) {
SkCubicBoundaryCurve L, T, R, B;
SkCubicBoundary cubic;
set_cubic(cubic.fPts + 0, 0, 0, 100, 0, scale);
set_cubic(cubic.fPts + 3, 100, 0, 100, 100, scale);
set_cubic(cubic.fPts + 6, 100, 100, 0, 100, -scale);
set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
set_cubic(L.fPts, 0, 0, 0, 100, scale);
set_cubic(T.fPts, 0, 0, 100, 0, scale);
set_cubic(R.fPts, 100, 0, 100, 100, -scale);
set_cubic(B.fPts, 0, 100, 100, 100, 0);
SkBoundaryPatch patch;
patch.setCurve(SkBoundaryPatch::kLeft, &L);
patch.setCurve(SkBoundaryPatch::kTop, &T);
patch.setCurve(SkBoundaryPatch::kRight, &R);
patch.setCurve(SkBoundaryPatch::kBottom, &B);
const int Rows = 25;
const int Cols = 25;
patch.setBoundary(&cubic);
const int Rows = 16;
const int Cols = 16;
SkPoint pts[Rows * Cols];
set_pts(pts, Rows, Cols, &patch);
patch.evalPatch(pts, Rows, Cols);
SkPaint paint;
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setStrokeWidth(1);
paint.setStrokeCap(SkPaint::kRound_Cap);
canvas->translate(50, 50);
canvas->scale(3, 3);
SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
}
draw_texture(canvas, pts, Rows, Cols, bm);
// canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(pts),
// pts, paint);
static void test_drag(SkCanvas* canvas, const SkBitmap& bm,
const SkPoint& p0, const SkPoint& p1) {
SkCubicBoundary cubic;
set_cubic(cubic.fPts + 0, 0, 0, 100, 0, 0);
set_cubic(cubic.fPts + 3, 100, 0, 100, 100, 0);
set_cubic(cubic.fPts + 6, 100, 100, 0, 100, 0);
set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
#if 0
cubic.fPts[1] += p1 - p0;
cubic.fPts[2] += p1 - p0;
#else
SkScalar dx = p1.fX - p0.fX;
if (dx > 0) dx = 0;
SkScalar dy = p1.fY - p0.fY;
if (dy > 0) dy = 0;
cubic.fPts[1].fY += dy;
cubic.fPts[2].fY += dy;
cubic.fPts[10].fX += dx;
cubic.fPts[11].fX += dx;
#endif
SkBoundaryPatch patch;
patch.setBoundary(&cubic);
const int Rows = 16;
const int Cols = 16;
SkPoint pts[Rows * Cols];
patch.evalPatch(pts, Rows, Cols);
SkPaint paint;
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setStrokeWidth(1);
paint.setStrokeCap(SkPaint::kRound_Cap);
canvas->translate(50, 50);
canvas->scale(3, 3);
SkAutoCanvasRestore acr(canvas, true);
SkRect r = { 0, 0, 100, 100 };
canvas->clipRect(r);
SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
}
///////////////////////////////////////////////////////////////////////////////
@ -255,7 +241,7 @@ void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) {
///////////////////////////////////////////////////////////////////////////////
static SkScalar gScale = 0;
static SkScalar gDScale = 0.01;
static SkScalar gDScale = 0.02;
class WarpView : public SkView {
Mesh fMesh, fOrig;
@ -263,8 +249,8 @@ class WarpView : public SkView {
public:
WarpView() {
SkBitmap bm;
// SkImageDecoder::DecodeFile("/skimages/beach.jpg", &bm);
SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm);
SkImageDecoder::DecodeFile("/skimages/beach.jpg", &bm);
// SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm);
fBitmap = bm;
SkRect bounds, texture;
@ -275,6 +261,9 @@ public:
// fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture);
fMesh.init(bounds, 30, 30, texture);
fOrig = fMesh;
fP0.set(0, 0);
fP1 = fP0;
}
protected:
@ -287,56 +276,9 @@ protected:
return this->INHERITED::onQuery(evt);
}
static SkPoint make_pt(SkScalar x, SkScalar y) {
SkPoint pt;
pt.set(x, y);
return pt;
}
static SkScalar mapx0(SkScalar min, SkScalar max, SkScalar x0, SkScalar x1,
SkScalar x) {
if (x < x0) {
SkASSERT(x0 > min);
return x1 - SkScalarMulDiv(x1 - min, x0 - x, x0 - min);
} else {
SkASSERT(max > x0);
return x1 + SkScalarMulDiv(max - x1, x - x0, max - x0);
}
}
static SkScalar mapx1(SkScalar min, SkScalar max, SkScalar x0, SkScalar x1,
SkScalar x) {
SkScalar newx;
if (x < x0) {
SkASSERT(x0 > min);
newx = x1 - SkScalarMulDiv(x1 - min, x0 - x, x0 - min);
} else {
SkASSERT(max > x0);
newx = x1 + SkScalarMulDiv(max - x1, x - x0, max - x0);
}
return x + (newx - x) * 0.5f;
}
static SkPoint mappt(const SkRect& r, const SkPoint& p0, const SkPoint& p1,
const SkPoint& pt) {
return make_pt(mapx0(r.fLeft, r.fRight, p0.fX, p1.fX, pt.fX),
mapx0(r.fTop, r.fBottom, p0.fY, p1.fY, pt.fY));
}
void warp(const SkPoint& p0, const SkPoint& p1) {
const SkRect& bounds = fOrig.bounds();
int rows = fMesh.rows();
int cols = fMesh.cols();
SkRect r = bounds;
r.inset(bounds.width() / 256, bounds.height() / 256);
if (r.contains(p0)) {
for (int y = 1; y < cols; y++) {
for (int x = 1; x < rows; x++) {
fMesh.pt(x, y) = mappt(bounds, p0, p1, fOrig.pt(x, y));
}
}
}
fP0 = p0;
fP1 = p1;
}
virtual void onDraw(SkCanvas* canvas) {
@ -352,7 +294,8 @@ protected:
paint.setShader(NULL);
paint.setColor(SK_ColorRED);
// fMesh.draw(canvas, paint);
#if 0
test_patch(canvas, fBitmap, gScale);
gScale += gDScale;
if (gScale > 2) {
@ -361,6 +304,9 @@ protected:
gDScale = -gDScale;
}
this->inval(NULL);
#else
test_drag(canvas, fBitmap, fP0, fP1);
#endif
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
@ -375,7 +321,7 @@ protected:
private:
SkIRect fBase, fRect;
SkPoint fP0, fP1;
typedef SkView INHERITED;
};

96
src/utils/SkMeshUtils.cpp Normal file
Просмотреть файл

@ -0,0 +1,96 @@
#include "SkMeshUtils.h"
#include "SkCanvas.h"
#include "SkPaint.h"
SkMeshIndices::SkMeshIndices() {
sk_bzero(this, sizeof(*this));
}
SkMeshIndices::~SkMeshIndices() {
sk_free(fStorage);
}
bool SkMeshIndices::init(SkPoint tex[], uint16_t indices[],
int texW, int texH, int rows, int cols) {
if (rows < 2 || cols < 2) {
sk_free(fStorage);
fStorage = NULL;
fTex = NULL;
fIndices = NULL;
fTexCount = fIndexCount = 0;
return false;
}
sk_free(fStorage);
fStorage = NULL;
fTexCount = rows * cols;
rows -= 1;
cols -= 1;
fIndexCount = rows * cols * 6;
if (tex) {
fTex = tex;
fIndices = indices;
} else {
fStorage = sk_malloc_throw(fTexCount * sizeof(SkPoint) +
fIndexCount * sizeof(uint16_t));
fTex = (SkPoint*)fStorage;
fIndices = (uint16_t*)(fTex + fTexCount);
}
// compute the indices
{
uint16_t* idx = fIndices;
int index = 0;
for (int y = 0; y < cols; y++) {
for (int x = 0; x < rows; x++) {
*idx++ = index;
*idx++ = index + rows + 1;
*idx++ = index + 1;
*idx++ = index + 1;
*idx++ = index + rows + 1;
*idx++ = index + rows + 2;
index += 1;
}
index += 1;
}
}
// compute texture coordinates
{
SkPoint* tex = fTex;
const SkScalar dx = SkIntToScalar(texW) / rows;
const SkScalar dy = SkIntToScalar(texH) / cols;
for (int y = 0; y <= cols; y++) {
for (int x = 0; x <= rows; x++) {
tex->set(x*dx, y*dy);
tex += 1;
}
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
#include "SkShader.h"
void SkMeshUtils::Draw(SkCanvas* canvas, const SkBitmap& bitmap,
int rows, int cols, const SkPoint verts[],
const SkColor colors[], const SkPaint& paint) {
SkMeshIndices idx;
if (idx.init(bitmap.width(), bitmap.height(), rows, cols)) {
SkPaint p(paint);
p.setShader(SkShader::CreateBitmapShader(bitmap,
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode))->unref();
canvas->drawVertices(SkCanvas::kTriangles_VertexMode,
rows * cols, verts, idx.tex(), colors, NULL,
idx.indices(), idx.indexCount(), p);
}
}