mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 771746 - Draw scrollbars using a white outline so it shows up on dark backgrounds. r=Cwiiis
This commit is contained in:
parent
e65170c39d
commit
7affc8fd4f
@ -572,6 +572,7 @@ RES_DRAWABLE_BASE = \
|
||||
res/drawable/handle_end.png \
|
||||
res/drawable/handle_middle.png \
|
||||
res/drawable/handle_start.png \
|
||||
res/drawable/scrollbar.png \
|
||||
$(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI))) \
|
||||
$(NULL)
|
||||
|
||||
|
@ -13,7 +13,10 @@ import org.mozilla.gecko.mozglue.DirectBufferAllocator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@ -134,8 +137,11 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
CairoImage shadowImage = new BufferedCairoImage(view.getShadowPattern());
|
||||
mShadowLayer = new NinePatchTileLayer(shadowImage);
|
||||
|
||||
mHorizScrollLayer = ScrollbarLayer.create(this, false);
|
||||
mVertScrollLayer = ScrollbarLayer.create(this, true);
|
||||
Bitmap scrollbarImage = view.getScrollbarImage();
|
||||
IntSize size = new IntSize(scrollbarImage.getWidth(), scrollbarImage.getHeight());
|
||||
scrollbarImage = expandCanvasToPowerOfTwo(scrollbarImage, size);
|
||||
mVertScrollLayer = new ScrollbarLayer(this, scrollbarImage, size, true);
|
||||
mHorizScrollLayer = new ScrollbarLayer(this, diagonalFlip(scrollbarImage), new IntSize(size.height, size.width), false);
|
||||
mFadeRunnable = new FadeRunnable();
|
||||
|
||||
mFrameTimings = new int[60];
|
||||
@ -150,6 +156,24 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
Tabs.registerOnTabsChangedListener(this);
|
||||
}
|
||||
|
||||
private Bitmap expandCanvasToPowerOfTwo(Bitmap image, IntSize size) {
|
||||
IntSize potSize = size.nextPowerOfTwo();
|
||||
if (size.equals(potSize)) {
|
||||
return image;
|
||||
}
|
||||
// make the bitmap size a power-of-two in both dimensions if it's not already.
|
||||
Bitmap potImage = Bitmap.createBitmap(potSize.width, potSize.height, image.getConfig());
|
||||
new Canvas(potImage).drawBitmap(image, new Matrix(), null);
|
||||
return potImage;
|
||||
}
|
||||
|
||||
private Bitmap diagonalFlip(Bitmap image) {
|
||||
Matrix rotation = new Matrix();
|
||||
rotation.setValues(new float[] { 0, 1, 0, 1, 0, 0, 0, 0, 1 }); // transform (x,y) into (y,x)
|
||||
Bitmap rotated = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), rotation, true);
|
||||
return rotated;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
DirectBufferAllocator.free(mCoordByteBuffer);
|
||||
mCoordByteBuffer = null;
|
||||
|
@ -319,6 +319,10 @@ public class LayerView extends FrameLayout {
|
||||
return getDrawable(R.drawable.shadow);
|
||||
}
|
||||
|
||||
Bitmap getScrollbarImage() {
|
||||
return getDrawable(R.drawable.scrollbar);
|
||||
}
|
||||
|
||||
private void onSizeChanged(int width, int height) {
|
||||
mGLController.surfaceChanged(width, height);
|
||||
|
||||
|
@ -20,17 +20,10 @@ import android.opengl.GLES20;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
/**
|
||||
* Draws a small rect. This is scaled to become a scrollbar.
|
||||
*/
|
||||
public class ScrollbarLayer extends TileLayer {
|
||||
public static final long FADE_DELAY = 500; // milliseconds before fade-out starts
|
||||
private static final float FADE_AMOUNT = 0.03f; // how much (as a percent) the scrollbar should fade per frame
|
||||
|
||||
private static final int PADDING = 1; // gap between scrollbar and edge of viewport
|
||||
private static final int BAR_SIZE = 6;
|
||||
private static final int CAP_RADIUS = (BAR_SIZE / 2);
|
||||
|
||||
private final boolean mVertical;
|
||||
private float mOpacity;
|
||||
|
||||
@ -60,50 +53,43 @@ public class ScrollbarLayer extends TileLayer {
|
||||
" gl_FragColor.a *= uOpacity;\n" +
|
||||
"}\n";
|
||||
|
||||
// Dimensions of the texture image
|
||||
private static final int TEX_HEIGHT = 8;
|
||||
private static final int TEX_WIDTH = 8;
|
||||
// Dimensions of the texture bitmap (will always be power-of-two)
|
||||
private final int mTexWidth;
|
||||
private final int mTexHeight;
|
||||
// Some useful dimensions of the actual content in the bitmap
|
||||
private final int mBarWidth;
|
||||
private final int mCapLength;
|
||||
|
||||
private static final Rect BODY_TEX_COORDS = new Rect(CAP_RADIUS, CAP_RADIUS, CAP_RADIUS + 1, CAP_RADIUS + 1);
|
||||
private static final Rect LEFT_CAP_TEX_COORDS = new Rect(0, TEX_HEIGHT - BAR_SIZE, CAP_RADIUS, TEX_HEIGHT);
|
||||
private static final Rect TOP_CAP_TEX_COORDS = new Rect(0, TEX_HEIGHT - CAP_RADIUS, BAR_SIZE, TEX_HEIGHT);
|
||||
private static final Rect RIGHT_CAP_TEX_COORDS = new Rect(CAP_RADIUS, TEX_HEIGHT - BAR_SIZE, BAR_SIZE, TEX_HEIGHT);
|
||||
private static final Rect BOT_CAP_TEX_COORDS = new Rect(0, TEX_HEIGHT - BAR_SIZE, BAR_SIZE, TEX_HEIGHT - CAP_RADIUS);
|
||||
private final Rect mStartCapTexCoords; // top/left endcap coordinates
|
||||
private final Rect mBodyTexCoords; // 1-pixel slice of the texture to be stretched
|
||||
private final Rect mEndCapTexCoords; // bottom/right endcap coordinates
|
||||
|
||||
private ScrollbarLayer(LayerRenderer renderer, CairoImage image, boolean vertical, ByteBuffer buffer) {
|
||||
super(image, TileLayer.PaintMode.NORMAL);
|
||||
mVertical = vertical;
|
||||
ScrollbarLayer(LayerRenderer renderer, Bitmap scrollbarImage, IntSize imageSize, boolean vertical) {
|
||||
super(new BufferedCairoImage(scrollbarImage), TileLayer.PaintMode.NORMAL);
|
||||
mRenderer = renderer;
|
||||
|
||||
IntSize size = image.getSize();
|
||||
Bitmap bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
// Paint a spot to use as the scroll indicator
|
||||
Paint foregroundPaint = new Paint();
|
||||
foregroundPaint.setAntiAlias(true);
|
||||
foregroundPaint.setStyle(Paint.Style.FILL);
|
||||
foregroundPaint.setColor(Color.argb(127, 0, 0, 0));
|
||||
|
||||
canvas.drawColor(Color.argb(0, 0, 0, 0), PorterDuff.Mode.CLEAR);
|
||||
canvas.drawCircle(CAP_RADIUS, CAP_RADIUS, CAP_RADIUS, foregroundPaint);
|
||||
|
||||
bitmap.copyPixelsToBuffer(buffer.asIntBuffer());
|
||||
mVertical = vertical;
|
||||
|
||||
mBarRectF = new RectF();
|
||||
mBarRect = new Rect();
|
||||
mCoords = new float[20];
|
||||
mCapRectF = new RectF();
|
||||
}
|
||||
|
||||
public static ScrollbarLayer create(LayerRenderer renderer, boolean vertical) {
|
||||
// just create an empty image for now, it will get drawn
|
||||
// on demand anyway
|
||||
int imageSize = IntSize.nextPowerOfTwo(BAR_SIZE);
|
||||
ByteBuffer buffer = DirectBufferAllocator.allocate(imageSize * imageSize * 4);
|
||||
CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize,
|
||||
CairoImage.FORMAT_ARGB32);
|
||||
return new ScrollbarLayer(renderer, image, vertical, buffer);
|
||||
mTexHeight = scrollbarImage.getHeight();
|
||||
mTexWidth = scrollbarImage.getWidth();
|
||||
|
||||
if (mVertical) {
|
||||
mBarWidth = imageSize.width;
|
||||
mCapLength = imageSize.height / 2;
|
||||
mStartCapTexCoords = new Rect(0, mTexHeight - mCapLength, imageSize.width, mTexHeight);
|
||||
mBodyTexCoords = new Rect(0, mTexHeight - (mCapLength + 1), imageSize.width, mTexHeight - mCapLength);
|
||||
mEndCapTexCoords = new Rect(0, mTexHeight - imageSize.height, imageSize.width, mTexHeight - (mCapLength + 1));
|
||||
} else {
|
||||
mBarWidth = imageSize.height;
|
||||
mCapLength = imageSize.width / 2;
|
||||
mStartCapTexCoords = new Rect(0, mTexHeight - imageSize.height, mCapLength, mTexHeight);
|
||||
mBodyTexCoords = new Rect(mCapLength, mTexHeight - imageSize.height, mCapLength + 1, mTexHeight);
|
||||
mEndCapTexCoords = new Rect(mCapLength + 1, mTexHeight - imageSize.height, imageSize.width, mTexHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void createProgram() {
|
||||
@ -209,8 +195,8 @@ public class ScrollbarLayer extends TileLayer {
|
||||
|
||||
mBarRectF.set(mBarRect.left, viewHeight - mBarRect.top, mBarRect.right, viewHeight - mBarRect.bottom);
|
||||
|
||||
// We take a 1x1 pixel from the center of the image and scale it to become the bar
|
||||
fillRectCoordBuffer(mCoords, mBarRectF, viewWidth, viewHeight, BODY_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
||||
// We take a 1-pixel slice from the center of the image and scale it to become the bar
|
||||
fillRectCoordBuffer(mCoords, mBarRectF, viewWidth, viewHeight, mBodyTexCoords, mTexWidth, mTexHeight);
|
||||
|
||||
// Get the buffer and handles from the context
|
||||
FloatBuffer coordBuffer = context.coordBuffer;
|
||||
@ -239,12 +225,13 @@ public class ScrollbarLayer extends TileLayer {
|
||||
coordBuffer.position(0);
|
||||
if (mVertical) {
|
||||
// top endcap
|
||||
mCapRectF.set(mBarRectF.left, mBarRectF.top + CAP_RADIUS, mBarRectF.left + BAR_SIZE, mBarRectF.top);
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, TOP_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
||||
mCapRectF.set(mBarRectF.left, mBarRectF.top + mCapLength, mBarRectF.right, mBarRectF.top);
|
||||
} else {
|
||||
mCapRectF.set(mBarRectF.left - CAP_RADIUS, mBarRectF.bottom + BAR_SIZE, mBarRectF.left, mBarRectF.bottom);
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, LEFT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
||||
// left endcap
|
||||
mCapRectF.set(mBarRectF.left - mCapLength, mBarRectF.bottom + mBarWidth, mBarRectF.left, mBarRectF.bottom);
|
||||
}
|
||||
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, mStartCapTexCoords, mTexWidth, mTexHeight);
|
||||
coordBuffer.put(mCoords);
|
||||
|
||||
// Vertex coordinates are x,y,z starting at position 0 into the buffer.
|
||||
@ -261,13 +248,12 @@ public class ScrollbarLayer extends TileLayer {
|
||||
coordBuffer.position(0);
|
||||
if (mVertical) {
|
||||
// bottom endcap
|
||||
mCapRectF.set(mBarRectF.left, mBarRectF.bottom, mBarRectF.left + BAR_SIZE, mBarRectF.bottom - CAP_RADIUS);
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, BOT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
||||
mCapRectF.set(mBarRectF.left, mBarRectF.bottom, mBarRectF.right, mBarRectF.bottom - mCapLength);
|
||||
} else {
|
||||
// right endcap
|
||||
mCapRectF.set(mBarRectF.right, mBarRectF.bottom + BAR_SIZE, mBarRectF.right + CAP_RADIUS, mBarRectF.bottom);
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, RIGHT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
||||
mCapRectF.set(mBarRectF.right, mBarRectF.bottom + mBarWidth, mBarRectF.right + mCapLength, mBarRectF.bottom);
|
||||
}
|
||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, mEndCapTexCoords, mTexWidth, mTexHeight);
|
||||
coordBuffer.put(mCoords);
|
||||
|
||||
// Vertex coordinates are x,y,z starting at position 0 into the buffer.
|
||||
@ -291,26 +277,24 @@ public class ScrollbarLayer extends TileLayer {
|
||||
private void getVerticalRect(RenderContext context, RectF dest) {
|
||||
RectF viewport = context.viewport;
|
||||
RectF pageRect = context.pageRect;
|
||||
float barStart = ((viewport.top - pageRect.top) * (viewport.height() / pageRect.height())) + CAP_RADIUS;
|
||||
float barEnd = ((viewport.bottom - pageRect.top) * (viewport.height() / pageRect.height())) - CAP_RADIUS;
|
||||
float barStart = ((viewport.top - pageRect.top) * (viewport.height() / pageRect.height())) + mCapLength;
|
||||
float barEnd = ((viewport.bottom - pageRect.top) * (viewport.height() / pageRect.height())) - mCapLength;
|
||||
if (barStart > barEnd) {
|
||||
float middle = (barStart + barEnd) / 2.0f;
|
||||
barStart = barEnd = middle;
|
||||
}
|
||||
float right = viewport.width() - PADDING;
|
||||
dest.set(right - BAR_SIZE, barStart, right, barEnd);
|
||||
dest.set(viewport.width() - mBarWidth, barStart, viewport.width(), barEnd);
|
||||
}
|
||||
|
||||
private void getHorizontalRect(RenderContext context, RectF dest) {
|
||||
RectF viewport = context.viewport;
|
||||
RectF pageRect = context.pageRect;
|
||||
float barStart = ((viewport.left - pageRect.left) * (viewport.width() / pageRect.width())) + CAP_RADIUS;
|
||||
float barEnd = ((viewport.right - pageRect.left) * (viewport.width() / pageRect.width())) - CAP_RADIUS;
|
||||
float barStart = ((viewport.left - pageRect.left) * (viewport.width() / pageRect.width())) + mCapLength;
|
||||
float barEnd = ((viewport.right - pageRect.left) * (viewport.width() / pageRect.width())) - mCapLength;
|
||||
if (barStart > barEnd) {
|
||||
float middle = (barStart + barEnd) / 2.0f;
|
||||
barStart = barEnd = middle;
|
||||
}
|
||||
float bottom = viewport.height() - PADDING;
|
||||
dest.set(barStart, bottom - BAR_SIZE, barEnd, bottom);
|
||||
dest.set(barStart, viewport.height() - mBarWidth, barEnd, viewport.height());
|
||||
}
|
||||
}
|
||||
|
BIN
mobile/android/base/resources/drawable/scrollbar.png
Normal file
BIN
mobile/android/base/resources/drawable/scrollbar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 337 B |
Loading…
Reference in New Issue
Block a user