Skip to content

Commit

Permalink
Maximus5gh-741, Maximus5gh-722: Glyphs widths evaluation and alignmen…
Browse files Browse the repository at this point in the history
…t were changed.

  So, symbols are expected to be painted properly, uncropped.
  Examples: U+276F (❯), U+2794 (➔), U+27F6 (⟶).
  • Loading branch information
Maximus5 committed Jul 6, 2016
1 parent 2aa888b commit 7e5b95d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/ConEmu/RConData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ UINT CRConData::GetConsoleData(wchar_t* rpChar, CharAttr* rpAttr, UINT anWidth,

if (bPair)
{
lca.Flags2 |= CharAttr2_Surrogate;
CharAttr& lca2 = pcaDst[nX+1];
lca2 = lca;
lca2.Flags2 = (lca.Flags2 & ~(CharAttr2_Combining)) | CharAttr2_NonSpacing;
Expand Down
77 changes: 32 additions & 45 deletions src/ConEmu/VConText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void VConTextPart::Init(uint anIndex, uint anCell, CVConLine* pLine)
{
Flags = TRF_None;
Length = 1; // initially, we'll enlarge it later
TotalWidth = MinWidth = 0;
TotalWidth = 0;
Index = anIndex;
Cell = anCell; // May differs from anIndex on DBCS systems
PositionX = CellPosX = Cell * pLine->FontWidth;
Expand All @@ -325,11 +325,10 @@ void VConTextPart::Init(uint anIndex, uint anCell, CVConLine* pLine)
CharWidth = pLine->TempCharWidth + anIndex;
}

void VConTextPart::Done(uint anLen, uint FontWidth)
void VConTextPart::SetLen(uint anLen, uint FontWidth)
{
_ASSERTE(anLen>0 && anLen<=0xFFFF && FontWidth>0 && FontWidth<=0xFFFF);
_ASSERTE(anLen>0 && anLen<=0xFFFF);
Length = anLen;
TotalWidth = MinWidth = 0;

// May this part be shrinked freely?
if (Flags & TRF_TextSpacing)
Expand All @@ -350,79 +349,58 @@ void VConTextPart::Done(uint anLen, uint FontWidth)
Flags |= TRF_SizeFree;
}

// Helper - double cell characters
uint FontWidth2 = 2*FontWidth;
uint FontWidth2M = FontWidth2 * DEF_DOUBLE_MUL / DEF_DOUBLE_DIV;
uint FontWidthM = FontWidth * DEF_SINGLE_MUL / DEF_SINGLE_DIV;

const wchar_t* pch = Chars;
const CharAttr* pca = Attrs;
TextCharType* pcf = CharFlags;
uint* pcw = CharWidth;

ZeroStruct(AllWidths);
// Preliminary character widths estimation

if (Flags & TRF_SizeFree)
{
// spaces, horizontal lines (frames), etc. They may be shrinked freely
VConTextPartWidth& aw = AllWidths[TCF_WidthFree];
for (uint left = anLen; left--; pch++, pca++, pcf++, pcw++)
for (uint left = anLen; left--; pca++, pcf++)
{
_ASSERTE(!(pca->Flags2 & (CharAttr2_NonSpacing|CharAttr2_Combining|CharAttr2_DoubleSpaced)));
*pcw = FontWidth; // if non-shrinked
*pcf = TCF_WidthFree;
aw.Count++;
aw.Width += FontWidth;
}
aw.MinWidth += FontWidth;
}
else
{
//WARNING: We rely here on pca->Flags2, but not on self evaluated data?
for (uint left = anLen; left--; pch++, pca++, pcf++, pcw++)
for (uint left = anLen; left--; pca++, pcf++, pcw++)
{
if (pca->Flags2 & (CharAttr2_NonSpacing|CharAttr2_Combining))
{
// zero-width
*pcw = 0;
*pcf = TCF_WidthZero;
VConTextPartWidth& aw = AllWidths[TCF_WidthZero];
aw.Count++; // Informational
}
else if (pca->Flags2 & CharAttr2_DoubleSpaced)
{
*pcw = FontWidth2;
*pcf = TCF_WidthDouble;
// Even double-width space have to be same width as ‘normal’ CJK glyph
VConTextPartWidth& aw = AllWidths[TCF_WidthDouble];
aw.Count++;
aw.Width += FontWidth2;
aw.MinWidth += FontWidth2M;
}
else /*if (gpSet->isMonospace
|| (gpSet->isFixFarBorders && isCharAltFont(ch))
|| (gpSet->isEnhanceGraphics && isCharProgress(ch))
)*/
else
{
//TODO: Caller must process fonts and set "real" character widths for proportinal fonts
*pcw = FontWidth;
*pcf = TCF_WidthNormal;
VConTextPartWidth& aw = AllWidths[TCF_WidthNormal];
aw.Count++;
aw.Width += FontWidth;
aw.MinWidth += FontWidthM;
}
}
}
}

void VConTextPart::Done()
{
_ASSERTE(Length>0 && Length<=0xFFFF);
TotalWidth = 0;

TotalWidth = AllWidths[TCF_WidthFree].Width
+ AllWidths[TCF_WidthNormal].Width
+ AllWidths[TCF_WidthDouble].Width
;
MinWidth = AllWidths[TCF_WidthFree].MinWidth
+ AllWidths[TCF_WidthNormal].MinWidth
+ AllWidths[TCF_WidthDouble].MinWidth
;
uint* pcw = CharWidth;
for (uint left = Length; left--; pcw++)
{
TotalWidth += *pcw; // if non-shrinked
}
}


Expand All @@ -446,7 +424,6 @@ CVConLine::CVConLine(CRealConsole* apRCon)
, TempCharFlags(NULL)
, TempCharWidth(NULL)
, TotalLineWidth(0)
, MinLineWidth(0)
, isFixFrameCoord(true)
, NextDialog(true)
, NextDialogX(0)
Expand Down Expand Up @@ -644,9 +621,12 @@ bool CVConLine::ParseLine(bool abForce, uint anTextWidth, uint anFontWidth, uint

/* *** We shall prepare this token (default/initial widths must be set) *** */
_ASSERTE(j2>j);
p->Done(j2-j, FontWidth);
p->SetLen(j2-j, FontWidth);

#if 0
TotalLineWidth += p->TotalWidth;
MinLineWidth += p->MinWidth;
#endif

/* Next part */
j = j2;
Expand Down Expand Up @@ -675,6 +655,15 @@ void CVConLine::PolishParts(DWORD* pnXCoords)
}
#endif

// VirtualConsole has set proper character widths, adopt them
TotalLineWidth = 0;
for (uint k = 0; k < PartsCount; k++)
{
VConTextPart& part = TextParts[k];
part.Done();
TotalLineWidth += part.TotalWidth;
}

uint PosX, CharIdx;
int prevFixedPart; // !SIGNED!

Expand Down Expand Up @@ -729,7 +718,7 @@ void CVConLine::PolishParts(DWORD* pnXCoords)

/* Fill all X coordinates */
PosX = CharIdx = 0;
TotalLineWidth = MinLineWidth = 0;
TotalLineWidth = 0;
for (uint k = 0; k < PartsCount; k++)
{
VConTextPart& part = TextParts[k];
Expand All @@ -748,7 +737,6 @@ void CVConLine::PolishParts(DWORD* pnXCoords)
part.PositionX = PosX;
}
TotalLineWidth += part.TotalWidth;
MinLineWidth += part.MinWidth;

uint charPosX = PosX;
uint* ptrWidth = part.CharWidth;
Expand Down Expand Up @@ -791,7 +779,6 @@ void CVConLine::PolishParts(DWORD* pnXCoords)
break;
part.Length += part2.Length;
part.TotalWidth += part2.TotalWidth;
part.MinWidth += part2.MinWidth;
// "Hide" this part from list
part2.Flags = TRF_None;
k = k2;
Expand Down
11 changes: 8 additions & 3 deletions src/ConEmu/VConText.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum TextCharType
class CVConLine;
class CRealConsole;

#if 0
// Used as array[TextCharType::TCF_WidthLast]
struct VConTextPartWidth
{
Expand All @@ -92,6 +93,7 @@ struct VConTextPartWidth
uint MinWidth; // Some parts (continuous spaces, horz frames) may be hard shrinked
uint ReqWidth; // For internal purposes
};
#endif

struct VConTextPart
{
Expand All @@ -107,14 +109,16 @@ struct VConTextPart
// Cell in the RealConsole. It may differs from Index on DBCS systems
uint Cell;
// Helper, to ensure our text parts fit in the terminal window
uint TotalWidth, MinWidth;
uint TotalWidth;
// Final position in VCon
uint PositionX;
// Preferred position calculated by Cell*FontWidth
uint CellPosX;

#if 0
// Chars distribution
VConTextPartWidth AllWidths[TCF_WidthLast];
#endif

// CharFlags is a pointer to buffer+idx from CVConLine
TextCharType* CharFlags;
Expand All @@ -126,7 +130,8 @@ struct VConTextPart


void Init(uint anIndex, uint anCell, CVConLine* pLine);
void Done(uint anLen, uint FontWidth);
void SetLen(uint anLen, uint FontWidth);
void Done();
};

class CVConLine
Expand Down Expand Up @@ -196,7 +201,7 @@ class CVConLine
uint* TempCharWidth/*[MaxBufferSize]*/;

// Just for information
uint TotalLineWidth, MinLineWidth;
uint TotalLineWidth;

// Pseudographics alignments
bool isFixFrameCoord;
Expand Down
15 changes: 7 additions & 8 deletions src/ConEmu/VirtualConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2963,20 +2963,19 @@ void CVirtualConsole::UpdateText()

// Calculate proper widths for proportional fonts
//TODO: Evaluate width for monospace fonts too! Linked fonts may be used for some char ranges!
if (bFontProportional)
//if (bFontProportional)
{
partIndex = 0;
while (lp.GetNextPart(partIndex, part, nextPart))
{
part->TotalWidth = 0;
for (uint i = 0; i < part->Length; i++)
TextCharType* pcf = part->CharFlags;
uint* pcw = part->CharWidth;
for (uint i = 0; i < part->Length; i++, pcf++, pcw++)
{
if (part->CharFlags[i] >= TCF_WidthFree)
if (*pcf >= TCF_WidthFree)
{
//TODO: Use ucs32 (surrogates) to evaluate width
WORD cw = CharWidth(part->Chars[i], part->Attrs[i]);
part->CharWidth[i] = cw;
part->TotalWidth += cw;
TODO("Use ucs32 (surrogates) to evaluate width");
*pcw = CharWidth(part->Chars[i], part->Attrs[i]);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/common/RgnDetect.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef struct tag_CharAttr
#define CharAttr2_Combining 2 // combining characters, drawn over previous one
#define CharAttr2_DoubleSpaced 4 // DBCS glyphs used full (double) space
#define CharAttr2_DialogCorner 8
#define CharAttr2_Surrogate 16 // high-surrogate pair
unsigned int Flags2 : 8; // вспомогательные флаги CharAttr_XXX
unsigned int nForeIdx : 8; // Only 5 bits are used at the moment (0..15 base colors + 15..31 extended colors)
unsigned int nBackIdx : 8; // Used to ExtendColors and ExtendFonts
Expand Down
3 changes: 1 addition & 2 deletions src/common/wcwidth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,6 @@ bool is_char_cjk(ucs32 ucs)
return (ucs >= 0x1100
&& ((ucs <= 0x115f) || /* Hangul Jamo init. consonants */
(ucs == 0x2329 || ucs == 0x232a) || /* Angular brackets */
//BUG: Remove this, need to reuse is_char_ambiguous!
(ucs >= 0x2700 && ucs <= 0x27BF) || /* Dingbats (gh-722) */
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
Expand Down Expand Up @@ -287,6 +285,7 @@ bool is_char_ambiguous(ucs32 ucs)
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
};
//TODO: Add (0x2700 ... 0x27BF) Dingbats (gh-722)?

/* binary search in table of non-spacing characters */
return bisearch(ucs, ambiguous, countof(ambiguous));
Expand Down

0 comments on commit 7e5b95d

Please sign in to comment.