/* * Tries to handle the image with PIEX. If PIEX returns kOk and finds the preview image, create a * SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr. In other cases, * fallback to create SkRawCodec for DNG images. */ SkCodec* SkRawCodec::NewFromStream(SkStream* stream) { SkAutoTDelete<SkRawStream> rawStream; if (is_asset_stream(*stream)) { rawStream.reset(new SkRawAssetStream(stream)); } else { rawStream.reset(new SkRawBufferedStream(stream)); } // Does not take the ownership of rawStream. SkPiexStream piexStream(rawStream.get()); ::piex::PreviewImageData imageData; if (::piex::IsRaw(&piexStream)) { ::piex::Error error = ::piex::GetPreviewImageData(&piexStream, &imageData); if (error == ::piex::Error::kOk && imageData.preview.length > 0) { // transferBuffer() is destructive to the rawStream. Abandon the rawStream after this // function call. // FIXME: one may avoid the copy of memoryStream and use the buffered rawStream. SkMemoryStream* memoryStream = rawStream->transferBuffer(imageData.preview.offset, imageData.preview.length); return memoryStream ? SkJpegCodec::NewFromStream(memoryStream) : nullptr; } else if (error == ::piex::Error::kFail) { return nullptr; } } // Takes the ownership of the rawStream. SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(rawStream.release())); if (!dngImage) { return nullptr; } return new SkRawCodec(dngImage.release()); }
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) { for (int i = 0; i < fContexts.count(); ++i) { Context& context = fContexts[i]; if (context.fType == type && context.fOptions == options && !context.fAbandoned) { if (context.fGLContext) { context.fGLContext->makeCurrent(); } return ContextInfo(context.fGrContext, context.fGLContext); } } SkAutoTDelete<GLTestContext> glCtx; sk_sp<GrContext> grCtx; GrBackendContext backendContext = 0; sk_sp<const GrGLInterface> glInterface; #ifdef SK_VULKAN sk_sp<const GrVkBackendContext> vkBackend; #endif GrBackend backend = ContextTypeBackend(type); switch (backend) { case kOpenGL_GrBackend: switch (type) { case kGL_ContextType: glCtx.reset(CreatePlatformGLTestContext(kGL_GrGLStandard)); break; case kGLES_ContextType: glCtx.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard)); break; #if SK_ANGLE # ifdef SK_BUILD_FOR_WIN case kANGLE_ContextType: glCtx.reset(CreateANGLEDirect3DGLTestContext()); break; # endif case kANGLE_GL_ContextType: glCtx.reset(CreateANGLEOpenGLGLTestContext()); break; #endif #if SK_COMMAND_BUFFER case kCommandBuffer_ContextType: glCtx.reset(CommandBufferGLTestContext::Create()); break; #endif #if SK_MESA case kMESA_ContextType: glCtx.reset(CreateMesaGLTestContext()); break; #endif case kNullGL_ContextType: glCtx.reset(CreateNullGLTestContext()); break; case kDebugGL_ContextType: glCtx.reset(CreateDebugGLTestContext()); break; default: return ContextInfo(); } if (nullptr == glCtx.get()) { return ContextInfo(); } glInterface.reset(SkRef(glCtx->gl())); // Block NVPR from non-NVPR types. if (!(kEnableNVPR_ContextOptions & options)) { glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get())); if (!glInterface) { return ContextInfo(); } } backendContext = reinterpret_cast<GrBackendContext>(glInterface.get()); glCtx->makeCurrent(); break; #ifdef SK_VULKAN case kVulkan_GrBackend: SkASSERT(kVulkan_ContextType == type); if ((kEnableNVPR_ContextOptions & options) || (kRequireSRGBSupport_ContextOptions & options)) { return ContextInfo(); } vkBackend.reset(GrVkBackendContext::Create()); if (!vkBackend) { return ContextInfo(); } backendContext = reinterpret_cast<GrBackendContext>(vkBackend.get()); // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice // destruction will hang occaisonally. For some reason having an existing GL // context fixes this. if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard)); if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard)); } } break; #endif default: return ContextInfo(); } grCtx.reset(GrContext::Create(backend, backendContext, fGlobalOptions)); if (!grCtx.get()) { return ContextInfo(); } if (kEnableNVPR_ContextOptions & options) { if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) { return ContextInfo(); } } if (kRequireSRGBSupport_ContextOptions & options) { if (!grCtx->caps()->srgbSupport()) { return ContextInfo(); } } Context& context = fContexts.push_back(); context.fGLContext = glCtx.release(); context.fGrContext = SkRef(grCtx.get()); context.fType = type; context.fOptions = options; context.fAbandoned = false; return ContextInfo(context.fGrContext, context.fGLContext); }
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) { for (int i = 0; i < fContexts.count(); ++i) { Context& context = fContexts[i]; if (context.fType == type && context.fOptions == options && !context.fAbandoned) { context.fTestContext->makeCurrent(); return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext); } } SkAutoTDelete<TestContext> testCtx; sk_sp<GrContext> grCtx; GrBackendContext backendContext = 0; sk_sp<const GrGLInterface> glInterface; GrBackend backend = ContextTypeBackend(type); switch (backend) { case kOpenGL_GrBackend: { GLTestContext* glCtx; switch (type) { case kGL_ContextType: glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard); break; case kGLES_ContextType: glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard); break; #if SK_ANGLE # ifdef SK_BUILD_FOR_WIN case kANGLE_ContextType: glCtx = CreateANGLEDirect3DGLTestContext(); break; # endif case kANGLE_GL_ContextType: glCtx = CreateANGLEOpenGLGLTestContext(); break; #endif #if SK_COMMAND_BUFFER case kCommandBuffer_ContextType: glCtx = CommandBufferGLTestContext::Create(); break; #endif #if SK_MESA case kMESA_ContextType: glCtx = CreateMesaGLTestContext(); break; #endif case kNullGL_ContextType: glCtx = CreateNullGLTestContext(kEnableNVPR_ContextOptions & options); break; case kDebugGL_ContextType: glCtx = CreateDebugGLTestContext(); break; default: return ContextInfo(); } if (!glCtx) { return ContextInfo(); } testCtx.reset(glCtx); glInterface.reset(SkRef(glCtx->gl())); // Block NVPR from non-NVPR types. We don't block NVPR from contexts that will use // instanced rendering because that would prevent us from testing mixed samples. if (!((kEnableNVPR_ContextOptions | kUseInstanced_ContextOptions) & options)) { glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get())); if (!glInterface) { return ContextInfo(); } } backendContext = reinterpret_cast<GrBackendContext>(glInterface.get()); break; } #ifdef SK_VULKAN case kVulkan_GrBackend: SkASSERT(kVulkan_ContextType == type); if (kEnableNVPR_ContextOptions & options) { return ContextInfo(); } testCtx.reset(CreatePlatformVkTestContext()); if (!testCtx) { return ContextInfo(); } // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice // destruction will hang occaisonally. For some reason having an existing GL // context fixes this. if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard)); if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard)); } } backendContext = testCtx->backendContext(); break; #endif default: return ContextInfo(); } testCtx->makeCurrent(); SkASSERT(testCtx && testCtx->backend() == backend); GrContextOptions grOptions = fGlobalOptions; if (kUseInstanced_ContextOptions & options) { grOptions.fEnableInstancedRendering = true; } grCtx.reset(GrContext::Create(backend, backendContext, grOptions)); if (!grCtx.get()) { return ContextInfo(); } if (kEnableNVPR_ContextOptions & options) { if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) { return ContextInfo(); } } if (kUseInstanced_ContextOptions & options) { if (GrCaps::InstancedSupport::kNone == grCtx->caps()->instancedSupport()) { return ContextInfo(); } } if (kRequireSRGBSupport_ContextOptions & options) { if (!grCtx->caps()->srgbSupport()) { return ContextInfo(); } } Context& context = fContexts.push_back(); context.fBackend = backend; context.fTestContext = testCtx.release(); context.fGrContext = SkRef(grCtx.get()); context.fType = type; context.fOptions = options; context.fAbandoned = false; return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext); }
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData( FontHandle fontHandle, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) { // Assuming that on average, the ASCII representation of an advance plus // a space is 8 characters and the ASCII representation of a glyph id is 3 // characters, then the following cut offs for using different range types // apply: // The cost of stopping and starting the range is 7 characers // a. Removing 4 0's or don't care's is a win // The cost of stopping and starting the range plus a run is 22 // characters // b. Removing 3 repeating advances is a win // c. Removing 2 repeating advances and 3 don't cares is a win // When not currently in a range the cost of a run over a range is 16 // characaters, so: // d. Removing a leading 0/don't cares is a win because it is omitted // e. Removing 2 repeating advances is a win SkAutoTDelete<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result; SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange; SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = nullptr; Data lastAdvance = kInvalidAdvance; int repeatedAdvances = 0; int wildCardsInRun = 0; int trailingWildCards = 0; uint32_t subsetIndex = 0; // Limit the loop count to glyph id ranges provided. int firstIndex = 0; int lastIndex = num_glyphs; if (subsetGlyphIDs) { firstIndex = static_cast<int>(subsetGlyphIDs[0]); lastIndex = static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; } curRange = appendRange(&result, firstIndex); for (int gId = firstIndex; gId <= lastIndex; gId++) { Data advance = kInvalidAdvance; if (gId < lastIndex) { // Get glyph id only when subset is nullptr, or the id is in subset. SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex])); if (!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) { SkAssertResult(getAdvance(fontHandle, gId, &advance)); ++subsetIndex; } else { advance = kDontCareAdvance; } } if (advance == lastAdvance) { repeatedAdvances++; trailingWildCards = 0; } else if (advance == kDontCareAdvance) { wildCardsInRun++; trailingWildCards++; } else if (curRange->fAdvance.count() == repeatedAdvances + 1 + wildCardsInRun) { // All in run. if (lastAdvance == 0) { resetRange(curRange, gId); trailingWildCards = 0; } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) { finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } else { if (lastAdvance == 0 && repeatedAdvances + 1 + wildCardsInRun >= 4) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) { finishRange(curRange, gId - trailingWildCards - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (lastAdvance != 0 && (repeatedAdvances + 1 >= 3 || (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); curRange = appendRange(&curRange->fNext, gId - repeatedAdvances - wildCardsInRun - 1); curRange->fAdvance.append(1, &lastAdvance); finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } curRange->fAdvance.append(1, &advance); if (advance != kDontCareAdvance) { lastAdvance = advance; } } if (curRange->fStartId == lastIndex) { SkASSERT(prevRange); SkASSERT(prevRange->fNext->fStartId == lastIndex); prevRange->fNext.reset(); } else { finishRange(curRange, lastIndex - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); } return result.release(); }