Lines 86-93
Link Here
|
86 |
FILE * grLog() |
86 |
FILE * grLog() |
87 |
{ |
87 |
{ |
88 |
#ifdef WNT |
88 |
#ifdef WNT |
89 |
std::string logFileName(getenv("TEMP")); |
89 |
std::string logFileName(getenv("TEMP")); |
90 |
logFileName.append("\\graphitelayout.log"); |
90 |
logFileName.append("\\graphitelayout.log"); |
91 |
if (grLogFile == NULL) grLogFile = fopen(logFileName.c_str(),"w"); |
91 |
if (grLogFile == NULL) grLogFile = fopen(logFileName.c_str(),"w"); |
92 |
else fflush(grLogFile); |
92 |
else fflush(grLogFile); |
93 |
return grLogFile; |
93 |
return grLogFile; |
Lines 293-303
Link Here
|
293 |
} |
293 |
} |
294 |
long nXOffset = round(fMinX * fScaling); |
294 |
long nXOffset = round(fMinX * fScaling); |
295 |
rWidth = round(fMaxX * fScaling) - nXOffset + nDxOffset; |
295 |
rWidth = round(fMaxX * fScaling) - nXOffset + nDxOffset; |
296 |
if (rWidth < 0) |
296 |
if (rWidth < 0) |
297 |
{ |
297 |
{ |
298 |
// This can happen when there was no base inside the range |
298 |
// This can happen when there was no base inside the range |
299 |
rWidth = 0; |
299 |
rWidth = 0; |
300 |
} |
300 |
} |
301 |
// fill up non-base char dx with cluster widths from previous base glyph |
301 |
// fill up non-base char dx with cluster widths from previous base glyph |
302 |
if (bRtl) |
302 |
if (bRtl) |
303 |
{ |
303 |
{ |
Lines 353-358
Link Here
|
353 |
assert(size() < rGlyph2Char.size()); |
353 |
assert(size() < rGlyph2Char.size()); |
354 |
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] = size(); |
354 |
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] = size(); |
355 |
rGlyph2Char[size()] = nFirstCharInCluster; |
355 |
rGlyph2Char[size()] = nFirstCharInCluster; |
|
|
356 |
|
357 |
// can we break before this cluster? |
358 |
// Glyphs may have eitehr a positive or negative breakWeight refering to |
359 |
// the position after or before the glyph respectively |
360 |
int nPrevBreakWeight = 0; |
361 |
if (nFirstGlyphInCluster > 0) |
362 |
{ |
363 |
nPrevBreakWeight = (iGlyphs.first + (nFirstGlyphInCluster - 1))->breakweight(); |
364 |
} |
365 |
int nBreakWeight = aFirstGlyph.breakweight(); |
366 |
if (nBreakWeight < 0) |
367 |
{ |
368 |
// negative means it applies to the position before the glyph's character |
369 |
nBreakWeight *= -1; |
370 |
if (nPrevBreakWeight > 0 && nPrevBreakWeight < nBreakWeight) |
371 |
{ |
372 |
// prevBreakWeight wins |
373 |
nBreakWeight = nPrevBreakWeight; |
374 |
} |
375 |
} |
376 |
else |
377 |
{ |
378 |
nBreakWeight = 0; |
379 |
// positive means break after |
380 |
if (nPrevBreakWeight > 0) |
381 |
nBreakWeight = nPrevBreakWeight; |
382 |
} |
383 |
if (nBreakWeight > gr::klbNoBreak/*0*/ && |
384 |
// nBreakWeight <= gr::klbHyphenBreak) // uses Graphite hyphenation |
385 |
nBreakWeight <= gr::klbLetterBreak) // Needed for issue 111272 |
386 |
{ |
387 |
if (nBreakWeight < gr::klbHyphenBreak) |
388 |
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= WORD_BREAK_BEFORE; |
389 |
else |
390 |
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= HYPHEN_BREAK_BEFORE; |
391 |
} |
392 |
// always allow a break before a space even if graphite doesn't |
393 |
if (rArgs.mpStr[nFirstCharInCluster] == 0x20) |
394 |
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= WORD_BREAK_BEFORE; |
395 |
|
356 |
bool bBaseGlyph = true; |
396 |
bool bBaseGlyph = true; |
357 |
for (int j = nFirstGlyphInCluster; |
397 |
for (int j = nFirstGlyphInCluster; |
358 |
j != nNextGlyph; j += nDelta) |
398 |
j != nNextGlyph; j += nDelta) |
Lines 409-415
Link Here
|
409 |
} |
449 |
} |
410 |
} |
450 |
} |
411 |
#ifdef GRLAYOUT_DEBUG |
451 |
#ifdef GRLAYOUT_DEBUG |
412 |
fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset()); |
452 |
fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f bw%d\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset(), nBreakWeight); |
413 |
#endif |
453 |
#endif |
414 |
return aBounds; |
454 |
return aBounds; |
415 |
} |
455 |
} |
Lines 641-646
Link Here
|
641 |
if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl)) |
681 |
if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl)) |
642 |
maLayout.setRightToLeft(bRtl); |
682 |
maLayout.setRightToLeft(bRtl); |
643 |
|
683 |
|
|
|
684 |
// Context is often needed beyond the specified end, however, we don't |
685 |
// want it if there has been a direction change, since it is hard |
686 |
// to tell between reordering within one direction and multi-directional |
687 |
// text. Extra context, can also cause problems with ligatures stradling |
688 |
// a hyphenation point, so disable if CTL is disabled. |
689 |
const int nSegCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH); |
690 |
int limit = rArgs.mnEndCharPos; |
691 |
if ((nSegCharLimit > limit) && !(SAL_LAYOUT_COMPLEX_DISABLED & rArgs.mnFlags)) |
692 |
{ |
693 |
limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos, |
694 |
nSegCharLimit - rArgs.mnEndCharPos, bRtl); |
695 |
} |
696 |
|
644 |
#ifdef GRCACHE |
697 |
#ifdef GRCACHE |
645 |
GrFontHasher hasher(mrFont); |
698 |
GrFontHasher hasher(mrFont); |
646 |
sal_Int32 aFontHash = hasher.hashCode(mpFeatures); |
699 |
sal_Int32 aFontHash = hasher.hashCode(mpFeatures); |
Lines 648-654
Link Here
|
648 |
(GraphiteCacheHandler::instance).getCache(aFontHash); |
701 |
(GraphiteCacheHandler::instance).getCache(aFontHash); |
649 |
if (pCache) |
702 |
if (pCache) |
650 |
{ |
703 |
{ |
651 |
*pSegRecord = pCache->getSegment(rArgs, bRtl); |
704 |
*pSegRecord = pCache->getSegment(rArgs, bRtl, nSegCharLimit); |
652 |
if (*pSegRecord) |
705 |
if (*pSegRecord) |
653 |
{ |
706 |
{ |
654 |
pSegment = (*pSegRecord)->getSegment(); |
707 |
pSegment = (*pSegRecord)->getSegment(); |
Lines 667-684
Link Here
|
667 |
} |
720 |
} |
668 |
#endif |
721 |
#endif |
669 |
|
722 |
|
670 |
// Context is often needed beyond the specified end, however, we don't |
|
|
671 |
// want it if there has been a direction change, since it is hard |
672 |
// to tell between reordering within one direction and multi-directional |
673 |
// text. |
674 |
const int segCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH); |
675 |
int limit = rArgs.mnEndCharPos; |
676 |
if (segCharLimit > limit) |
677 |
{ |
678 |
limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos, |
679 |
segCharLimit - rArgs.mnEndCharPos, bRtl); |
680 |
} |
681 |
|
682 |
// Create a new TextSource object for the engine. |
723 |
// Create a new TextSource object for the engine. |
683 |
mpTextSrc = new TextSourceAdaptor(rArgs, limit); |
724 |
mpTextSrc = new TextSourceAdaptor(rArgs, limit); |
684 |
if (mpFeatures) mpTextSrc->setFeatures(mpFeatures); |
725 |
if (mpFeatures) mpTextSrc->setFeatures(mpFeatures); |
Lines 744-752
Link Here
|
744 |
// rightToLeft() may no longer be valid if the engine has been run |
785 |
// rightToLeft() may no longer be valid if the engine has been run |
745 |
// ltr since the segment was created. |
786 |
// ltr since the segment was created. |
746 |
#ifdef GRCACHE |
787 |
#ifdef GRCACHE |
747 |
bool bRtl = pSegRecord? pSegRecord->isRtl() : pSegment->rightToLeft(); |
788 |
bool bRtl = pSegRecord? pSegRecord->isRtl() : pSegment->rightToLeft(); |
748 |
#else |
789 |
#else |
749 |
bool bRtl = pSegment->rightToLeft(); |
790 |
bool bRtl = pSegment->rightToLeft(); |
750 |
#endif |
791 |
#endif |
751 |
mvGlyphs.fill_from(*pSegment, rArgs, bRtl, |
792 |
mvGlyphs.fill_from(*pSegment, rArgs, bRtl, |
752 |
mnWidth, mfScaling, mvChar2BaseGlyph, mvGlyph2Char, mvCharDxs); |
793 |
mnWidth, mfScaling, mvChar2BaseGlyph, mvGlyph2Char, mvCharDxs); |
Lines 785-791
Link Here
|
785 |
#endif |
826 |
#endif |
786 |
return false; |
827 |
return false; |
787 |
} |
828 |
} |
788 |
} |
829 |
} |
789 |
else |
830 |
else |
790 |
{ |
831 |
{ |
791 |
mnWidth = 0; |
832 |
mnWidth = 0; |
Lines 795-821
Link Here
|
795 |
|
836 |
|
796 |
int GraphiteLayout::GetTextBreak(long maxmnWidth, long char_extra, int factor) const |
837 |
int GraphiteLayout::GetTextBreak(long maxmnWidth, long char_extra, int factor) const |
797 |
{ |
838 |
{ |
798 |
// Adjust maxmnWidth so FindNextBreakPoint returns a sensible answer. |
839 |
#ifdef GRLAYOUT_DEBUG |
799 |
maxmnWidth -= (mnEndCharPos-mnMinCharPos-1)*char_extra; // extra character spacing. |
840 |
fprintf(grLog(),"Gr::GetTextBreak c[%d-%d) maxWidth %ld char extra %ld factor %d\n", |
800 |
maxmnWidth /= factor; // scaling factor. |
841 |
mnMinCharPos, mnEndCharPos, maxmnWidth, char_extra, factor); |
|
|
842 |
#endif |
801 |
|
843 |
|
802 |
// Ask the segment for the nearest whole letter break for the width. |
|
|
803 |
//float width; |
804 |
float targetWidth = maxmnWidth/mfScaling; |
805 |
// return quickly if this segment is narrower than the target width |
844 |
// return quickly if this segment is narrower than the target width |
806 |
// (sometimes graphite doesn't seem to realise this!) |
845 |
if (maxmnWidth > mnWidth * factor + char_extra * (mnEndCharPos - mnMinCharPos - 1)) |
807 |
if (targetWidth > mnWidth) |
|
|
808 |
return STRING_LEN; |
846 |
return STRING_LEN; |
809 |
//int nBreak = mpSegment->findNextBreakPoint(mnMinCharPos, |
|
|
810 |
// gr::klbWordBreak, gr::klbLetterBreak, targetWidth, &width); |
811 |
|
847 |
|
812 |
// LineFillSegment seems to give better results that findNextBreakPoint |
848 |
long nWidth = mvCharDxs[0] * factor; |
813 |
// though it may be slower |
849 |
int nLastBreak = -1; |
814 |
gr::LayoutEnvironment aLE; |
850 |
for (size_t i = 1; i < mvCharDxs.size(); i++) |
815 |
gr::LineFillSegment lineSeg(const_cast<gr::Font *>(&mrFont), mpTextSrc, &aLE, |
851 |
{ |
816 |
mnMinCharPos, mpTextSrc->getContextLength(), |
852 |
nWidth += char_extra; |
817 |
targetWidth); |
853 |
if (nWidth > maxmnWidth) break; |
818 |
int nBreak = lineSeg.stopCharacter(); |
854 |
if (mvChar2BaseGlyph[i] != -1) |
|
|
855 |
{ |
856 |
if (mvChar2BaseGlyph[i] & (WORD_BREAK_BEFORE | HYPHEN_BREAK_BEFORE)) |
857 |
nLastBreak = static_cast<int>(i); |
858 |
} |
859 |
nWidth += (mvCharDxs[i] - mvCharDxs[i-1]) * factor; |
860 |
} |
861 |
int nBreak = mnMinCharPos; |
862 |
if (nLastBreak > -1) |
863 |
nBreak += nLastBreak; |
864 |
|
865 |
#ifdef GRLAYOUT_DEBUG |
866 |
fprintf(grLog(), "Gr::GetTextBreak break after %d\n", nBreak - mnMinCharPos); |
867 |
#endif |
819 |
|
868 |
|
820 |
if (nBreak > mnEndCharPos) nBreak = STRING_LEN; |
869 |
if (nBreak > mnEndCharPos) nBreak = STRING_LEN; |
821 |
else if (nBreak < mnMinCharPos) nBreak = mnMinCharPos; |
870 |
else if (nBreak < mnMinCharPos) nBreak = mnMinCharPos; |
Lines 833-841
Link Here
|
833 |
{ |
882 |
{ |
834 |
for (size_t i = 0; i < mvCharDxs.size(); i++) |
883 |
for (size_t i = 0; i < mvCharDxs.size(); i++) |
835 |
{ |
884 |
{ |
836 |
assert((mvChar2BaseGlyph[i] >= -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size())); |
885 |
assert((mvChar2BaseGlyph[i] >= -1) && |
|
|
886 |
((mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK) < (signed)mvGlyphs.size())); |
837 |
if (mvChar2BaseGlyph[i] != -1 && |
887 |
if (mvChar2BaseGlyph[i] != -1 && |
838 |
mvGlyphs[mvChar2BaseGlyph[i]].mnGlyphIndex == GF_DROPPED) |
888 |
mvGlyphs[mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK].mnGlyphIndex == GF_DROPPED) |
839 |
{ |
889 |
{ |
840 |
// when used in MultiSalLayout::GetTextBreak dropped glyphs |
890 |
// when used in MultiSalLayout::GetTextBreak dropped glyphs |
841 |
// must have zero width |
891 |
// must have zero width |
Lines 865-871
Link Here
|
865 |
void GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs) |
915 |
void GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs) |
866 |
{ |
916 |
{ |
867 |
SalLayout::AdjustLayout(rArgs); |
917 |
SalLayout::AdjustLayout(rArgs); |
868 |
|
|
|
869 |
if(rArgs.mpDXArray) |
918 |
if(rArgs.mpDXArray) |
870 |
{ |
919 |
{ |
871 |
std::vector<int> vDeltaWidths(mvGlyphs.size(), 0); |
920 |
std::vector<int> vDeltaWidths(mvGlyphs.size(), 0); |
Lines 894-901
Link Here
|
894 |
} |
943 |
} |
895 |
} |
944 |
} |
896 |
} |
945 |
} |
|
|
946 |
else if (rArgs.mnLayoutWidth > 0) |
947 |
{ |
948 |
#ifdef GRLAYOUT_DEBUG |
949 |
fprintf(grLog(), "AdjustLayout width %ld=>%ld\n", mnWidth, rArgs.mnLayoutWidth); |
950 |
#endif |
951 |
expandOrCondense(rArgs); |
952 |
} |
897 |
} |
953 |
} |
898 |
|
954 |
|
|
|
955 |
void GraphiteLayout::expandOrCondense(ImplLayoutArgs &rArgs) |
956 |
{ |
957 |
int nDeltaWidth = rArgs.mnLayoutWidth - mnWidth; |
958 |
if (nDeltaWidth > 0) // expand, just expand between clusters |
959 |
{ |
960 |
int nClusterCount = 0; |
961 |
for (size_t j = 0; j < mvGlyphs.size(); j++) |
962 |
{ |
963 |
if (mvGlyphs[j].IsClusterStart()) |
964 |
{ |
965 |
++nClusterCount; |
966 |
} |
967 |
} |
968 |
if (nClusterCount > 1) |
969 |
{ |
970 |
float fExtraPerCluster = static_cast<float>(nDeltaWidth) / static_cast<float>(nClusterCount - 1); |
971 |
int nCluster = 0; |
972 |
int nOffset = 0; |
973 |
for (size_t i = 0; i < mvGlyphs.size(); i++) |
974 |
{ |
975 |
if (mvGlyphs[i].IsClusterStart()) |
976 |
{ |
977 |
nOffset = fExtraPerCluster * nCluster; |
978 |
size_t nCharIndex = mvGlyph2Char[i]; |
979 |
mvCharDxs[nCharIndex] += nOffset; |
980 |
// adjust char dxs for rest of characters in cluster |
981 |
while (++nCharIndex < mvGlyph2Char.size()) |
982 |
{ |
983 |
int nChar2Base = (mvChar2BaseGlyph[nCharIndex] == -1)? -1 : mvChar2BaseGlyph[nCharIndex] & GLYPH_INDEX_MASK; |
984 |
if (nChar2Base == -1 || nChar2Base == static_cast<int>(i)) |
985 |
mvCharDxs[nCharIndex] += nOffset; |
986 |
} |
987 |
++nCluster; |
988 |
} |
989 |
mvGlyphs[i].maLinearPos.X() += nOffset; |
990 |
} |
991 |
} |
992 |
} |
993 |
else // condense - apply a factor to all glyph positions |
994 |
{ |
995 |
if (mvGlyphs.size() == 0) return; |
996 |
Glyphs::iterator iLastGlyph = mvGlyphs.begin() + (mvGlyphs.size() - 1); |
997 |
// position last glyph using original width |
998 |
float fXFactor = static_cast<float>(rArgs.mnLayoutWidth - iLastGlyph->mnOrigWidth) / static_cast<float>(iLastGlyph->maLinearPos.X()); |
999 |
#ifdef GRLAYOUT_DEBUG |
1000 |
fprintf(grLog(), "Condense by factor %f\n", fXFactor); |
1001 |
#endif |
1002 |
iLastGlyph->maLinearPos.X() = rArgs.mnLayoutWidth - iLastGlyph->mnOrigWidth; |
1003 |
Glyphs::iterator iGlyph = mvGlyphs.begin(); |
1004 |
while (iGlyph != iLastGlyph) |
1005 |
{ |
1006 |
iGlyph->maLinearPos.X() = static_cast<float>(iGlyph->maLinearPos.X()) * fXFactor; |
1007 |
++iGlyph; |
1008 |
} |
1009 |
for (size_t i = 0; i < mvCharDxs.size(); i++) |
1010 |
{ |
1011 |
mvCharDxs[i] = fXFactor * static_cast<float>(mvCharDxs[i]); |
1012 |
} |
1013 |
} |
1014 |
} |
899 |
|
1015 |
|
900 |
void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDeltaWidth) |
1016 |
void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDeltaWidth) |
901 |
{ |
1017 |
{ |
Lines 917-953
Link Here
|
917 |
int nPrevClusterLastChar = -1; |
1033 |
int nPrevClusterLastChar = -1; |
918 |
for (size_t i = 0; i < nChars; i++) |
1034 |
for (size_t i = 0; i < nChars; i++) |
919 |
{ |
1035 |
{ |
920 |
if (mvChar2BaseGlyph[i] > -1 && mvChar2BaseGlyph[i] != nPrevClusterGlyph) |
1036 |
int nChar2Base = (mvChar2BaseGlyph[i] == -1)? -1 : mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK; |
|
|
1037 |
if ((nChar2Base > -1) && (nChar2Base != nPrevClusterGlyph)) |
921 |
{ |
1038 |
{ |
922 |
assert((mvChar2BaseGlyph[i] > -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size())); |
1039 |
assert((nChar2Base > -1) && (nChar2Base < (signed)mvGlyphs.size())); |
923 |
GlyphItem & gi = mvGlyphs[mvChar2BaseGlyph[i]]; |
1040 |
GlyphItem & gi = mvGlyphs[nChar2Base]; |
924 |
if (!gi.IsClusterStart()) |
1041 |
if (!gi.IsClusterStart()) |
925 |
continue; |
1042 |
continue; |
926 |
|
1043 |
|
927 |
// find last glyph of this cluster |
1044 |
// find last glyph of this cluster |
928 |
size_t j = i + 1; |
1045 |
size_t j = i + 1; |
929 |
int nLastChar = i; |
1046 |
int nLastChar = i; |
930 |
int nLastGlyph = mvChar2BaseGlyph[i]; |
1047 |
int nLastGlyph = nChar2Base; |
931 |
for (; j < nChars; j++) |
1048 |
for (; j < nChars; j++) |
932 |
{ |
1049 |
{ |
933 |
assert((mvChar2BaseGlyph[j] >= -1) && (mvChar2BaseGlyph[j] < (signed)mvGlyphs.size())); |
1050 |
int nChar2BaseJ = (mvChar2BaseGlyph[j] == -1)? -1 : mvChar2BaseGlyph[j] & GLYPH_INDEX_MASK; |
934 |
if (mvChar2BaseGlyph[j] != -1 && mvGlyphs[mvChar2BaseGlyph[j]].IsClusterStart()) |
1051 |
assert((nChar2BaseJ >= -1) && (nChar2BaseJ < (signed)mvGlyphs.size())); |
|
|
1052 |
if (nChar2BaseJ != -1 && mvGlyphs[nChar2BaseJ].IsClusterStart()) |
935 |
{ |
1053 |
{ |
936 |
nLastGlyph = mvChar2BaseGlyph[j] + ((bRtl)? 1 : -1); |
1054 |
nLastGlyph = nChar2BaseJ + ((bRtl)? 1 : -1); |
937 |
nLastChar = j - 1; |
1055 |
nLastChar = j - 1; |
938 |
break; |
1056 |
break; |
939 |
} |
1057 |
} |
940 |
} |
1058 |
} |
941 |
if (nLastGlyph < 0) |
1059 |
if (nLastGlyph < 0) |
942 |
{ |
1060 |
{ |
943 |
nLastGlyph = mvChar2BaseGlyph[i]; |
1061 |
nLastGlyph = nChar2Base; |
944 |
} |
1062 |
} |
945 |
// Its harder to find the last glyph rtl, since the first of |
1063 |
// Its harder to find the last glyph rtl, since the first of |
946 |
// cluster is still on the left so we need to search towards |
1064 |
// cluster is still on the left so we need to search towards |
947 |
// the previous cluster to the right |
1065 |
// the previous cluster to the right |
948 |
if (bRtl) |
1066 |
if (bRtl) |
949 |
{ |
1067 |
{ |
950 |
nLastGlyph = mvChar2BaseGlyph[i]; |
1068 |
nLastGlyph = nChar2Base; |
951 |
while (nLastGlyph + 1 < (signed)mvGlyphs.size() && |
1069 |
while (nLastGlyph + 1 < (signed)mvGlyphs.size() && |
952 |
!mvGlyphs[nLastGlyph+1].IsClusterStart()) |
1070 |
!mvGlyphs[nLastGlyph+1].IsClusterStart()) |
953 |
{ |
1071 |
{ |
Lines 983-989
Link Here
|
983 |
// update glyph positions |
1101 |
// update glyph positions |
984 |
if (bRtl) |
1102 |
if (bRtl) |
985 |
{ |
1103 |
{ |
986 |
for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++) |
1104 |
for (int n = nChar2Base; n <= nLastGlyph; n++) |
987 |
{ |
1105 |
{ |
988 |
assert((n > - 1) && (n < (signed)mvGlyphs.size())); |
1106 |
assert((n > - 1) && (n < (signed)mvGlyphs.size())); |
989 |
mvGlyphs[n].maLinearPos.X() += -nDGlyphOrigin + nXOffset; |
1107 |
mvGlyphs[n].maLinearPos.X() += -nDGlyphOrigin + nXOffset; |
Lines 991-1007
Link Here
|
991 |
} |
1109 |
} |
992 |
else |
1110 |
else |
993 |
{ |
1111 |
{ |
994 |
for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++) |
1112 |
for (int n = nChar2Base; n <= nLastGlyph; n++) |
995 |
{ |
1113 |
{ |
996 |
assert((n > - 1) && (n < (signed)mvGlyphs.size())); |
1114 |
assert((n > - 1) && (n < (signed)mvGlyphs.size())); |
997 |
mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + nXOffset; |
1115 |
mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + nXOffset; |
998 |
} |
1116 |
} |
999 |
} |
1117 |
} |
1000 |
rDeltaWidth[mvChar2BaseGlyph[i]] = nDWidth; |
1118 |
rDeltaWidth[nChar2Base] = nDWidth; |
1001 |
#ifdef GRLAYOUT_DEBUG |
1119 |
#ifdef GRLAYOUT_DEBUG |
1002 |
fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, mvChar2BaseGlyph[i], nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[mvChar2BaseGlyph[i]].maLinearPos.X()); |
1120 |
fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, nChar2Base, nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[nChar2Base].maLinearPos.X()); |
1003 |
#endif |
1121 |
#endif |
1004 |
nPrevClusterGlyph = mvChar2BaseGlyph[i]; |
1122 |
nPrevClusterGlyph = nChar2Base; |
1005 |
nPrevClusterLastChar = nLastChar; |
1123 |
nPrevClusterLastChar = nLastChar; |
1006 |
i = nLastChar; |
1124 |
i = nLastChar; |
1007 |
} |
1125 |
} |
Lines 1043-1049
Link Here
|
1043 |
continue; |
1161 |
continue; |
1044 |
} |
1162 |
} |
1045 |
// calculate gap, ignore if too small |
1163 |
// calculate gap, ignore if too small |
1046 |
int nGapWidth = rDeltaWidths[nOrigGlyphIndex];; |
1164 |
int nGapWidth = rDeltaWidths[nOrigGlyphIndex]; |
1047 |
// worst case is one kashida even for mini-gaps |
1165 |
// worst case is one kashida even for mini-gaps |
1048 |
if( 3 * nGapWidth < nKashidaWidth ) |
1166 |
if( 3 * nGapWidth < nKashidaWidth ) |
1049 |
{ |
1167 |
{ |
Lines 1104-1116
Link Here
|
1104 |
{ |
1222 |
{ |
1105 |
if (mvChar2BaseGlyph[nCharSlot] != -1) |
1223 |
if (mvChar2BaseGlyph[nCharSlot] != -1) |
1106 |
{ |
1224 |
{ |
1107 |
assert((mvChar2BaseGlyph[nCharSlot] > -1) && (mvChar2BaseGlyph[nCharSlot] < (signed)mvGlyphs.size())); |
1225 |
int nChar2Base = mvChar2BaseGlyph[nCharSlot] & GLYPH_INDEX_MASK; |
1108 |
GlyphItem gi = mvGlyphs[mvChar2BaseGlyph[nCharSlot]]; |
1226 |
assert((mvChar2BaseGlyph[nCharSlot] > -1) && (nChar2Base < (signed)mvGlyphs.size())); |
|
|
1227 |
GlyphItem gi = mvGlyphs[nChar2Base]; |
1109 |
if (gi.mnGlyphIndex == GF_DROPPED) |
1228 |
if (gi.mnGlyphIndex == GF_DROPPED) |
1110 |
{ |
1229 |
{ |
1111 |
continue; |
1230 |
continue; |
1112 |
} |
1231 |
} |
1113 |
int nCluster = mvChar2BaseGlyph[nCharSlot]; |
1232 |
int nCluster = nChar2Base; |
1114 |
long origClusterWidth = gi.mnNewWidth; |
1233 |
long origClusterWidth = gi.mnNewWidth; |
1115 |
long nMin = gi.maLinearPos.X(); |
1234 |
long nMin = gi.maLinearPos.X(); |
1116 |
long nMax = gi.maLinearPos.X() + gi.mnNewWidth; |
1235 |
long nMax = gi.maLinearPos.X() + gi.mnNewWidth; |
Lines 1135-1141
Link Here
|
1135 |
pCaretXArray[i] = nMin; |
1254 |
pCaretXArray[i] = nMin; |
1136 |
pCaretXArray[i+1] = nMax; |
1255 |
pCaretXArray[i+1] = nMax; |
1137 |
} |
1256 |
} |
1138 |
prevBase = mvChar2BaseGlyph[nCharSlot]; |
1257 |
prevBase = nChar2Base; |
1139 |
prevClusterWidth = origClusterWidth; |
1258 |
prevClusterWidth = origClusterWidth; |
1140 |
} |
1259 |
} |
1141 |
else if (prevBase > -1) |
1260 |
else if (prevBase > -1) |
Lines 1268-1274
Link Here
|
1268 |
|
1387 |
|
1269 |
#ifdef GRLAYOUT_DEBUG |
1388 |
#ifdef GRLAYOUT_DEBUG |
1270 |
fprintf(grLog(),"GetNextGlyphs g%d c%d x%ld,%ld adv%ld, pos %ld,%ld\n", glyph_slot - 1, |
1389 |
fprintf(grLog(),"GetNextGlyphs g%d c%d x%ld,%ld adv%ld, pos %ld,%ld\n", glyph_slot - 1, |
1271 |
mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance, |
1390 |
GLYPH_INDEX_MASK&mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance, |
1272 |
aPosOut.X(), aPosOut.Y()); |
1391 |
aPosOut.X(), aPosOut.Y()); |
1273 |
#endif |
1392 |
#endif |
1274 |
|
1393 |
|