/*! @brief Formats error message */ void GSTraceFormatter::format(std::ostream &stream, util::TraceRecord &record) { util::Exception cause; GSExceptionRegenerator regenerator(record.namedErrorCode_, record.message_, NULL, NULL, 0, record.causeInHandling_, NULL, util::Exception::STACK_TRACE_NONE); if (regenerator.getCause(cause)) { record.cause_ = &cause; if (record.namedErrorCode_.isEmpty()) { record.namedErrorCode_ = regenerator.getNamedErrorCode(); } } u8string message; try { util::NormalOStringStream oss; regenerator.formatField(oss, util::Exception::FIELD_MESSAGE); message = oss.str(); record.message_ = message.c_str(); } catch (std::bad_alloc &) { record.message_ = "(Failed to format error message by not enough memory)"; } catch (...) { record.message_ = "(Failed to format error message by unknown error)"; } Base::format(stream, record); }
void GrAtlasTextOp::onPrepareDraws(Target* target) { auto resourceProvider = target->resourceProvider(); // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix. // TODO actually only invert if we don't have RGBA SkMatrix localMatrix; if (this->usesLocalCoords() && !fGeoData[0].fViewMatrix.invert(&localMatrix)) { return; } GrAtlasManager* atlasManager = target->atlasManager(); GrGlyphCache* glyphCache = target->glyphCache(); GrMaskFormat maskFormat = this->maskFormat(); unsigned int numActiveProxies; const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(maskFormat, &numActiveProxies); if (!proxies) { SkDebugf("Could not allocate backing texture for atlas\n"); return; } SkASSERT(proxies[0]); static constexpr int kMaxTextures = GrBitmapTextGeoProc::kMaxTextures; GR_STATIC_ASSERT(GrDistanceFieldA8TextGeoProc::kMaxTextures == kMaxTextures); GR_STATIC_ASSERT(GrDistanceFieldLCDTextGeoProc::kMaxTextures == kMaxTextures); static const uint32_t kPipelineFlags = 0; auto pipe = target->makePipeline(kPipelineFlags, std::move(fProcessors), target->detachAppliedClip(), kMaxTextures); for (unsigned i = 0; i < numActiveProxies; ++i) { pipe.fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get(); } FlushInfo flushInfo; flushInfo.fPipeline = pipe.fPipeline; flushInfo.fFixedDynamicState = pipe.fFixedDynamicState; bool vmPerspective = fGeoData[0].fViewMatrix.hasPerspective(); if (this->usesDistanceFields()) { flushInfo.fGeometryProcessor = this->setupDfProcessor(*target->caps().shaderCaps(), proxies, numActiveProxies); } else { GrSamplerState samplerState = fNeedsGlyphTransform ? GrSamplerState::ClampBilerp() : GrSamplerState::ClampNearest(); flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make( *target->caps().shaderCaps(), this->color(), proxies, numActiveProxies, samplerState, maskFormat, localMatrix, vmPerspective); } flushInfo.fGlyphsToFlush = 0; size_t vertexStride = GrTextBlob::GetVertexStride(maskFormat, vmPerspective); SkASSERT(vertexStride == flushInfo.fGeometryProcessor->debugOnly_vertexStride()); int glyphCount = this->numGlyphs(); const GrBuffer* vertexBuffer; void* vertices = target->makeVertexSpace( vertexStride, glyphCount * kVerticesPerGlyph, &vertexBuffer, &flushInfo.fVertexOffset); flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); flushInfo.fIndexBuffer = target->resourceProvider()->refQuadIndexBuffer(); if (!vertices || !flushInfo.fVertexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } char* currVertex = reinterpret_cast<char*>(vertices); SkExclusiveStrikePtr autoGlyphCache; // each of these is a SubRun for (int i = 0; i < fGeoCount; i++) { const Geometry& args = fGeoData[i]; Blob* blob = args.fBlob; GrTextBlob::VertexRegenerator regenerator( resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor, target->deferredUploadTarget(), glyphCache, atlasManager, &autoGlyphCache); bool done = false; while (!done) { GrTextBlob::VertexRegenerator::Result result; if (!regenerator.regenerate(&result)) { break; } done = result.fFinished; // Copy regenerated vertices from the blob to our vertex buffer. size_t vertexBytes = result.fGlyphsRegenerated * kVerticesPerGlyph * vertexStride; if (args.fClipRect.isEmpty()) { memcpy(currVertex, result.fFirstVertex, vertexBytes); } else { SkASSERT(!vmPerspective); clip_quads(args.fClipRect, currVertex, result.fFirstVertex, vertexStride, result.fGlyphsRegenerated); } if (fNeedsGlyphTransform && !args.fViewMatrix.isIdentity()) { // We always do the distance field view matrix transformation after copying rather // than during blob vertex generation time in the blob as handling successive // arbitrary transformations would be complicated and accumulate error. if (args.fViewMatrix.hasPerspective()) { auto* pos = reinterpret_cast<SkPoint3*>(currVertex); SkMatrixPriv::MapHomogeneousPointsWithStride( args.fViewMatrix, pos, vertexStride, pos, vertexStride, result.fGlyphsRegenerated * kVerticesPerGlyph); } else { auto* pos = reinterpret_cast<SkPoint*>(currVertex); SkMatrixPriv::MapPointsWithStride( args.fViewMatrix, pos, vertexStride, result.fGlyphsRegenerated * kVerticesPerGlyph); } } flushInfo.fGlyphsToFlush += result.fGlyphsRegenerated; if (!result.fFinished) { this->flush(target, &flushInfo); } currVertex += vertexBytes; } } this->flush(target, &flushInfo); }