Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: src/core/SkPatch.cpp

Issue 405163003: SkPatch abstraction (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« include/core/SkPatch.h ('K') | « include/core/SkPatch.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkPatch.cpp
diff --git a/src/core/SkPatch.cpp b/src/core/SkPatch.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8814addae37bb8d6630d8a53b12b1817b9651ba9
--- /dev/null
+++ b/src/core/SkPatch.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPatch.h"
+#include "SkGr.h"
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+CubicEvaluator::CubicEvaluator(SkPoint a, SkPoint b, SkPoint c, SkPoint d){
egdaniel 2014/07/21 21:16:03 There are already some of the eval and coeff calcu
dandov 2014/07/22 13:55:14 I removed the eval function since we already have
+ fPoints[0] = a;
+ fPoints[1] = b;
+ fPoints[2] = c;
+ fPoints[3] = d;
+
+ // save coefficients
+ fCoefs[0].set(-a.x() + 3.0f*b.x() - 3.0f*c.x() + d.x(),
+ -a.y() + 3.0f*b.y() - 3.0f*c.y() + d.y());
+ fCoefs[1].set(3.0f*a.x() - 6.0f*b.x() + 3.0f*c.x(),
+ 3.0f*a.y() - 6.0f*b.y() + 3.0f*c.y());
+ fCoefs[2].set(-3.0f*a.x() + 3.0f*b.x(),
+ -3.0f*a.y() + 3.0f*b.y());
+ fCoefs[3].set(a.x(), a.y());
+}
+
+SkPoint CubicEvaluator::eval(SkScalar t){
+ return SkPoint::Make(fCoefs[0].x()*t*t*t + fCoefs[1].x()*t*t + fCoefs[2].x()*t +
+ fCoefs[3].x(),
+ fCoefs[0].y()*t*t*t + fCoefs[1].y()*t*t + fCoefs[2].y()*t +
+ fCoefs[3].y());
+}
+
+bool CubicEvaluator::hasNext(){
jvanverth1 2014/07/21 22:10:10 This and next() are simple enough, they could be p
dandov 2014/07/22 13:55:14 I substituted this ones with the operator* and ope
+ return fCurrent <= fMax;
+}
+
+SkPoint CubicEvaluator::next(){
+ SkPoint point = fFwDiff[0];
+ fFwDiff[0] += fFwDiff[1];
+ fFwDiff[1] += fFwDiff[2];
+ fFwDiff[2] += fFwDiff[3];
+ fCurrent++;
+
+ return point;
+}
+
+void CubicEvaluator::reset(int res){
+ fRes = res;
jvanverth1 2014/07/21 22:10:10 Indent
dandov 2014/07/22 13:55:14 Also is ok in my files, I don't know what happened
+ SkScalar h = 1.f/res;
+ fCurrent = 0;
+ fMax = res + 1;
+ fFwDiff[0] = fCoefs[3];
+ SkScalar h2 = h*h;
+ SkScalar h3 = h2*h;
+
+ fFwDiff[3].set(6.f*fCoefs[0].x()*h3, 6.f*fCoefs[0].y()*h3); //6ah^3
+ fFwDiff[2].set(fFwDiff[3].x() + 2.f*fCoefs[1].x()*h2, //6ah^3 + 2bh^2
+ fFwDiff[3].y() + 2.f*fCoefs[1].y()*h2);
+ fFwDiff[1].set(fCoefs[0].x()*h3 + fCoefs[1].x()*h2 + fCoefs[2].x()*h, //ah^3 + bh^2 + ch
+ fCoefs[0].y()*h3 + fCoefs[1].y()*h2 + fCoefs[2].y()*h);
+}
+
+const SkPoint* CubicEvaluator::getPoints() {
+ return fPoints;
+}
+
+const SkPoint* CubicEvaluator::getCoefs() {
+ return fCoefs;
+}
+
+int CubicEvaluator::getResolution() {
+ return fRes;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkPatchMesh::SkPatchMesh()
+ : fVertCount(0)
+ , fIndexCount(0)
+ , fData(NULL)
+ , fIndices(NULL)
+ , fUseColors(false)
+ , fUseTexCoords(false)
+ , fIntercalate(false)
+ , fColorFormat(kSkColor_ColorFormat) { }
+
+void SkPatchMesh::init(int vertCount, int indexCount, SkColorFormat format, bool useTexCoords,
+ bool intercalate) {
+
+ this->reset();
+
+ fUseColors = format != kNoColor_ColorFormat;
+ fUseTexCoords = useTexCoords;
+ fIntercalate = intercalate;
jvanverth1 2014/07/21 22:10:09 I don't know this term. Should this be fInterpolat
dandov 2014/07/22 13:55:14 I couldn't find a nice word to say that the data i
+ fColorFormat = format;
+
+ int colorSize = 0;
+ switch (format) {
+ case SkPatchMesh::kNoColor_ColorFormat:
+ colorSize = 0;
+ break;
+ case SkPatchMesh::kSkColor_ColorFormat:
+ colorSize = sizeof(SkColor);
+ break;
+ //case SkPatchMesh::kSkPMColor_ColorFormat:
+ // colorSize = sizeof(SkPMColor);
+ // break;
+ case SkPatchMesh::kGrColor_ColorFormat:
+ colorSize = sizeof(GrColor);
+ break;
+ }
+
+ fVertCount = vertCount;
+ fIndexCount = indexCount;
+ int totalBytes = fVertCount*sizeof(SkPoint) + (fUseColors ? fVertCount*colorSize : 0)
+ + (fUseTexCoords*sizeof(SkPoint) ? fVertCount : 0);
+
+ fData = SkNEW_ARRAY(uint8_t, totalBytes);
+ fIndices = SkNEW_ARRAY(uint16_t, fIndexCount);
+
+ if (fIntercalate) {
+ //here the offset represents the offset inside an intercalated object;
+ // if using colors then the offset is the size of the vertex
+ fColorOffset = fUseColors ? sizeof(SkPoint) : 0;
+ //if using colors then it is the size of the vertex + the size of the color
+ //else is the size of the vertex only
+ fTexOffset = fUseColors ? (fUseTexCoords ? sizeof(SkPoint)+colorSize : 0)
+ : (fUseTexCoords ? sizeof(SkPoint) : 0);
+ fDataSize = sizeof(SkPoint) + (fUseColors ? colorSize : 0) +
+ (fUseTexCoords ? sizeof(SkPoint) : 0);
+ } else {
+ //here the offset is when the array of colors or uv's starts based on fData in bytes
+ fColorOffset = fUseColors ? fVertCount*sizeof(SkPoint) : 0;
+ fTexOffset = fUseTexCoords ?
+ (fUseColors ? fVertCount*sizeof(SkPoint) + fVertCount*colorSize :
+ fVertCount*sizeof(SkPoint))
+ : 0;
+ fDataSize = 0;
+ }
+}
+
+void SkPatchMesh::reset() {
+ SkDELETE_ARRAY (fData);
+ SkDELETE_ARRAY (fIndices);
+ fVertCount = 0;
+ fIndexCount = 0;
+ fData = NULL;
+ fIndices = NULL;
+ fUseColors = false;
+ fUseTexCoords = false;
+ fIntercalate = false;
+ fColorFormat = kSkColor_ColorFormat;
+}
+
+SkPatchMesh::~SkPatchMesh() {
+ this->reset();
+}
+
+const SkPoint* SkPatchMesh::getPoints() {
+ if (fIntercalate) {
+ return NULL;
+ } else {
+ return reinterpret_cast<SkPoint*>(fData);
+ }
+}
+
+const uint16_t* SkPatchMesh::getIndices() {
+ return fIndices;
+}
+
+const SkColor* SkPatchMesh::getColors() {
+ if (fIntercalate || !fUseColors) {
+ return NULL;
+ } else {
+ return reinterpret_cast<SkColor*>(fData + fColorOffset);
+ }
+}
+
+const SkPoint* SkPatchMesh::getTexCoords() {
+ if (fIntercalate || !fUseTexCoords) {
+ return NULL;
+ } else {
+ return reinterpret_cast<SkPoint*>(fData + fTexOffset);
+ }
+}
+
+const uint8_t* SkPatchMesh::getData() {
+ return reinterpret_cast<uint8_t*>(fData);
+}
+
+SkPoint& SkPatchMesh::pointAt(int index) {
+ if (fIntercalate) {
+ index *= fDataSize;
+ }else {
+ index *= sizeof(SkPoint);
+ }
+ return *reinterpret_cast<SkPoint*>(fData + index);
+}
+
+uint32_t& SkPatchMesh::colorAt(int index) {
+ SkASSERT(fUseColors);
+
+ if (fIntercalate) {
+ //getting the address of object with fDatasize in position index, move to color in that obj
+ index = index * fDataSize + fColorOffset;
+ } else {
+ //starting in the colors array, move to the indexth color
+ index = fColorOffset + index * sizeof(SkColor);
+ }
+ return *reinterpret_cast<SkColor*>(fData + index);
+}
+
+bool SkPatchMesh::setColorAt(int index, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
+ if (!fUseColors) {
+ return false;
+ }
+ SkColor& colorRef = this->colorAt(index);
+
+ switch (fColorFormat) {
+ case SkPatchMesh::kSkColor_ColorFormat:
+ colorRef = SkColorSetARGB(a,r,g,b);
+ break;
+ //case SkPatchMesh::kSkPMColor_ColorFormat:
+ // colorSize = sizeof(SkPMColor);
+ // break;
+ case SkPatchMesh::kGrColor_ColorFormat:
+ colorRef = SkColor2GrColor(SkPreMultiplyARGB(a,r,g,b));//GrColorPackRGBA(r,g,b,a);
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+SkPoint& SkPatchMesh::texCoordAt(int index) {
+ SkASSERT(fUseTexCoords);
+
+ if (fIntercalate) {
+ index = index * fDataSize + fTexOffset;
+ } else {
+ index = fTexOffset + index * sizeof(SkPoint);
+ }
+ return *reinterpret_cast<SkPoint*>(fData + index);
+}
+
+void SkPatchMesh::setIndices(int index, uint16_t* indices, int size) {
+ for (int i = 0; i < size; ++i) {
+ fIndices[index + i] = indices[i];
+ }
+}
+
+int SkPatchMesh::getVertexCount() {
+ return fVertCount;
+}
+
+int SkPatchMesh::getIndexCount() {
+ return fIndexCount;
+}
+
+bool SkPatchMesh::useColors() {
+ return fUseColors;
+}
+
+bool SkPatchMesh::useTexCoords() {
+ return fUseTexCoords;
+}
+
+bool SkPatchMesh::isIntercalated() {
+ return fIntercalate;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkCoonsPatch::SkCoonsPatch(SkPoint points[12], SkColor (*colors)[4], int res)
+ : fPoints(points)
+ , fBottom(points[0], points[1], points[2], points[3])
+ , fTop(points[4], points[5], points[6], points[7])
+ , fLeft(points[0], points[8], points[9], points[4])
+ , fRight(points[3], points[10], points[11], points[7])
+ , fResX(res)
+ , fResY(res) {
+ fColors[0] = ((*colors)[0]);
+ fColors[1] = ((*colors)[1]);
+ fColors[2] = ((*colors)[2]);
+ fColors[3] = ((*colors)[3]);
+}
+
+uint8_t bilinear(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar c01, SkScalar c11) {
+ SkScalar a = c00 * (1.f - tx) + c10 * tx;
+ SkScalar b = c01 * (1.f - tx) + c11 * tx;
+ return uint8_t(a * (1.f - ty) + b * ty);
+}
+
+// Each patch has the responsability to generate its mesh and the meshpatch handles the type of data
+// This method first initializes the mesh by providing the number of vertices, indices, the format
+// of the colors, if it needs texture coordinates and if the data should be intercalated.
+bool SkCoonsPatch::genMesh(SkPatchMesh* mesh, SkPatchMesh::SkColorFormat format, bool useTexCoords,
+ bool intercalate) const {
+
+ //setup how we are going to use the data based on the client preferences and how the patch
+ //behaves, the derived class could just hardcode this parameters or take into account the
+ //preferences of the caller like we do in this example
+ if (!this->usesColors()) {
+ format = SkPatchMesh::kNoColor_ColorFormat;
+ }
+ mesh->init((fResX + 1) * (fResY + 1), fResX * fResY * 6, format,
+ this->usesTexCoords() && useTexCoords, intercalate);
+
+ fBottom.reset(fResX);
+ fTop.reset(fResX);
+
+ SkScalar u = 0.0f;
+ int stride = fResY+1;
+ for (int x = 0; x <= fResX; x++) {
+ SkPoint bottom = fBottom.next(), top = fTop.next();
+ fLeft.reset(fResY);
+ fRight.reset(fResY);
+ SkScalar v = 0.f;
+ for (int y = 0; y <= fResY; y++) {
+ int dataIndex = x*(fResX + 1) + y;
+
+ SkPoint left = fLeft.next(), right = fRight.next();
+
+ SkPoint s0 = SkPoint::Make((1.0f - v)*bottom.x() + v*top.x(),
+ (1.0f - v)*bottom.y() + v*top.y());
+ SkPoint s1 = SkPoint::Make((1.0f - u)*left.x() + u*right.x(),
+ (1.0f - u)*left.y() + u*right.y());
+ SkPoint s2 = SkPoint::Make(
+ (1.0f - v)*((1.0f - u)*fBottom.getPoints()[0].x()
+ + u*fBottom.getPoints()[3].x())
+ + v*((1.0f - u)*fTop.getPoints()[0].x() + u*fTop.getPoints()[3].x()),
+ (1.0f - v)*((1.0f - u)*fBottom.getPoints()[0].y()
+ + u*fBottom.getPoints()[3].y())
+ + v*((1.0f - u)*fTop.getPoints()[0].y() + u*fTop.getPoints()[3].y()));
+ //always set the point
+ mesh->pointAt(dataIndex) = s0 + s1 - s2;
+
+ //check if we should set the color
+ if(mesh->useColors()) {
+ //these colors should be premultiplied for the bilerp but currently drawVertices
+ //premultiplies them, so here they will be darker
+ uint8_t a = bilinear(u, v, SkScalar(SkColorGetA(fColors[0])),
+ SkScalar(SkColorGetA(fColors[1])), SkScalar(SkColorGetA(fColors[2])),
+ SkScalar(SkColorGetA(fColors[3])));
+ uint8_t r = bilinear(u, v, SkScalar(SkColorGetR(fColors[0])),
+ SkScalar(SkColorGetR(fColors[1])), SkScalar(SkColorGetR(fColors[2])),
+ SkScalar(SkColorGetR(fColors[3])));
+ uint8_t g = bilinear(u, v, SkScalar(SkColorGetG(fColors[0])),
+ SkScalar(SkColorGetG(fColors[1])), SkScalar(SkColorGetG(fColors[2])),
+ SkScalar(SkColorGetG(fColors[3])));
+ uint8_t b = bilinear(u, v, SkScalar(SkColorGetB(fColors[0])),
+ SkScalar(SkColorGetB(fColors[1])), SkScalar(SkColorGetB(fColors[2])),
+ SkScalar(SkColorGetB(fColors[3])));
+ //mesh->colorAt(dataIndex) = SkColorSetARGB(a, r, g, b);
+ mesh->setColorAt(dataIndex, r,g,b,a);
+ }
+
+ //check if we should set the texture coordinates
+ if (mesh->useTexCoords()) {
+ mesh->texCoordAt(dataIndex) = SkPoint::Make(u, v);
+ }
+
+ //set the indices
+ if(x < fResX && y < fResY) {
+ uint16_t indices[6];
+ int i = 6*(x*fResY + y);
+ indices[0] = x*stride+y;
+ indices[1] = x*stride+1+y;
+ indices[2] = (x+1)*stride+1+y;
+ indices[3] = indices[0];
+ indices[4] = indices[2];
+ indices[5] = (x+1)*stride+y;
+ mesh->setIndices(i, indices, 6);
+ }
+
+ v+=1.f/fResY;
+ }
+ u+=1.f/fResX;
+ }
+ return true;
+}
« include/core/SkPatch.h ('K') | « include/core/SkPatch.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698