cocos2d-x 文本 优化

  不得不说,CCLabelTTF是一个很鸡肋的组件,在2dx for ios库里面,它的底层使用了UIKit包来实现文本显示,但其显示特性较弱,几乎不可扩展。比如实现文字阴影,描边还有另一个更2的问题,当我们采用2dx的多分辨解决方案时,如

CCDirector::sharedDirector()->setContentScaleFactor(2.0); 这时的所有的文字都模糊不清,惨不忍睹。很多人此时会考虑抛弃ios默认字体,该自定义字体库,但几千个字符(包括诸如日文,韩文等)全部整合起来还是很麻烦的

    首先,我们追根溯源,查看2dx源代码,发现CCLabelTTF底层是由CCImage来渲染的,核心代码 

《CCImage.mm》

static bool _initWithString(const char * pText, cocos2d::CCImage::ETextAlign eAlign, const char * pFontName, int nSize, tImageInfo* pInfo)

关于代码细节此处不再详解,大致是用NSString 的draw方法来绘制文字,这里我们仿造来写一个

1.在《CCImage.h》中加入这些方法

//UIImage转CCImage

    bool initWithUIImage(void* uimg);

 /**

获取文字显示大小,注意,只是获取文字的显示区域大小,这个大小是 依据文字fontsize,是否换行等属性来确定,也就是说,调用该方法,文字并未渲染!*/

    static CCSize getImageStringSize(const char *pText,float fontSize, ccColor3B fillColor,ccColor4B shadowColor,bool isShadow,CCSize dimensions,CCTextAlignment hAlignment ,CCVerticalTextAlignment vAlignment);

