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