diff options
Diffstat (limited to 'services/core/java/com/android/server/wm/Watermark.java')
-rw-r--r-- | services/core/java/com/android/server/wm/Watermark.java | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java new file mode 100644 index 0000000..e226e3d --- /dev/null +++ b/services/core/java/com/android/server/wm/Watermark.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.Paint.FontMetricsInt; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.Display; +import android.view.Surface.OutOfResourcesException; +import android.view.Surface; +import android.view.SurfaceControl; +import android.view.SurfaceSession; + +/** + * Displays a watermark on top of the window manager's windows. + */ +class Watermark { + private final Display mDisplay; + private final String[] mTokens; + private final String mText; + private final Paint mTextPaint; + private final int mTextWidth; + private final int mTextHeight; + private final int mDeltaX; + private final int mDeltaY; + + private final SurfaceControl mSurfaceControl; + private final Surface mSurface = new Surface(); + private int mLastDW; + private int mLastDH; + private boolean mDrawNeeded; + + Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) { + if (false) { + Log.i(WindowManagerService.TAG, "*********************** WATERMARK"); + for (int i=0; i<tokens.length; i++) { + Log.i(WindowManagerService.TAG, " TOKEN #" + i + ": " + tokens[i]); + } + } + + mDisplay = display; + mTokens = tokens; + + StringBuilder builder = new StringBuilder(32); + int len = mTokens[0].length(); + len = len & ~1; + for (int i=0; i<len; i+=2) { + int c1 = mTokens[0].charAt(i); + int c2 = mTokens[0].charAt(i+1); + if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10; + else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10; + else c1 -= '0'; + if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10; + else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10; + else c2 -= '0'; + builder.append((char)(255-((c1*16)+c2))); + } + mText = builder.toString(); + if (false) { + Log.i(WindowManagerService.TAG, "Final text: " + mText); + } + + int fontSize = WindowManagerService.getPropertyInt(tokens, 1, + TypedValue.COMPLEX_UNIT_DIP, 20, dm); + + mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTextPaint.setTextSize(fontSize); + mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); + + FontMetricsInt fm = mTextPaint.getFontMetricsInt(); + mTextWidth = (int)mTextPaint.measureText(mText); + mTextHeight = fm.descent - fm.ascent; + + mDeltaX = WindowManagerService.getPropertyInt(tokens, 2, + TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm); + mDeltaY = WindowManagerService.getPropertyInt(tokens, 3, + TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm); + int shadowColor = WindowManagerService.getPropertyInt(tokens, 4, + TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm); + int color = WindowManagerService.getPropertyInt(tokens, 5, + TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm); + int shadowRadius = WindowManagerService.getPropertyInt(tokens, 6, + TypedValue.COMPLEX_UNIT_PX, 7, dm); + int shadowDx = WindowManagerService.getPropertyInt(tokens, 8, + TypedValue.COMPLEX_UNIT_PX, 0, dm); + int shadowDy = WindowManagerService.getPropertyInt(tokens, 9, + TypedValue.COMPLEX_UNIT_PX, 0, dm); + + mTextPaint.setColor(color); + mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor); + + SurfaceControl ctrl = null; + try { + ctrl = new SurfaceControl(session, "WatermarkSurface", + 1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + ctrl.setLayerStack(mDisplay.getLayerStack()); + ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100); + ctrl.setPosition(0, 0); + ctrl.show(); + mSurface.copyFrom(ctrl); + } catch (OutOfResourcesException e) { + } + mSurfaceControl = ctrl; + } + + void positionSurface(int dw, int dh) { + if (mLastDW != dw || mLastDH != dh) { + mLastDW = dw; + mLastDH = dh; + mSurfaceControl.setSize(dw, dh); + mDrawNeeded = true; + } + } + + void drawIfNeeded() { + if (mDrawNeeded) { + final int dw = mLastDW; + final int dh = mLastDH; + + mDrawNeeded = false; + Rect dirty = new Rect(0, 0, dw, dh); + Canvas c = null; + try { + c = mSurface.lockCanvas(dirty); + } catch (IllegalArgumentException e) { + } catch (Surface.OutOfResourcesException e) { + } + if (c != null) { + c.drawColor(0, PorterDuff.Mode.CLEAR); + + int deltaX = mDeltaX; + int deltaY = mDeltaY; + + // deltaX shouldn't be close to a round fraction of our + // x step, or else things will line up too much. + int div = (dw+mTextWidth)/deltaX; + int rem = (dw+mTextWidth) - (div*deltaX); + int qdelta = deltaX/4; + if (rem < qdelta || rem > (deltaX-qdelta)) { + deltaX += deltaX/3; + } + + int y = -mTextHeight; + int x = -mTextWidth; + while (y < (dh+mTextHeight)) { + c.drawText(mText, x, y, mTextPaint); + x += deltaX; + if (x >= dw) { + x -= (dw+mTextWidth); + y += deltaY; + } + } + mSurface.unlockCanvasAndPost(c); + } + } + } +} |