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