1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.layoutlib.bridge.shadowutil; 18 19import android.annotation.NonNull; 20import android.graphics.Bitmap; 21import android.graphics.Bitmap.Config; 22import android.graphics.Canvas; 23 24public class ShadowBuffer { 25 26 private int mWidth; 27 private int mHeight; 28 private Bitmap mBitmap; 29 private int[] mData; 30 31 public ShadowBuffer(int width, int height) { 32 mWidth = width; 33 mHeight = height; 34 mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); 35 mData = new int[mBitmap.getWidth() * mBitmap.getHeight()]; 36 mBitmap.getPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(), 37 mBitmap.getHeight()); 38 } 39 40 public void generateTriangles(@NonNull float[] strip, float scale) { 41 for (int i = 0; i < strip.length - 8; i += 3) { 42 float fx3 = strip[i]; 43 float fy3 = strip[i + 1]; 44 float fz3 = scale * strip[i + 2]; 45 46 float fx2 = strip[i + 3]; 47 float fy2 = strip[i + 4]; 48 float fz2 = scale * strip[i + 5]; 49 50 float fx1 = strip[i + 6]; 51 float fy1 = strip[i + 7]; 52 float fz1 = scale * strip[i + 8]; 53 54 if (fx1 * (fy2 - fy3) + fx2 * (fy3 - fy1) + fx3 * (fy1 - fy2) == 0) { 55 continue; 56 } 57 58 triangleZBuffMin(mData, mWidth, mHeight, fx3, fy3, fz3, fx2, fy2, fz2, fx1, fy1, fz1); 59 triangleZBuffMin(mData, mWidth, mHeight, fx1, fy1, fz1, fx2, fy2, fz2, fx3, fy3, fz3); 60 } 61 mBitmap.setPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(), 62 mBitmap.getHeight()); 63 } 64 65 private void triangleZBuffMin(@NonNull int[] buff, int w, int h, float fx3, float fy3, 66 float fz3, float fx2, float fy2, float fz2, float fx1, float fy1, float fz1) { 67 if (((fx1 - fx2) * (fy3 - fy2) - (fy1 - fy2) * (fx3 - fx2)) < 0) { 68 float tmpX = fx1; 69 float tmpY = fy1; 70 float tmpZ = fz1; 71 fx1 = fx2; 72 fy1 = fy2; 73 fz1 = fz2; 74 fx2 = tmpX; 75 fy2 = tmpY; 76 fz2 = tmpZ; 77 } 78 double d = (fx1 * (fy3 - fy2) - fx2 * fy3 + fx3 * fy2 + (fx2 - fx3) * fy1); 79 80 if (d == 0) { 81 return; 82 } 83 float dx = (float) (-(fy1 * (fz3 - fz2) - fy2 * fz3 + fy3 * fz2 + (fy2 - fy3) * fz1) / d); 84 float dy = (float) ((fx1 * (fz3 - fz2) - fx2 * fz3 + fx3 * fz2 + (fx2 - fx3) * fz1) / d); 85 float zOff = (float) ((fx1 * (fy3 * fz2 - fy2 * fz3) + fy1 * (fx2 * fz3 - fx3 * fz2) + 86 (fx3 * fy2 - fx2 * fy3) * fz1) / d); 87 88 int Y1 = (int) (16.0f * fy1 + .5f); 89 int Y2 = (int) (16.0f * fy2 + .5f); 90 int Y3 = (int) (16.0f * fy3 + .5f); 91 92 int X1 = (int) (16.0f * fx1 + .5f); 93 int X2 = (int) (16.0f * fx2 + .5f); 94 int X3 = (int) (16.0f * fx3 + .5f); 95 96 int DX12 = X1 - X2; 97 int DX23 = X2 - X3; 98 int DX31 = X3 - X1; 99 100 int DY12 = Y1 - Y2; 101 int DY23 = Y2 - Y3; 102 int DY31 = Y3 - Y1; 103 104 int FDX12 = DX12 << 4; 105 int FDX23 = DX23 << 4; 106 int FDX31 = DX31 << 4; 107 108 int FDY12 = DY12 << 4; 109 int FDY23 = DY23 << 4; 110 int FDY31 = DY31 << 4; 111 112 int minX = (min(X1, X2, X3) + 0xF) >> 4; 113 int maxX = (max(X1, X2, X3) + 0xF) >> 4; 114 int minY = (min(Y1, Y2, Y3) + 0xF) >> 4; 115 int maxY = (max(Y1, Y2, Y3) + 0xF) >> 4; 116 117 if (minY < 0) { 118 minY = 0; 119 } 120 if (minX < 0) { 121 minX = 0; 122 } 123 if (maxX > w) { 124 maxX = w; 125 } 126 if (maxY > h) { 127 maxY = h; 128 } 129 int off = minY * w; 130 131 int C1 = DY12 * X1 - DX12 * Y1; 132 int C2 = DY23 * X2 - DX23 * Y2; 133 int C3 = DY31 * X3 - DX31 * Y3; 134 135 if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) { 136 C1++; 137 } 138 if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) { 139 C2++; 140 } 141 if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) { 142 C3++; 143 } 144 int CY1 = C1 + DX12 * (minY << 4) - DY12 * (minX << 4); 145 int CY2 = C2 + DX23 * (minY << 4) - DY23 * (minX << 4); 146 int CY3 = C3 + DX31 * (minY << 4) - DY31 * (minX << 4); 147 148 for (int y = minY; y < maxY; y++) { 149 int CX1 = CY1; 150 int CX2 = CY2; 151 int CX3 = CY3; 152 float p = zOff + dy * y; 153 for (int x = minX; x < maxX; x++) { 154 if (CX1 > 0 && CX2 > 0 && CX3 > 0) { 155 int point = x + off; 156 float zVal = p + dx * x; 157 buff[point] |= ((int) (zVal * 255)) << 24; 158 } 159 CX1 -= FDY12; 160 CX2 -= FDY23; 161 CX3 -= FDY31; 162 } 163 CY1 += FDX12; 164 CY2 += FDX23; 165 CY3 += FDX31; 166 off += w; 167 } 168 } 169 170 private int min(int x1, int x2, int x3) { 171 return (x1 > x2) ? ((x2 > x3) ? x3 : x2) : ((x1 > x3) ? x3 : x1); 172 } 173 174 private int max(int x1, int x2, int x3) { 175 return (x1 < x2) ? ((x2 < x3) ? x3 : x2) : ((x1 < x3) ? x3 : x1); 176 } 177 178 public void draw(@NonNull Canvas c) { 179 c.drawBitmap(mBitmap, 0, 0, null); 180 } 181} 182