把android 项目下的 org.cocos2dx.lib 包下的 Cocos2dxBitmap.java 替换成
1 package org.cocos2dx.lib; 2 3 import java.nio.ByteBuffer; 4 import java.nio.ByteOrder; 5 import java.util.LinkedList; 6 7 import android.content.Context; 8 import android.graphics.Bitmap; 9 import android.graphics.Canvas; 10 import android.graphics.Color; 11 import android.graphics.Paint; 12 import android.graphics.Typeface; 13 import android.graphics.Paint.Align; 14 import android.graphics.Paint.FontMetricsInt; 15 import android.util.Log; 16 17 public class Cocos2dxBitmap{ 18 /* 19 * The values are the same as cocos2dx/platform/CCImage.h. 20 * I think three alignments are OK. 21 */ 22 private static final int ALIGNCENTER = 0x33; 23 private static final int ALIGNLEFT = 0x31; 24 private static final int ALIGNRIGHT = 0x32; 25 26 private static Context context; 27 28 public static void setContext(Context context){ 29 Cocos2dxBitmap.context = context; 30 } 31 32 /* 33 * @width: the width to draw, it can be 0 34 * @height: the height to draw, it can be 0 35 */ 36 public static void createTextBitmap(String content, String fontName, 37 int fontSize, int alignment, int width, int height){ 38 39 content = refactorString(content); 40 Paint paint = newPaint(fontName, fontSize, alignment); 41 42 TextProperty textProperty = computeTextProperty(content, paint, width, height); 43 44 int bitmapTotalHeight = (height == 0 ? textProperty.totalHeight:height); 45 46 // Draw text to bitmap 47 Bitmap bitmap = Bitmap.createBitmap(textProperty.maxWidth, 48 bitmapTotalHeight, Bitmap.Config.ARGB_8888); 49 Canvas canvas = new Canvas(bitmap); 50 51 // Draw string 52 FontMetricsInt fm = paint.getFontMetricsInt(); 53 int x = 0; 54 int y = height == 0 ?(-fm.top): 55 (-fm.top + (height - textProperty.totalHeight)/2); 56 String[] lines = textProperty.lines; 57 for (String line : lines){ 58 x = computeX(paint, line, textProperty.maxWidth, alignment); 59 canvas.drawText(line, x, y, paint); 60 y += textProperty.heightPerLine; 61 } 62 63 initNativeObject(bitmap); 64 } 65 66 private static int computeX(Paint paint, String content, int w, int alignment){ 67 int ret = 0; 68 69 switch (alignment){ 70 case ALIGNCENTER: 71 ret = w / 2; 72 break; 73 74 // ret = 0 75 case ALIGNLEFT: 76 break; 77 78 case ALIGNRIGHT: 79 ret = w; 80 break; 81 82 /* 83 * Default is align left. 84 * Should be same as newPaint(). 85 */ 86 default: 87 break; 88 } 89 90 return ret; 91 } 92 93 private static class TextProperty{ 94 // The max width of lines 95 int maxWidth; 96 // The height of all lines 97 int totalHeight; 98 int heightPerLine; 99 String[] lines; 100 101 TextProperty(int w, int h, String[] lines){ 102 this.maxWidth = w; 103 this.heightPerLine = h; 104 this.totalHeight = h * lines.length; 105 this.lines = lines; 106 } 107 } 108 109 private static TextProperty computeTextProperty(String content, Paint paint, 110 int maxWidth, int maxHeight){ 111 FontMetricsInt fm = paint.getFontMetricsInt(); 112 int h = (int)Math.ceil(fm.bottom - fm.top); 113 int maxContentWidth = 0; 114 115 String[] lines = splitString(content, maxHeight, maxWidth, paint); 116 117 if (maxWidth != 0){ 118 maxContentWidth = maxWidth; 119 } 120 else { 121 /* 122 * Compute the max width 123 */ 124 int temp = 0; 125 for (String line : lines){ 126 temp = (int)Math.ceil(paint.measureText(line, 0, line.length())); 127 if (temp > maxContentWidth){ 128 maxContentWidth = temp; 129 } 130 } 131 } 132 133 return new TextProperty(maxContentWidth, h, lines); 134 } 135 136 /* 137 * If maxWidth or maxHeight is not 0, 138 * split the string to fix the maxWidth and maxHeight. 139 */ 140 private static String[] splitString(String content, int maxHeight, int maxWidth, 141 Paint paint){ 142 String[] lines = content.split("\\n"); 143 String[] ret = null; 144 FontMetricsInt fm = paint.getFontMetricsInt(); 145 int heightPerLine = (int)Math.ceil(fm.bottom - fm.top); 146 int maxLines = maxHeight / heightPerLine; 147 148 if (maxWidth != 0){ 149 LinkedList<String> strList = new LinkedList<String>(); 150 for (String line : lines){ 151 /* 152 * The width of line is exceed maxWidth, should divide it into 153 * two or more lines. 154 */ 155 int lineWidth = (int)Math.ceil(paint.measureText(line)); 156 if (lineWidth > maxWidth){ 157 strList.addAll(divideStringWithMaxWidth(paint, line, maxWidth)); 158 } 159 else{ 160 strList.add(line); 161 } 162 163 /* 164 * Should not exceed the max height; 165 */ 166 if (maxLines > 0 && strList.size() >= maxLines){ 167 break; 168 } 169 } 170 171 /* 172 * Remove exceeding lines 173 */ 174 if (maxLines > 0 && strList.size() > maxLines){ 175 while (strList.size() > maxLines){ 176 strList.removeLast(); 177 } 178 } 179 180 ret = new String[strList.size()]; 181 strList.toArray(ret); 182 } else 183 if (maxHeight != 0 && lines.length > maxLines) { 184 /* 185 * Remove exceeding lines 186 */ 187 LinkedList<String> strList = new LinkedList<String>(); 188 for (int i = 0; i < maxLines; i++){ 189 strList.add(lines[i]); 190 } 191 ret = new String[strList.size()]; 192 strList.toArray(ret); 193 } 194 else { 195 ret = lines; 196 } 197 198 return ret; 199 } 200 201 private static LinkedList<String> divideStringWithMaxWidth(Paint paint, String content, 202 int width){ 203 int charLength = content.length(); 204 int start = 0; 205 int tempWidth = 0; 206 LinkedList<String> strList = new LinkedList<String>(); 207 208 /* 209 * Break a String into String[] by the width & should wrap the word 210 */ 211 for (int i = 1; i <= charLength; ++i){ 212 tempWidth = (int)Math.ceil(paint.measureText(content, start, i)); 213 if (tempWidth >= width){ 214 int lastIndexOfSpace = content.substring(0, i).lastIndexOf(" "); 215 216 if (lastIndexOfSpace != -1 && lastIndexOfSpace > start){ 217 /** 218 * Should wrap the word 219 */ 220 strList.add(content.substring(start, lastIndexOfSpace)); 221 i = lastIndexOfSpace; 222 } 223 else { 224 /* 225 * Should not exceed the width 226 */ 227 if (tempWidth > width){ 228 strList.add(content.substring(start, i - 1)); 229 /* 230 * compute from previous char 231 */ 232 --i; 233 } 234 else { 235 strList.add(content.substring(start, i)); 236 } 237 } 238 239 start = i; 240 } 241 } 242 243 /* 244 * Add the last chars 245 */ 246 if (start < charLength){ 247 strList.add(content.substring(start)); 248 } 249 250 return strList; 251 } 252 253 private static Paint newPaint(String fontName, int fontSize, int alignment){ 254 Paint paint = new Paint(); 255 paint.setColor(Color.WHITE); 256 paint.setTextSize(fontSize); 257 paint.setAntiAlias(true); 258 259 /* 260 * Set type face for paint, now it support .ttf file. 261 */ 262 if (fontName.endsWith(".ttf")){ 263 try { 264 //Typeface typeFace = Typeface.createFromAsset(context.getAssets(), fontName); 265 Typeface typeFace = Cocos2dxTypefaces.get(context, fontName); 266 paint.setTypeface(typeFace); 267 } catch (Exception e){ 268 Log.e("Cocos2dxBitmap", 269 "error to create ttf type face: " + fontName); 270 271 /* 272 * The file may not find, use system font 273 */ 274 paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL)); 275 } 276 } 277 else { 278 paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL)); 279 } 280 281 switch (alignment){ 282 case ALIGNCENTER: 283 paint.setTextAlign(Align.CENTER); 284 break; 285 286 case ALIGNLEFT: 287 paint.setTextAlign(Align.LEFT); 288 break; 289 290 case ALIGNRIGHT: 291 paint.setTextAlign(Align.RIGHT); 292 break; 293 294 default: 295 paint.setTextAlign(Align.LEFT); 296 break; 297 } 298 299 return paint; 300 } 301 302 private static String refactorString(String str){ 303 // Avoid error when content is "" 304 if (str.compareTo("") == 0){ 305 return " "; 306 } 307 308 /* 309 * If the font of "\n" is "" or "\n", insert " " in front of it. 310 * 311 * For example: 312 * "\nabc" -> " \nabc" 313 * "\nabc\n\n" -> " \nabc\n \n" 314 */ 315 StringBuilder strBuilder = new StringBuilder(str); 316 int start = 0; 317 int index = strBuilder.indexOf("\n"); 318 while (index != -1){ 319 if (index == 0 || strBuilder.charAt(index -1) == '\n'){ 320 strBuilder.insert(start, " "); 321 start = index + 2; 322 } else { 323 start = index + 1; 324 } 325 326 if (start > strBuilder.length() || index == strBuilder.length()){ 327 break; 328 } 329 330 index = strBuilder.indexOf("\n", start); 331 } 332 333 return strBuilder.toString(); 334 } 335 336 private static void initNativeObject(Bitmap bitmap){ 337 byte[] pixels = getPixels(bitmap); 338 if (pixels == null){ 339 return; 340 } 341 342 nativeInitBitmapDC(bitmap.getWidth(), bitmap.getHeight(), pixels); 343 } 344 345 private static byte[] getPixels(Bitmap bitmap){ 346 if (bitmap != null){ 347 byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 4]; 348 ByteBuffer buf = ByteBuffer.wrap(pixels); 349 buf.order(ByteOrder.nativeOrder()); 350 bitmap.copyPixelsToBuffer(buf); 351 return pixels; 352 } 353 354 return null; 355 } 356 357 private static native void nativeInitBitmapDC(int width, int height, byte[] pixels); 358 }