Beispiel #1
0
int FontEnumForV2Console(ENUMLOGFONT *pelf, NEWTEXTMETRIC *pntm, int nFontType, LPARAM lParam)
{
    UINT i;
    LPCWSTR pwszFace = pelf->elfLogFont.lfFaceName;

    BOOL const fIsEastAsianCP = IsEastAsianCP(GetACP());

    LPCWSTR pwszCharSet;

    switch (pelf->elfLogFont.lfCharSet)
    {
    case ANSI_CHARSET:
        pwszCharSet = L"ANSI";
        break;
    case CHINESEBIG5_CHARSET:
        pwszCharSet = L"Chinese Big5";
        break;
    case EASTEUROPE_CHARSET:
        pwszCharSet = L"East Europe";
        break;
    case GREEK_CHARSET:
        pwszCharSet = L"Greek";
        break;
    case MAC_CHARSET:
        pwszCharSet = L"Mac";
        break;
    case RUSSIAN_CHARSET:
        pwszCharSet = L"Russian";
        break;
    case SYMBOL_CHARSET:
        pwszCharSet = L"Symbol";
        break;
    case BALTIC_CHARSET:
        pwszCharSet = L"Baltic";
        break;
    case DEFAULT_CHARSET:
        pwszCharSet = L"Default";
        break;
    case GB2312_CHARSET:
        pwszCharSet = L"Chinese GB2312";
        break;
    case HANGUL_CHARSET:
        pwszCharSet = L"Korean Hangul";
        break;
    case OEM_CHARSET:
        pwszCharSet = L"OEM";
        break;
    case SHIFTJIS_CHARSET:
        pwszCharSet = L"Japanese Shift-JIS";
        break;
    case TURKISH_CHARSET:
        pwszCharSet = L"Turkish";
        break;
    default:
        pwszCharSet = L"Unknown";
        break;

    }

    wprintf(L"Enum'd font: '%ls' (X: %d, Y: %d) weight 0x%lx (%d) charset %s \r\n",
            pelf->elfLogFont.lfFaceName,
            pelf->elfLogFont.lfWidth,
            pelf->elfLogFont.lfHeight,
            pelf->elfLogFont.lfWeight,
            pelf->elfLogFont.lfWeight,
            pwszCharSet);

    // reject non-monospaced fonts
    if (!(pelf->elfLogFont.lfPitchAndFamily & FIXED_PITCH))
    {
        wprintf(L"Rejecting non-monospaced font. \r\n");
        return CONTINUE_ENUM;
    }

    // reject non-modern or italic TT fonts
    if ((nFontType == TRUETYPE_FONTTYPE) &&
        (((pelf->elfLogFont.lfPitchAndFamily & 0xf0) != FF_MODERN) ||
         pelf->elfLogFont.lfItalic))
    {
        wprintf(L"Rejecting non-FF_MODERN or Italic TrueType font.\r\n");
        return CONTINUE_ENUM;
    }

    // reject non-TT fonts that aren't OEM
    if ((nFontType != TRUETYPE_FONTTYPE) &&
        (!fIsEastAsianCP || !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) &&
        (pelf->elfLogFont.lfCharSet != OEM_CHARSET)) {
        wprintf(L"Rejecting raster font that isn't OEM_CHARSET.\r\n");
        return CONTINUE_ENUM;
    }

    // reject fonts that are vertical
    if (pwszFace[0] == TEXT('@'))
    {
        wprintf(L"Rejecting font face designed for vertical text.\r\n");
        return CONTINUE_ENUM;
    }

    // reject non-TT fonts that aren't terminal
    if ((nFontType != TRUETYPE_FONTTYPE) && (0 != lstrcmp(pwszFace, L"Terminal")))
    {
        wprintf(L"Rejecting raster font that isn't 'Terminal'.\r\n");
        return CONTINUE_ENUM;
    }

    // reject East Asian TT fonts that aren't East Asian charset.
    if (fIsEastAsianCP && !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) {
        wprintf(L"Rejecting East Asian TrueType font that isn't marked with East Asian charsets.\r\n");
        return CONTINUE_ENUM;
    }

    // reject East Asian TT fonts on non-East Asian systems
    if (!fIsEastAsianCP && IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet))
    {
        wprintf(L"Rejecting East Asian TrueType font when Windows non-Unicode codepage isn't from CJK country.\r\n");
        return CONTINUE_ENUM;
    }

    if (nFontType & TRUETYPE_FONTTYPE) {
        for (i = 0; i < ARRAYSIZE(TTPoints); i++) {
            pelf->elfLogFont.lfHeight = TTPoints[i];

            // If it's an East Asian enum, skip all odd height fonts.
            if (fIsEastAsianCP && (pelf->elfLogFont.lfHeight % 2) != 0)
            {
                continue;
            }

            pelf->elfLogFont.lfWidth = 0;
            pelf->elfLogFont.lfWeight = pntm->tmWeight;
            AddFont(pelf, pntm, nFontType, (HDC)lParam);
        }
    }
    else {
        AddFont(pelf, pntm, nFontType, (HDC)lParam);
    }

    return CONTINUE_ENUM;  // and continue enumeration
}
Beispiel #2
0
BOOL IsUnicodeFullWidth(
    IN WCHAR wch
    )
{
    if (0x20 <= wch && wch <= 0x7e)
        /* ASCII */
        return FALSE;
    else if (0x3041 <= wch && wch <= 0x3094)
        /* Hiragana */
        return TRUE;
    else if (0x30a1 <= wch && wch <= 0x30f6)
        /* Katakana */
        return TRUE;
    else if (0x3105 <= wch && wch <= 0x312c)
        /* Bopomofo */
        return TRUE;
    else if (0x3131 <= wch && wch <= 0x318e)
        /* Hangul Elements */
        return TRUE;
    else if (0xac00 <= wch && wch <= 0xd7a3)
        /* Korean Hangul Syllables */
        return TRUE;
    else if (0xff01 <= wch && wch <= 0xff5e)
        /* Fullwidth ASCII variants */
        return TRUE;
    else if (0xff61 <= wch && wch <= 0xff9f)
        /* Halfwidth Katakana variants */
        return FALSE;
    else if ( (0xffa0 <= wch && wch <= 0xffbe) ||
              (0xffc2 <= wch && wch <= 0xffc7) ||
              (0xffca <= wch && wch <= 0xffcf) ||
              (0xffd2 <= wch && wch <= 0xffd7) ||
              (0xffda <= wch && wch <= 0xffdc)   )
        /* Halfwidth Hangule variants */
        return FALSE;
    else if (0xffe0 <= wch && wch <= 0xffe6)
        /* Fullwidth symbol variants */
        return TRUE;
    else if (0x4e00 <= wch && wch <= 0x9fa5)
        /* Han Ideographic */
        return TRUE;
    else if (0xf900 <= wch && wch <= 0xfa2d)
        /* Han Ideographic Compatibility */
        return TRUE;
    else
    {
#if 0
        /*
         * Hack this block for I don't know FONT of Console Window.
         *
         * If you would like perfect result from IsUnicodeFullWidth routine,
         * then you should enable this block and
         * you should know FONT of Console Window.
         */

        INT Width;
        TEXTMETRIC tmi;

        /* Unknown character */

        GetTextMetricsW(hDC, &tmi);
        if (IS_ANY_DBCS_CHARSET(tmi.tmCharSet))
            tmi.tmMaxCharWidth /= 2;

        GetCharWidth32(hDC, wch, wch, &Width);
        if (Width == tmi.tmMaxCharWidth)
            return FALSE;
        else if (Width == tmi.tmMaxCharWidth*2)
            return TRUE;
#else
        ULONG MultiByteSize;

        RtlUnicodeToMultiByteSize(&MultiByteSize, &wch, sizeof(WCHAR));
        if (MultiByteSize == 2)
            return TRUE ;
        else
            return FALSE ;
#endif
    }
    ASSERT(FALSE);
    return FALSE;
#if 0
    ULONG MultiByteSize;

    RtlUnicodeToMultiByteSize(&MultiByteSize, &wch, sizeof(WCHAR));
    if (MultiByteSize == 2)
        return TRUE ;
    else
        return FALSE ;
#endif
}
Beispiel #3
0
/*
 * Returns bit combination
 *  FE_ABANDONFONT  - do not continue enumerating this font
 *  FE_FONTOK       - font was created and added to cache or already there
 */
