void Area::load() { Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' '), true); loadARE(are.getTopLevel()); Aurora::GFF3File git(_resRef, Aurora::kFileTypeGIT, MKTAG('G', 'I', 'T', ' '), true); loadGIT(git.getTopLevel()); }
void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture, GrDrawTarget* target, const SkIRect& rect) { GrDrawState* drawState = target->drawState(); GrDrawState::AutoViewMatrixRestore avmr; if (!avmr.setIdentity(drawState)) { return; } GrDrawState::AutoRestoreEffects are(drawState); SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft, SK_Scalar1 * rect.fTop, SK_Scalar1 * rect.fRight, SK_Scalar1 * rect.fBottom); // We want to use device coords to compute the texture coordinates. We set our matrix to be // equal to the view matrix followed by a translation so that the top-left of the device bounds // maps to 0,0, and then a scaling matrix to normalized coords. We apply this matrix to the // vertex positions rather than local coords. SkMatrix maskMatrix; maskMatrix.setIDiv(texture->width(), texture->height()); maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop)); maskMatrix.preConcat(drawState->getViewMatrix()); drawState->addCoverageEffect( GrSimpleTextureEffect::Create(texture, maskMatrix, GrTextureParams::kNone_FilterMode, kPosition_GrCoordSet))->unref(); target->drawSimpleRect(dstRect); }
void GrBitmapTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); GrDrawState::AutoRestoreEffects are(drawState); drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); // This effect could be stored with one of the cache objects (atlas?) drawState->addCoverageEffect( GrCustomCoordsTextureEffect::Create(fCurrTexture, params), kGlyphCoordsAttributeIndex)->unref(); if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(0xffffffff); } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { GrPrintf("LCD Text will not draw correctly.\n"); } // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); } else { // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(fPaint.getColor()); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; fVertexBounds.setLargestInverted(); SkSafeSetNull(fCurrTexture); } }
void Area::load() { Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' ')); loadARE(are.getTopLevel()); loadResources(); Aurora::GFF3File sav(_resRef, Aurora::kFileTypeSAV, MKTAG('S', 'A', 'V', ' ')); loadSAV(sav.getTopLevel()); loadLYT(); // Room layout loadVIS(); // Room visibilities loadRooms(); }
Aurora::LocString Area::getName(const Common::UString &resRef) { try { Aurora::GFF3File are(resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' ')); Aurora::LocString name; are.getTopLevel().getLocString("Name", name); return name; } catch (...) { } return Aurora::LocString(); }
Common::UString Area::getName(const Common::UString &resRef) { try { Aurora::GFF3File are(resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' '), true); Common::UString name = are.getTopLevel().getString("Name"); if (!name.empty() && (*--name.end() == '\n')) name.erase(--name.end()); return name; } catch (...) { } return ""; }
void Area::load(const Common::UString &resRef) { _resRef = resRef; loadLYT(); // Room layout loadVIS(); // Room visibilities loadRooms(); Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' ')); loadARE(are.getTopLevel()); Aurora::GFF3File git(_resRef, Aurora::kFileTypeGIT, MKTAG('G', 'I', 'T', ' ')); loadGIT(git.getTopLevel()); _loaded = true; }
Area::Area(Module &module, const Common::UString &resRef) : Object(kObjectTypeArea), _module(&module), _resRef(resRef), _visible(false), _activeObject(0), _highlightAll(false) { try { // Load ARE and GIT Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' ')); loadARE(are.getTopLevel()); Aurora::GFF3File git(_resRef, Aurora::kFileTypeGIT, MKTAG('G', 'I', 'T', ' ')); loadGIT(git.getTopLevel()); } catch (...) { clear(); throw; } // Tell the module that we exist _module->addObject(*this); }
void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, GrDrawState* drawState, GrColor color, const SkRect& devOutside, const SkRect& devOutsideAssist, const SkRect& devInside, bool miterStroke) { GrDrawState::AutoRestoreEffects are(drawState); CoverageAttribType type; SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*drawState, color, &type)); int innerVertexNum = 4; int outerVertexNum = miterStroke ? 4 : 8; int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; size_t vstride = gp->getVertexStride(); GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, vstride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; } GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(miterStroke); if (NULL == indexBuffer) { SkDebugf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. // The following pointers refer to the four rects, from outermost to innermost. SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstride); SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vstride); SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride); #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX // TODO: this only really works if the X & Y margins are the same all around // the rect (or if they are all >= 1.0). SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight); inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); if (miterStroke) { inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom); } else { inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom); } SkASSERT(inset >= 0); #else SkScalar inset = SK_ScalarHalf; #endif if (miterStroke) { // outermost set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); // inner two set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); } else { SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride); SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vstride); // outermost set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); // outer one of the inner two set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset); // inner one of the inner two set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); // innermost set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); } // Make verts point to vertex color and then set all the color and coverage vertex attrs values. // The outermost rect has 0 coverage verts += sizeof(SkPoint); for (int i = 0; i < outerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; } } // scale is the coverage for the the inner two rects. int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); verts += outerVertexNum * vstride; for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<float*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = scaledColor; } } // The innermost rect has 0 coverage verts += (outerVertexNum + innerVertexNum) * vstride; for (int i = 0; i < innerVertexNum; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vstride) = color; *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; } } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, totalVertexNum, aa_stroke_rect_index_count(miterStroke)); target->resetIndexSource(); }
void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target, GrDrawState* drawState, GrColor color, const SkRect& rect, const SkMatrix& combinedMatrix, const SkRect& devRect) { GrDrawState::AutoRestoreEffects are(drawState); CoverageAttribType type; SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(*drawState, color, &type)); size_t vertexStride = gp->getVertexStride(); GrDrawTarget::AutoReleaseGeometry geo(target, 8, vertexStride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; } if (NULL == fAAFillRectIndexBuffer) { fAAFillRectIndexBuffer = fGpu->createInstancedIndexBuffer(gFillAARectIdx, kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect); } GrIndexBuffer* indexBuffer = fAAFillRectIndexBuffer; if (NULL == indexBuffer) { SkDebugf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); if (combinedMatrix.rectStaysRect()) { // Temporarily #if'ed out. We don't want to pass in the devRect but // right now it is computed in GrContext::apply_aa_to_rect and we don't // want to throw away the work #if 0 SkRect devRect; combinedMatrix.mapRect(&devRect, rect); #endif set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); } else { // compute transformed (1, 0) and (0, 1) vectors SkVector vec[2] = { { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } }; vec[0].normalize(); vec[0].scale(SK_ScalarHalf); vec[1].normalize(); vec[1].scale(SK_ScalarHalf); // create the rotated rect fan0Pos->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); combinedMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); // Now create the inset points and then outset the original // rotated points // TL *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1]; // BL *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1]; // BR *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1]; // TR *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1]; *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1]; } // Make verts point to vertex color and then set all the color and coverage vertex attrs values. verts += sizeof(SkPoint); for (int i = 0; i < 4; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; } } int scale; if (inset < SK_ScalarHalf) { scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); SkASSERT(scale >= 0 && scale <= 255); } else { scale = 0xff; } verts += 4 * vertexStride; float innerCoverage = GrNormalizeByteToFloat(scale); GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); for (int i = 0; i < 4; ++i) { if (kUseCoverage_CoverageAttribType == type) { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = innerCoverage; } else { *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; } } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, kVertsPerAAFillRect, kIndicesPerAAFillRect); target->resetIndexSource(); }
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { GrDrawState* drawState = target->drawState(); SkScalar hairlineCoverage; if (IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), &hairlineCoverage)) { uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * target->getDrawState().getCoverage()); target->drawState()->setCoverage(newCoverage); } SkIRect devClipBounds; target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds); int lineCnt; int quadCnt; int conicCnt; PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; PREALLOC_PTARRAY(128) conics; IntArray qSubdivs; FloatArray cWeights; quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClipBounds, &lines, &quads, &conics, &qSubdivs, &cWeights); lineCnt = lines.count() / 2; conicCnt = conics.count() / 3; // do lines first if (lineCnt) { GrDrawTarget::AutoReleaseGeometry arg; SkRect devBounds; if (!this->createLineGeom(path, target, lines, lineCnt, &arg, &devBounds)) { return false; } GrDrawTarget::AutoStateRestore asr; // createLineGeom transforms the geometry to device space when the matrix does not have // perspective. if (target->getDrawState().getViewMatrix().hasPerspective()) { asr.set(target, GrDrawTarget::kPreserve_ASRInit); } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { return false; } GrDrawState* drawState = target->drawState(); // Check devBounds SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), kVertsPerLineSeg * lineCnt)); { GrDrawState::AutoRestoreEffects are(drawState); target->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; while (lines < lineCnt) { int n = SkTMin(lineCnt - lines, kNumLineSegsInIdxBuffer); target->drawIndexed(kTriangles_GrPrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI kVertsPerLineSeg*n, // vCount kIdxsPerLineSeg*n, // iCount &devBounds); lines += n; } } } // then quadratics/conics if (quadCnt || conicCnt) { GrDrawTarget::AutoReleaseGeometry arg; SkRect devBounds; if (!this->createBezierGeom(path, target, quads, quadCnt, conics, conicCnt, qSubdivs, cWeights, &arg, &devBounds)) { return false; } GrDrawTarget::AutoStateRestore asr; // createGeom transforms the geometry to device space when the matrix does not have // perspective. if (target->getDrawState().getViewMatrix().hasPerspective()) { asr.set(target, GrDrawTarget::kPreserve_ASRInit); } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { return false; } GrDrawState* drawState = target->drawState(); static const int kEdgeAttrIndex = 1; // Check devBounds SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices(), kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt)); if (quadCnt > 0) { GrEffect* hairQuadEffect = GrQuadEffect::Create(kHairlineAA_GrEffectEdgeType, *target->caps()); SkASSERT(hairQuadEffect); GrDrawState::AutoRestoreEffects are(drawState); target->setIndexSourceToBuffer(fQuadsIndexBuffer); drawState->setGeometryProcessor(hairQuadEffect, kEdgeAttrIndex)->unref(); int quads = 0; while (quads < quadCnt) { int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer); target->drawIndexed(kTriangles_GrPrimitiveType, kVertsPerQuad*quads, // startV 0, // startI kVertsPerQuad*n, // vCount kIdxsPerQuad*n, // iCount &devBounds); quads += n; } } if (conicCnt > 0) { GrDrawState::AutoRestoreEffects are(drawState); GrEffect* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrEffectEdgeType, *target->caps()); SkASSERT(hairConicEffect); drawState->setGeometryProcessor(hairConicEffect, 1, 2)->unref(); int conics = 0; while (conics < conicCnt) { int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer); target->drawIndexed(kTriangles_GrPrimitiveType, kVertsPerQuad*(quadCnt + conics), // startV 0, // startI kVertsPerQuad*n, // vCount kIdxsPerQuad*n, // iCount &devBounds); conics += n; } } } target->resetIndexSource(); return true; }
void GrBitmapTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); GrDrawState::AutoRestoreEffects are(drawState); drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); uint32_t textureUniqueID = fCurrTexture->getUniqueID(); if (textureUniqueID != fEffectTextureUniqueID) { fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, params)); fEffectTextureUniqueID = textureUniqueID; } // This effect could be stored with one of the cache objects (atlas?) int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex : kGlyphCoordsNoColorAttributeIndex; drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx); SkASSERT(NULL != fStrike); switch (fStrike->getMaskFormat()) { // Color bitmap text case kARGB_GrMaskFormat: SkASSERT(!drawState->hasColorVertexAttribute()); drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(0xffffffff); break; // LCD text case kA888_GrMaskFormat: case kA565_GrMaskFormat: { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { GrPrintf("LCD Text will not draw correctly.\n"); } SkASSERT(!drawState->hasColorVertexAttribute()); // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); break; } // Grayscale/BW text case kA8_GrMaskFormat: // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); // We're using per-vertex color. SkASSERT(drawState->hasColorVertexAttribute()); break; default: SkFAIL("Unexepected mask format."); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; fVertexBounds.setLargestInverted(); SkSafeSetNull(fCurrTexture); } }
void infinite_taunt3(struct mtwist_state *mt, char *buffer, int buflen) { snprintf(buffer, buflen, "%s %s %s %s %s", you(mt), are(mt), adjective(mt), nationality(mt), bad_thing(mt)); }