void LayerTextureUpdaterSkPicture::updateTextureRect(LayerTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { if (m_createFrameBuffer) { deleteFrameBuffer(); createFrameBuffer(); m_createFrameBuffer = false; } if (!m_fbo) return; // Bind texture. context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); texture->framebufferTexture2D(); ASSERT(context()->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE); // Notify SKIA to sync its internal GL state. m_skiaContext->resetContext(); m_canvas->save(); m_canvas->clipRect(SkRect(destRect)); // Translate the origin of contentRect to that of destRect. // Note that destRect is defined relative to sourceRect. m_canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(), contentRect().y() - sourceRect.y() + destRect.y()); m_canvas->drawPicture(m_picture); m_canvas->restore(); // Flush SKIA context so that all the rendered stuff appears on the texture. m_skiaContext->flush(GrContext::kForceCurrentRenderTarget_FlushBit); // Unbind texture. context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0); context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); }
void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { GraphicsContext3D* context3d = context->context3D(); if (!context3d) { // FIXME: Implement this path for software compositing. return; } // Make sure ganesh uses the correct GL context. context3d->makeContextCurrent(); // Notify ganesh to sync its internal GL state. context3d->grContext()->resetContext(); // Create an accelerated canvas to draw on. OwnPtr<SkCanvas> canvas = createAcceleratedCanvas(context3d, allocator, texture); // The compositor expects the textures to be upside-down so it can flip // the final composited image. Ganesh renders the image upright so we // need to do a y-flip. canvas->translate(0.0, texture->size().height()); canvas->scale(1.0, -1.0); // Only the region corresponding to destRect on the texture must be updated. canvas->clipRect(SkRect(destRect)); // Translate the origin of contentRect to that of destRect. // Note that destRect is defined relative to sourceRect. canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(), contentRect().y() - sourceRect.y() + destRect.y()); drawPicture(canvas.get()); // Flush ganesh context so that all the rendered stuff appears on the texture. context3d->grContext()->flush(); }
SkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect) : fInputCount(1), fInputs(new SkImageFilter*[1]), fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { fInputs[0] = input; SkSafeRef(fInputs[0]); }
SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect) : fInputCount(2), fInputs(new SkImageFilter*[2]), fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { fInputs[0] = input1; fInputs[1] = input2; SkSafeRef(fInputs[0]); SkSafeRef(fInputs[1]); }
SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) : fUsesSrcInput(false) , fCropRect(SkRect(), 0x0) , fUniqueID(next_image_filter_unique_id()) { Common common; if (common.unflatten(buffer, inputCount)) { this->init(common.inputs(), common.inputCount(), &common.cropRect()); } }
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect) : fInputCount(inputCount), fInputs(new SkImageFilter*[inputCount]), fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { for (int i = 0; i < inputCount; ++i) { fInputs[i] = inputs[i]; SkSafeRef(fInputs[i]); } }
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect) : fInputCount(inputCount), fInputs(new SkImageFilter*[inputCount]), fUsesSrcInput(false), fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)), fUniqueID(next_image_filter_unique_id()) { for (int i = 0; i < inputCount; ++i) { if (NULL == inputs[i] || inputs[i]->usesSrcInput()) { fUsesSrcInput = true; } fInputs[i] = inputs[i]; SkSafeRef(fInputs[i]); } }
void SkImageFilter::init(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect) { fCropRect = cropRect ? *cropRect : CropRect(SkRect(), 0x0); fInputs.reset(inputCount); for (int i = 0; i < inputCount; ++i) { if (!inputs[i] || inputs[i]->usesSrcInput()) { fUsesSrcInput = true; } fInputs[i] = inputs[i]; } }
GLuint VideoLayerAndroid::createTextureFromImage(int buttonType) { SkRect rect = SkRect(buttonRect); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); bitmap.allocPixels(); bitmap.eraseColor(0); SkCanvas canvas(bitmap); canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true); GLuint texture; glGenTextures(1, &texture); GLUtils::createTextureWithBitmap(texture, bitmap); bitmap.reset(); return texture; }
void LayerTextureUpdaterSkPicture::updateTextureRect(GraphicsContext3D* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { // Make sure SKIA uses the correct GL context. context->makeContextCurrent(); // Notify SKIA to sync its internal GL state. context->grContext()->resetContext(); // Create an accelerated canvas to draw on. FrameBuffer buffer; SkCanvas* canvas = buffer.initialize(context, allocator, texture); canvas->clipRect(SkRect(destRect)); // Translate the origin of contentRect to that of destRect. // Note that destRect is defined relative to sourceRect. canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(), contentRect().y() - sourceRect.y() + destRect.y()); canvas->drawPicture(m_picture); // Flush SKIA context so that all the rendered stuff appears on the texture. context->grContext()->flush(); }
void LayerTextureUpdaterSkPicture::updateTextureRect(GraphicsContext3D* compositorContext, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { ASSERT(!m_context || m_context == compositorContext); m_context = compositorContext; if (m_createFrameBuffer) { deleteFrameBuffer(); createFrameBuffer(); m_createFrameBuffer = false; } if (!m_fbo) return; // Bind texture. context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); texture->framebufferTexture2D(context(), allocator); ASSERT(context()->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE); // Make sure SKIA uses the correct GL context. context()->makeContextCurrent(); GrContext* skiaContext = m_context->grContext(); // Notify SKIA to sync its internal GL state. skiaContext->resetContext(); m_canvas->save(); m_canvas->clipRect(SkRect(destRect)); // Translate the origin of contentRect to that of destRect. // Note that destRect is defined relative to sourceRect. m_canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(), contentRect().y() - sourceRect.y() + destRect.y()); m_canvas->drawPicture(m_picture); m_canvas->restore(); // Flush SKIA context so that all the rendered stuff appears on the texture. skiaContext->flush(); // Unbind texture. context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0); context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); }
void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const { writeHexVal(file, indentLevel + 1, "layer", (int)this); writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); writeSize(file, indentLevel + 1, "size", getSize()); writePoint(file, indentLevel + 1, "position", getPosition()); writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); if (m_content) { writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); } if (m_fixedPosition) return m_fixedPosition->dumpLayer(file, indentLevel); }
static void test_drawPathEmpty(skiatest::Reporter*, SkCanvas* canvas) { // Filling an empty path should not crash. SkPaint paint; canvas->drawRect(SkRect(), paint); canvas->drawPath(SkPath(), paint); canvas->drawOval(SkRect(), paint); canvas->drawRect(SkRect(), paint); canvas->drawRRect(SkRRect(), paint); // Stroking an empty path should not crash. paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setColor(SK_ColorGRAY); paint.setStrokeWidth(SkIntToScalar(20)); paint.setStrokeJoin(SkPaint::kRound_Join); canvas->drawRect(SkRect(), paint); canvas->drawPath(SkPath(), paint); canvas->drawOval(SkRect(), paint); canvas->drawRect(SkRect(), paint); canvas->drawRRect(SkRRect(), paint); }
bool VideoLayerAndroid::drawGL() { // Lazily allocated the textures. if (!m_createdTexture) { m_backgroundTextureId = createBackgroundTexture(); m_spinnerOuterTextureId = createSpinnerOuterTexture(); m_spinnerInnerTextureId = createSpinnerInnerTexture(); m_posterTextureId = createPosterTexture(); m_createdTexture = true; } SkRect rect = SkRect::MakeSize(getSize()); GLfloat surfaceMatrix[16]; SkRect innerRect = SkRect(buttonRect); if (innerRect.contains(rect)) innerRect = rect; innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2); // Draw the poster image, the progressing image or the Video depending // on the player's state. if (m_playerState == PREPARING) { // Show the progressing animation, with two rotating circles // SSG if (m_surfaceTexture.get() && (m_surfaceTexture->getTimestamp() > 0)) { m_surfaceTexture->getTransformMatrix(surfaceMatrix); GLuint textureId = TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, rect, textureId); TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(), surfaceMatrix); } else { TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true); } TransformationMatrix addReverseRotation; TransformationMatrix addRotation = m_drawTransform; addRotation.translate(innerRect.fLeft, innerRect.fTop); addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2); addReverseRotation = addRotation; addRotation.rotate(m_rotateDegree); addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); TilesManager::instance()->shader()->drawLayerQuad(addRotation, size, m_spinnerOuterTextureId, 1, true); addReverseRotation.rotate(-m_rotateDegree); addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size, m_spinnerInnerTextureId, 1, true); m_rotateDegree += ROTATESTEP; } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { // Show the real video. m_surfaceTexture->updateTexImage(); m_surfaceTexture->getTransformMatrix(surfaceMatrix); GLuint textureId = TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, rect, textureId); TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(), surfaceMatrix); } else { GLuint textureId = TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); GLfloat* matrix = TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId()); if (textureId && matrix) { // Show the screen shot for each video. TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, matrix, rect, textureId); } else { // Show the static poster b/c there is no screen shot available. TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true); TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect, m_posterTextureId, 1, true); } } return drawChildrenGL(); }
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point, const FloatRect& textRect) const { SkColor color = graphicsContext->effectiveFillColor(); unsigned char alpha = SkColorGetA(color); // Skip 100% transparent text; no need to draw anything. if (!alpha && graphicsContext->strokeStyle() == NoStroke && !graphicsContext->hasShadow()) return; // We draw the glyphs in chunks to avoid having to do a heap allocation for // the arrays of characters and advances. const int kMaxBufferLength = 256; Vector<int, kMaxBufferLength> advances; int glyphIndex = 0; // The starting glyph of the current chunk. float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph. #if ENABLE(OPENTYPE_VERTICAL) const OpenTypeVerticalData* verticalData = font->verticalData(); if (verticalData) { Vector<FloatPoint, kMaxBufferLength> translations; Vector<GOFFSET, kMaxBufferLength> offsets; // Skia doesn't have matrix for glyph coordinate space, so we rotate back the CTM. AffineTransform savedMatrix = graphicsContext->getCTM(); graphicsContext->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y())); graphicsContext->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y())); const FontMetrics& metrics = font->fontMetrics(); SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline)); while (glyphIndex < numGlyphs) { // How many chars will be in this chunk? int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex); const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex); translations.resize(curLen); verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], curLen, reinterpret_cast<float*>(&translations[0])); // To position glyphs vertically, we use offsets instead of advances. advances.resize(curLen); advances.fill(0); offsets.resize(curLen); float currentWidth = 0; for (int i = 0; i < curLen; ++i, ++glyphIndex) { offsets[i].du = lroundf(translations[i].x()); offsets[i].dv = -lroundf(currentWidth - translations[i].y()); currentWidth += glyphBuffer.advanceAt(from + glyphIndex); } SkPoint origin; origin.set(verticalOriginX, SkFloatToScalar(point.y() + horizontalOffset - point.x())); horizontalOffset += currentWidth; paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], &offsets[0], origin, SkRect(textRect)); } graphicsContext->setCTM(savedMatrix); return; } #endif // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position // of each glyph in floating point units and rounds to integer advances at the last possible moment. int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered. Vector<WORD, kMaxBufferLength> glyphs; while (glyphIndex < numGlyphs) { // How many chars will be in this chunk? int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex); glyphs.resize(curLen); advances.resize(curLen); float currentWidth = 0; for (int i = 0; i < curLen; ++i, ++glyphIndex) { glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex); horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex); advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded; lastHorizontalOffsetRounded += advances[i]; currentWidth += glyphBuffer.advanceAt(from + glyphIndex); // Bug 26088 - very large positive or negative runs can fail to // render so we clamp the size here. In the specs, negative // letter-spacing is implementation-defined, so this should be // fine, and it matches Safari's implementation. The call actually // seems to crash if kMaxNegativeRun is set to somewhere around // -32830, so we give ourselves a little breathing room. const int maxNegativeRun = -32768; const int maxPositiveRun = 32768; if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) advances[i] = 0; } SkPoint origin = point; origin.fX += SkFloatToScalar(horizontalOffset - point.x() - currentWidth); paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], 0, origin, SkRect(textRect)); } }