📄 usplib.c
字号:
uspData->widthList = realloc(uspData->widthList, uspData->glyphAllocLen * sizeof(int));
uspData->svaList = realloc(uspData->svaList, uspData->glyphAllocLen * sizeof(SCRIPT_VISATTR));
}
//
// Convert the unicode-text into an array of glyphs
//
hr = ScriptShape(
hdc,
&uspFont->scriptCache,
wrunstr,
itemRun->len,
uspData->glyphAllocLen - uspData->glyphCount,
&itemRun->analysis,
uspData->glyphList + itemRun->glyphPos,
uspData->clusterList + itemRun->charPos, // already allocated in UspAnalyze
uspData->svaList + itemRun->glyphPos,
&itemRun->glyphCount
);
// no glyphs in the font - try again
if(hr == USP_E_SCRIPT_NOT_IN_FONT)
{
itemRun->analysis.eScript = SCRIPT_UNDEFINED;
}
// unknown failure
else if(hr != S_OK && hr != E_OUTOFMEMORY)
{
SelectObject(hdc, holdFont);
return FALSE;
}
} while(hr != S_OK);
// expand the glyph-list to include this item-run
uspData->glyphCount += itemRun->glyphCount;
//
// Generate glyph advance-widths for this run
//
ScriptPlace(
hdc,
&uspFont->scriptCache,
uspData->glyphList + itemRun->glyphPos,
itemRun->glyphCount,
uspData->svaList + itemRun->glyphPos,
&itemRun->analysis,
uspData->widthList + itemRun->glyphPos,
uspData->offsetList + itemRun->glyphPos,
&abc
);
//
// Control-characters require special handling
//
if(itemRun->ctrl && itemRun->chcode != '\t')
{
// chcode is only valid for control-characters
int chwidth = CtrlCharWidth(uspFont, hdc, itemRun->chcode);
uspData->widthList[itemRun->glyphPos] = chwidth;
itemRun->width = chwidth;
}
else
{
// remember the item-run width
itemRun->width = abc.abcA + abc.abcB + abc.abcC;
}
// restore the font
SelectObject(hdc, holdFont);
return TRUE;
}
//
// Remember the selection-state of an ITEM_RUN:
//
// 0 - no characters selected
// 1 - all characters selected
// 2 - some characters selected
//
// This is a useful optimization used for drawing - under some
// circumstances, an ITEM_RUN can be skipped if it's neighbouring
// runs share the same selection-state
//
static
void IdentifyRunSelections(USPDATA *uspData, ITEM_RUN *itemRun)
{
int c;
int numsel = 0;
// analyze run to see which characters are selected
for(c = itemRun->charPos; c < itemRun->charPos + itemRun->len; c++)
if(uspData->attrList[c].sel)
numsel++;
// set the selection state accordingly
if(numsel == 0) itemRun->selstate = 0;
else if(numsel == itemRun->len) itemRun->selstate = 1;
else itemRun->selstate = 2;
}
//
// Update the USPDATA with a new attribute-run-list.
//
// The font-information stored in ATTR::font is ignored, as are
// the ::ctrl and ::eol flags
//
VOID WINAPI UspApplyAttributes(USPDATA *uspData, ATTR *attrRunList)
{
int i, a, c=0;
//
// 'Flatten' the user-supplied attribute-run-list to an array
// of single ATTR structures, each 1-unit long.
//
for(a = 0, i = 0; i < uspData->stringLen; i++)
{
uspData->attrList[i] = attrRunList[a];
uspData->attrList[i].len = 1;
if(++c == attrRunList[a].len)
{
a++;
c = 0;
}
}
// Identify the selection state of each run (none,all,partial)
for(i = 0; i < uspData->itemRunCount; i++)
{
IdentifyRunSelections(uspData, &uspData->itemRunList[i]);
}
}
//
// Update USPDATA with new selection information - only modify
// the ATTR::sel values within our internal attribute-list
// (i.e. leave all other text styles untouched)
//
VOID WINAPI UspApplySelection(USPDATA *uspData, int selStart, int selEnd)
{
int i,p;
if(selStart >= selEnd)
{
int t = selStart;
selStart = selEnd;
selEnd = t;
}
for(i = 0; i < uspData->itemRunCount; i++)
{
ITEM_RUN *itemRun = &uspData->itemRunList[i];
for(p = itemRun->charPos; p < itemRun->charPos + itemRun->len; p++)
uspData->attrList[p].sel = (p >= selStart && p < selEnd);
IdentifyRunSelections(uspData, itemRun);
}
}
//
// Initialize the USPDATA line-state with a new text-string,
// and an optional attribute-run-list. We reuse any previously
// allocated arrays in the USPDATA structure, minimizing heap-access
//
// *attrRunList can be NULL, in which case the line of text is initialized
// with the default Windows text-colours and with font#0.
// Otherwise, attrRunList is expected to describe a range of text the
// same length as the text-input buffer.
//
// *uspFontList can also be NULL, in which case the currently selected font
// is used to shape the text. This same font *must* be reselected into
// the device context when UspTextOut is called.
//
// Any change to the fonts in uspFontList requires UspAnalyze to be called again.
//
BOOL WINAPI UspAnalyze (
USPDATA * uspData,
HDC hdc,
WCHAR * wstr,
int wlen,
ATTR * attrRunList,
UINT flags,
USPFONT * uspFontList,
SCRIPT_CONTROL * scriptControl,
SCRIPT_STATE * scriptState,
SCRIPT_TABDEF * scriptTabdef
)
{
ATTR defAttr;
int itemRunAllocLen;
int i;
if(uspData == 0)
return FALSE;
// reset the lists
uspData->itemRunCount = 0;
uspData->glyphCount = 0;
uspData->uspFontList = uspFontList;
uspData->stringLen = wlen;
// nothing to do?
if(wstr == 0 || wlen == 0)
return TRUE;
// remember current allocation-size of itemRunList
itemRunAllocLen = uspData->itemRunAllocLen;
// use the default font if no user-supplied list
if(uspFontList == 0)
{
uspData->defaultFont.hFont = 0;
uspData->uspFontList = &uspData->defaultFont;
}
//
// if no attributes specified then default to a single span
// covering the entire length of the text
//
if(attrRunList == 0)
{
// create the default attribute
defAttr.fg = GetSysColor(COLOR_WINDOWTEXT);
defAttr.bg = GetSysColor(COLOR_WINDOW);
defAttr.font = 0;
defAttr.sel = 0;
defAttr.ctrl = 0;
defAttr.eol = 0;
defAttr.len = wlen;
attrRunList = &defAttr;
}
//
// Build a list of runs by calling ScriptItemize and merging
// those spans with the attribute-list. When BuildMergedItemRunList
// returns, the itemRunList array has been stored in uspData
//
if(!BuildMergedItemRunList(
uspData,
wstr,
wlen,
attrRunList,
scriptControl,
scriptState)
)
{
return FALSE;
}
// reallocate BIDI-arrays if item-run-list changed size
if(itemRunAllocLen < uspData->itemRunAllocLen)
{
uspData->bidiLevels = realloc(uspData->bidiLevels, uspData->itemRunAllocLen * sizeof(BYTE));
uspData->visualToLogicalList = realloc(uspData->visualToLogicalList, uspData->itemRunAllocLen * sizeof(int));
}
// Analyze the resulting runlist and build the BIDI-level array
if(!BuildVisualMapping( uspData->itemRunList,
uspData->itemRunCount,
uspData->bidiLevels,
uspData->visualToLogicalList)
)
{
return FALSE;
}
// Rellocate logical cluster+attribute arrays prior to shaping
if(uspData->stringAllocLen < wlen)
{
uspData->stringAllocLen = wlen;
uspData->clusterList = realloc(uspData->clusterList, wlen * sizeof(WORD));
uspData->attrList = realloc(uspData->attrList, wlen * sizeof(ATTR));
uspData->breakList = realloc(uspData->breakList, wlen * sizeof(SCRIPT_LOGATTR));
}
// Generate the word-break information in logical order
for(i = 0; i < uspData->itemRunCount; i++)
{
ITEM_RUN *itemRun = &uspData->itemRunList[i];
ScriptBreak(
wstr + itemRun->charPos,
itemRun->len,
&itemRun->analysis,
uspData->breakList + itemRun->charPos
);
}
// Perform shaping + generate glyph data
for(i = 0; i < uspData->itemRunCount; i++)
{
ITEM_RUN *itemRun = GetItemRun(uspData, i);//;//&uspData->itemRunList[i]; //
ShapeAndPlaceItemRun(
uspData,
itemRun,
hdc,
wstr + itemRun->charPos
);
}
//
// locate tab-characters and expand the corresponding glyph-widths appropriately.
// this must happen after *all* shaping/widths have been generated
//
if(scriptTabdef)
{
if(ExpandTabs(uspData, wstr, wlen, scriptTabdef))
{
// modify the SCRIPT_LOGATTR list to make tabs whitespace
for(i = 0; i < wlen; i++)
{
if(wstr[i] == '\t')
uspData->breakList[i].fWhiteSpace = TRUE;
}
}
else
{
return FALSE;
}
}
//
// Keep a flattened copy of the attribute-run-list, but
// with one element per character rather than larger runs.
//
UspApplyAttributes(uspData, attrRunList);
return TRUE;
}
//
// Create the control structure
//
USPDATA * WINAPI UspAllocate()
{
USPDATA *uspData = malloc(sizeof(USPDATA));
if(uspData)
{
// set all members to zero including run-counts etc
memset(uspData, 0, sizeof(USPDATA));
uspData->selFG = GetSysColor(COLOR_HIGHLIGHTTEXT);
uspData->selBG = GetSysColor(COLOR_HIGHLIGHT);
}
return uspData;
}
//
// Free everything
//
VOID WINAPI UspFree(USPDATA *uspData)
{
if(uspData)
{
// free the script-cache (will be NULL if a user-supplied fontlist was specified)
ScriptFreeCache(&uspData->defaultFont.scriptCache);
// free the glyph-buffers
free(uspData->glyphList);
free(uspData->svaList);
free(uspData->widthList);
free(uspData->offsetList);
// free the item-run buffers
free(uspData->itemRunList);
free(uspData->visualToLogicalList);
free(uspData->bidiLevels);
free(uspData->tempItemList);
// free the logical character-buffers
free(uspData->clusterList);
free(uspData->attrList);
// free the control structure
free(uspData);
}
}
BOOL WINAPI UspGetSize(USPDATA *uspData, SIZE * size)
{
int i;
size->cx = 0;
size->cy = 0;
for(i = 0; i < uspData->itemRunCount; i++)
{
size->cx += uspData->itemRunList[i].width;
}
return TRUE;
}
SCRIPT_LOGATTR * WINAPI UspGetLogAttr(USPDATA *uspData)
{
if(uspData && uspData->breakList)
{
return uspData->breakList;
}
else
{
return NULL;
}
}
BOOL WINAPI UspBuildAttr (
ATTR * attr,
COLORREF colfg,
COLORREF colbg,
int len,
int font,
int sel,
int ctrl,
int eol
)
{
if(attr == 0)
return FALSE;
attr->fg = colfg;
attr->bg = colbg;
attr->len = len;
attr->font = font;
attr->sel = sel;
attr->ctrl = ctrl;
attr->eol = eol;
attr->reserved = 0;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -