1 /* 2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Mikael Konradson, mikael.konradson@gmail.com 7 */ 8 9 10 #include "FontDemoView.h" 11 12 #include <math.h> 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <string.h> 16 17 #include <Bitmap.h> 18 #include <Font.h> 19 #include <Message.h> 20 #include <Shape.h> 21 22 #include "messages.h" 23 24 25 FontDemoView::FontDemoView(BRect rect) 26 : BView(rect, "FontDemoView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), 27 fBitmap(NULL), 28 fBufferView(NULL), 29 fString(NULL), 30 fFontSize(50.0), 31 fSpacing(0.0), 32 fOutLineLevel(0), 33 fDrawingMode(B_OP_COPY), 34 fBoundingBoxes(false), 35 fDrawShapes(false), 36 fShapes(NULL) 37 { 38 SetViewColor(B_TRANSPARENT_COLOR); 39 SetString("Haiku, Inc."); 40 SetFontSize(fFontSize); 41 SetAntialiasing(true); 42 43 _NewBitmap(Bounds()); 44 } 45 46 47 FontDemoView::~FontDemoView() 48 { 49 free(fString); 50 free(fShapes); 51 52 fBitmap->Lock(); 53 delete fBitmap; 54 } 55 56 57 void 58 FontDemoView::FrameResized(float width, float height) 59 { 60 // TODO: We shouldnt invalidate the whole view when bounding boxes are 61 // working as wanted 62 Invalidate(/*fBoxRegion.Frame()*/); 63 BView::FrameResized(width, height); 64 } 65 66 67 void 68 FontDemoView::Draw(BRect updateRect) 69 { 70 BRect rect = Bounds(); 71 fBufferView = _GetView(rect); 72 _DrawView(fBufferView); 73 74 fBufferView->Sync(); 75 DrawBitmap(fBitmap, rect); 76 fBitmap->Unlock(); 77 } 78 79 80 void 81 FontDemoView::_DrawView(BView* view) 82 { 83 if (!view) 84 return; 85 86 view->SetDrawingMode(B_OP_COPY); 87 88 89 BRect rect = view->Bounds(); 90 view->SetHighColor(255, 255, 255); 91 view->FillRect(rect); 92 93 if (!fString) 94 return; 95 96 view->SetFont(&fFont, B_FONT_ALL); 97 98 const size_t size = strlen(fString); 99 BRect boundBoxes[size]; 100 101 if (OutLineLevel()) 102 fFont.GetGlyphShapes(fString, size, fShapes); 103 else 104 fFont.GetBoundingBoxesAsGlyphs(fString, size, B_SCREEN_METRIC, boundBoxes); 105 106 float escapementArray[size]; 107 //struct escapement_delta escapeDeltas[size]; 108 struct edge_info edgeInfo[size]; 109 /* 110 for (size_t j = 0; j < size; j++) { 111 escapeDeltas[j].nonspace = 0.0f; 112 escapeDeltas[j].space = 0.0f; 113 } 114 */ 115 fFont.GetEdges(fString, size, edgeInfo); 116 fFont.GetEscapements(fString, size, /*escapeDeltas,*/ escapementArray); 117 118 font_height fh; 119 fFont.GetHeight(&fh); 120 121 float xCoordArray[size]; 122 float yCoordArray[size]; 123 124 float yCoord = (rect.Height() + fh.ascent - fh.descent) / 2; 125 float xCoord = -rect.Width() / 2; 126 const float xCenter = xCoord * -1; 127 const float r = Rotation() * (M_PI / 180.0); 128 const float cosinus = cos(r); 129 const float sinus = -sin(r); 130 131 // When the bounding boxes workes properly we will invalidate only the 132 // region area instead of the whole view. 133 134 fBoxRegion.MakeEmpty(); 135 136 for (size_t i = 0; i < size; i++) { 137 xCoordArray[i] = 0.0f; 138 yCoordArray[i] = 0.0f; 139 140 yCoordArray[i] = sinus * (xCoord - xCoordArray[i]); 141 xCoordArray[i] = cosinus * xCoord; 142 143 xCoordArray[i] += xCenter; 144 yCoordArray[i] += yCoord; 145 146 boundBoxes[i].OffsetBy(xCoordArray[i], yCoordArray[i]); 147 148 if (OutLineLevel()) { 149 view->MovePenTo(xCoordArray[i], yCoordArray[i]); 150 view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 151 view->FillShape(fShapes[i]); 152 view->SetPenSize(OutLineLevel()); 153 view->SetHighColor(0, 0, 0); 154 view->StrokeShape(fShapes[i]); 155 } else { 156 view->SetHighColor(0, 0, 0); 157 view->SetDrawingMode(fDrawingMode); 158 view->DrawChar(fString[i], BPoint(xCoordArray[i], yCoordArray[i])); 159 } 160 161 if (BoundingBoxes() && !OutLineLevel()) { 162 if (i % 2) 163 view->SetHighColor(0, 255, 0); 164 else 165 view->SetHighColor(255, 0, 0); 166 view->SetDrawingMode(B_OP_COPY); 167 view->StrokeRect(boundBoxes[i]); 168 } 169 170 // add the bounding to the region. 171 fBoxRegion.Include(boundBoxes[i]); 172 173 xCoord += (escapementArray[i] /*+ escapeDeltas[i].nonspace + escapeDeltas[i].space*/) 174 * FontSize() + Spacing(); 175 //printf("xCoord %f\n", xCoord); 176 } 177 } 178 179 180 void 181 FontDemoView::MessageReceived(BMessage* msg) 182 { 183 switch (msg->what) { 184 case TEXT_CHANGED_MSG: 185 { 186 const char* text = NULL; 187 if (msg->FindString("_text", &text) == B_OK) { 188 SetString(text); 189 Invalidate(/*&fBoxRegion*/); 190 } 191 break; 192 } 193 194 case FONTSTYLE_CHANGED_MSG: 195 { 196 BMessage fontMessage; 197 if (msg->FindMessage("_fontMessage", &fontMessage) != B_OK) 198 return; 199 200 const char* family; 201 const char* style; 202 if (fontMessage.FindString("_family", &family) != B_OK 203 || fontMessage.FindString("_style", &style) != B_OK) 204 return; 205 206 fFont.SetFamilyAndStyle(family, style); 207 Invalidate(); 208 break; 209 } 210 211 case FONTFAMILY_CHANGED_MSG: 212 { 213 BMessage fontMessage; 214 if (msg->FindMessage("_fontMessage", &fontMessage) != B_OK) 215 return; 216 217 const char* family; 218 if (fontMessage.FindString("_family", &family) != B_OK) 219 return; 220 221 font_style style; 222 if (get_font_style(const_cast<char*>(family), 0, &style) == B_OK) { 223 fFont.SetFamilyAndStyle(family, style); 224 Invalidate(/*&fBoxRegion*/); 225 } 226 break; 227 } 228 229 case FONTSIZE_MSG: 230 { 231 float size = 0.0; 232 if (msg->FindFloat("_size", &size) == B_OK) { 233 SetFontSize(size); 234 Invalidate(/*&fBoxRegion*/); 235 } 236 break; 237 } 238 239 case FONTSHEAR_MSG: 240 { 241 float shear = 90.0; 242 if (msg->FindFloat("_shear", &shear) == B_OK) { 243 SetFontShear(shear); 244 Invalidate(/*&fBoxRegion*/); 245 } 246 break; 247 } 248 249 case ROTATION_MSG: 250 { 251 float rotation = 0.0; 252 if (msg->FindFloat("_rotation", &rotation) == B_OK) { 253 SetFontRotation(rotation); 254 Invalidate(/*&fBoxRegion*/); 255 } 256 break; 257 } 258 259 case SPACING_MSG: 260 { 261 float space = 0.0; 262 if (msg->FindFloat("_spacing", &space) == B_OK) { 263 SetSpacing(space); 264 Invalidate(/*&fBoxRegion*/); 265 } 266 break; 267 } 268 269 case OUTLINE_MSG: 270 { 271 int8 outline = 0; 272 if (msg->FindInt8("_outline", &outline) == B_OK) { 273 SetOutlineLevel(outline); 274 Invalidate(/*&fBoxRegion*/); 275 } 276 break; 277 } 278 279 case ALIASING_MSG: 280 { 281 bool aliased = false; 282 if (msg->FindBool("_aliased", &aliased) == B_OK) { 283 SetAntialiasing(aliased); 284 Invalidate(/*&fBoxRegion*/); 285 } 286 break; 287 } 288 289 case DRAWINGMODE_CHANGED_MSG: 290 { 291 if (msg->FindInt32("_mode", (int32 *)&fDrawingMode) == B_OK) { 292 Invalidate(/*&fBoxRegion*/); 293 } 294 break; 295 } 296 297 case BOUNDING_BOX_MSG: 298 { 299 bool boundingbox = false; 300 if (msg->FindBool("_boundingbox", &boundingbox) == B_OK) { 301 SetDrawBoundingBoxes(boundingbox); 302 Invalidate(/*&fBoxRegion*/); 303 } 304 break; 305 } 306 307 default: 308 BView::MessageReceived(msg); 309 break; 310 } 311 } 312 313 314 void 315 FontDemoView::SetString(const char* string) 316 { 317 free(fString); 318 fString = strdup(string); 319 free(fShapes); 320 _AddShapes(fString); 321 } 322 323 324 const char* 325 FontDemoView::String() const 326 { 327 return fString; 328 } 329 330 331 void 332 FontDemoView::SetFontSize(float size) 333 { 334 fFont.SetSize(size); 335 } 336 337 338 void 339 FontDemoView::SetFontShear(float shear) 340 { 341 fFont.SetShear(shear); 342 } 343 344 345 void 346 FontDemoView::SetFontRotation(float rotation) 347 { 348 fFont.SetRotation(rotation); 349 } 350 351 352 void 353 FontDemoView::SetDrawBoundingBoxes(bool state) 354 { 355 fBoundingBoxes = state; 356 } 357 358 359 void 360 FontDemoView::SetAntialiasing(bool state) 361 { 362 fFont.SetFlags(state ? B_FORCE_ANTIALIASING : B_DISABLE_ANTIALIASING); 363 } 364 365 366 void 367 FontDemoView::SetSpacing(float space) 368 { 369 fSpacing = space; 370 } 371 372 373 void 374 FontDemoView::SetOutlineLevel(int8 outline) 375 { 376 fOutLineLevel = outline; 377 } 378 379 380 void 381 FontDemoView::_AddShapes(const char* string) 382 { 383 const size_t size = strlen(string); 384 fShapes = (BShape**)malloc(sizeof(BShape*)*size); 385 386 for (size_t i = 0; i < size; i++) { 387 fShapes[i] = new BShape(); 388 } 389 } 390 391 392 BView* 393 FontDemoView::_GetView(BRect rect) 394 { 395 if (!fBitmap || fBitmap->Bounds() != rect) 396 _NewBitmap(rect); 397 398 fBitmap->Lock(); 399 return fBitmap->ChildAt(0); 400 } 401 402 403 void 404 FontDemoView::_NewBitmap(BRect rect) 405 { 406 delete fBitmap; 407 fBitmap = new BBitmap(rect, B_RGB16, true); 408 409 if (fBitmap->Lock()) { 410 BView* view = new BView(rect, "", B_FOLLOW_NONE, B_WILL_DRAW); 411 fBitmap->AddChild(view); 412 fBitmap->Unlock(); 413 } else { 414 delete fBitmap; 415 fBitmap = NULL; 416 } 417 } 418 419