Changeset 197
- Timestamp:
- 07/22/10 00:39:20 (2 years ago)
- Files:
-
- trunk/src/demo1/main.d (modified) (1 diff)
- trunk/src/demo2/main.d (modified) (1 diff)
- trunk/src/yage/gui/surface.d (modified) (10 diffs)
- trunk/src/yage/gui/textblock.d (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/demo1/main.d
r193 r197 229 229 { float framerate = fps/frame.tell(); 230 230 window.setCaption(format("Yage Demo | %.2f fps\0", framerate)); 231 info. text= format(231 info.innerHtml = format( 232 232 `%.2f <b>fps</span><br/>` 233 233 `%d <b>objects</b><br/>` trunk/src/demo2/main.d
r195 r197 126 126 if (frame.tell()>=.25f) 127 127 { 128 info. text= `In a <s>traditional</s> <span style="color: green; text-decoration: overline; font-size:40px">`~128 info.innerHtml = `In a <s>traditional</s> <span style="color: green; text-decoration: overline; font-size:40px">`~ 129 129 `<u>M</u>a<s>nua</s>l <u style="font-size: 18px">printing</u></span> (letterpress) `~ 130 130 `<span style="text-decoration: overline">house</span> the font would refer to a complete set of metal `~ trunk/src/yage/gui/surface.d
r195 r197 34 34 Style style; 35 35 36 char[] text; /// This html text will be rendered inside the surface.36 protected char[] text; /// This html text will be rendered inside the surface. 37 37 bool editable = false; /// The text of this surface is editable. 38 38 bool mouseChildren = true; /// Allow the mouse to interact with this Surface's children. … … 79 79 }; 80 80 81 protected char[] oldText; // Used for comparison to see if text has changed. setHtml() would be more performant.82 81 protected Texture textTexture; // texture that constains rendered text image. 83 82 … … 90 89 protected bool mouseMoved; // used for click() event. 91 90 protected bool resizeDirty = true; 91 protected bool textDirty = true; 92 92 93 93 protected SurfaceGeometry geometry; // geometry used to render this surface … … 261 261 } 262 262 263 /// 264 public char[] innerHtml() 265 { return text; 266 } 267 /// ditto 268 public void innerHtml(char[] html) 269 { this.text = html; 270 textDirty = true; 271 } 263 272 264 273 /** … … 351 360 { 352 361 Style cs = getComputedStyle(); 353 //alias computedStyle cs;354 362 updateDimensions(cs); 355 363 if (resizeDirty) … … 365 373 366 374 // Text 367 if (text.length && ( text != oldText || resizeDirty))375 if (text.length && (resizeDirty || textDirty)) 368 376 { 369 377 int width = cast(int)width(); … … 371 379 372 380 textBlock.update(text, cs, width, height); 373 Image textImage = textBlock.render(cs, true, editable && focusSurface ==this ? &textCursor : null); // TODO: Change true to Probe.NextPow2381 Image textImage = textBlock.render(cs, true, editable && focusSurface is this ? &textCursor : null); // TODO: Change true to Probe.NextPow2 374 382 assert(textImage !is null); 375 383 … … 380 388 textTexture.padding = Vec2i(nextPow2(width)-width, -(nextPow2(height)-height)); 381 389 382 oldText = text;390 textDirty = false; 383 391 } 384 392 … … 480 488 textBlock.input(key, mod, unicode, textCursor, getComputedStyle()); 481 489 text = textBlock.toString(); // TODO: Do this lazily? 490 textDirty = true; 482 491 } 483 492 if(parent) … … 687 696 { resizeDirty = true; 688 697 resize(size-old_size); // trigger resize event. 689 foreach (c; children)690 c.updateDimensions(c.getComputedStyle());698 //foreach (c; children) 699 // c.updateDimensions(c.getComputedStyle()); 691 700 } 692 701 } trunk/src/yage/gui/textblock.d
r195 r197 48 48 struct TextBlock 49 49 { 50 private static const char[] whitespace = " \t\r\n";51 private static const char[] breaks = " *()-+=/\\,.;:|()[]{}<>\t\r\n"; // breaking characters50 private static const dchar[] whitespace = " \t\r\n"d; 51 private static const dchar[] breaks = " *()-+=/\\,.;:|()[]{}<>\t\r\n"d; // breaking characters 52 52 53 53 private ubyte[] imageLookaside; // TODO: Have the lookaside passed into Render … … 69 69 /// 70 70 Vec2i cursorToXy(int position) 71 { Vec2i result; 71 { 72 if (!lines.length) 73 return Vec2i(0); 74 Vec2i result; 72 75 int line = cursorToLine(position); 73 76 for (int i=0; i<line; i++) 74 77 result.y += lines[i].height; 75 78 line = min(line, lines.length-1); 76 Log.trace(position);77 79 int last = min(lines[line].letters.length, position); 78 80 for (int i=0; i<last; i++) … … 180 182 } 181 183 break; 182 case SDLK_HOME: 183 //cursorToLine(position); // position is now relativeto the beginning of the line. 184 case SDLK_HOME: 184 185 cursor.position -= position; 185 186 break; 186 187 case SDLK_END: 187 //cursorToLine(position);188 188 cursor.position += (lines[currentLine].letters.length - position); 189 189 break; … … 225 225 226 226 227 //lines = lettersToLines(letters.data, width, lines);227 lines = lettersToLines(letters.data, width, lines); 228 228 229 229 //return toString(); … … 288 288 if (istyle.textDecoration == Style.TextDecoration.UNDERLINE) 289 289 for (int h=max(0, baseline); h<min(baseline+lineWidth, height); h++) 290 for (int j=x; j<x+letter.advanceX; j++) // [above] make underline 1/10th as thick as line-height291 result[ j, h] = istyle.color.ub;290 for (int w=x; w<min(x+letter.advanceX, width); w++) // [above] make underline 1/10th as thick as line-height 291 result[w, h] = istyle.color.ub; 292 292 else if (istyle.textDecoration == Style.TextDecoration.OVERLINE) 293 293 for (int h=max(0, capheight); h<min(capheight+lineWidth, height); h++) 294 for (int j=x; j<x+letter.advanceX; j++)295 result[ j, h] = istyle.color.ub;294 for (int w=x; w<min(x+letter.advanceX, width); w++) 295 result[w, h] = istyle.color.ub; 296 296 else if (istyle.textDecoration == Style.TextDecoration.LINETHROUGH) 297 297 for (int h=max(0, midline); h<min(midline+lineWidth, height); h++) 298 for (int j=x; j<x+letter.advanceX; j++) 299 result[j, h] = istyle.color.ub; 300 301 302 if (cursor) 303 { 304 Vec2i xy = cursorToXy(cursor.position+1); 305 for (int h=max(0, xy.y); h<min(line.height+xy.y, height); h++) 306 for (int w=max(0, xy.x); w<min(xy.x+2, width); w++) 307 result[w, h] = style.color.ub; 308 309 } 298 for (int w=x; w<min(x+letter.advanceX, width); w++) 299 result[w, h] = istyle.color.ub; 310 300 311 301 x+= letter.advanceX; // + istyle.letterSpacing; … … 317 307 break; 318 308 } 319 } 309 } 310 311 // Draw cursor 312 if (cursor) 313 { Vec2i xy = cursorToXy(cursor.position); 314 int lineHeight = cast(int)style.lineHeight.toPx(0); 315 if (letters.length) 316 { //xy.x += letters[cursor.position].advanceX; 317 int position = cursor.position; // copy 318 int line = min(cursorToLine(position), lines.length-1); 319 lineHeight = lines[line].height; 320 } 321 int hmin = max(0, xy.y), hmax = min(lineHeight+xy.y, height); 322 int wmin = max(0, xy.x), wmax = min(xy.x+2, width); 323 for (int h=hmin; h<hmax; h++) 324 for (int w=wmin; w<wmax; w++) 325 result[w, h] = style.color.ub; 326 } 327 320 328 return result; 321 329 } … … 426 434 // Build lines from letters 427 435 // TODO: Instead of having this here, create lettersToLines function (to Match HtmlParse.htmlToLetters()) 428 int i ;436 int i, lineEnd; 429 437 while (i<letters.length) 430 { int start=i;438 { int lineStart = i = lineEnd; 431 439 int x=0, lineHeight=0; 432 int last_break=i; 440 Line line; 441 442 // Skip beginning spaces unless they are on a line started from a line return. 443 if (i>0 && letters[i-1].letter != '\n' && letters[i].letter == ' ') 444 { while (i<letters.length && letters[i].letter == ' ') 445 i++; 446 lineStart = lineEnd = i; 447 } 433 448 434 449 // Loop through as many as we can fit on this line 435 while (x<width && i<letters.length) 436 { InlineStyle* letterStyle = (cast(InlineStyle*)letters[i].extra); 437 438 // Get line height (Defaults to fontSize*1.2 if not specified) 439 int calculatedLineHeight = cast(int)(isNaN(letterStyle.lineHeight) ? letterStyle.fontSize : letterStyle.lineHeight); 440 if (lineHeight < calculatedLineHeight) 441 lineHeight = calculatedLineHeight; 442 443 x+= letters[i].advanceX; 444 445 // Convert letter to utf-8 for comparison. TODO: This won't be necessary if we store breaks as utf-32. 446 char[4] lookaside; 447 char[] utf8 = letters[i].toString(lookaside); 448 449 if (containsPattern(breaks, utf8)) // store position of last breaking character 450 last_break = i; 451 if (x<width) 452 i++; 453 if (i==letters.length) // include the final characters. 454 last_break = i; 455 456 if (utf8[0] == '\n') // break on line returns. 450 // and populate lineStart and lineEnd 451 while (i<letters.length) 452 { 453 // Get line height (Defaults to fontSize if not specified) 454 // TODO: Don't change lineHeight if it's already specified. 455 InlineStyle* letterStyle = (cast(InlineStyle*)letters[i].extra); 456 if (lineHeight < letterStyle.fontSize) 457 lineHeight = letterStyle.fontSize; 458 459 dchar letter = letters[i].letter; 460 dchar letterBefore = i>0 ? letters[i-1].letter : letter; 461 bool letterCanBreak = contains(breaks, letterBefore); 462 463 // Store position of last breakable character 464 if (letterCanBreak) 465 lineEnd = i; 466 467 468 // Store position of last breakable character 469 if (letterCanBreak) 470 lineEnd = i; 471 472 //line.xOffsets.append(x); 473 x+= letters[i].advanceX; // + style.letterSpacing; 474 //if (!whitespace.contains(letterBefore) && whitespace.contains(letter)) 475 // x+= style.wordSpacing * fontScale; 476 477 // Time to go to the next line 478 if (letter == '\n' || (x >= width && i > lineStart)) 479 { if (letter == '\n') // If line return 480 lineEnd = i+1; 481 else if (lineEnd == lineStart) // if word is too long to fit on one line. 482 lineEnd = i; 457 483 break; 458 } 459 460 // Add a new line 461 Line line; 462 if (start<last_break) // don't count spaces at the end of the line. 463 { i = last_break; 464 if (i < letters.length && letters[i].letter=='\n') 465 i++; // skip line returns 466 assert(last_break <= letters.length); 467 line.letters = letters[start..last_break]; // slice directly from the letters array to avoid copy allocation 468 } 469 470 // trim line 471 int firstChar, lastChar=line.letters.length-1; 472 while (firstChar < line.letters.length && whitespace.contains(cast(char)line.letters[firstChar].letter)) 473 firstChar++; 474 while (lastChar>=0 && whitespace.contains(cast(char)line.letters[lastChar].letter)) 475 lastChar--; 476 line.letters = line.letters[firstChar..lastChar+1]; 477 478 // Calculate line width 479 foreach (letter; line.letters) 480 line.width += letter.advanceX; 481 484 } else if (i+1==letters.length) // include the final characters. 485 lineEnd = i+1; 486 487 i++; 488 } 489 490 // Add a new line 491 if (lineStart < lineEnd) // if line has characters 492 { assert(lineEnd <= letters.length); 493 line.letters = letters[lineStart..lineEnd]; 494 //line.xOffsets.resize(lineEnd); 495 496 if (line.letters[$-1].letter == '\n') 497 line.letters.length = line.letters.length-1; 498 499 // Calculate line.width 500 int lastLetter = line.letters.length-1; 501 while (lastLetter >=0 && whitespace.contains(line.letters[lastLetter].letter)) 502 lastLetter--; // trim whitespace from end 503 504 //Style style = *styles.at(lastLetter); 505 //style.size *= fontScale; 506 //Letter* letter = ResourceManager::getLetter(text.at(lastLetter), &style); 507 //line.width = line.xOffsets.at(lastLetter) + letter->left + letter->advanceX; 508 for (int i=0; i<=lastLetter; i++) 509 line.width += line.letters[i].advanceX; 510 } 511 482 512 line.height = lineHeight; 483 513 lines ~= line;
