nsresult CacheFileMetadata::SetElement(const char *aKey, const char *aValue) { LOG(("CacheFileMetadata::SetElement() [this=%p, key=%s, value=%p]", this, aKey, aValue)); MarkDirty(); const uint32_t keySize = strlen(aKey) + 1; char *pos = const_cast<char *>(GetElement(aKey)); if (!aValue) { // No value means remove the key/value pair completely, if existing if (pos) { uint32_t oldValueSize = strlen(pos) + 1; uint32_t offset = pos - mBuf; uint32_t remainder = mElementsSize - (offset + oldValueSize); memmove(pos - keySize, pos + oldValueSize, remainder); mElementsSize -= keySize + oldValueSize; } return NS_OK; } const uint32_t valueSize = strlen(aValue) + 1; uint32_t newSize = mElementsSize + valueSize; if (pos) { const uint32_t oldValueSize = strlen(pos) + 1; const uint32_t offset = pos - mBuf; const uint32_t remainder = mElementsSize - (offset + oldValueSize); // Update the value in place newSize -= oldValueSize; EnsureBuffer(newSize); // Move the remainder to the right place pos = mBuf + offset; memmove(pos + valueSize, pos + oldValueSize, remainder); } else { // allocate new meta data element newSize += keySize; EnsureBuffer(newSize); // Add after last element pos = mBuf + mElementsSize; memcpy(pos, aKey, keySize); pos += keySize; } // Update value memcpy(pos, aValue, valueSize); mElementsSize = newSize; return NS_OK; }
nsresult nsCacheMetaData::SetElement(const char * key, const char * value) { const PRUint32 keySize = strlen(key) + 1; char * pos = (char *)GetElement(key); if (!value) { // No value means remove the key/value pair completely, if existing if (pos) { PRUint32 oldValueSize = strlen(pos) + 1; PRUint32 offset = pos - mBuffer; PRUint32 remainder = mMetaSize - (offset + oldValueSize); memmove(pos - keySize, pos + oldValueSize, remainder); mMetaSize -= keySize + oldValueSize; } return NS_OK; } const PRUint32 valueSize = strlen(value) + 1; PRUint32 newSize = mMetaSize + valueSize; if (pos) { const PRUint32 oldValueSize = strlen(pos) + 1; const PRUint32 offset = pos - mBuffer; const PRUint32 remainder = mMetaSize - (offset + oldValueSize); // Update the value in place newSize -= oldValueSize; nsresult rv = EnsureBuffer(newSize); NS_ENSURE_SUCCESS(rv, rv); // Move the remainder to the right place pos = mBuffer + offset; memmove(pos + valueSize, pos + oldValueSize, remainder); } else { // allocate new meta data element newSize += keySize; nsresult rv = EnsureBuffer(newSize); NS_ENSURE_SUCCESS(rv, rv); // Add after last element pos = mBuffer + mMetaSize; memcpy(pos, key, keySize); pos += keySize; } // Update value memcpy(pos, value, valueSize); mMetaSize = newSize; return NS_OK; }
nsresult Http2PushTransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer, uint32_t count, uint32_t *countWritten) { if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) { EnsureBuffer(mBufferedHTTP1,mBufferedHTTP1Size + kDefaultBufferSize, mBufferedHTTP1Used, mBufferedHTTP1Size); } count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used); nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used, count, countWritten); if (NS_SUCCEEDED(rv)) { mBufferedHTTP1Used += *countWritten; } else if (rv == NS_BASE_STREAM_CLOSED) { mIsDone = true; } if (Available() || mIsDone) { Http2Stream *consumer = mPushStream->GetConsumerStream(); if (consumer) { LOG3(("Http2PushTransactionBuffer::WriteSegments notifying connection " "consumer data available 0x%X [%u] done=%d\n", mPushStream->StreamID(), Available(), mIsDone)); mPushStream->ConnectPushedStream(consumer); } } return rv; }
void CBuffer::AddReversed(const void * pData, DWORD nLength) { EnsureBuffer( nLength ); ReverseBuffer( pData, m_pBuffer + m_nLength, nLength ); m_nLength += nLength; }
nsresult nsCacheMetaData::UnflattenMetaData(const char * data, PRUint32 size) { if (data && size) { // Check if the metadata ends with a zero byte. if (data[size-1] != '\0') { NS_ERROR("Cache MetaData is not null terminated"); return NS_ERROR_ILLEGAL_VALUE; } // Check that there are an even number of zero bytes // to match the pattern { key \0 value \0 } bool odd = false; for (PRUint32 i = 0; i < size; i++) { if (data[i] == '\0') odd = !odd; } if (odd) { NS_ERROR("Cache MetaData is malformed"); return NS_ERROR_ILLEGAL_VALUE; } nsresult rv = EnsureBuffer(size); NS_ENSURE_SUCCESS(rv, rv); memcpy(mBuffer, data, size); mMetaSize = size; } return NS_OK; }
/** * @param aXSide LEFT means we draw from the left side of the buffer (which * is drawn on the right side of mBufferRect). RIGHT means we draw from * the right side of the buffer (which is drawn on the left side of * mBufferRect). * @param aYSide TOP means we draw from the top side of the buffer (which * is drawn on the bottom side of mBufferRect). BOTTOM means we draw from * the bottom side of the buffer (which is drawn on the top side of * mBufferRect). */ void ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide, float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) { // The rectangle that we're going to fill. Basically we're going to // render the buffer at mBufferRect + quadrantTranslation to get the // pixels in the right place, but we're only going to paint within // mBufferRect nsIntRect quadrantRect = GetQuadrantRectangle(aXSide, aYSide); nsIntRect fillRect; if (!fillRect.IntersectRect(mBufferRect, quadrantRect)) return; aTarget->NewPath(); aTarget->Rectangle(gfxRect(fillRect.x, fillRect.y, fillRect.width, fillRect.height), true); gfxPoint quadrantTranslation(quadrantRect.x, quadrantRect.y); nsRefPtr<gfxPattern> pattern = new gfxPattern(EnsureBuffer()); #ifdef MOZ_GFX_OPTIMIZE_MOBILE gfxPattern::GraphicsFilter filter = gfxPattern::FILTER_NEAREST; pattern->SetFilter(filter); #endif gfxContextMatrixAutoSaveRestore saveMatrix(aTarget); // Transform from user -> buffer space. gfxMatrix transform; transform.Translate(-quadrantTranslation); pattern->SetMatrix(transform); aTarget->SetPattern(pattern); if (aMask) { if (aOpacity == 1.0) { aTarget->SetMatrix(*aMaskTransform); aTarget->Mask(aMask); } else { aTarget->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); aTarget->Paint(aOpacity); aTarget->PopGroupToSource(); aTarget->SetMatrix(*aMaskTransform); aTarget->Mask(aMask); } } else { if (aOpacity == 1.0) { aTarget->Fill(); } else { aTarget->Save(); aTarget->Clip(); aTarget->Paint(aOpacity); aTarget->Restore(); } } }
void CBuffer::Print(LPCWSTR pszText) { int nLength = wcslen( pszText ); EnsureBuffer( (DWORD)nLength + 1 ); wcstombs( (LPSTR)( m_pBuffer + m_nLength ), pszText, nLength ); m_nLength += nLength - 1; }
// Takes a pointer to some memory, and the number of bytes we can read there // Adds them to this buffer, except in reverse order void CBuffer::AddReversed(const void *pData, DWORD nLength) { // Make sure this buffer has enough memory allocated to hold another nLength bytes EnsureBuffer( nLength ); // Copy nLength bytes from pData to the end of the buffer, except in reverse order ReverseBuffer( pData, m_pBuffer + m_nLength, nLength ); // Record the new length m_nLength += nLength; }
void CBuffer::Print(LPCWSTR pszText, UINT nCodePage) { if ( pszText == NULL ) return; int nLength = wcslen( pszText ); int nBytes = WideCharToMultiByte( nCodePage, 0, pszText, nLength, NULL, 0, NULL, NULL ); EnsureBuffer( (DWORD)nBytes ); WideCharToMultiByte( nCodePage, 0, pszText, nLength, (LPSTR)( m_pBuffer + m_nLength ), nBytes, NULL, NULL ); m_nLength += nBytes; }
// Add data to the buffer void CBuffer::Add(const void* pData, const size_t nLength) //throw() { // If the text is blank, don't do anything if ( pData == NULL ) return; if ( ! EnsureBuffer( nLength ) ) return; // Copy the given memory into the end of the memory block CopyMemory( m_pBuffer + m_nLength, pData, nLength ); // Add the length of the new memory to the total length in the buffer m_nLength += static_cast< DWORD >( nLength ); }
// Takes a pointer to some memory, and the number of bytes we can read there // Adds them to this buffer, except in reverse order void CBuffer::AddReversed(const void *pData, const size_t nLength) { ASSERT( pData ); if ( pData == NULL ) return; // Make sure this buffer has enough memory allocated to hold another nLength bytes if ( ! EnsureBuffer( nLength ) ) return; // Copy nLength bytes from pData to the end of the buffer, except in reverse order ReverseBuffer( pData, m_pBuffer + m_nLength, nLength ); // Record the new length m_nLength += static_cast< DWORD >( nLength ); }
BOOL CNktStringW::ConcatN(__in_nz_opt LPCWSTR szSrcW, __in SIZE_T nSrcLen) { if (nSrcLen == 0) return TRUE; if (szSrcW == NULL) return FALSE; if (nLen+nSrcLen < nLen) return FALSE; //overflow if (EnsureBuffer(nLen+nSrcLen) == FALSE) return FALSE; memcpy(szStrW+nLen, szSrcW, nSrcLen*sizeof(WCHAR)); nLen += nSrcLen; szStrW[nLen] = 0; return TRUE; }
void RotatedContentBuffer::DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) { if (!EnsureBuffer()) { return; } RefPtr<DrawTarget> dt = aTarget->GetDrawTarget(); MOZ_ASSERT(dt, "Did you pass a non-Azure gfxContext?"); bool clipped = false; // If the entire buffer is valid, we can just draw the whole thing, // no need to clip. But we'll still clip if clipping is cheap --- // that might let us copy a smaller region of the buffer. // Also clip to the visible region if we're told to. if (!aLayer->GetValidRegion().Contains(BufferRect()) || (ToData(aLayer)->GetClipToVisibleRegion() && !aLayer->GetVisibleRegion().Contains(BufferRect())) || IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) { // We don't want to draw invalid stuff, so we need to clip. Might as // well clip to the smallest area possible --- the visible region. // Bug 599189 if there is a non-integer-translation transform in aTarget, // we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong // and may cause gray lines. gfxUtils::ClipToRegionSnapped(dt, aLayer->GetEffectiveVisibleRegion()); clipped = true; } RefPtr<gfx::SourceSurface> mask; if (aMask) { mask = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aMask); } Matrix maskTransform; if (aMaskTransform) { maskTransform = ToMatrix(*aMaskTransform); } CompositionOp op = CompositionOpForOp(aTarget->CurrentOperator()); DrawBufferWithRotation(dt, BUFFER_BLACK, aOpacity, op, mask, &maskTransform); if (clipped) { dt->PopClip(); } }
already_AddRefed<gfxContext> ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds) { nsRefPtr<gfxContext> ctx = new gfxContext(EnsureBuffer()); // Figure out which quadrant to draw in int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x; int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y; XSide sideX = aBounds.XMost() <= xBoundary ? RIGHT : LEFT; YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP; nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY); NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants"); ctx->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y)); return ctx.forget(); }
BOOL CNktStringW::InsertN(__in_nz_opt LPCWSTR szSrcW, __in SIZE_T nInsertPosition, __in SIZE_T nSrcLen) { if (nSrcLen == 0) return TRUE; if (szSrcW == NULL) return FALSE; if (nLen+nSrcLen < nLen) return FALSE; //overflow if (EnsureBuffer(nLen+nSrcLen) == FALSE) return FALSE; if (nInsertPosition > nLen) nInsertPosition = nLen; memmove(szStrW+nInsertPosition+nSrcLen, szStrW+nInsertPosition, (nLen-nInsertPosition)*sizeof(WCHAR)); memcpy(szStrW+nInsertPosition, szSrcW, nSrcLen*sizeof(WCHAR)); nLen += nSrcLen; szStrW[nLen] = 0; return TRUE; }
NS_IMETHODIMP npAPInsIInputStreamShim::CopyFromPluginHostToBuffer(int32 len, void* buf, int32 * outWritten) { nsresult rv = NS_ERROR_NULL_POINTER; if (nsnull == outWritten) { return rv; } if (mDoClose) { DoClose(); return NS_ERROR_NOT_AVAILABLE; } rv = EnsureBuffer(len); if (NS_FAILED(rv)) { return rv; } mNumWrittenFromPluginHost = len; *outWritten = mNumWrittenFromPluginHost; if (0 < mNumWrittenFromPluginHost) { // copy the bytes the from the plugin host into our buffer memcpy(((char *) mBuffer) + mCountFromPluginHost, buf, (size_t) mNumWrittenFromPluginHost); mCountFromPluginHost += mNumWrittenFromPluginHost; mAvailableForPluglet = mCountFromPluginHost - mCountFromPluglet; } // if we have bytes available for the pluglet, and they have // requested a callback when bytes are available. if (mCallback && 0 < mAvailableForPluglet && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) { rv = mCallback->OnInputStreamReady(this); mCallback = nsnull; mCallbackFlags = nsnull; } rv = NS_OK; return rv; }
// Takes a handle to a socket // Reads in data from the socket, moving it into the buffer // Returns the number of bytes we got DWORD CBuffer::Receive(SOCKET hSocket, DWORD nSpeedLimit) { // Start the total at 0 DWORD nTotal = 0ul; // Read bytes from the socket until the limit has run out while ( nSpeedLimit ) { // Limit nLength to the free buffer space or the maximum size of an int size_t nLength = min( GetBufferFree(), (size_t)INT_MAX ); // static_cast< size_t >( INT_MAX ) if ( nLength ) nLength = min( nLength, (size_t)nSpeedLimit ); // Limit nLength to the speed limit else nLength = min( (size_t)nSpeedLimit, MAX_RECV_SIZE ); // Limit nLength to the maximum receive size // Exit loop if the buffer isn't big enough to hold the data if ( ! EnsureBuffer( nLength ) ) break; // Point where the data is to be stored. This needs to be done after // EnsureBuffer() is called as it may have changed the buffer char* const pData = reinterpret_cast< char* >( GetDataEnd() ); // Read the bytes from the socket and record how many are actually read const int nRead = ::Recv( hSocket, pData, static_cast< int >( nLength ) ); // Exit loop if nothing is left or an error occurs if ( nRead <= 0 ) break; m_nLength += nRead; // Add to the buffer size nTotal += nRead; // Add to the total nSpeedLimit -= nRead; // Adjust the limit } // Add the total to statistics (Moved to Connection.cpp) //Statistics.Current.Bandwidth.Incoming += nTotal; //Statistics.Current.Downloads.Volume += ( nTotal / 1024 ); // Return the total #bytes read return nTotal; }
void DelayBuffer::Write(const AudioChunk& aInputChunk) { // We must have a reference to the buffer if there are channels MOZ_ASSERT(aInputChunk.IsNull() == !aInputChunk.mChannelData.Length()); #ifdef DEBUG MOZ_ASSERT(!mHaveWrittenBlock); mHaveWrittenBlock = true; #endif if (!EnsureBuffer()) { return; } if (mCurrentChunk == mLastReadChunk) { mLastReadChunk = -1; // invalidate cache } mChunks[mCurrentChunk] = aInputChunk; }
BOOL CNktStringW::AppendFormatV(__in LPCWSTR szFormatW, __in va_list argptr) { int nChars; if (szFormatW == NULL) return FALSE; nChars = _vscwprintf(szFormatW, argptr); if (nChars > 0) { if (nLen+(SIZE_T)nChars+1 < nLen) return FALSE; //overflow if (EnsureBuffer(nLen+(SIZE_T)nChars+1) == FALSE) return FALSE; vswprintf_s(szStrW+nLen, (size_t)nChars+1, szFormatW, argptr); nLen += (SIZE_T)nChars; szStrW[nLen] = 0; } return TRUE; }
already_AddRefed<gfxContext> RotatedContentBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource, nsIntPoint *aTopLeft) { if (!EnsureBuffer()) { return nullptr; } nsRefPtr<gfxContext> ctx; if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) { if (!EnsureBufferOnWhite()) { return nullptr; } MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite); RefPtr<DrawTarget> dualDT = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite); ctx = new gfxContext(dualDT); } else if (aSource == BUFFER_WHITE) { if (!EnsureBufferOnWhite()) { return nullptr; } ctx = new gfxContext(mDTBufferOnWhite); } else { // BUFFER_BLACK, or BUFFER_BOTH with a single buffer. ctx = new gfxContext(mDTBuffer); } // Figure out which quadrant to draw in int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x; int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y; XSide sideX = aBounds.XMost() <= xBoundary ? RIGHT : LEFT; YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP; nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY); NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants"); ctx->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y)); if (aTopLeft) { *aTopLeft = nsIntPoint(quadrantRect.x, quadrantRect.y); } return ctx.forget(); }
nsresult SpdyConnectTransaction::WriteSegments(nsAHttpSegmentWriter *writer, uint32_t count, uint32_t *countWritten) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); LOG(("SpdyConnectTransaction::WriteSegments %p max=%d cb=%p\n", this, count, mTunneledConn ? mTunnelStreamIn->mCallback : nullptr)); // first call into the tunnel stream to get the demux'd data out of the // spdy session. EnsureBuffer(mInputData, mInputDataUsed + count, mInputDataUsed, mInputDataSize); nsresult rv = writer->OnWriteSegment(mInputData + mInputDataUsed, count, countWritten); if (NS_FAILED(rv)) { if (rv != NS_BASE_STREAM_WOULD_BLOCK) { LOG(("SpdyConnectTransaction::WriteSegments wrapped writer %p Error %x\n", this, rv)); CreateShimError(rv); } return rv; } mInputDataUsed += *countWritten; LOG(("SpdyConnectTransaction %p %d new bytes [%d total] of ciphered data buffered\n", this, *countWritten, mInputDataUsed - mInputDataOffset)); if (!mTunneledConn || !mTunnelStreamIn->mCallback) { return NS_BASE_STREAM_WOULD_BLOCK; } rv = mTunnelStreamIn->mCallback->OnInputStreamReady(mTunnelStreamIn); LOG(("SpdyConnectTransaction::WriteSegments %p " "after InputStreamReady callback %d total of ciphered data buffered rv=%x\n", this, mInputDataUsed - mInputDataOffset, rv)); LOG(("SpdyConnectTransaction::WriteSegments %p " "goodput %p out %llu\n", this, mTunneledConn.get(), mTunneledConn->ContentBytesWritten())); if (NS_SUCCEEDED(rv) && !mTunneledConn->ContentBytesWritten()) { mTunnelStreamOut->AsyncWait(mTunnelStreamOut->mCallback, 0, 0, nullptr); } return rv; }
// DIME is a specification for sending and receiving SOAP messages along with additional attachments, like binary files or XML fragments // Takes information to create a DIME message // Composes the DIME message and writes it into this buffer void CBuffer::WriteDIME( DWORD nFlags, // 0, 1, or 2 LPCSTR pszID, // Blank, or a GUID in hexadecimal encoding LPCSTR pszType, // "text/xml" or a URI to an XML specification LPCVOID pBody, // The XML fragment we're wrapping DWORD nBody) // How long it is { // Format lengths into the bytes of the DIME header EnsureBuffer( 12 ); // Make sure this buffer has at least 12 bytes of space BYTE* pOut = m_pBuffer + m_nLength; // Point pOut at the end of the memory block in this buffer *pOut++ = 0x08 | ( nFlags & 1 ? 4 : 0 ) | ( nFlags & 2 ? 2 : 0 ); // *pOut++ = 0x08 sets the byte at pOut and then moves the pointer forward *pOut++ = strchr( pszType, ':' ) ? 0x20 : 0x10; *pOut++ = 0x00; *pOut++ = 0x00; *pOut++ = ( ( strlen( pszID ) & 0xFF00 ) >> 8 ); *pOut++ = ( strlen( pszID ) & 0xFF ); *pOut++ = ( ( strlen( pszType ) & 0xFF00 ) >> 8 ); *pOut++ = ( strlen( pszType ) & 0xFF ); *pOut++ = (BYTE)( ( nBody & 0xFF000000 ) >> 24 ); *pOut++ = (BYTE)( ( nBody & 0x00FF0000 ) >> 16 ); *pOut++ = (BYTE)( ( nBody & 0x0000FF00 ) >> 8 ); *pOut++ = (BYTE)( nBody & 0x000000FF ); m_nLength += 12; // Record that we wrote 12 bytes, but we really only wrote 11 (do) // Print pszID, which is blank or a GUID in hexadecimal encoding, and bytes of 0 until the total length we added is a multiple of 4 Print( pszID ); DWORD nPad; for ( nPad = strlen( pszID ) ; nPad & 3 ; nPad++ ) Add( "", 1 ); // If we added "a", add "000" to get to the next group of 4 // Print pszType, which is "text/xml" or a URI to an XML specification, and bytes of 0 until the total length we added is a multiple of 4 Print( pszType ); for ( nPad = strlen( pszType ) ; nPad & 3 ; nPad++ ) Add( "", 1 ); // If we added "abcdef", add "00" to get to the next group of 4 // If there is body text if ( pBody != NULL ) { // Add it, followed by bytes of 0 until the total length we added is a multiple of 4 Add( pBody, nBody ); for ( nPad = nBody ; nPad & 3 ; nPad++ ) Add( "", 1 ); } }
// Convert Unicode text to ASCII and add it to the buffer void CBuffer::Print(const LPCWSTR pszText, const size_t nLength, const UINT nCodePage) { // Primitive overflow protection (relevant for 64bit) if ( nLength > INT_MAX ) return; // If the text is blank or no memory, don't do anything ASSERT( pszText ); if ( pszText == NULL ) return; // Find out the required buffer size, in bytes, for the translated string int nBytes = WideCharToMultiByte( nCodePage, 0, pszText, static_cast< int >( nLength ), NULL, 0, NULL, NULL ); // Make sure the buffer is big enough for this, making it larger if necessary if ( ! EnsureBuffer( nBytes ) ) return; // Convert the Unicode string into ASCII characters in the buffer WideCharToMultiByte( nCodePage, 0, pszText, static_cast< int >( nLength ), (LPSTR)( m_pBuffer + m_nLength ), nBytes, NULL, NULL ); m_nLength += nBytes; }
BOOL CNktStringW::ConcatN(__in_nz_opt LPCSTR szSrcA, __in SIZE_T nSrcLen) { int nDestLen; if (nSrcLen == 0) return TRUE; if (szSrcA == NULL) return FALSE; nDestLen = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSrcA, (int)nSrcLen, NULL, 0); if (nDestLen > 0) { if (nLen+(SIZE_T)nDestLen < nLen) return FALSE; //overflow if (EnsureBuffer(nLen+nDestLen) == FALSE) return FALSE; ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSrcA, (int)nSrcLen, szStrW+nLen, nDestLen); nLen += (SIZE_T)nDestLen; szStrW[nLen] = 0; } return TRUE; }
// Takes offset, a position in the memory block to insert some new memory at // Inserts the memory there, shifting anything after it further to the right void CBuffer::Insert(const DWORD nOffset, const void * pData, const size_t nLength) { ASSERT( pData ); if ( pData == NULL ) return; if ( ! EnsureBuffer( nLength ) ) return; // Cut the memory block sitting in the buffer in two, slicing it at offset and shifting that part forward nLength MoveMemory( m_pBuffer + nOffset + nLength, // Destination is the offset plus the length of the memory block to insert m_pBuffer + nOffset, // Source is at the offset m_nLength - nOffset ); // Length is the size of the memory block beyond the offset // Now that there is nLength of free space in the buffer at nOffset, copy the given memory to fill it CopyMemory( m_pBuffer + nOffset, // Destination is at the offset in the buffer pData, // Source is the given pointer to the memory to insert nLength ); // Length is the length of that memory // Add the length of the new memory to the total length in the buffer m_nLength += static_cast< DWORD >( nLength ); }
NS_IMETHODIMP OutputStreamShim::Write(const char * aBuf, uint32_t aCount, uint32_t *_retval) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); if (NS_FAILED(mStatus)) { return mStatus; } nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans)); if (!baseTrans) { return NS_ERROR_FAILURE; } SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction(); MOZ_ASSERT(trans); if (!trans) { return NS_ERROR_UNEXPECTED; } if ((trans->mOutputDataUsed + aCount) >= 512000) { *_retval = 0; // time for some flow control; return NS_BASE_STREAM_WOULD_BLOCK; } EnsureBuffer(trans->mOutputData, trans->mOutputDataUsed + aCount, trans->mOutputDataUsed, trans->mOutputDataSize); memcpy(trans->mOutputData + trans->mOutputDataUsed, aBuf, aCount); trans->mOutputDataUsed += aCount; *_retval = aCount; LOG(("OutputStreamShim::Write %p new %d total %d\n", this, aCount, trans->mOutputDataUsed)); trans->mSession->TransactionHasDataToWrite(trans); return NS_OK; }
// Takes Unicode text, along with the code page it uses // Converts it to ASCII and prints each ASCII character into the buffer, not printing a null terminator void CBuffer::Print(LPCWSTR pszText, UINT nCodePage) { // If the text is blank, don't do anything if ( pszText == NULL ) return; // Find the number of wide characters in the Unicode text int nLength = wcslen(pszText); // Length of "hello" is 5, does not include null terminator // Find out the required buffer size, in bytes, for the translated string int nBytes = WideCharToMultiByte( // Bytes required for "hello" is 5, does not include null terminator nCodePage, // Specify the code page used to perform the conversion 0, // No special flags to handle unmapped characters pszText, // Wide character string to convert nLength, // The number of wide characters in that string NULL, // No output buffer given, we just want to know how long it needs to be 0, NULL, // No replacement character given NULL ); // We don't want to know if a character didn't make it through the translation // Make sure the buffer is big enough for this, making it larger if necessary EnsureBuffer( (DWORD)nBytes ); // Convert the Unicode string into ASCII characters in the buffer WideCharToMultiByte( // Writes 5 bytes "hello", does not write a null terminator after that nCodePage, // Specify the code page used to perform the conversion 0, // No special flags to handle unmapped characters pszText, // Wide character string to convert nLength, // The number of wide characters in that string (LPSTR)( m_pBuffer + m_nLength ), // Put the output ASCII characters at the end of the buffer nBytes, // There is at least this much space there NULL, // No replacement character given NULL ); // We don't want to know if a character didn't make it through the translation // Add the newly written bytes to the buffer's record of how many bytes it is holding m_nLength += nBytes; }
RotatedContentBuffer::PaintState RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, uint32_t aFlags) { PaintState result; // We need to disable rotation if we're going to be resampled when // drawing, because we might sample across the rotation boundary. bool canHaveRotation = gfxPlatform::BufferRotationEnabled() && !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION)); nsIntRegion validRegion = aLayer->GetValidRegion(); Layer::SurfaceMode mode; ContentType contentType; nsIntRegion neededRegion; bool canReuseBuffer; nsIntRect destBufferRect; while (true) { mode = aLayer->GetSurfaceMode(); contentType = aContentType; neededRegion = aLayer->GetVisibleRegion(); canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size()); if (canReuseBuffer) { if (mBufferRect.Contains(neededRegion.GetBounds())) { // We don't need to adjust mBufferRect. destBufferRect = mBufferRect; } else if (neededRegion.GetBounds().Size() <= mBufferRect.Size()) { // The buffer's big enough but doesn't contain everything that's // going to be visible. We'll move it. destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size()); } else { destBufferRect = neededRegion.GetBounds(); } } else { // We won't be reusing the buffer. Compute a new rect. destBufferRect = ComputeBufferRect(neededRegion.GetBounds()); } if (mode == Layer::SURFACE_COMPONENT_ALPHA) { #if defined(MOZ_GFX_OPTIMIZE_MOBILE) || defined(MOZ_WIDGET_GONK) mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; #else if (!aLayer->GetParent() || !aLayer->GetParent()->SupportsComponentAlphaChildren() || !aLayer->Manager()->IsCompositingCheap() || !aLayer->AsShadowableLayer() || !aLayer->AsShadowableLayer()->HasShadow() || !gfxPlatform::ComponentAlphaEnabled()) { mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; } else { contentType = GFX_CONTENT_COLOR; } #endif } if ((aFlags & PAINT_WILL_RESAMPLE) && (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) || neededRegion.GetNumRects() > 1)) { // The area we add to neededRegion might not be painted opaquely if (mode == Layer::SURFACE_OPAQUE) { contentType = GFX_CONTENT_COLOR_ALPHA; mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; } // We need to validate the entire buffer, to make sure that only valid // pixels are sampled neededRegion = destBufferRect; } // If we have an existing buffer, but the content type has changed or we // have transitioned into/out of component alpha, then we need to recreate it. if (HaveBuffer() && (contentType != BufferContentType() || (mode == Layer::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite())) { // We're effectively clearing the valid region, so we need to draw // the entire needed region now. result.mRegionToInvalidate = aLayer->GetValidRegion(); validRegion.SetEmpty(); Clear(); // Restart decision process with the cleared buffer. We can only go // around the loop one more iteration, since mDTBuffer is null now. continue; } break; } NS_ASSERTION(destBufferRect.Contains(neededRegion.GetBounds()), "Destination rect doesn't contain what we need to paint"); result.mRegionToDraw.Sub(neededRegion, validRegion); if (result.mRegionToDraw.IsEmpty()) return result; nsIntRect drawBounds = result.mRegionToDraw.GetBounds(); RefPtr<DrawTarget> destDTBuffer; RefPtr<DrawTarget> destDTBufferOnWhite; uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0; if (mode == Layer::SURFACE_COMPONENT_ALPHA) { bufferFlags |= BUFFER_COMPONENT_ALPHA; } if (canReuseBuffer) { if (!EnsureBuffer()) { return result; } nsIntRect keepArea; if (keepArea.IntersectRect(destBufferRect, mBufferRect)) { // Set mBufferRotation so that the pixels currently in mDTBuffer // will still be rendered in the right place when mBufferRect // changes to destBufferRect. nsIntPoint newRotation = mBufferRotation + (destBufferRect.TopLeft() - mBufferRect.TopLeft()); WrapRotationAxis(&newRotation.x, mBufferRect.width); WrapRotationAxis(&newRotation.y, mBufferRect.height); NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation), "newRotation out of bounds"); int32_t xBoundary = destBufferRect.XMost() - newRotation.x; int32_t yBoundary = destBufferRect.YMost() - newRotation.y; if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) || (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) || (newRotation != nsIntPoint(0,0) && !canHaveRotation)) { // The stuff we need to redraw will wrap around an edge of the // buffer, so move the pixels we can keep into a position that // lets us redraw in just one quadrant. if (mBufferRotation == nsIntPoint(0,0)) { nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size()); nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft(); MOZ_ASSERT(mDTBuffer); mDTBuffer->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height), IntPoint(dest.x, dest.y)); if (mode == Layer::SURFACE_COMPONENT_ALPHA) { if (!EnsureBufferOnWhite()) { return result; } MOZ_ASSERT(mDTBufferOnWhite); mDTBufferOnWhite->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height), IntPoint(dest.x, dest.y)); } result.mDidSelfCopy = true; mDidSelfCopy = true; // Don't set destBuffer; we special-case self-copies, and // just did the necessary work above. mBufferRect = destBufferRect; } else { // With azure and a data surface perform an buffer unrotate // (SelfCopy). unsigned char* data; IntSize size; int32_t stride; SurfaceFormat format; if (mDTBuffer->LockBits(&data, &size, &stride, &format)) { uint8_t bytesPerPixel = BytesPerPixel(format); BufferUnrotate(data, size.width * bytesPerPixel, size.height, stride, newRotation.x * bytesPerPixel, newRotation.y); mDTBuffer->ReleaseBits(data); if (mode == Layer::SURFACE_COMPONENT_ALPHA) { if (!EnsureBufferOnWhite()) { return result; } MOZ_ASSERT(mDTBufferOnWhite); mDTBufferOnWhite->LockBits(&data, &size, &stride, &format); uint8_t bytesPerPixel = BytesPerPixel(format); BufferUnrotate(data, size.width * bytesPerPixel, size.height, stride, newRotation.x * bytesPerPixel, newRotation.y); mDTBufferOnWhite->ReleaseBits(data); } // Buffer unrotate moves all the pixels, note that // we self copied for SyncBackToFrontBuffer result.mDidSelfCopy = true; mDidSelfCopy = true; mBufferRect = destBufferRect; mBufferRotation = nsIntPoint(0, 0); } if (!result.mDidSelfCopy) { destBufferRect = ComputeBufferRect(neededRegion.GetBounds()); CreateBuffer(contentType, destBufferRect, bufferFlags, &destDTBuffer, &destDTBufferOnWhite); if (!destDTBuffer) { return result; } } } } else { mBufferRect = destBufferRect; mBufferRotation = newRotation; } } else { // No pixels are going to be kept. The whole visible region // will be redrawn, so we don't need to copy anything, so we don't // set destBuffer. mBufferRect = destBufferRect; mBufferRotation = nsIntPoint(0,0); } } else { // The buffer's not big enough, so allocate a new one CreateBuffer(contentType, destBufferRect, bufferFlags, &destDTBuffer, &destDTBufferOnWhite); if (!destDTBuffer) { return result; } } NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(), "If we're resampling, we need to validate the entire buffer"); // If we have no buffered data already, then destBuffer will be a fresh buffer // and we do not need to clear it below. bool isClear = !HaveBuffer(); if (destDTBuffer) { if (!isClear && (mode != Layer::SURFACE_COMPONENT_ALPHA || HaveBufferOnWhite())) { // Copy the bits nsIntPoint offset = -destBufferRect.TopLeft(); Matrix mat; mat.Translate(offset.x, offset.y); destDTBuffer->SetTransform(mat); if (!EnsureBuffer()) { return result; } MOZ_ASSERT(mDTBuffer, "Have we got a Thebes buffer for some reason?"); DrawBufferWithRotation(destDTBuffer, BUFFER_BLACK, 1.0, OP_SOURCE); destDTBuffer->SetTransform(Matrix()); if (mode == Layer::SURFACE_COMPONENT_ALPHA) { NS_ASSERTION(destDTBufferOnWhite, "Must have a white buffer!"); destDTBufferOnWhite->SetTransform(mat); if (!EnsureBufferOnWhite()) { return result; } MOZ_ASSERT(mDTBufferOnWhite, "Have we got a Thebes buffer for some reason?"); DrawBufferWithRotation(destDTBufferOnWhite, BUFFER_WHITE, 1.0, OP_SOURCE); destDTBufferOnWhite->SetTransform(Matrix()); } } mDTBuffer = destDTBuffer.forget(); mDTBufferOnWhite = destDTBufferOnWhite.forget(); mBufferRect = destBufferRect; mBufferRotation = nsIntPoint(0,0); } NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0), "Rotation disabled, but we have nonzero rotation?"); nsIntRegion invalidate; invalidate.Sub(aLayer->GetValidRegion(), destBufferRect); result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate); nsIntPoint topLeft; result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH, &topLeft); result.mClip = CLIP_DRAW_SNAPPED; if (mode == Layer::SURFACE_COMPONENT_ALPHA) { MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite); nsIntRegionRectIterator iter(result.mRegionToDraw); const nsIntRect *iterRect; while ((iterRect = iter.Next())) { mDTBuffer->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height), ColorPattern(Color(0.0, 0.0, 0.0, 1.0))); mDTBufferOnWhite->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0))); } } else if (contentType == GFX_CONTENT_COLOR_ALPHA && !isClear) { nsIntRegionRectIterator iter(result.mRegionToDraw); const nsIntRect *iterRect; while ((iterRect = iter.Next())) { result.mContext->GetDrawTarget()->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height)); } } return result; }
ThebesLayerBuffer::PaintState ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, uint32_t aFlags) { PaintState result; // We need to disable rotation if we're going to be resampled when // drawing, because we might sample across the rotation boundary. bool canHaveRotation = !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION)); nsIntRegion validRegion = aLayer->GetValidRegion(); ContentType contentType; nsIntRegion neededRegion; bool canReuseBuffer; nsIntRect destBufferRect; while (true) { contentType = aContentType; neededRegion = aLayer->GetVisibleRegion(); canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size()); if (canReuseBuffer) { if (mBufferRect.Contains(neededRegion.GetBounds())) { // We don't need to adjust mBufferRect. destBufferRect = mBufferRect; } else if (neededRegion.GetBounds().Size() <= mBufferRect.Size()) { // The buffer's big enough but doesn't contain everything that's // going to be visible. We'll move it. destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size()); } else { destBufferRect = neededRegion.GetBounds(); } } else { destBufferRect = neededRegion.GetBounds(); } if ((aFlags & PAINT_WILL_RESAMPLE) && (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) || neededRegion.GetNumRects() > 1)) { // The area we add to neededRegion might not be painted opaquely contentType = gfxASurface::CONTENT_COLOR_ALPHA; // We need to validate the entire buffer, to make sure that only valid // pixels are sampled neededRegion = destBufferRect; } if (HaveBuffer() && contentType != BufferContentType()) { // We're effectively clearing the valid region, so we need to draw // the entire needed region now. result.mRegionToInvalidate = aLayer->GetValidRegion(); validRegion.SetEmpty(); Clear(); // Restart decision process with the cleared buffer. We can only go // around the loop one more iteration, since mBuffer is null now. continue; } break; } NS_ASSERTION(destBufferRect.Contains(neededRegion.GetBounds()), "Destination rect doesn't contain what we need to paint"); result.mRegionToDraw.Sub(neededRegion, validRegion); if (result.mRegionToDraw.IsEmpty()) return result; nsIntRect drawBounds = result.mRegionToDraw.GetBounds(); nsRefPtr<gfxASurface> destBuffer; uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0; if (canReuseBuffer) { nsIntRect keepArea; if (keepArea.IntersectRect(destBufferRect, mBufferRect)) { // Set mBufferRotation so that the pixels currently in mBuffer // will still be rendered in the right place when mBufferRect // changes to destBufferRect. nsIntPoint newRotation = mBufferRotation + (destBufferRect.TopLeft() - mBufferRect.TopLeft()); WrapRotationAxis(&newRotation.x, mBufferRect.width); WrapRotationAxis(&newRotation.y, mBufferRect.height); NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation), "newRotation out of bounds"); int32_t xBoundary = destBufferRect.XMost() - newRotation.x; int32_t yBoundary = destBufferRect.YMost() - newRotation.y; if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) || (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) || (newRotation != nsIntPoint(0,0) && !canHaveRotation)) { // The stuff we need to redraw will wrap around an edge of the // buffer, so move the pixels we can keep into a position that // lets us redraw in just one quadrant. if (mBufferRotation == nsIntPoint(0,0)) { nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size()); nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft(); EnsureBuffer()->MovePixels(srcRect, dest); result.mDidSelfCopy = true; // Don't set destBuffer; we special-case self-copies, and // just did the necessary work above. mBufferRect = destBufferRect; } else { // We can't do a real self-copy because the buffer is rotated. // So allocate a new buffer for the destination. destBufferRect = neededRegion.GetBounds(); destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags); if (!destBuffer) return result; } } else { mBufferRect = destBufferRect; mBufferRotation = newRotation; } } else { // No pixels are going to be kept. The whole visible region // will be redrawn, so we don't need to copy anything, so we don't // set destBuffer. mBufferRect = destBufferRect; mBufferRotation = nsIntPoint(0,0); } } else { // The buffer's not big enough, so allocate a new one destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags); if (!destBuffer) return result; } NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(), "If we're resampling, we need to validate the entire buffer"); // If we have no buffered data already, then destBuffer will be a fresh buffer // and we do not need to clear it below. bool isClear = mBuffer == nullptr; if (destBuffer) { if (HaveBuffer()) { // Copy the bits nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBuffer); nsIntPoint offset = -destBufferRect.TopLeft(); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); tmpCtx->Translate(gfxPoint(offset.x, offset.y)); DrawBufferWithRotation(tmpCtx, 1.0); } mBuffer = destBuffer.forget(); mBufferRect = destBufferRect; mBufferRotation = nsIntPoint(0,0); } NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0), "Rotation disabled, but we have nonzero rotation?"); nsIntRegion invalidate; invalidate.Sub(aLayer->GetValidRegion(), destBufferRect); result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate); result.mContext = GetContextForQuadrantUpdate(drawBounds); gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw); if (contentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) { result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR); result.mContext->Paint(); result.mContext->SetOperator(gfxContext::OPERATOR_OVER); } return result; }