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