本文整理汇总了C++中SkMatrix类的典型用法代码示例。如果您正苦于以下问题:C++ SkMatrix类的具体用法?C++ SkMatrix怎么用?C++ SkMatrix使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了SkMatrix类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: GaussianBlur
GrTexture* GaussianBlur(GrContext* context,
GrTexture* srcTexture,
bool canClobberSrc,
const SkRect& dstBounds,
const SkRect* srcBounds,
float sigmaX,
float sigmaY,
GrTextureProvider::SizeConstraint constraint) {
SkASSERT(context);
SkIRect clearRect;
int scaleFactorX, radiusX;
int scaleFactorY, radiusY;
int maxTextureSize = context->caps()->maxTextureSize();
sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
SkPoint srcOffset = SkPoint::Make(-dstBounds.x(), -dstBounds.y());
SkRect localDstBounds = SkRect::MakeWH(dstBounds.width(), dstBounds.height());
SkRect localSrcBounds;
SkRect srcRect;
if (srcBounds) {
srcRect = localSrcBounds = *srcBounds;
srcRect.offset(srcOffset);
srcBounds = &localSrcBounds;
} else {
srcRect = localDstBounds;
}
scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
srcRect.roundOut(&srcRect);
scale_rect(&srcRect, static_cast<float>(scaleFactorX),
static_cast<float>(scaleFactorY));
// setup new clip
GrClip clip(localDstBounds);
SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
kRGBA_8888_GrPixelConfig == srcTexture->config() ||
kAlpha_8_GrPixelConfig == srcTexture->config());
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = SkScalarFloorToInt(dstBounds.width());
desc.fHeight = SkScalarFloorToInt(dstBounds.height());
desc.fConfig = srcTexture->config();
GrTexture* dstTexture;
GrTexture* tempTexture;
SkAutoTUnref<GrTexture> temp1, temp2;
temp1.reset(context->textureProvider()->createTexture(desc, constraint));
dstTexture = temp1.get();
if (canClobberSrc) {
tempTexture = srcTexture;
} else {
temp2.reset(context->textureProvider()->createTexture(desc, constraint));
tempTexture = temp2.get();
}
if (nullptr == dstTexture || nullptr == tempTexture) {
return nullptr;
}
SkAutoTUnref<GrDrawContext> srcDrawContext;
for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
GrPaint paint;
SkMatrix matrix;
matrix.setIDiv(srcTexture->width(), srcTexture->height());
SkRect dstRect(srcRect);
if (srcBounds && i == 1) {
SkRect domain;
matrix.mapRect(&domain, *srcBounds);
domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width() : 0.0f,
(i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height() : 0.0f);
SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create(
srcTexture,
matrix,
domain,
GrTextureDomain::kDecal_Mode,
GrTextureParams::kBilerp_FilterMode));
paint.addColorFragmentProcessor(fp);
srcRect.offset(-srcOffset);
srcOffset.set(0, 0);
} else {
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
paint.addColorTextureProcessor(srcTexture, matrix, params);
}
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
i < scaleFactorY ? 0.5f : 1.0f);
SkAutoTUnref<GrDrawContext> dstDrawContext(
context->drawContext(dstTexture->asRenderTarget()));
if (!dstDrawContext) {
return nullptr;
}
dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
srcDrawContext.swap(dstDrawContext);
//.........这里部分代码省略.........
示例2: computeSize
static SkSize computeSize(const SkBitmap& bm, const SkMatrix& mat) {
SkRect bounds = SkRect::MakeWH(SkIntToScalar(bm.width()),
SkIntToScalar(bm.height()));
mat.mapRect(&bounds);
return SkSize::Make(bounds.width(), bounds.height());
}
示例3: test_fade
// test drawing with strips of fading gradient above and below
static void test_fade(SkCanvas* canvas) {
SkAutoCanvasRestore ar(canvas, true);
SkRect r;
SkPaint p;
p.setAlpha(0x88);
SkAutoCanvasRestore ar2(canvas, false);
// create the layers
r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
canvas->clipRect(r);
r.fBottom = SkIntToScalar(20);
canvas->saveLayer(&r, NULL);
r.fTop = SkIntToScalar(80);
r.fBottom = SkIntToScalar(100);
canvas->saveLayer(&r, NULL);
// now draw the "content"
if (true) {
r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
canvas->saveLayerAlpha(&r, 0x80);
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
canvas->drawOval(r, p);
dump_layers("inside layer alpha", canvas);
canvas->restore();
} else {
r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
canvas->drawOval(r, p);
}
// return;
dump_layers("outside layer alpha", canvas);
// now apply an effect
SkMatrix m;
m.setScale(SK_Scalar1, -SK_Scalar1);
m.postTranslate(0, SkIntToScalar(100));
SkPaint paint;
make_paint(&paint, m);
r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
// SkDebugf("--------- draw top grad\n");
canvas->drawRect(r, paint);
r.fTop = SkIntToScalar(80);
r.fBottom = SkIntToScalar(100);
// SkDebugf("--------- draw bot grad\n");
canvas->drawRect(r, paint);
}
示例4: SkASSERT
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
const SkGlyph* glyph = &origGlyph;
SkGlyph tmpGlyph;
if (fMaskFilter) { // restore the prefilter bounds
tmpGlyph.init(origGlyph.fID);
// need the original bounds, sans our maskfilter
SkMaskFilter* mf = fMaskFilter;
fMaskFilter = NULL; // temp disable
this->getMetrics(&tmpGlyph);
fMaskFilter = mf; // restore
tmpGlyph.fImage = origGlyph.fImage;
// we need the prefilter bounds to be <= filter bounds
SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
glyph = &tmpGlyph;
}
if (fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
const bool lcdMode = fRec.fMaskFormat == SkMask::kHorizontalLCD_Format ||
fRec.fMaskFormat == SkMask::kVerticalLCD_Format;
if (fRasterizer) {
SkMask mask;
glyph->toMask(&mask);
mask.fFormat = SkMask::kA8_Format;
sk_bzero(glyph->fImage, mask.computeImageSize());
if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
fMaskFilter, &mask,
SkMask::kJustRenderImage_CreateMode)) {
return;
}
} else {
SkBitmap bm;
SkBitmap::Config config;
SkMatrix matrix;
SkRegion clip;
SkPaint paint;
SkDraw draw;
if (SkMask::kA8_Format == fRec.fMaskFormat || lcdMode) {
config = SkBitmap::kA8_Config;
paint.setAntiAlias(true);
} else {
SkASSERT(SkMask::kBW_Format == fRec.fMaskFormat);
config = SkBitmap::kA1_Config;
paint.setAntiAlias(false);
}
clip.setRect(0, 0, glyph->fWidth, glyph->fHeight);
matrix.setTranslate(-SkIntToScalar(glyph->fLeft),
-SkIntToScalar(glyph->fTop));
bm.setConfig(config, glyph->fWidth, glyph->fHeight,
glyph->rowBytes());
bm.setPixels(glyph->fImage);
sk_bzero(glyph->fImage, bm.height() * bm.rowBytes());
draw.fClip = &clip;
draw.fMatrix = &matrix;
draw.fBitmap = &bm;
draw.fBounder = NULL;
draw.drawPath(devPath, paint);
}
if (lcdMode)
glyph->expandA8ToLCD();
} else {
this->getGlyphContext(*glyph)->generateImage(*glyph);
}
if (fMaskFilter) {
SkMask srcM, dstM;
SkMatrix matrix;
// the src glyph image shouldn't be 3D
SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
glyph->toMask(&srcM);
fRec.getMatrixFrom2x2(&matrix);
if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
int dstRB = origGlyph.rowBytes();
int srcRB = dstM.fRowBytes;
const uint8_t* src = (const uint8_t*)dstM.fImage;
uint8_t* dst = (uint8_t*)origGlyph.fImage;
if (SkMask::k3D_Format == dstM.fFormat) {
// we have to copy 3 times as much
//.........这里部分代码省略.........
示例5: cull_line
// Attempt to trim the line to minimally cover the cull rect (currently
// only works for horizontal and vertical lines).
// Return true if processing should continue; false otherwise.
static bool cull_line(SkPoint* pts, const SkStrokeRec& rec,
const SkMatrix& ctm, const SkRect* cullRect,
const SkScalar intervalLength) {
if (nullptr == cullRect) {
SkASSERT(false); // Shouldn't ever occur in practice
return false;
}
SkScalar dx = pts[1].x() - pts[0].x();
SkScalar dy = pts[1].y() - pts[0].y();
if ((dx && dy) || (!dx && !dy)) {
return false;
}
SkRect bounds = *cullRect;
outset_for_stroke(&bounds, rec);
// cullRect is in device space while pts are in the local coordinate system
// defined by the ctm. We want our answer in the local coordinate system.
SkASSERT(ctm.rectStaysRect());
SkMatrix inv;
if (!ctm.invert(&inv)) {
return false;
}
inv.mapRect(&bounds);
if (dx) {
SkASSERT(dx && !dy);
SkScalar minX = pts[0].fX;
SkScalar maxX = pts[1].fX;
if (dx < 0) {
SkTSwap(minX, maxX);
}
SkASSERT(minX < maxX);
if (maxX <= bounds.fLeft || minX >= bounds.fRight) {
return false;
}
// Now we actually perform the chop, removing the excess to the left and
// right of the bounds (keeping our new line "in phase" with the dash,
// hence the (mod intervalLength).
if (minX < bounds.fLeft) {
minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX, intervalLength);
}
if (maxX > bounds.fRight) {
maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight, intervalLength);
}
SkASSERT(maxX > minX);
if (dx < 0) {
SkTSwap(minX, maxX);
}
pts[0].fX = minX;
pts[1].fX = maxX;
} else {
SkASSERT(dy && !dx);
SkScalar minY = pts[0].fY;
SkScalar maxY = pts[1].fY;
if (dy < 0) {
SkTSwap(minY, maxY);
}
SkASSERT(minY < maxY);
if (maxY <= bounds.fTop || minY >= bounds.fBottom) {
return false;
}
// Now we actually perform the chop, removing the excess to the top and
// bottom of the bounds (keeping our new line "in phase" with the dash,
// hence the (mod intervalLength).
if (minY < bounds.fTop) {
minY = bounds.fTop - SkScalarMod(bounds.fTop - minY, intervalLength);
}
if (maxY > bounds.fBottom) {
maxY = bounds.fBottom + SkScalarMod(maxY - bounds.fBottom, intervalLength);
}
SkASSERT(maxY > minY);
if (dy < 0) {
SkTSwap(minY, maxY);
}
pts[0].fY = minY;
pts[1].fY = maxY;
}
return true;
}
示例6: computeShapeMatrix
bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
{
// Compute a shape matrix compatible with Cairo's _compute_transform.
// Finds major/minor scales and uses them to normalize the transform.
double scaleX = m.getScaleX();
double skewX = m.getSkewX();
double skewY = m.getSkewY();
double scaleY = m.getScaleY();
double det = scaleX * scaleY - skewY * skewX;
if (!std::isfinite(det)) {
fScaleX = fRec.fTextSize * fRec.fPreScaleX;
fScaleY = fRec.fTextSize;
fHaveShape = false;
return false;
}
double major = det != 0.0 ? hypot(scaleX, skewY) : 0.0;
double minor = major != 0.0 ? fabs(det) / major : 0.0;
// Limit scales to be above 1pt.
major = SkTMax(major, 1.0);
minor = SkTMax(minor, 1.0);
// If the font is not scalable, then choose the best available size.
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
if (face && !FT_IS_SCALABLE(face)) {
double bestDist = DBL_MAX;
FT_Int bestSize = -1;
for (FT_Int i = 0; i < face->num_fixed_sizes; i++) {
// Distance is positive if strike is larger than desired size,
// or negative if smaller. If previously a found smaller strike,
// then prefer a larger strike. Otherwise, minimize distance.
double dist = face->available_sizes[i].y_ppem / 64.0 - minor;
if (bestDist < 0 ? dist >= bestDist : fabs(dist) <= bestDist) {
bestDist = dist;
bestSize = i;
}
}
if (bestSize < 0) {
fScaleX = fRec.fTextSize * fRec.fPreScaleX;
fScaleY = fRec.fTextSize;
fHaveShape = false;
return false;
}
major = face->available_sizes[bestSize].x_ppem / 64.0;
minor = face->available_sizes[bestSize].y_ppem / 64.0;
fHaveShape = true;
} else {
fHaveShape = !m.isScaleTranslate();
}
fScaleX = SkDoubleToScalar(major);
fScaleY = SkDoubleToScalar(minor);
if (fHaveShape) {
// Normalize the transform and convert to fixed-point.
double invScaleX = 65536.0 / major;
double invScaleY = 65536.0 / minor;
fShapeMatrix.xx = (FT_Fixed)(scaleX * invScaleX);
fShapeMatrix.yx = -(FT_Fixed)(skewY * invScaleX);
fShapeMatrix.xy = -(FT_Fixed)(skewX * invScaleY);
fShapeMatrix.yy = (FT_Fixed)(scaleY * invScaleY);
}
return true;
}
示例7: SkPDFDict
SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
: SkPDFDict("Pattern"),
fState(state) {
SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL;
SkPoint transformPoints[2];
// Depending on the type of the gradient, we want to transform the
// coordinate space in different ways.
const SkShader::GradientInfo* info = &fState.get()->fInfo;
transformPoints[0] = info->fPoint[0];
transformPoints[1] = info->fPoint[1];
switch (fState.get()->fType) {
case SkShader::kLinear_GradientType:
codeFunction = &linearCode;
break;
case SkShader::kRadial_GradientType:
transformPoints[1] = transformPoints[0];
transformPoints[1].fX += info->fRadius[0];
codeFunction = &radialCode;
break;
case SkShader::kRadial2_GradientType: {
// Bail out if the radii are the same. Empty fResources signals
// an error and isValid will return false.
if (info->fRadius[0] == info->fRadius[1]) {
return;
}
transformPoints[1] = transformPoints[0];
SkScalar dr = info->fRadius[1] - info->fRadius[0];
transformPoints[1].fX += dr;
codeFunction = &twoPointRadialCode;
break;
}
case SkShader::kSweep_GradientType:
transformPoints[1] = transformPoints[0];
transformPoints[1].fX += SK_Scalar1;
codeFunction = &sweepCode;
break;
case SkShader::kColor_GradientType:
case SkShader::kNone_GradientType:
default:
return;
}
// Move any scaling (assuming a unit gradient) or translation
// (and rotation for linear gradient), of the final gradient from
// info->fPoints to the matrix (updating bbox appropriately). Now
// the gradient can be drawn on on the unit segment.
SkMatrix mapperMatrix;
unitToPointsMatrix(transformPoints, &mapperMatrix);
SkMatrix finalMatrix = fState.get()->fCanvasTransform;
finalMatrix.preConcat(mapperMatrix);
finalMatrix.preConcat(fState.get()->fShaderTransform);
SkRect bbox;
bbox.set(fState.get()->fBBox);
if (!transformBBox(finalMatrix, &bbox)) {
return;
}
SkRefPtr<SkPDFArray> domain = new SkPDFArray;
domain->unref(); // SkRefPtr and new both took a reference.
domain->reserve(4);
domain->appendScalar(bbox.fLeft);
domain->appendScalar(bbox.fRight);
domain->appendScalar(bbox.fTop);
domain->appendScalar(bbox.fBottom);
SkString functionCode;
// The two point radial gradient further references fState.get()->fInfo
// in translating from x, y coordinates to the t parameter. So, we have
// to transform the points and radii according to the calculated matrix.
if (fState.get()->fType == SkShader::kRadial2_GradientType) {
SkShader::GradientInfo twoPointRadialInfo = *info;
SkMatrix inverseMapperMatrix;
if (!mapperMatrix.invert(&inverseMapperMatrix)) {
return;
}
inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2);
twoPointRadialInfo.fRadius[0] =
inverseMapperMatrix.mapRadius(info->fRadius[0]);
twoPointRadialInfo.fRadius[1] =
inverseMapperMatrix.mapRadius(info->fRadius[1]);
functionCode = codeFunction(twoPointRadialInfo);
} else {
functionCode = codeFunction(*info);
}
SkRefPtr<SkPDFStream> function = makePSFunction(functionCode, domain.get());
// Pass one reference to fResources, SkRefPtr and new both took a reference.
fResources.push(function.get());
SkRefPtr<SkPDFDict> pdfShader = new SkPDFDict;
pdfShader->unref(); // SkRefPtr and new both took a reference.
pdfShader->insertInt("ShadingType", 1);
pdfShader->insertName("ColorSpace", "DeviceRGB");
pdfShader->insert("Domain", domain.get());
pdfShader->insert("Function", new SkPDFObjRef(function.get()))->unref();
insertInt("PatternType", 2);
insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
insert("Shading", pdfShader.get());
//.........这里部分代码省略.........
示例8: GetLocalBounds
void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatrix& ctm,
SkRect* bounds) {
SkRect ambientBounds = path.getBounds();
SkScalar occluderZ;
if (SkScalarNearlyZero(rec.fZPlaneParams.fX) && SkScalarNearlyZero(rec.fZPlaneParams.fY)) {
occluderZ = rec.fZPlaneParams.fZ;
} else {
occluderZ = compute_z(ambientBounds.fLeft, ambientBounds.fTop, rec.fZPlaneParams);
occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fTop,
rec.fZPlaneParams));
occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fLeft, ambientBounds.fBottom,
rec.fZPlaneParams));
occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fBottom,
rec.fZPlaneParams));
}
SkScalar ambientBlur;
SkScalar spotBlur;
SkScalar spotScale;
SkPoint spotOffset;
if (ctm.hasPerspective()) {
// transform ambient and spot bounds into device space
ctm.mapRect(&ambientBounds);
// get ambient blur (in device space)
ambientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
// get spot params (in device space)
SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
ctm.mapPoints(&devLightPos, 1);
SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
rec.fLightPos.fZ, rec.fLightRadius,
&spotBlur, &spotScale, &spotOffset);
} else {
SkScalar devToSrcScale = SkScalarInvert(ctm.getMinScale());
// get ambient blur (in local space)
SkScalar devSpaceAmbientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
ambientBlur = devSpaceAmbientBlur*devToSrcScale;
// get spot params (in local space)
SkDrawShadowMetrics::GetSpotParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
rec.fLightPos.fZ, rec.fLightRadius,
&spotBlur, &spotScale, &spotOffset);
// convert spot blur to local space
spotBlur *= devToSrcScale;
}
// in both cases, adjust ambient and spot bounds
SkRect spotBounds = ambientBounds;
ambientBounds.outset(ambientBlur, ambientBlur);
spotBounds.fLeft *= spotScale;
spotBounds.fTop *= spotScale;
spotBounds.fRight *= spotScale;
spotBounds.fBottom *= spotScale;
spotBounds.offset(spotOffset.fX, spotOffset.fY);
spotBounds.outset(spotBlur, spotBlur);
// merge bounds
*bounds = ambientBounds;
bounds->join(spotBounds);
// outset a bit to account for floating point error
bounds->outset(1, 1);
// if perspective, transform back to src space
if (ctm.hasPerspective()) {
// TODO: create tighter mapping from dev rect back to src rect
SkMatrix inverse;
if (ctm.invert(&inverse)) {
inverse.mapRect(bounds);
}
}
}
示例9: GetSpotShadowTransform
bool GetSpotShadowTransform(const SkPoint3& lightPos, SkScalar lightRadius,
const SkMatrix& ctm, const SkPoint3& zPlaneParams,
const SkRect& pathBounds, SkMatrix* shadowTransform, SkScalar* radius) {
auto heightFunc = [zPlaneParams] (SkScalar x, SkScalar y) {
return zPlaneParams.fX*x + zPlaneParams.fY*y + zPlaneParams.fZ;
};
SkScalar occluderHeight = heightFunc(pathBounds.centerX(), pathBounds.centerY());
if (!ctm.hasPerspective()) {
SkScalar scale;
SkVector translate;
SkDrawShadowMetrics::GetSpotParams(occluderHeight, lightPos.fX, lightPos.fY, lightPos.fZ,
lightRadius, radius, &scale, &translate);
shadowTransform->setScaleTranslate(scale, scale, translate.fX, translate.fY);
shadowTransform->preConcat(ctm);
} else {
if (SkScalarNearlyZero(pathBounds.width()) || SkScalarNearlyZero(pathBounds.height())) {
return false;
}
// get rotated quad in 3D
SkPoint pts[4];
ctm.mapRectToQuad(pts, pathBounds);
// No shadows for bowties or other degenerate cases
if (!SkIsConvexPolygon(pts, 4)) {
return false;
}
SkPoint3 pts3D[4];
SkScalar z = heightFunc(pathBounds.fLeft, pathBounds.fTop);
pts3D[0].set(pts[0].fX, pts[0].fY, z);
z = heightFunc(pathBounds.fRight, pathBounds.fTop);
pts3D[1].set(pts[1].fX, pts[1].fY, z);
z = heightFunc(pathBounds.fRight, pathBounds.fBottom);
pts3D[2].set(pts[2].fX, pts[2].fY, z);
z = heightFunc(pathBounds.fLeft, pathBounds.fBottom);
pts3D[3].set(pts[3].fX, pts[3].fY, z);
// project from light through corners to z=0 plane
for (int i = 0; i < 4; ++i) {
SkScalar dz = lightPos.fZ - pts3D[i].fZ;
// light shouldn't be below or at a corner's z-location
if (dz <= SK_ScalarNearlyZero) {
return false;
}
SkScalar zRatio = pts3D[i].fZ / dz;
pts3D[i].fX -= (lightPos.fX - pts3D[i].fX)*zRatio;
pts3D[i].fY -= (lightPos.fY - pts3D[i].fY)*zRatio;
pts3D[i].fZ = SK_Scalar1;
}
// Generate matrix that projects from [-1,1]x[-1,1] square to projected quad
SkPoint3 h0, h1, h2;
// Compute homogenous crossing point between top and bottom edges (gives new x-axis).
h0 = (pts3D[1].cross(pts3D[0])).cross(pts3D[2].cross(pts3D[3]));
// Compute homogenous crossing point between left and right edges (gives new y-axis).
h1 = (pts3D[0].cross(pts3D[3])).cross(pts3D[1].cross(pts3D[2]));
// Compute homogenous crossing point between diagonals (gives new origin).
h2 = (pts3D[0].cross(pts3D[2])).cross(pts3D[1].cross(pts3D[3]));
// If h2 is a vector (z=0 in 2D homogeneous space), that means that at least
// two of the quad corners are coincident and we don't have a realistic projection
if (SkScalarNearlyZero(h2.fZ)) {
return false;
}
// In some cases the crossing points are in the wrong direction
// to map (-1,-1) to pts3D[0], so we need to correct for that.
// Want h0 to be to the right of the left edge.
SkVector3 v = pts3D[3] - pts3D[0];
SkVector3 w = h0 - pts3D[0];
SkScalar perpDot = v.fX*w.fY - v.fY*w.fX;
if (perpDot > 0) {
h0 = -h0;
}
// Want h1 to be above the bottom edge.
v = pts3D[1] - pts3D[0];
perpDot = v.fX*w.fY - v.fY*w.fX;
if (perpDot < 0) {
h1 = -h1;
}
shadowTransform->setAll(h0.fX / h2.fZ, h1.fX / h2.fZ, h2.fX / h2.fZ,
h0.fY / h2.fZ, h1.fY / h2.fZ, h2.fY / h2.fZ,
h0.fZ / h2.fZ, h1.fZ / h2.fZ, 1);
// generate matrix that transforms from bounds to [-1,1]x[-1,1] square
SkMatrix toHomogeneous;
SkScalar xScale = 2/(pathBounds.fRight - pathBounds.fLeft);
SkScalar yScale = 2/(pathBounds.fBottom - pathBounds.fTop);
toHomogeneous.setAll(xScale, 0, -xScale*pathBounds.fLeft - 1,
0, yScale, -yScale*pathBounds.fTop - 1,
0, 0, 1);
shadowTransform->preConcat(toHomogeneous);
*radius = SkDrawShadowMetrics::SpotBlurRadius(occluderHeight, lightPos.fZ, lightRadius);
}
return true;
}
示例10: TestMatrix
void TestMatrix(skiatest::Reporter* reporter) {
SkMatrix mat, inverse, iden1, iden2;
mat.reset();
mat.setTranslate(SK_Scalar1, SK_Scalar1);
mat.invert(&inverse);
iden1.setConcat(mat, inverse);
REPORTER_ASSERT(reporter, is_identity(iden1));
mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
mat.invert(&inverse);
iden1.setConcat(mat, inverse);
REPORTER_ASSERT(reporter, is_identity(iden1));
test_flatten(reporter, mat);
mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
mat.invert(&inverse);
iden1.setConcat(mat, inverse);
REPORTER_ASSERT(reporter, is_identity(iden1));
test_flatten(reporter, mat);
mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
mat.postRotate(SkIntToScalar(25));
REPORTER_ASSERT(reporter, mat.invert(NULL));
mat.invert(&inverse);
iden1.setConcat(mat, inverse);
REPORTER_ASSERT(reporter, is_identity(iden1));
iden2.setConcat(inverse, mat);
REPORTER_ASSERT(reporter, is_identity(iden2));
test_flatten(reporter, mat);
test_flatten(reporter, iden2);
// rectStaysRect test
{
static const struct {
SkScalar m00, m01, m10, m11;
bool mStaysRect;
}
gRectStaysRectSamples[] = {
{ 0, 0, 0, 0, false },
{ 0, 0, 0, SK_Scalar1, false },
{ 0, 0, SK_Scalar1, 0, false },
{ 0, 0, SK_Scalar1, SK_Scalar1, false },
{ 0, SK_Scalar1, 0, 0, false },
{ 0, SK_Scalar1, 0, SK_Scalar1, false },
{ 0, SK_Scalar1, SK_Scalar1, 0, true },
{ 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false },
{ SK_Scalar1, 0, 0, 0, false },
{ SK_Scalar1, 0, 0, SK_Scalar1, true },
{ SK_Scalar1, 0, SK_Scalar1, 0, false },
{ SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false },
{ SK_Scalar1, SK_Scalar1, 0, 0, false },
{ SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false },
{ SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false },
{ SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
SkMatrix m;
m.reset();
m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01);
m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10);
m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
REPORTER_ASSERT(reporter,
m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
}
}
mat.reset();
mat.set(SkMatrix::kMScaleX, SkIntToScalar(1));
mat.set(SkMatrix::kMSkewX, SkIntToScalar(2));
mat.set(SkMatrix::kMTransX, SkIntToScalar(3));
mat.set(SkMatrix::kMSkewY, SkIntToScalar(4));
mat.set(SkMatrix::kMScaleY, SkIntToScalar(5));
mat.set(SkMatrix::kMTransY, SkIntToScalar(6));
SkScalar affine[6];
REPORTER_ASSERT(reporter, mat.asAffine(affine));
#define affineEqual(e) affine[SkMatrix::kA##e] == mat.get(SkMatrix::kM##e)
REPORTER_ASSERT(reporter, affineEqual(ScaleX));
REPORTER_ASSERT(reporter, affineEqual(SkewY));
REPORTER_ASSERT(reporter, affineEqual(SkewX));
REPORTER_ASSERT(reporter, affineEqual(ScaleY));
REPORTER_ASSERT(reporter, affineEqual(TransX));
REPORTER_ASSERT(reporter, affineEqual(TransY));
#undef affineEqual
mat.set(SkMatrix::kMPersp1, SkScalarToPersp(SK_Scalar1 / 2));
REPORTER_ASSERT(reporter, !mat.asAffine(affine));
SkMatrix mat2;
mat2.reset();
mat.reset();
SkScalar zero = 0;
mat.set(SkMatrix::kMSkewX, -zero);
REPORTER_ASSERT(reporter, are_equal(reporter, mat, mat2));
mat2.reset();
//.........这里部分代码省略.........
示例11: is_identity
static bool is_identity(const SkMatrix& m) {
SkMatrix identity;
identity.reset();
return nearly_equal(m, identity);
}
示例12: test_matrix_max_stretch
void test_matrix_max_stretch(skiatest::Reporter* reporter) {
SkMatrix identity;
identity.reset();
REPORTER_ASSERT(reporter, SK_Scalar1 == identity.getMaxStretch());
SkMatrix scale;
scale.setScale(SK_Scalar1 * 2, SK_Scalar1 * 4);
REPORTER_ASSERT(reporter, SK_Scalar1 * 4 == scale.getMaxStretch());
SkMatrix rot90Scale;
rot90Scale.setRotate(90 * SK_Scalar1);
rot90Scale.postScale(SK_Scalar1 / 4, SK_Scalar1 / 2);
REPORTER_ASSERT(reporter, SK_Scalar1 / 2 == rot90Scale.getMaxStretch());
SkMatrix rotate;
rotate.setRotate(128 * SK_Scalar1);
REPORTER_ASSERT(reporter, SkScalarAbs(SK_Scalar1 - rotate.getMaxStretch()) <= SK_ScalarNearlyZero);
SkMatrix translate;
translate.setTranslate(10 * SK_Scalar1, -5 * SK_Scalar1);
REPORTER_ASSERT(reporter, SK_Scalar1 == translate.getMaxStretch());
SkMatrix perspX;
perspX.reset();
perspX.setPerspX(SkScalarToPersp(SK_Scalar1 / 1000));
REPORTER_ASSERT(reporter, -SK_Scalar1 == perspX.getMaxStretch());
SkMatrix perspY;
perspY.reset();
perspY.setPerspX(SkScalarToPersp(-SK_Scalar1 / 500));
REPORTER_ASSERT(reporter, -SK_Scalar1 == perspY.getMaxStretch());
SkMatrix baseMats[] = {scale, rot90Scale, rotate,
translate, perspX, perspY};
SkMatrix mats[2*SK_ARRAY_COUNT(baseMats)];
for (size_t i = 0; i < SK_ARRAY_COUNT(baseMats); ++i) {
mats[i] = baseMats[i];
bool invertable = mats[i].invert(&mats[i + SK_ARRAY_COUNT(baseMats)]);
REPORTER_ASSERT(reporter, invertable);
}
SkRandom rand;
for (int m = 0; m < 1000; ++m) {
SkMatrix mat;
mat.reset();
for (int i = 0; i < 4; ++i) {
int x = rand.nextU() % SK_ARRAY_COUNT(mats);
mat.postConcat(mats[x]);
}
SkScalar stretch = mat.getMaxStretch();
if ((stretch < 0) != mat.hasPerspective()) {
stretch = mat.getMaxStretch();
}
REPORTER_ASSERT(reporter, (stretch < 0) == mat.hasPerspective());
if (mat.hasPerspective()) {
m -= 1; // try another non-persp matrix
continue;
}
// test a bunch of vectors. None should be scaled by more than stretch
// (modulo some error) and we should find a vector that is scaled by
// almost stretch.
static const SkScalar gStretchTol = (105 * SK_Scalar1) / 100;
static const SkScalar gMaxStretchTol = (97 * SK_Scalar1) / 100;
SkScalar max = 0;
SkVector vectors[1000];
for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
vectors[i].fX = rand.nextSScalar1();
vectors[i].fY = rand.nextSScalar1();
if (!vectors[i].normalize()) {
i -= 1;
continue;
}
}
mat.mapVectors(vectors, SK_ARRAY_COUNT(vectors));
for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
SkScalar d = vectors[i].length();
REPORTER_ASSERT(reporter, SkScalarDiv(d, stretch) < gStretchTol);
if (max < d) {
max = d;
}
}
REPORTER_ASSERT(reporter, SkScalarDiv(max, stretch) >= gMaxStretchTol);
}
}
示例13: generateGlyphImage
void SkScalerContext_FreeType_Base::generateGlyphImage(
FT_Face face,
const SkGlyph& glyph,
const SkMatrix& bitmapTransform)
{
const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
switch ( face->glyph->format ) {
case FT_GLYPH_FORMAT_OUTLINE: {
FT_Outline* outline = &face->glyph->outline;
FT_BBox bbox;
FT_Bitmap target;
int dx = 0, dy = 0;
if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
dx = SkFixedToFDot6(glyph.getSubXFixed());
dy = SkFixedToFDot6(glyph.getSubYFixed());
// negate dy since freetype-y-goes-up and skia-y-goes-down
dy = -dy;
}
FT_Outline_Get_CBox(outline, &bbox);
/*
what we really want to do for subpixel is
offset(dx, dy)
compute_bounds
offset(bbox & !63)
but that is two calls to offset, so we do the following, which
achieves the same thing with only one offset call.
*/
FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
dy - ((bbox.yMin + dy) & ~63));
if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD);
SkMask mask;
glyph.toMask(&mask);
if (fPreBlend.isApplicable()) {
copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
} else {
copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
}
} else {
target.width = glyph.fWidth;
target.rows = glyph.fHeight;
target.pitch = glyph.rowBytes();
target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
target.num_grays = 256;
memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
}
} break;
case FT_GLYPH_FORMAT_BITMAP: {
FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
// Assume that the other formats do not exist.
SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
FT_PIXEL_MODE_GRAY == pixel_mode ||
FT_PIXEL_MODE_BGRA == pixel_mode);
// These are the only formats this ScalerContext should request.
SkASSERT(SkMask::kBW_Format == maskFormat ||
SkMask::kA8_Format == maskFormat ||
SkMask::kARGB32_Format == maskFormat ||
SkMask::kLCD16_Format == maskFormat);
// If no scaling needed, directly copy glyph bitmap.
if (bitmapTransform.isIdentity()) {
SkMask dstMask;
glyph.toMask(&dstMask);
copyFTBitmap(face->glyph->bitmap, dstMask);
break;
}
// Otherwise, scale the bitmap.
// Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
SkBitmap unscaledBitmap;
// TODO: mark this as sRGB when the blits will be sRGB.
unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
face->glyph->bitmap.rows,
SkColorType_for_FTPixelMode(pixel_mode),
kPremul_SkAlphaType));
SkMask unscaledBitmapAlias;
unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height());
unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
// Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
// BW requires an A8 target for resizing, which can then be down sampled.
// LCD should use a 4x A8 target, which will then be down sampled.
//.........这里部分代码省略.........
示例14: SkASSERT
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const
{
// compile-time assert
SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t));
if (numGlyphs == 1 && glyphBuffer.glyphAt(from) == 0x3) {
// Webkit likes to draw end text control command for some reason
// Just ignore it
return;
}
SkPaint paint;
if (!setupForText(&paint, gc, font)) {
return;
}
SkScalar x = SkFloatToScalar(point.x());
SkScalar y = SkFloatToScalar(point.y());
const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
SkPoint* pos = storage.get();
SkCanvas* canvas = gc->platformContext()->recordingCanvas();
/* We need an array of [x,y,x,y,x,y,...], but webkit is giving us
point.xy + [width, height, width, height, ...], so we have to convert
*/
if (font->platformData().orientation() == Vertical) {
float yOffset = SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
gc->platformContext()->setTextOffset(FloatSize(0.0f, -yOffset)); // compensate for offset in bounds calculation
y += yOffset;
}
if (EmojiFont::IsAvailable()) {
// set filtering, to make scaled images look nice(r)
paint.setFilterBitmap(true);
SkMatrix rotator;
rotator.reset();
if (font->platformData().orientation() == Vertical) {
canvas->save();
canvas->rotate(-90);
rotator.setRotate(90);
}
int localIndex = 0;
int localCount = 0;
for (int i = 0; i < numGlyphs; i++) {
if (EmojiFont::IsEmojiGlyph(glyphs[i])) {
if (localCount) {
rotator.mapPoints(&pos[localIndex], localCount);
canvas->drawPosText(&glyphs[localIndex],
localCount * sizeof(uint16_t),
&pos[localIndex], paint);
}
EmojiFont::Draw(canvas, glyphs[i], x, y, paint);
// reset local index/count track for "real" glyphs
localCount = 0;
localIndex = i + 1;
} else {
pos[i].set(x, y);
localCount += 1;
}
x += SkFloatToScalar(adv[i].width());
y += SkFloatToScalar(adv[i].height());
}
// draw the last run of glyphs (if any)
if (localCount) {
rotator.mapPoints(&pos[localIndex], localCount);
canvas->drawPosText(&glyphs[localIndex],
localCount * sizeof(uint16_t),
&pos[localIndex], paint);
}
if (font->platformData().orientation() == Vertical)
canvas->restore();
} else {
for (int i = 0; i < numGlyphs; i++) {
pos[i].set(x, y);
y += SkFloatToScalar(adv[i].height());
x += SkFloatToScalar(adv[i].width());
}
if (font->platformData().orientation() == Vertical) {
canvas->save();
canvas->rotate(-90);
SkMatrix rotator;
rotator.reset();
rotator.setRotate(90);
rotator.mapPoints(pos, numGlyphs);
}
canvas->drawPosText(glyphs,
numGlyphs * sizeof(uint16_t), pos, paint);
//.........这里部分代码省略.........
示例15: translate
static SkMatrix translate(SkScalar dx, SkScalar dy) {
SkMatrix matrix;
matrix.setTranslate(dx, dy);
return matrix;
}