//渲染文字

    void initWithShadowLabel( const char * pText,float fontSize,ccColor3B fillColor,ccColor4B shadowColor,bool isShadow = true,CCSize dimensions = CCSizeZero,CCTextAlignment h = kCCTextAlignmentLeft,CCVerticalTextAlignment v = kCCVerticalTextAlignmentTop);

 2. 

  1 // UIImage转CCImage
  2 
  3 bool CCImage::initWithUIImage(void* uimg)
  4 
  5 {
  6 
  7     CGImageRef CGImage = [(UIImage *)uimg CGImage];
  8 
  9     tImageInfo info = {0};
 10 
 11     bool bRet = _initWithImage(CGImage, &info);
 12 
 13     if (bRet)
 14 
 15     {
 16 
 17         m_nHeight = (short)info.height;
 18 
 19         m_nWidth = (short)info.width;
 20 
 21         m_nBitsPerComponent = info.bitsPerComponent;
 22 
 23         m_bHasAlpha = info.hasAlpha;
 24 
 25         m_bPreMulti = info.isPremultipliedAlpha;
 26 
 27         m_pData = info.data;
 28 
 29     }
 30 
 31     return bRet;
 32 
 33 }
 34 
 35 CCSize CCImage::getImageStringSize(const char *pText,float fontSize, ccColor3B fillColor,ccColor4B shadowColor,bool isShadow,CCSize dimensions,CCTextAlignment hAlignment ,CCVerticalTextAlignment vAlignment)
 36 
 37 {
 38 
 39     ETextAlign align;
 40 
 41     //获取文本对齐方式
 42 
 43     if (kCCVerticalTextAlignmentTop == vAlignment)
 44 
 45     {
 46 
 47         align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignTop
 48 
 49         : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignTopLeft : CCImage::kAlignTopRight;
 50 
 51     }
 52 
 53     elseif (kCCVerticalTextAlignmentCenter == vAlignment)
 54 
 55     {
 56 
 57         align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignCenter
 58 
 59         : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignLeft : CCImage::kAlignRight;
 60 
 61     }
 62 
 63     elseif (kCCVerticalTextAlignmentBottom == vAlignment)
 64 
 65     {
 66 
 67         align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignBottom
 68 
 69         : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignBottomLeft : CCImage::kAlignBottomRight;
 70 
 71     }
 72 
 73     else
 74 
 75     {
 76 
 77         CCAssert(false, "Not supported alignment format!");
 78 
 79     }
 80 
 81 //此处可以自己修改成其他字体样式,经过比较,我们选择使用系统加粗字体
 82 
 83     UIFont *font = [UIFont boldSystemFontOfSize:fontSize];
 84 
 85     NSString *str = [NSString stringWithUTF8String:pText];
 86 
 87     CGSize dim, constrainSize;
 88 
 89     constrainSize.width = dimensions.width;
 90 
 91     constrainSize.height = dimensions.height;
 92 
 93     // create the font ,这块代码 从引擎拷贝过来
 94 
 95     if (font)
 96 
 97     {
 98 
 99         dim = _calculateStringSize(str, font, &constrainSize);
100 
101     }
102 
103     // compute start point
104 
105     int startH = 0;
106 
107     if (constrainSize.height > dim.height)
108 
109     {
110 
111         // vertical alignment
112 
113         unsigned int vAlignment = (align >> 4) & 0x0F;
114 
115         if (vAlignment == ALIGN_TOP)
116 
117         {
118 
119             startH = 0;
120 
121         }
122 
123         else if (vAlignment == ALIGN_CENTER)
124 
125         {
126 
127             startH = (constrainSize.height - dim.height) / 2;
128 
129         }
130 
131         else
132 
133         {
134 
135             startH = constrainSize.height - dim.height;
136 
137         }
138 
139     }
140 
141     return CCSizeMake(dim.width, dim.height - startH);
142 
143 }
144 
145  
146 
147 void CCImage::initWithShadowLabel(const char *pText,float fontSize, ccColor3B fillColor,ccColor4B shadowColor,bool isShadow,CCSize dimensions,CCTextAlignment hAlignment ,CCVerticalTextAlignment vAlignment)
148 
149 {
150 
151     do {    
152 
153         CGFloat scaleFactor = CCDirector::sharedDirector()->getContentScaleFactor();
154 
155         //获取文本对齐方式
156 
157         ETextAlign align;
158 
159         if (kCCVerticalTextAlignmentTop == vAlignment)
160 
161         {
162 
163             align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignTop
164 
165             : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignTopLeft : CCImage::kAlignTopRight;
166 
167         }
168 
169         elseif (kCCVerticalTextAlignmentCenter == vAlignment)
170 
171         {
172 
173             align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignCenter
174 
175             : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignLeft : CCImage::kAlignRight;
176 
177         }
178 
179         elseif (kCCVerticalTextAlignmentBottom == vAlignment)
180 
181         {
182 
183             align = (kCCTextAlignmentCenter == hAlignment) ? CCImage::kAlignBottom
184 
185             : (kCCTextAlignmentLeft == hAlignment) ? CCImage::kAlignBottomLeft : CCImage::kAlignBottomRight;
186 
187         }
188 
189         else
190 
191         {
192 
193             break;
194 
195         }
196 
197         UIFont *font = [UIFont boldSystemFontOfSize:fontSize];
198 
199         NSString *str = [NSString stringWithUTF8String:pText];
200 
201         CC_BREAK_IF(!font);
202 
203         CGSize dim, constrainSize;
204 
205         constrainSize.width = dimensions.width;
206 
207         constrainSize.height = dimensions.height;
208 
209         
210 
211         // create the font
212 
213  
214 
215         dim = _calculateStringSize(str, font, &constrainSize);
216 
217         
218 
219         // compute start point
220 
221         int startH = 0;
222 
223         if (constrainSize.height > dim.height)
224 
225         {
226 
227             // vertical alignment
228 
229             unsigned int vAlignment = (align >> 4) & 0x0F;
230 
231             if (vAlignment == ALIGN_TOP)
232 
233             {
234 
235                 startH = 0;
236 
237             }
238 
239             else if (vAlignment == ALIGN_CENTER)
240 
241             {
242 
243                 startH = (constrainSize.height - dim.height) / 2;
244 
245             }
246 
247             else
248 
249             {
250 
251                 startH = constrainSize.height - dim.height;
252 
253             }
254 
255         }
256 
257         // adjust text rect
258 
259         if (constrainSize.width > 0 && constrainSize.width > dim.width)
260 
261         {
262 
263             dim.width = constrainSize.width;
264 
265         }
266 
267         if (constrainSize.height > 0 && constrainSize.height > dim.height)
268 
269         {
270 
271             dim.height = constrainSize.height;
272 
273         }
274 
275         
276 
277         CGSize size;
278 
279         size.width = dim.width * scaleFactor;
280 
281         size.height = dim.height * scaleFactor;
282 
283         
284 
285         UIGraphicsBeginImageContextWithOptions(size,false,scaleFactor);
286 
287         
288 
289         CGContextRef context = UIGraphicsGetCurrentContext();
290 
291         CC_BREAK_IF(!context);
292 
293  
294 
295         //    CGContextSetLineWidth(context, 2);
296 
297         ccColor4F fillColor4f = ccc4FFromccc3B(fillColor);
298 
299    //设置文本颜色
300 
301         CGContextSetRGBFillColor(context, fillColor4f.r, fillColor4f.g, fillColor4f.b, fillColor4f.a);
302 
303         // 这个地方 绘制文本阴影
304 
305         ccColor4F sColor4F =ccc4FFromccc4B(shadowColor);
306 
307         float sColor[4] = {sColor4F.r, sColor4F.g, sColor4F.b, sColor4F.a};
308 
309         CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
310 
311         CGColorRef color = CGColorCreate(colorSpace,sColor);
312 
         313 CGColorSpaceRelease(colorSpace); 314 315 if (isShadow) 316 317 { 318 319     //设置文字阴影 320 321 CGContextSetShadowWithColor(context, CGSizeMake(1.0, 1.0), 0.0, color); 322 323 } 324 325 // draw in context 326 327 CGContextScaleCTM(context, scaleFactor, scaleFactor);
328     CGColorRelease(color);
329    //绘制换行文本
330 
331         [str drawInRect:CGRectMake(0, startH, dim.width, dim.height) withFont:font lineBreakMode:(UILineBreakMode)UILineBreakModeWordWrapalignment:align];
332 
333         //    [str drawAtPoint:CGPointMake(0.0, 0.0) withFont:font]; // 画单行文本
334 
335         UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
336 
337         UIGraphicsEndImageContext();
338 
339         this->initWithUIImage(image);        
340 
341     }
342 
343     while (0);
344 
345 }

 

剩下的就是把CCImage转成CCtexture2D,然后交给CCSprite显示

 

 

posted @ 2013-04-09 15:12  haroel  阅读(2282)  评论(0编辑  收藏  举报