From ab3604f492ed54861e0591d87a04529094fb46e1 Mon Sep 17 00:00:00 2001
From: Dale Cieslak <dcieslak@yahoo.com>
Date: Sun, 21 May 2017 23:39:22 +0000
Subject: [PATCH 2/2] Fixes #13526 so that BFont::Blocks properly set bitmask
for Unicode blocks in a font.
ParseFcMap had several logic errors.
- fixed variable being initialized in the wrong part of the loops
- fixed problem of ANDing bit with 0x8 instead of 0x1
- changed some variable names; 'foundStartBlock' implies a boolean but
it is a block number, so it is now just 'startBlock'
- added const BITS_PER_BLOCK for magic number 32
- added short-circuit for empty full or partial blocks
- initialized variables to -1 when 0 is a valid value
- added code to handle when the end of a block is reached and a range
was started but never finished.
---
src/servers/app/ServerFont.cpp | 94 +++++++++++++++++++++++++++---------------
1 file changed, 60 insertions(+), 34 deletions(-)
diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp
index 74dd8f9..cd9015c 100644
a
|
b
|
static
|
497 | 497 | void |
498 | 498 | ParseFcMap(FcChar32 charMap[], FcChar32 baseCodePoint, unicode_block& blocksForMap) |
499 | 499 | { |
| 500 | uint32 block = 0; |
| 501 | const uint8 BITS_PER_BLOCK = 32; |
| 502 | uint32 currentCodePoint = 0; |
| 503 | |
500 | 504 | for (int i = 0; i < FC_CHARSET_MAP_SIZE; ++i) { |
501 | 505 | FcChar32 curMapBlock = charMap[i]; |
502 | | uint32 rangeStart = 0; |
503 | | uint32 block = 0; |
504 | | |
505 | | for (int bit = 0; bit < 32; ++bit) { |
506 | | uint32 startPoint = 0; |
507 | | int32 foundStartBlock = -1; |
508 | | int32 foundEndBlock = -1; |
509 | | |
510 | | if ((curMapBlock & 0x8) != 0) { |
511 | | if (rangeStart == 0) { |
512 | | rangeStart = bit; |
513 | | startPoint = baseCodePoint + block + (rangeStart); |
514 | | foundStartBlock = FindBlockForCodepoint(startPoint, 0); |
515 | | if (foundStartBlock >= 0) { |
516 | | blocksForMap = blocksForMap |
517 | | | kUnicodeBlockMap[foundStartBlock].block; |
518 | | } |
519 | | } |
520 | | } else if (rangeStart > 0 && foundStartBlock > 0) { |
| 506 | int32 rangeStart = -1; |
| 507 | int32 startBlock = -1; |
| 508 | int32 endBlock = -1; |
| 509 | uint32 startPoint = 0; |
| 510 | |
| 511 | currentCodePoint = baseCodePoint + block; |
| 512 | |
| 513 | for (int bit = 0; bit < BITS_PER_BLOCK; ++bit) { |
| 514 | if (curMapBlock == 0 && startBlock < 0) |
| 515 | // if no more bits are set then short-circuit the loop |
| 516 | break; |
| 517 | |
| 518 | if ((curMapBlock & 0x1) != 0 && rangeStart < 0) { |
| 519 | rangeStart = bit; |
| 520 | startPoint = currentCodePoint + rangeStart; |
| 521 | startBlock = FindBlockForCodepoint(startPoint, 0); |
| 522 | if (startBlock >= 0) { |
| 523 | blocksForMap = blocksForMap |
| 524 | | kUnicodeBlockMap[startBlock].block; |
| 525 | } |
| 526 | } else if (rangeStart >= 0 && startBlock >= 0) { |
521 | 527 | // when we find an empty bit, that's the end of the range |
522 | | uint32 endPoint = baseCodePoint + block + (bit - 1); |
| 528 | uint32 endPoint = currentCodePoint + (bit - 1); |
523 | 529 | |
524 | | foundEndBlock = FindBlockForCodepoint(endPoint, |
525 | | foundStartBlock); |
| 530 | endBlock = FindBlockForCodepoint(endPoint, |
| 531 | startBlock); |
526 | 532 | // start the binary search at the block where we found the |
527 | 533 | // start codepoint to ideally find the end in the same |
528 | 534 | // block. |
529 | | ++foundStartBlock; |
| 535 | ++startBlock; |
530 | 536 | |
531 | | while (foundStartBlock <= foundEndBlock) { |
| 537 | while (startBlock <= endBlock) { |
532 | 538 | // if the starting codepoint is found in a different block |
533 | 539 | // than the ending codepoint, we should add all the blocks |
534 | 540 | // inbetween. |
535 | 541 | blocksForMap = blocksForMap |
536 | | | kUnicodeBlockMap[foundStartBlock].block; |
537 | | ++foundStartBlock; |
| 542 | | kUnicodeBlockMap[startBlock].block; |
| 543 | ++startBlock; |
538 | 544 | } |
539 | 545 | |
540 | | foundStartBlock = -1; |
541 | | foundEndBlock = -1; |
542 | | rangeStart = 0; |
543 | | } else { |
544 | | foundStartBlock = -1; |
545 | | rangeStart = 0; |
546 | | } |
| 546 | startBlock = -1; |
| 547 | endBlock = -1; |
| 548 | rangeStart = -1; |
| 549 | } |
547 | 550 | |
548 | 551 | curMapBlock >>= 1; |
549 | 552 | } |
| 553 | |
| 554 | if (rangeStart >= 0 && startBlock >= 0) { |
| 555 | // if we hit the end of the block and had |
| 556 | // found a start of the range then we |
| 557 | // should end the range at the end of the block |
| 558 | uint32 endPoint = currentCodePoint + BITS_PER_BLOCK - 1; |
| 559 | |
| 560 | endBlock = FindBlockForCodepoint(endPoint, |
| 561 | startBlock); |
| 562 | // start the binary search at the block where we found the |
| 563 | // start codepoint to ideally find the end in the same |
| 564 | // block. |
| 565 | ++startBlock; |
| 566 | |
| 567 | while (startBlock <= endBlock) { |
| 568 | // if the starting codepoint is found in a different block |
| 569 | // than the ending codepoint, we should add all the blocks |
| 570 | // inbetween. |
| 571 | blocksForMap = blocksForMap |
| 572 | | kUnicodeBlockMap[startBlock].block; |
| 573 | ++startBlock; |
| 574 | } |
| 575 | } |
550 | 576 | |
551 | | block += 32; |
| 577 | block += BITS_PER_BLOCK; |
552 | 578 | } |
553 | 579 | } |
554 | 580 | |