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