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