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_end.png \
|
||||||
res/drawable/handle_middle.png \
|
res/drawable/handle_middle.png \
|
||||||
res/drawable/handle_start.png \
|
res/drawable/handle_start.png \
|
||||||
|
res/drawable/scrollbar.png \
|
||||||
$(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI))) \
|
$(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI))) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ import org.mozilla.gecko.mozglue.DirectBufferAllocator;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
@ -134,8 +137,11 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
CairoImage shadowImage = new BufferedCairoImage(view.getShadowPattern());
|
CairoImage shadowImage = new BufferedCairoImage(view.getShadowPattern());
|
||||||
mShadowLayer = new NinePatchTileLayer(shadowImage);
|
mShadowLayer = new NinePatchTileLayer(shadowImage);
|
||||||
|
|
||||||
mHorizScrollLayer = ScrollbarLayer.create(this, false);
|
Bitmap scrollbarImage = view.getScrollbarImage();
|
||||||
mVertScrollLayer = ScrollbarLayer.create(this, true);
|
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();
|
mFadeRunnable = new FadeRunnable();
|
||||||
|
|
||||||
mFrameTimings = new int[60];
|
mFrameTimings = new int[60];
|
||||||
@ -150,6 +156,24 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
Tabs.registerOnTabsChangedListener(this);
|
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() {
|
public void destroy() {
|
||||||
DirectBufferAllocator.free(mCoordByteBuffer);
|
DirectBufferAllocator.free(mCoordByteBuffer);
|
||||||
mCoordByteBuffer = null;
|
mCoordByteBuffer = null;
|
||||||
|
@ -319,6 +319,10 @@ public class LayerView extends FrameLayout {
|
|||||||
return getDrawable(R.drawable.shadow);
|
return getDrawable(R.drawable.shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bitmap getScrollbarImage() {
|
||||||
|
return getDrawable(R.drawable.scrollbar);
|
||||||
|
}
|
||||||
|
|
||||||
private void onSizeChanged(int width, int height) {
|
private void onSizeChanged(int width, int height) {
|
||||||
mGLController.surfaceChanged(width, height);
|
mGLController.surfaceChanged(width, height);
|
||||||
|
|
||||||
|
@ -20,17 +20,10 @@ import android.opengl.GLES20;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws a small rect. This is scaled to become a scrollbar.
|
|
||||||
*/
|
|
||||||
public class ScrollbarLayer extends TileLayer {
|
public class ScrollbarLayer extends TileLayer {
|
||||||
public static final long FADE_DELAY = 500; // milliseconds before fade-out starts
|
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 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 final boolean mVertical;
|
||||||
private float mOpacity;
|
private float mOpacity;
|
||||||
|
|
||||||
@ -60,50 +53,43 @@ public class ScrollbarLayer extends TileLayer {
|
|||||||
" gl_FragColor.a *= uOpacity;\n" +
|
" gl_FragColor.a *= uOpacity;\n" +
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Dimensions of the texture image
|
// Dimensions of the texture bitmap (will always be power-of-two)
|
||||||
private static final int TEX_HEIGHT = 8;
|
private final int mTexWidth;
|
||||||
private static final int TEX_WIDTH = 8;
|
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 final Rect mStartCapTexCoords; // top/left endcap coordinates
|
||||||
private static final Rect LEFT_CAP_TEX_COORDS = new Rect(0, TEX_HEIGHT - BAR_SIZE, CAP_RADIUS, TEX_HEIGHT);
|
private final Rect mBodyTexCoords; // 1-pixel slice of the texture to be stretched
|
||||||
private static final Rect TOP_CAP_TEX_COORDS = new Rect(0, TEX_HEIGHT - CAP_RADIUS, BAR_SIZE, TEX_HEIGHT);
|
private final Rect mEndCapTexCoords; // bottom/right endcap coordinates
|
||||||
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 ScrollbarLayer(LayerRenderer renderer, CairoImage image, boolean vertical, ByteBuffer buffer) {
|
ScrollbarLayer(LayerRenderer renderer, Bitmap scrollbarImage, IntSize imageSize, boolean vertical) {
|
||||||
super(image, TileLayer.PaintMode.NORMAL);
|
super(new BufferedCairoImage(scrollbarImage), TileLayer.PaintMode.NORMAL);
|
||||||
mVertical = vertical;
|
|
||||||
mRenderer = renderer;
|
mRenderer = renderer;
|
||||||
|
mVertical = vertical;
|
||||||
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());
|
|
||||||
|
|
||||||
mBarRectF = new RectF();
|
mBarRectF = new RectF();
|
||||||
mBarRect = new Rect();
|
mBarRect = new Rect();
|
||||||
mCoords = new float[20];
|
mCoords = new float[20];
|
||||||
mCapRectF = new RectF();
|
mCapRectF = new RectF();
|
||||||
}
|
|
||||||
|
|
||||||
public static ScrollbarLayer create(LayerRenderer renderer, boolean vertical) {
|
mTexHeight = scrollbarImage.getHeight();
|
||||||
// just create an empty image for now, it will get drawn
|
mTexWidth = scrollbarImage.getWidth();
|
||||||
// on demand anyway
|
|
||||||
int imageSize = IntSize.nextPowerOfTwo(BAR_SIZE);
|
if (mVertical) {
|
||||||
ByteBuffer buffer = DirectBufferAllocator.allocate(imageSize * imageSize * 4);
|
mBarWidth = imageSize.width;
|
||||||
CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize,
|
mCapLength = imageSize.height / 2;
|
||||||
CairoImage.FORMAT_ARGB32);
|
mStartCapTexCoords = new Rect(0, mTexHeight - mCapLength, imageSize.width, mTexHeight);
|
||||||
return new ScrollbarLayer(renderer, image, vertical, buffer);
|
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() {
|
private void createProgram() {
|
||||||
@ -209,8 +195,8 @@ public class ScrollbarLayer extends TileLayer {
|
|||||||
|
|
||||||
mBarRectF.set(mBarRect.left, viewHeight - mBarRect.top, mBarRect.right, viewHeight - mBarRect.bottom);
|
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
|
// We take a 1-pixel slice 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);
|
fillRectCoordBuffer(mCoords, mBarRectF, viewWidth, viewHeight, mBodyTexCoords, mTexWidth, mTexHeight);
|
||||||
|
|
||||||
// Get the buffer and handles from the context
|
// Get the buffer and handles from the context
|
||||||
FloatBuffer coordBuffer = context.coordBuffer;
|
FloatBuffer coordBuffer = context.coordBuffer;
|
||||||
@ -239,12 +225,13 @@ public class ScrollbarLayer extends TileLayer {
|
|||||||
coordBuffer.position(0);
|
coordBuffer.position(0);
|
||||||
if (mVertical) {
|
if (mVertical) {
|
||||||
// top endcap
|
// top endcap
|
||||||
mCapRectF.set(mBarRectF.left, mBarRectF.top + CAP_RADIUS, mBarRectF.left + BAR_SIZE, mBarRectF.top);
|
mCapRectF.set(mBarRectF.left, mBarRectF.top + mCapLength, mBarRectF.right, mBarRectF.top);
|
||||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, TOP_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
|
||||||
} else {
|
} else {
|
||||||
mCapRectF.set(mBarRectF.left - CAP_RADIUS, mBarRectF.bottom + BAR_SIZE, mBarRectF.left, mBarRectF.bottom);
|
// left endcap
|
||||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, LEFT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
mCapRectF.set(mBarRectF.left - mCapLength, mBarRectF.bottom + mBarWidth, mBarRectF.left, mBarRectF.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, mStartCapTexCoords, mTexWidth, mTexHeight);
|
||||||
coordBuffer.put(mCoords);
|
coordBuffer.put(mCoords);
|
||||||
|
|
||||||
// Vertex coordinates are x,y,z starting at position 0 into the buffer.
|
// 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);
|
coordBuffer.position(0);
|
||||||
if (mVertical) {
|
if (mVertical) {
|
||||||
// bottom endcap
|
// bottom endcap
|
||||||
mCapRectF.set(mBarRectF.left, mBarRectF.bottom, mBarRectF.left + BAR_SIZE, mBarRectF.bottom - CAP_RADIUS);
|
mCapRectF.set(mBarRectF.left, mBarRectF.bottom, mBarRectF.right, mBarRectF.bottom - mCapLength);
|
||||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, BOT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
|
||||||
} else {
|
} else {
|
||||||
// right endcap
|
// right endcap
|
||||||
mCapRectF.set(mBarRectF.right, mBarRectF.bottom + BAR_SIZE, mBarRectF.right + CAP_RADIUS, mBarRectF.bottom);
|
mCapRectF.set(mBarRectF.right, mBarRectF.bottom + mBarWidth, mBarRectF.right + mCapLength, mBarRectF.bottom);
|
||||||
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, RIGHT_CAP_TEX_COORDS, TEX_WIDTH, TEX_HEIGHT);
|
|
||||||
}
|
}
|
||||||
|
fillRectCoordBuffer(mCoords, mCapRectF, viewWidth, viewHeight, mEndCapTexCoords, mTexWidth, mTexHeight);
|
||||||
coordBuffer.put(mCoords);
|
coordBuffer.put(mCoords);
|
||||||
|
|
||||||
// Vertex coordinates are x,y,z starting at position 0 into the buffer.
|
// 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) {
|
private void getVerticalRect(RenderContext context, RectF dest) {
|
||||||
RectF viewport = context.viewport;
|
RectF viewport = context.viewport;
|
||||||
RectF pageRect = context.pageRect;
|
RectF pageRect = context.pageRect;
|
||||||
float barStart = ((viewport.top - 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())) - CAP_RADIUS;
|
float barEnd = ((viewport.bottom - pageRect.top) * (viewport.height() / pageRect.height())) - mCapLength;
|
||||||
if (barStart > barEnd) {
|
if (barStart > barEnd) {
|
||||||
float middle = (barStart + barEnd) / 2.0f;
|
float middle = (barStart + barEnd) / 2.0f;
|
||||||
barStart = barEnd = middle;
|
barStart = barEnd = middle;
|
||||||
}
|
}
|
||||||
float right = viewport.width() - PADDING;
|
dest.set(viewport.width() - mBarWidth, barStart, viewport.width(), barEnd);
|
||||||
dest.set(right - BAR_SIZE, barStart, right, barEnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getHorizontalRect(RenderContext context, RectF dest) {
|
private void getHorizontalRect(RenderContext context, RectF dest) {
|
||||||
RectF viewport = context.viewport;
|
RectF viewport = context.viewport;
|
||||||
RectF pageRect = context.pageRect;
|
RectF pageRect = context.pageRect;
|
||||||
float barStart = ((viewport.left - 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())) - CAP_RADIUS;
|
float barEnd = ((viewport.right - pageRect.left) * (viewport.width() / pageRect.width())) - mCapLength;
|
||||||
if (barStart > barEnd) {
|
if (barStart > barEnd) {
|
||||||
float middle = (barStart + barEnd) / 2.0f;
|
float middle = (barStart + barEnd) / 2.0f;
|
||||||
barStart = barEnd = middle;
|
barStart = barEnd = middle;
|
||||||
}
|
}
|
||||||
float bottom = viewport.height() - PADDING;
|
dest.set(barStart, viewport.height() - mBarWidth, barEnd, viewport.height());
|
||||||
dest.set(barStart, bottom - BAR_SIZE, barEnd, bottom);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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