bool ArrangeSpriteOP<TBase>::onMouseLeftUp(int x, int y) { if (TBase::onMouseLeftUp(x, y)) return true; setScalingFromSelected(); if (m_firstPos.isValid() && !m_selection->empty() && !m_bRightPress) { Vector pos = m_editPanel->transPosScreenToProject(x, y); m_editPanel->addHistoryOP(new arrange_sprite::MoveSpritesAOP(*m_selection, pos - m_firstPos)); m_firstPos.setInvalid(); } if (m_propertyPanel && m_bDirty) { m_propertyPanel->enablePropertyGrid(true); m_propertyPanel->updatePropertyGrid(); m_bDirty = false; } if (m_autoAlignOpen && !m_selection->empty()) { std::vector<ISprite*> sprites; m_selection->traverse(FetchAllVisitor<ISprite>(sprites)); autoAlign(sprites); } return false; }
uint32_t ReadPixel(SharedSurface* src) { GLContext* gl = src->mGL; uint32_t pixel; ScopedReadbackFB a(src); { ScopedPackAlignment autoAlign(gl, 4); UniquePtr<uint8_t[]> bytes(new uint8_t[4]); gl->raw_fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, bytes.get()); memcpy(&pixel, bytes.get(), 4); } return pixel; }
static already_AddRefed<TextureClient> TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator, TextureFlags baseFlags, LayersBackend layersBackend) { auto backendType = gfx::BackendType::CAIRO; TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType, baseFlags, layersBackend); RefPtr<TextureClient> texClient; { gl::ScopedReadbackFB autoReadback(src); // We have a source FB, now we need a format. GLenum destFormat = LOCAL_GL_BGRA; GLenum destType = LOCAL_GL_UNSIGNED_BYTE; GLenum readFormat; GLenum readType; // We actually don't care if they match, since we can handle // any read{Format,Type} we get. auto gl = src->mGL; GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType); MOZ_ASSERT(readFormat == LOCAL_GL_RGBA || readFormat == LOCAL_GL_BGRA); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); // With a format and type, we can create texClient. if (readFormat == LOCAL_GL_BGRA && readType == LOCAL_GL_UNSIGNED_BYTE) { // 0xAARRGGBB // In Lendian: [BB, GG, RR, AA] texClient = factory.CreateB8G8R8AX8(); } else if (readFormat == LOCAL_GL_RGBA && readType == LOCAL_GL_UNSIGNED_BYTE) { // [RR, GG, BB, AA] texClient = factory.CreateR8G8B8AX8(); } else { MOZ_CRASH("GFX: Bad `read{Format,Type}`."); } MOZ_ASSERT(texClient); if (!texClient) return nullptr; // With a texClient, we can lock for writing. TextureClientAutoLock autoLock(texClient, OpenMode::OPEN_WRITE); DebugOnly<bool> succeeded = autoLock.Succeeded(); MOZ_ASSERT(succeeded, "texture should have locked"); MappedTextureData mapped; texClient->BorrowMappedData(mapped); // ReadPixels from the current FB into mapped.data. auto width = src->mSize.width; auto height = src->mSize.height; { ScopedPackAlignment autoAlign(gl, 4); MOZ_ASSERT(mapped.stride/4 == mapped.size.width); gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, mapped.data); } // RB_SWAPPED doesn't work with D3D11. (bug 1051010) // RB_SWAPPED doesn't work with Basic. (bug ???????) // RB_SWAPPED doesn't work with D3D9. (bug ???????) bool layersNeedsManualSwap = layersBackend == LayersBackend::LAYERS_BASIC || layersBackend == LayersBackend::LAYERS_D3D9 || layersBackend == LayersBackend::LAYERS_D3D11; if (texClient->HasFlags(TextureFlags::RB_SWAPPED) && layersNeedsManualSwap) { size_t pixels = width * height; uint8_t* itr = mapped.data; for (size_t i = 0; i < pixels; i++) { SwapRB_R8G8B8A8(itr); itr += 4; } texClient->RemoveFlags(TextureFlags::RB_SWAPPED); } } return texClient.forget(); }
void ArrangeSpriteOP<TBase>::autoAlign(const std::vector<ISprite*>& sprites) { m_autoAlignHor[0].set(0, 0); m_autoAlignHor[1].set(0, 0); m_autoAlignVer[0].set(0, 0); m_autoAlignVer[1].set(0, 0); std::vector<ISprite*> sources; m_spritesImpl->traverseSprites(FetchAllVisitor<ISprite>(sources)); // not support multi src now if (sprites.size() > 1) return; const float DIS = 5; ISprite *horNearest = NULL, *verNearest = NULL; float disHor = DIS, disVer = DIS; // hor for (size_t i = 0, n = sources.size(); i < n; ++i) { ISprite *dst = sprites[0], *src = sources[i]; if (src == dst) continue; const float srcHalfHeight = src->getBounding()->height() * 0.5f; const float dstHalfHeight = dst->getBounding()->height() * 0.5f; float srcDown = src->getPosition().y - srcHalfHeight; float srcUp = src->getPosition().y + srcHalfHeight; float dstDown = dst->getPosition().y - dstHalfHeight; float dstUp = dst->getPosition().y + dstHalfHeight; // up if (float dis = fabs(dstUp - srcUp) < disHor) { disHor = dis; horNearest = src; } else if (float dis = fabs(dstUp - srcDown) < disHor) { disHor = dis; horNearest = src; } // down if (float dis = fabs(dstDown - srcUp) < disHor) { disHor = dis; horNearest = src; } else if (float dis = fabs(dstDown - srcDown) < disHor) { disHor = dis; horNearest = src; } } // ver for (size_t i = 0, n = sources.size(); i < n; ++i) { ISprite *dst = sprites[0], *src = sources[i]; if (src == dst) continue; const float srcHalfWidth = src->getBounding()->width() * 0.5f; const float dstHalfWidth = dst->getBounding()->width() * 0.5f; float srcLeft = src->getPosition().x - srcHalfWidth; float srcRight = src->getPosition().x + srcHalfWidth; float dstLeft = dst->getPosition().x - dstHalfWidth; float dstRight = dst->getPosition().x + dstHalfWidth; // left if (float dis = fabs(dstLeft - srcLeft) < disVer) { disVer = dis; verNearest = src; } else if (float dis = fabs(dstLeft - srcRight) < disVer) { disVer = dis; verNearest = src; } // right if (float dis = fabs(dstRight - srcLeft) < disVer) { disVer = dis; verNearest = src; } else if (float dis = fabs(dstRight - srcRight) < disVer) { disVer = dis; verNearest = src; } } ////////////////////////////////////////////////////////////////////////// if (horNearest) autoAlign(horNearest, sprites[0]); if (verNearest && verNearest != horNearest) autoAlign(verNearest, sprites[0]); ////////////////////////////////////////////////////////////////////////// // for (size_t i = 0, n = sprites.size(); i < n; ++i) // { // for (size_t j = 0, m = sources.size(); j < m; ++j) // { // if (sprites[i] != sources[j]) // autoAlign(sources[j], sprites[i]); // } // } }
bool ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst) { AutoLockBits lock(dst); uint8_t* dstBytes; gfx::IntSize dstSize; int32_t dstStride; gfx::SurfaceFormat dstFormat; if (!lock.Lock(&dstBytes, &dstSize, &dstStride, &dstFormat)) return false; const bool isDstRGBA = (dstFormat == gfx::SurfaceFormat::R8G8B8A8 || dstFormat == gfx::SurfaceFormat::R8G8B8X8); MOZ_ASSERT_IF(!isDstRGBA, dstFormat == gfx::SurfaceFormat::B8G8R8A8 || dstFormat == gfx::SurfaceFormat::B8G8R8X8); size_t width = src->mSize.width; size_t height = src->mSize.height; MOZ_ASSERT(width == (size_t)dstSize.width); MOZ_ASSERT(height == (size_t)dstSize.height); GLenum readGLFormat; GLenum readType; { ScopedReadbackFB autoReadback(src); // We have a source FB, now we need a format. GLenum dstGLFormat = isDstRGBA ? LOCAL_GL_BGRA : LOCAL_GL_RGBA; GLenum dstType = LOCAL_GL_UNSIGNED_BYTE; // We actually don't care if they match, since we can handle // any read{Format,Type} we get. GLContext* gl = src->mGL; GetActualReadFormats(gl, dstGLFormat, dstType, &readGLFormat, &readType); MOZ_ASSERT(readGLFormat == LOCAL_GL_RGBA || readGLFormat == LOCAL_GL_BGRA); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); // ReadPixels from the current FB into lockedBits. { size_t alignment = 8; if (dstStride % 4 == 0) alignment = 4; ScopedPackAlignment autoAlign(gl, alignment); gl->raw_fReadPixels(0, 0, width, height, readGLFormat, readType, dstBytes); } } const bool isReadRGBA = readGLFormat == LOCAL_GL_RGBA; if (isReadRGBA != isDstRGBA) { for (size_t j = 0; j < height; ++j) { uint8_t* rowItr = dstBytes + j*dstStride; uint8_t* rowEnd = rowItr + 4*width; while (rowItr != rowEnd) { Swap(rowItr[0], rowItr[2]); rowItr += 4; } } } return true; }