Skip to content

Commit

Permalink
New: プロポーショナルフォント
Browse files Browse the repository at this point in the history
[patchunicode:#713] wiki:Request/500
フォント設定、印刷ページ設定でプロポーショナルフォントが使用できるようになります。

git-svn-id: https://svn.code.sf.net/p/sakura-editor/code/sakura/trunk2@4035 f7ce1907-e4c7-47ca-9f76-12c87ed2c91c
  • Loading branch information
syat committed Sep 20, 2015
1 parent 23f826e commit 66f5d68
Show file tree
Hide file tree
Showing 77 changed files with 1,239 additions and 784 deletions.
6 changes: 3 additions & 3 deletions sakura_core/CLoadAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ ELoadResult CLoadAgent::OnLoad(const SLoadInfo& sLoadInfo)
// 「指定桁で折り返す」以外の時は折り返し幅をMAXLINEKETASで初期化する
// 「右端で折り返す」は、この後のOnSize()で再設定される
const STypeConfig& ref = pcDoc->m_cDocType.GetDocumentAttribute();
CLayoutInt nMaxLineKetas = ref.m_nMaxLineKetas;
CKetaXInt nMaxLineKetas = ref.m_nMaxLineKetas;
if( ref.m_nTextWrapMethod != WRAP_SETTING_WIDTH )
nMaxLineKetas = MAXLINEKETAS;
nMaxLineKetas = CKetaXInt(MAXLINEKETAS);

CProgressSubject* pOld = CEditApp::getInstance()->m_pcVisualProgress->CProgressListener::Listen(&pcDoc->m_cLayoutMgr);
pcDoc->m_cLayoutMgr.SetLayoutInfo( true, ref, ref.m_nTabSpace, ref.m_nTsvMode, nMaxLineKetas );
pcDoc->m_cLayoutMgr.SetLayoutInfo( true, true, ref, ref.m_nTabSpace, ref.m_nTsvMode, nMaxLineKetas, CLayoutXInt(-1), &pcDoc->m_pcEditWnd->GetLogfont() );
pcDoc->m_pcEditWnd->ClearViewCaretPosInfo();
if (pcDoc->m_cLayoutMgr.m_tsvInfo.m_nTsvMode != TSV_MODE_NONE) {
pcDoc->m_cLayoutMgr.m_tsvInfo.CalcTabLength(pcDoc->m_cLayoutMgr.m_pcDocLineMgr);
Expand Down
5 changes: 0 additions & 5 deletions sakura_core/basis/SakuraBasis.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,8 @@ typedef CLayoutInt CLayoutYInt;
typedef int CPixelYInt;
typedef int CPixelXInt;

#ifdef BUILD_OPT_ENALBE_PPFONT_SUPPORT
typedef CLayoutXInt CHabaXInt;
typedef int CKetaXInt;
#else
typedef CPixelXInt CHabaXInt;
typedef CLayoutXInt CKetaXInt;
#endif


// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
Expand Down
200 changes: 158 additions & 42 deletions sakura_core/charset/charcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const unsigned char gm_keyword_char[128] = {

namespace WCODE
{
static bool s_MultiFont;

bool CalcHankakuByFont(wchar_t);

//2007.08.30 kobake 追加
Expand Down Expand Up @@ -139,11 +141,11 @@ namespace WCODE
{
/* LOGFONTの初期化 */
memset( &m_lf, 0, sizeof(m_lf) );
memset( &m_lf2, 0, sizeof(m_lf2) );

// HDC の初期化
HDC hdc=GetDC(NULL);
m_hdc = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
m_hdc = NULL;
m_hdcFull = NULL;

m_hFont =NULL;
m_hFontOld =NULL;
Expand All @@ -152,27 +154,71 @@ namespace WCODE
~LocalCache()
{
// -- -- 後始末 -- -- //
if (m_hFont != NULL) {
DeleteLocalData();
}
void DeleteLocalData(){
if (m_hFont != NULL) {
SelectObject(m_hdc, m_hFontOld);
DeleteObject(m_hFont);
m_hFont = NULL;
}
if (m_hFontFull != NULL) {
SelectObject(m_hdcFull, m_hFontFullOld);
DeleteObject(m_hFontFull);
m_hFontFull = NULL;
}
DeleteDC(m_hdc);
if(m_hdc){ DeleteDC(m_hdc); m_hdc = NULL;}
if(m_hdcFull){ DeleteDC(m_hdcFull); m_hdcFull = NULL;}
}
static bool IsEqual(const LOGFONT &lhs, const LOGFONT &rhs){
return &lhs == &rhs ||
0 == memcmp(&lhs, &rhs, sizeof(lhs));
}

// 再初期化
void Init( const LOGFONT &lf )
void Init(const LOGFONT &lf, const LOGFONT &lfFull, HDC hdcOrg)
{
if (m_hFontOld != NULL) {
m_hFontOld = (HFONT)SelectObject(m_hdc, m_hFontOld);
DeleteObject(m_hFontOld);
}
DeleteLocalData();

m_hdc = ::CreateCompatibleDC(hdcOrg);
m_lf = lf;
m_lf2 = lfFull;

m_hFont = ::CreateFontIndirect( &lf );
m_hFontOld = (HFONT)SelectObject(m_hdc,m_hFont);
bool bFullFont = !IsEqual(lf,lfFull);
if( bFullFont ){
m_bMultiFont = true;
m_hdcFull = CreateCompatibleDC(hdcOrg);
m_hFontFull = ::CreateFontIndirect(&lfFull);
m_hFontFullOld = (HFONT)SelectObject(m_hdcFull, m_hFontFull);
}else{
m_bMultiFont = false;
m_hdcFull = NULL;
m_hFontFull = NULL;
m_hFontFullOld = NULL;
}
s_MultiFont = m_bMultiFont;

// -- -- 半角基準 -- -- //
GetTextExtentPoint32W_AnyBuild(m_hdc,L"x",1,&m_han_size);
// CTextMetrics::Update と同じでなければならない
HDC hdcArr[2] = {m_hdc, m_hdcFull};
int size = (bFullFont ? 2 : 1);
m_han_size.cx = 1;
m_han_size.cy = 1;
for(int i = 0; i < size; i++){
// KB145994
// tmAveCharWidth は不正確(半角か全角なのかも不明な値を返す)
SIZE sz;
GetTextExtentPoint32W_AnyBuild(hdcArr[i], L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &sz);
sz.cx = (sz.cx / 26 + 1) / 2;
if( m_han_size.cx < sz.cx ){
m_han_size.cx = sz.cx;
}
if( m_han_size.cy < sz.cy ){
m_han_size.cy = sz.cy;
}
}
}
void SelectCache( SCharWidthCache* pCache )
{
Expand All @@ -183,46 +229,82 @@ namespace WCODE
assert(m_pCache!=0);
// キャッシュのクリア
memcpy(m_pCache->m_lfFaceName, m_lf.lfFaceName, sizeof(m_lf.lfFaceName));
memset(m_pCache->m_bCharWidthCache, 0, sizeof(m_pCache->m_bCharWidthCache));
memcpy(m_pCache->m_lfFaceName2, m_lf2.lfFaceName, sizeof(m_lf2.lfFaceName));
memset(m_pCache->m_nCharPxWidthCache, 0, sizeof(m_pCache->m_nCharPxWidthCache));
m_pCache->m_nCharWidthCacheTest=0x12345678;
}
bool IsSameFontFace( const LOGFONT &lf )
bool IsSameFontFace( const LOGFONT &lf1, const LOGFONT &lf2 )
{
assert(m_pCache!=0);
return ( memcmp(m_pCache->m_lfFaceName, lf.lfFaceName, sizeof(lf.lfFaceName)) == 0 );
return ( memcmp(m_pCache->m_lfFaceName, lf1.lfFaceName, sizeof(lf1.lfFaceName)) == 0 &&
memcmp(m_pCache->m_lfFaceName2, lf2.lfFaceName, sizeof(lf2.lfFaceName)) == 0 );
}
void SetCache(wchar_t c, bool cache_value)
void SetCachePx(wchar_t c, short cache_pxwidth)
{
int v=cache_value?0x1:0x2;
m_pCache->m_bCharWidthCache[c/4] &= ~( 0x3<< ((c%4)*2) ); //該当箇所クリア
m_pCache->m_bCharWidthCache[c/4] |= ( v << ((c%4)*2) ); //該当箇所セット
m_pCache->m_nCharPxWidthCache[c] = cache_pxwidth;
}
bool GetCache(wchar_t c) const
short GetCachePx(wchar_t c) const
{
return _GetRaw(c)==0x1?true:false;
return _GetRawPx(c);
}
bool ExistCache(wchar_t c) const
{
assert(m_pCache->m_nCharWidthCacheTest==0x12345678);
return _GetRaw(c)!=0x0;
return _GetRawPx(c)!=0x0;
}
bool CalcHankakuByFont(wchar_t c)
{
SIZE size={m_han_size.cx*2,0}; //関数が失敗したときのことを考え、全角幅で初期化しておく
GetTextExtentPoint32W_AnyBuild(m_hdc,&c,1,&size);
GetTextExtentPoint32W_AnyBuild(SelectHDC(c),&c,1,&size);
return (size.cx<=m_han_size.cx);
}
bool IsHankakuByWidth(int width){
return width<=m_han_size.cx;
}
int CalcPxWidthByFont(wchar_t c)
{
SIZE size={m_han_size.cx*2,0}; //関数が失敗したときのことを考え、全角幅で初期化しておく
// 2014.12.21 コントロールコードの表示・NULが1px幅になるのをスペース幅にする
if (WCODE::IsControlCode(c) || L'\0' == c) {
GetTextExtentPoint32W_AnyBuild(SelectHDC(c),&c,1,&size);
const int nCx = size.cx;
const wchar_t proxyChar = ((L'\0' == c) ? ' ' : L'');
GetTextExtentPoint32W_AnyBuild(SelectHDC(proxyChar),&proxyChar,1,&size);
return t_max<int>(nCx, size.cx);
}
GetTextExtentPoint32W_AnyBuild(SelectHDC(c),&c,1,&size);
return t_max<int>(1,size.cx);
}
int CalcPxWidthByFont2(const wchar_t* pc2)
{
SIZE size={m_han_size.cx*2,0};
// サロゲートは全角フォント
GetTextExtentPoint32W_AnyBuild(m_hdcFull?m_hdcFull:m_hdc,pc2,2,&size);
return t_max<int>(1,size.cx);
}
bool GetMultiFont() const
{
return m_bMultiFont;
}

protected:
int _GetRaw(wchar_t c) const
int _GetRawPx(wchar_t c) const
{
return m_pCache->m_nCharPxWidthCache[c];
}
HDC SelectHDC(wchar_t c) const
{
return (m_pCache->m_bCharWidthCache[c/4]>>((c%4)*2))&0x3;
return m_hdcFull && WCODE::GetFontNo(c) ? m_hdcFull : m_hdc;
}
private:
HDC m_hdc;
HFONT m_hFontOld;
HFONT m_hFont;
HDC m_hdcFull;
HFONT m_hFontOld, m_hFontFullOld;
HFONT m_hFont, m_hFontFull;
bool m_bMultiFont;
SIZE m_han_size;
LOGFONT m_lf; // 2008/5/15 Uchi
LOGFONT m_lf2;
SCharWidthCache* m_pCache;
};

Expand All @@ -243,14 +325,12 @@ namespace WCODE
m_parCache[i] = 0;
}
}
void Init( const LOGFONT &lf, ECharWidthFontMode fMode )
void Init( const LOGFONT &lf1, const LOGFONT &lf2, ECharWidthFontMode fMode, HDC hdc )
{
// Fontfaceが変更されていたらキャッシュをクリアする 2013.04.08 aroka
m_localcache[fMode].Init(lf);
if( !m_localcache[fMode].IsSameFontFace(lf) )
{
m_localcache[fMode].Clear();
}
m_localcache[fMode].Init(lf1, lf2, hdc);
// サイズやHDCが変わってもクリアする必要がある
m_localcache[fMode].Clear();
}
void Select( ECharWidthFontMode fMode, ECharWidthCacheMode cMode )
{
Expand All @@ -266,6 +346,7 @@ namespace WCODE
pcache->SelectCache( m_parCache[fMode] );
}
if( fMode==CWM_FONT_EDIT ){ m_eLastEditCacheMode = cmode; }
WCODE::s_MultiFont = pcache->GetMultiFont();
}
LocalCache* GetCache(){ return pcache; }
private:
Expand All @@ -280,31 +361,66 @@ namespace WCODE
static LocalCacheSelector selector;


//文字幅の動的計算。半角ならtrue。
bool CalcHankakuByFont(wchar_t c)
//文字幅の動的計算。ピクセル幅
int CalcPxWidthByFont(wchar_t c)
{
LocalCache* pcache = selector.GetCache();
// -- -- キャッシュが存在すれば、それをそのまま返す -- -- //
if(pcache->ExistCache(c))return pcache->GetCache(c);
if(pcache->ExistCache(c))return pcache->GetCachePx(c);

// -- -- 相対比較 -- -- //
bool value;
value = pcache->CalcHankakuByFont(c);
int width;
width = pcache->CalcPxWidthByFont(c);

// -- -- キャッシュ更新 -- -- //
pcache->SetCache(c,value);
pcache->SetCachePx(c,width);

return pcache->GetCache(c);
return pcache->GetCachePx(c);
}

int CalcPxWidthByFont2(const wchar_t* pc){
LocalCache* pcache = selector.GetCache();
return pcache->CalcPxWidthByFont2(pc);
}

//文字幅の動的計算。半角ならtrue。
bool CalcHankakuByFont(wchar_t c)
{
LocalCache* pcache = selector.GetCache();
return pcache->IsHankakuByWidth(CalcPxWidthByFont(c));
}

// 文字の使用フォントを返す
// @return 0:半角用 / 1:全角用
int GetFontNo( wchar_t c ){
if( s_MultiFont ){
if(0x0080 <= c && c <= 0xFFFF){
return 1;
}
}
return 0;
}
int GetFontNo2( wchar_t wc1, wchar_t wc2 ){
if( s_MultiFont ){
return 1;
}
return 0;
}
}

// 文字幅の動的計算用キャッシュの初期化。 2007/5/18 Uchi
void InitCharWidthCache( const LOGFONT &lf, ECharWidthFontMode fMode )
{
WCODE::selector.Init( lf, fMode );
HDC hdc = GetDC(NULL);
WCODE::selector.Init( lf, lf, fMode, hdc );
ReleaseDC(NULL, hdc);
}

void InitCharWidthCacheFromDC( const LOGFONT* lfs, ECharWidthFontMode fMode, HDC hdcOrg )
{
WCODE::selector.Init(lfs[0], lfs[1], fMode, hdcOrg);
}

// 文字幅の動的計算用キャッシュの選択 2013.04.08 aroka
// 文字幅の動的計算用キャッシュの選択 2013.04.08 aroka
void SelectCharWidthCache( ECharWidthFontMode fMode, ECharWidthCacheMode cMode )
{
assert( fMode==CWM_FONT_EDIT || cMode==CWM_CACHE_LOCAL );
Expand Down
15 changes: 14 additions & 1 deletion sakura_core/charset/charcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ namespace WCODE
return !IsHankaku(wc);
}

//!使用フォント番号を返す
// (0:半角/1:全角)
int GetFontNo(wchar_t);
int GetFontNo2(wchar_t, wchar_t);

//!全角スペースかどうか判定
inline bool IsZenkakuSpace(wchar_t wc)
{
Expand Down Expand Up @@ -242,6 +247,12 @@ namespace WCODE
return c>=0x2500 && c<=0x257F;
}

//!文字が半角かどうかを取得(DLLSHARE/フォント依存)
bool CalcHankakuByFont(wchar_t c);
//!文字のpx幅を取得(DLLSHARE/フォント依存)
int CalcPxWidthByFont(wchar_t c);
//!文字のpx幅を取得(DLLSHARE/フォント依存)
int CalcPxWidthByFont2(const wchar_t* c);
//! 句読点か
//bool IsKutoten( wchar_t wc );

Expand Down Expand Up @@ -320,7 +331,8 @@ namespace TCODE
struct SCharWidthCache {
// 文字半角全角キャッシュ
TCHAR m_lfFaceName[LF_FACESIZE];
BYTE m_bCharWidthCache[0x10000/4]; //16KB 文字半角全角キャッシュ 2008/5/16 Uchi
TCHAR m_lfFaceName2[LF_FACESIZE];
short m_nCharPxWidthCache[0x10000];
int m_nCharWidthCacheTest; //cache溢れ検出
};

Expand All @@ -339,6 +351,7 @@ enum ECharWidthCacheMode {
// キャッシュの初期化関数群
void SelectCharWidthCache( ECharWidthFontMode fMode, ECharWidthCacheMode cMode ); //<! モードを変更したいとき
void InitCharWidthCache( const LOGFONT &lf, ECharWidthFontMode fMode=CWM_FONT_EDIT ); //<! フォントを変更したとき
void InitCharWidthCacheFromDC(const LOGFONT* lfs, ECharWidthFontMode fMode, HDC hdcOrg );

#endif /* SAKURA_CHARCODE_5A887F7C_8E08_4940_AF65_BD6850C3A7B5_H_ */
/*[EOF]*/
3 changes: 1 addition & 2 deletions sakura_core/cmd/CViewCommander_Clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ void CViewCommander::Command_PASTEBOX( const wchar_t *szPaste, int nPasteSize )

int nBgn;
int nPos;
CLayoutInt nCount;
CLayoutPoint ptLayoutNew; //挿入された部分の次の位置
BOOL bAddLastCR;
CLayoutInt nInsPosX;
Expand All @@ -294,7 +293,7 @@ void CViewCommander::Command_PASTEBOX( const wchar_t *szPaste, int nPasteSize )

CLayoutPoint ptCurOld = GetCaret().GetCaretLayoutPos();

nCount = CLayoutInt(0);
CLayoutYInt nCount = CLayoutInt(0); // カーソル位置からのオフセット行数
bool bExtEol = GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol;

// Jul. 10, 2005 genta 貼り付けデータの最後にCR/LFが無い場合の対策
Expand Down
Loading

0 comments on commit 66f5d68

Please sign in to comment.