/** * This function is invoked by Gecko via JNI; be careful when modifying signature. The compositor * invokes this function whenever it determines that the page rect has changed (based on the * information it gets from layout). If setFirstPaintViewport is invoked on a frame, then this * function will not be. For any given frame, this function will be invoked before * syncViewportInfo. */ public void setPageRect( float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) { synchronized (this) { RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom); float ourZoom = getViewportMetrics().zoomFactor; setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect); // Here the page size of the document has changed, but the document being displayed // is still the same. Therefore, we don't need to send anything to browser.js; any // changes we need to make to the display port will get sent the next time we call // adjustViewport(). } }
/** Viewport message handler. */ private DisplayPortMetrics handleViewportMessage( ImmutableViewportMetrics messageMetrics, ViewportMessageType type) { synchronized (this) { ImmutableViewportMetrics metrics; ImmutableViewportMetrics oldMetrics = getViewportMetrics(); switch (type) { default: case UPDATE: // Keep the old viewport size metrics = messageMetrics.setViewportSize(oldMetrics.getWidth(), oldMetrics.getHeight()); abortPanZoomAnimation(); break; case PAGE_SIZE: // adjust the page dimensions to account for differences in zoom // between the rendered content (which is what Gecko tells us) // and our zoom level (which may have diverged). float scaleFactor = oldMetrics.zoomFactor / messageMetrics.zoomFactor; metrics = oldMetrics.setPageRect( RectUtils.scale(messageMetrics.getPageRect(), scaleFactor), messageMetrics.getCssPageRect()); break; } final ImmutableViewportMetrics newMetrics = metrics; post( new Runnable() { public void run() { mGeckoViewport = newMetrics; } }); setViewportMetrics(newMetrics, type == ViewportMessageType.UPDATE); mDisplayPort = DisplayPortCalculator.calculate(getViewportMetrics(), null); } return mDisplayPort; }
public Rect beginDrawing( int width, int height, int tileWidth, int tileHeight, String metadata, boolean hasDirectTexture) { setHasDirectTexture(hasDirectTexture); // Make sure the tile-size matches. If it doesn't, we could crash trying // to access invalid memory. if (mHasDirectTexture) { if (tileWidth != 0 || tileHeight != 0) { Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" + tileHeight); return null; } } else { if (tileWidth != TILE_SIZE.width || tileHeight != TILE_SIZE.height) { Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" + tileHeight); return null; } } LayerController controller = getLayerController(); try { JSONObject viewportObject = new JSONObject(metadata); mNewGeckoViewport = new ViewportMetrics(viewportObject); // Update the background color, if it's present. String backgroundColorString = viewportObject.optString("backgroundColor"); if (backgroundColorString != null) { controller.setCheckerboardColor(parseColorFromGecko(backgroundColorString)); } } catch (JSONException e) { Log.e(LOGTAG, "Aborting draw, bad viewport description: " + metadata); return null; } // Make sure we don't spend time painting areas we aren't interested in. // Only do this if the Gecko viewport isn't going to override our viewport. Rect bufferRect = new Rect(0, 0, width, height); if (!mUpdateViewportOnEndDraw) { // First, find out our ideal displayport. We do this by taking the // clamped viewport origin and taking away the optimum viewport offset. // This would be what we would send to Gecko if adjustViewport were // called now. ViewportMetrics currentMetrics = controller.getViewportMetrics(); PointF currentBestOrigin = RectUtils.getOrigin(currentMetrics.getClampedViewport()); PointF viewportOffset = currentMetrics.getOptimumViewportOffset(new IntSize(width, height)); currentBestOrigin.offset(-viewportOffset.x, -viewportOffset.y); Rect currentRect = RectUtils.round( new RectF( currentBestOrigin.x, currentBestOrigin.y, currentBestOrigin.x + width, currentBestOrigin.y + height)); // Second, store Gecko's displayport. PointF currentOrigin = mNewGeckoViewport.getDisplayportOrigin(); bufferRect = RectUtils.round( new RectF( currentOrigin.x, currentOrigin.y, currentOrigin.x + width, currentOrigin.y + height)); // Take the intersection of the two as the area we're interested in rendering. if (!bufferRect.intersect(currentRect)) { // If there's no intersection, we have no need to render anything, // but make sure to update the viewport size. beginTransaction(mTileLayer); try { updateViewport(true); } finally { endTransaction(mTileLayer); } return null; } bufferRect.offset(Math.round(-currentOrigin.x), Math.round(-currentOrigin.y)); } beginTransaction(mTileLayer); // Synchronise the buffer size with Gecko. if (mBufferSize.width != width || mBufferSize.height != height) { mBufferSize = new IntSize(width, height); // Reallocate the buffer if necessary if (mTileLayer instanceof MultiTileLayer) { int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8; int size = mBufferSize.getArea() * bpp; if (mBuffer == null || mBuffer.capacity() != size) { // Free the old buffer if (mBuffer != null) { GeckoAppShell.freeDirectBuffer(mBuffer); mBuffer = null; } mBuffer = GeckoAppShell.allocateDirectBuffer(size); } } } return bufferRect; }