int CALLBACK
FontEnum(
    LPENUMLOGFONTW lpLogFont,
    LPNEWTEXTMETRICW lpTextMetric,
    int nFontType,
    LPARAM lParam
    )

/*++

    Is called exactly once by GDI for each font in the system.  This
    routine is used to store the FONT_INFO structure.

--*/

{
    PFONTENUMDC pfed = (PFONTENUMDC)lParam;
    HDC hDC = pfed->hDC;
    BOOL bFindFaces = pfed->bFindFaces;
    HFONT hFont;
    TEXTMETRICW tmi;
    LONG nFont;
    LONG nFontNew;
    COORD SizeToShow;
    COORD SizeActual;
    COORD SizeWant;
    BYTE tmFamily;
    SIZE Size;
    LPWSTR pwszFace = lpLogFont->elfLogFont.lfFaceName;
    PFACENODE pFN;

    DBGFONTS(("  FontEnum \"%ls\" (%d,%d) weight 0x%lx(%d) -- %s\n",
            pwszFace,
            lpLogFont->elfLogFont.lfWidth, lpLogFont->elfLogFont.lfHeight,
            lpLogFont->elfLogFont.lfWeight, lpLogFont->elfLogFont.lfWeight,
            bFindFaces ? "Finding Faces" : "Creating Fonts"));

    //
    // reject variable width and italic fonts, also tt fonts with neg ac
    // also reject DBCS fonts because they are never really fixed pitch
    // they can be "binary" pitch meaning SBCS widths are the same as all
    // other SBCS widths and DBCS widhts the same as all DBCS widhts
    // (but DBCS widths won't be the same as SBCS widths)
    if
    (
      !(lpLogFont->elfLogFont.lfPitchAndFamily & FIXED_PITCH) ||
      (lpLogFont->elfLogFont.lfItalic)                        ||
      !(((NTMW_INTERNAL *)lpTextMetric)->tmd.fl & TMD_NONNEGATIVE_AC) ||
      (IS_ANY_DBCS_CHARSET(lpLogFont->elfLogFont.lfCharSet))
    )
    {
        DBGFONTS(("    REJECT  face (variable pitch, italic, or neg a&c)\n"));
        return bFindFaces ? TRUE : FALSE;  // unsuitable font
    }

    if (nFontType == TRUETYPE_FONTTYPE) {
        lpLogFont->elfLogFont.lfHeight = pfed->TTPointSize;
        lpLogFont->elfLogFont.lfWidth  = 0;
        lpLogFont->elfLogFont.lfWeight = FW_NORMAL;
    }

    /*
     * reject TT fonts for whoom family is not modern, that is do not use
     * FF_DONTCARE    // may be surprised unpleasantly
     * FF_DECORATIVE  // likely to be symbol fonts
     * FF_SCRIPT      // cursive, inappropriate for console
     * FF_SWISS OR FF_ROMAN // variable pitch
     */

    if ((nFontType == TRUETYPE_FONTTYPE) &&
            ((lpLogFont->elfLogFont.lfPitchAndFamily & 0xf0) != FF_MODERN)) {
        DBGFONTS(("    REJECT  face (TT but not FF_MODERN)\n"));
        return bFindFaces ? TRUE : FALSE;  // unsuitable font
    }

    /*
     * reject non-TT fonts that aren't OEM
     */
    if ((nFontType != TRUETYPE_FONTTYPE) &&
            (lpLogFont->elfLogFont.lfCharSet != OEM_CHARSET)) {
        DBGFONTS(("    REJECT  face (not TT nor OEM)\n"));
        return bFindFaces ? TRUE : FALSE;  // unsuitable font
    }

    /*
     * Add or find the facename
     */
    pFN = AddFaceNode(&gpFaceNames, pwszFace);
    if (pFN == NULL) {
        return FALSE;
    }

    if (bFindFaces) {
        if (nFontType == TRUETYPE_FONTTYPE) {
            DBGFONTS(("NEW TT FACE %ls\n", pwszFace));
            pFN->dwFlag |= EF_TTFONT;
        } else if (nFontType == RASTER_FONTTYPE) {
            DBGFONTS(("NEW OEM FACE %ls\n",pwszFace));
            pFN->dwFlag |= EF_OEMFONT;
        }
        return 0;
    }


    if (IS_BOLD(lpLogFont->elfLogFont.lfWeight)) {
        DBGFONTS2(("    A bold font (weight %d)\n", lpLogFont->elfLogFont.lfWeight));
        // return 0;
    }

    /* get font info */
    SizeWant.Y = (SHORT)lpLogFont->elfLogFont.lfHeight;
    SizeWant.X = (SHORT)lpLogFont->elfLogFont.lfWidth;
CreateBoldFont:
    lpLogFont->elfLogFont.lfQuality = NONANTIALIASED_QUALITY;
    hFont = CreateFontIndirectW(&lpLogFont->elfLogFont);
    ASSERT(hFont);
    if (!hFont) {
        DBGFONTS(("    REJECT  font (can't create)\n"));
        return 0;  // same font in other sizes may still be suitable
    }

    DBGFONTS2(("    hFont = %lx\n", hFont));

    //
    // for reasons unbeknownst to me, removing this code causes GDI
    // to yack, claiming that the font is owned by another process.
    //

    SelectObject(hDC,hFont);
    if (!GetTextMetricsW(hDC, &tmi)) {
        tmi = *((LPTEXTMETRICW)lpTextMetric);
    }

    if (GetTextExtentPoint32W(hDC, L"0", 1, &Size)) {
        SizeActual.X = (SHORT)Size.cx;
    } else {
        SizeActual.X = (SHORT)(tmi.tmMaxCharWidth);
    }
    SizeActual.Y = (SHORT)(tmi.tmHeight + tmi.tmExternalLeading);
    DBGFONTS2(("    actual size %d,%d\n", SizeActual.X, SizeActual.Y));
    tmFamily = tmi.tmPitchAndFamily;
    if (TM_IS_TT_FONT(tmFamily) && (SizeWant.Y >= 0)) {
        SizeToShow = SizeWant;
        if (SizeWant.X == 0) {
            // Asking for zero width height gets a default aspect-ratio width
            // It's better to show that width rather than 0.
            SizeToShow.X = SizeActual.X;
        }
    } else {
        SizeToShow = SizeActual;
    }
    DBGFONTS2(("    SizeToShow = (%d,%d), SizeActual = (%d,%d)\n",
            SizeToShow.X, SizeToShow.Y, SizeActual.X, SizeActual.Y));

    // there's a GDI bug - this assert fails occasionally
    //ASSERT (tmi.tmw.tmMaxCharWidth == lpTextMetric->tmMaxCharWidth);

    /*
     * NOW, determine whether this font entry has already been cached
     * LATER : it may be possible to do this before creating the font, if
     * we can trust the dimensions & other info from lpTextMetric.
     * Sort by size:
     *  1) By pixelheight (negative Y values)
     *  2) By height (as shown)
     *  3) By width (as shown)
     */
    for (nFont = 0; nFont < (LONG)NumberOfFonts; ++nFont) {
        COORD SizeShown;

        if (FontInfo[nFont].hFont == NULL) {
            DBGFONTS(("!   Font %x has a NULL hFont\n", nFont));
            continue;
        }


        if (FontInfo[nFont].SizeWant.X > 0) {
            SizeShown.X = FontInfo[nFont].SizeWant.X;
        } else {
            SizeShown.X = FontInfo[nFont].Size.X;
        }

        if (FontInfo[nFont].SizeWant.Y > 0) {
            // This is a font specified by cell height.
            SizeShown.Y = FontInfo[nFont].SizeWant.Y;
        } else {
            SizeShown.Y = FontInfo[nFont].Size.Y;
            if (FontInfo[nFont].SizeWant.Y < 0) {
                // This is a TT font specified by character height.
                if (SizeWant.Y < 0 && SizeWant.Y > FontInfo[nFont].SizeWant.Y) {
                    // Requested pixelheight is smaller than this one.
                    DBGFONTS(("INSERT %d pt at %x, before %d pt\n",
                            -SizeWant.Y, nFont, -FontInfo[nFont].SizeWant.Y));
                    nFontNew = nFont;
                    goto InsertNewFont;
                }
            }
        }

        // DBGFONTS(("    SizeShown(%x) = (%d,%d)\n",nFont,SizeShown.X,SizeShown.Y));

        if (SIZE_EQUAL(SizeShown, SizeToShow) &&
                FontInfo[nFont].Family == tmFamily &&
                FontInfo[nFont].Weight == tmi.tmWeight &&
                wcscmp(FontInfo[nFont].FaceName, pwszFace) == 0) {
            /*
             * Already have this font
             */
            DBGFONTS2(("    Already have the font\n"));
            DeleteObject(hFont);
            pfed->ulFE |= FE_FONTOK;
            return TRUE;
        }


        if ((SizeToShow.Y < SizeShown.Y) ||
                (SizeToShow.Y == SizeShown.Y && SizeToShow.X < SizeShown.X)) {
            /*
             * This new font is smaller than nFont
             */
            DBGFONTS(("INSERT at %x, SizeToShow = (%d,%d)\n", nFont,
                    SizeToShow.X,SizeToShow.Y));
            nFontNew = nFont;
            goto InsertNewFont;
        }
    }

    /*
     * The font we are adding should be appended to the list,
     * since it is bigger (or equal) to the last one.
     */
    nFontNew = (LONG)NumberOfFonts;

InsertNewFont: // at nFontNew

//  ASSERT ((lpTextMetric->tmPitchAndFamily & 1) == 0);
    /* If we have to grow our font table, do it */

    if (NumberOfFonts == FontInfoLength) {
        PFONT_INFO Temp;

        FontInfoLength += FONT_INCREMENT;
        Temp = (PFONT_INFO)HeapReAlloc(pConHeap,MAKE_TAG( FONT_TAG ),FontInfo,sizeof(FONT_INFO) * FontInfoLength);
        ASSERT(Temp);
        if (Temp == NULL) {
            FontInfoLength -= FONT_INCREMENT;
            return FALSE;
        }
        FontInfo = Temp;
    }

    if (nFontNew < (LONG)NumberOfFonts) {
        RtlMoveMemory(&FontInfo[nFontNew+1],
                &FontInfo[nFontNew],
                sizeof(FONT_INFO)*(NumberOfFonts - nFontNew));
    }

    /*
     * Store the font info
     */
    FontInfo[nFontNew].hFont = hFont;
    FontInfo[nFontNew].Family = tmFamily;
    FontInfo[nFontNew].Size = SizeActual;
    if (TM_IS_TT_FONT(tmFamily)) {
        FontInfo[nFontNew].SizeWant = SizeWant;
    } else {
        FontInfo[nFontNew].SizeWant.X = 0;
        FontInfo[nFontNew].SizeWant.Y = 0;
    }
    FontInfo[nFontNew].Weight = tmi.tmWeight;
    FontInfo[nFont].FaceName = pFN->awch;

    ++NumberOfFonts;

    if (nFontType == TRUETYPE_FONTTYPE && !IS_BOLD(FontInfo[nFontNew].Weight)) {
          lpLogFont->elfLogFont.lfWeight = FW_BOLD;
          goto CreateBoldFont;
    }

    pfed->ulFE |= FE_FONTOK;  // and continue enumeration
    return TRUE;
}