Exemplo n.º 1
0
    void loadFont()
    {
        SetMapperFlags (dc, 0);
        SetMapMode (dc, MM_TEXT);

        LOGFONTW lf = { 0 };
        lf.lfCharSet = DEFAULT_CHARSET;
        lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
        lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
        lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
        lf.lfQuality = PROOF_QUALITY;
        lf.lfItalic = (BYTE) (style == "Italic" ? TRUE : FALSE);
        lf.lfWeight = style == "Bold" ? FW_BOLD : FW_NORMAL;
        lf.lfHeight = -256;
        family.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));

        HFONT standardSizedFont = CreateFontIndirect (&lf);

        if (standardSizedFont != 0)
        {
            if ((previousFontH = SelectObject (dc, standardSizedFont)) != 0)
            {
                fontH = standardSizedFont;

                OUTLINETEXTMETRIC otm;
                if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
                {
                    lf.lfHeight = -(int) otm.otmEMSquare;
                    fontH = CreateFontIndirect (&lf);

                    SelectObject (dc, fontH);
                    DeleteObject (standardSizedFont);
                }
            }
        }
    }
Exemplo n.º 2
0
    //==============================================================================
    HDC loadFont (const String& fontName_, const bool bold_, const bool italic_, const int size_)
    {
        if (fontName != fontName_ || bold != bold_ || italic != italic_ || size != size_)
        {
            fontName = fontName_;
            bold = bold_;
            italic = italic_;
            size = size_;

            if (dc != 0)
            {
                DeleteDC (dc);
                DeleteObject (fontH);
                kps.free();
            }

            fontH = 0;

            dc = CreateCompatibleDC (0);
            SetMapperFlags (dc, 0);
            SetMapMode (dc, MM_TEXT);

            LOGFONTW lfw;
            zerostruct (lfw);

            lfw.lfCharSet = DEFAULT_CHARSET;
            lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS;
            lfw.lfOutPrecision = OUT_OUTLINE_PRECIS;
            lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
            lfw.lfQuality = PROOF_QUALITY;
            lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE);
            lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL;
            fontName.copyToUnicode (lfw.lfFaceName, LF_FACESIZE - 1);

            lfw.lfHeight = size > 0 ? size : -256;
            HFONT standardSizedFont = CreateFontIndirect (&lfw);

            if (standardSizedFont != 0)
            {
                if (SelectObject (dc, standardSizedFont) != 0)
                {
                    fontH = standardSizedFont;

                    if (size == 0)
                    {
                        OUTLINETEXTMETRIC otm;
                        if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
                        {
                            lfw.lfHeight = -(int) otm.otmEMSquare;
                            fontH = CreateFontIndirect (&lfw);

                            SelectObject (dc, fontH);
                            DeleteObject (standardSizedFont);
                        }
                    }
                }
                else
                {
                    jassertfalse;
                }
            }
            else
            {
                jassertfalse;
            }
        }

        return dc;
    }
Exemplo n.º 3
0
void
gfxGDIFont::Initialize()
{
    NS_ASSERTION(!mMetrics, "re-creating metrics? this will leak");

    LOGFONTW logFont;

    // Figure out if we want to do synthetic oblique styling.
    GDIFontEntry* fe = static_cast<GDIFontEntry*>(GetFontEntry());
    bool wantFakeItalic =
        (mStyle.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) &&
        !fe->IsItalic();

    // If the font's family has an actual italic face (but font matching
    // didn't choose it), we have to use a cairo transform instead of asking
    // GDI to italicize, because that would use a different face and result
    // in a possible glyph ID mismatch between shaping and rendering.
    //
    // We use the mFamilyHasItalicFace flag in the entry in case of user fonts,
    // where the *CSS* family may not know about italic faces that are present
    // in the *GDI* family, and which GDI would use if we asked it to perform
    // the "italicization".
    bool useCairoFakeItalic = wantFakeItalic && fe->mFamilyHasItalicFace;

    if (mAdjustedSize == 0.0) {
        mAdjustedSize = mStyle.size;
        if (mStyle.sizeAdjust != 0.0 && mAdjustedSize > 0.0) {
            // to implement font-size-adjust, we first create the "unadjusted" font
            FillLogFont(logFont, mAdjustedSize,
                        wantFakeItalic && !useCairoFakeItalic);
            mFont = ::CreateFontIndirectW(&logFont);

            // initialize its metrics so we can calculate size adjustment
            Initialize();

            // calculate the properly adjusted size, and then proceed
            // to recreate mFont and recalculate metrics
            gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
            mAdjustedSize = mStyle.GetAdjustedSize(aspect);

            // delete the temporary font and metrics
            ::DeleteObject(mFont);
            mFont = nullptr;
            delete mMetrics;
            mMetrics = nullptr;
        }
    }

    // (bug 724231) for local user fonts, we don't use GDI's synthetic bold,
    // as it could lead to a different, incompatible face being used
    // but instead do our own multi-striking
    if (mNeedsBold && GetFontEntry()->IsLocalUserFont()) {
        mApplySyntheticBold = true;
    }

    // this may end up being zero
    mAdjustedSize = ROUND(mAdjustedSize);
    FillLogFont(logFont, mAdjustedSize, wantFakeItalic && !useCairoFakeItalic);
    mFont = ::CreateFontIndirectW(&logFont);

    mMetrics = new gfxFont::Metrics;
    ::memset(mMetrics, 0, sizeof(*mMetrics));

    AutoDC dc;
    SetGraphicsMode(dc.GetDC(), GM_ADVANCED);
    AutoSelectFont selectFont(dc.GetDC(), mFont);

    // Get font metrics if size > 0
    if (mAdjustedSize > 0.0) {

        OUTLINETEXTMETRIC oMetrics;
        TEXTMETRIC& metrics = oMetrics.otmTextMetrics;

        if (0 < GetOutlineTextMetrics(dc.GetDC(), sizeof(oMetrics), &oMetrics)) {
            mMetrics->superscriptOffset = (double)oMetrics.otmptSuperscriptOffset.y;
            // Some fonts have wrong sign on their subscript offset, bug 410917.
            mMetrics->subscriptOffset = fabs((double)oMetrics.otmptSubscriptOffset.y);
            mMetrics->strikeoutSize = (double)oMetrics.otmsStrikeoutSize;
            mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
            mMetrics->underlineSize = (double)oMetrics.otmsUnderscoreSize;
            mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;

            const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
            GLYPHMETRICS gm;
            DWORD len = GetGlyphOutlineW(dc.GetDC(), PRUnichar('x'), GGO_METRICS, &gm, 0, nullptr, &kIdentityMatrix);
            if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
                // 56% of ascent, best guess for true type
                mMetrics->xHeight =
                    ROUND((double)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
            } else {
                mMetrics->xHeight = gm.gmptGlyphOrigin.y;
            }
            mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
            gfxFloat typEmHeight = (double)oMetrics.otmAscent - (double)oMetrics.otmDescent;
            mMetrics->emAscent = ROUND(mMetrics->emHeight * (double)oMetrics.otmAscent / typEmHeight);
            mMetrics->emDescent = mMetrics->emHeight - mMetrics->emAscent;
            if (oMetrics.otmEMSquare > 0) {
                mFUnitsConvFactor = float(mAdjustedSize / oMetrics.otmEMSquare);
            }
        } else {
            // Make a best-effort guess at extended metrics
            // this is based on general typographic guidelines

            // GetTextMetrics can fail if the font file has been removed
            // or corrupted recently.
            BOOL result = GetTextMetrics(dc.GetDC(), &metrics);
            if (!result) {
                NS_WARNING("Missing or corrupt font data, fasten your seatbelt");
                mIsValid = false;
                memset(mMetrics, 0, sizeof(*mMetrics));
                return;
            }

            mMetrics->xHeight =
                ROUND((float)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
            mMetrics->superscriptOffset = mMetrics->xHeight;
            mMetrics->subscriptOffset = mMetrics->xHeight;
            mMetrics->strikeoutSize = 1;
            mMetrics->strikeoutOffset = ROUND(mMetrics->xHeight * 0.5f); // 50% of xHeight
            mMetrics->underlineSize = 1;
            mMetrics->underlineOffset = -ROUND((float)metrics.tmDescent * 0.30f); // 30% of descent
            mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
            mMetrics->emAscent = metrics.tmAscent - metrics.tmInternalLeading;
            mMetrics->emDescent = metrics.tmDescent;
        }

        mMetrics->internalLeading = metrics.tmInternalLeading;
        mMetrics->externalLeading = metrics.tmExternalLeading;
        mMetrics->maxHeight = metrics.tmHeight;
        mMetrics->maxAscent = metrics.tmAscent;
        mMetrics->maxDescent = metrics.tmDescent;
        mMetrics->maxAdvance = metrics.tmMaxCharWidth;
        mMetrics->aveCharWidth = NS_MAX<gfxFloat>(1, metrics.tmAveCharWidth);
        // The font is monospace when TMPF_FIXED_PITCH is *not* set!
        // See http://msdn2.microsoft.com/en-us/library/ms534202(VS.85).aspx
        if (!(metrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
            mMetrics->maxAdvance = mMetrics->aveCharWidth;
        }

        // Cache the width of a single space.
        SIZE size;
        GetTextExtentPoint32W(dc.GetDC(), L" ", 1, &size);
        mMetrics->spaceWidth = ROUND(size.cx);

        // Cache the width of digit zero.
        // XXX MSDN (http://msdn.microsoft.com/en-us/library/ms534223.aspx)
        // does not say what the failure modes for GetTextExtentPoint32 are -
        // is it safe to assume it will fail iff the font has no '0'?
        if (GetTextExtentPoint32W(dc.GetDC(), L"0", 1, &size)) {
            mMetrics->zeroOrAveCharWidth = ROUND(size.cx);
        } else {
            mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
        }

        mSpaceGlyph = 0;
        if (metrics.tmPitchAndFamily & TMPF_TRUETYPE) {
            WORD glyph;
            DWORD ret = GetGlyphIndicesW(dc.GetDC(), L" ", 1, &glyph,
                                         GGI_MARK_NONEXISTING_GLYPHS);
            if (ret != GDI_ERROR && glyph != 0xFFFF) {
                mSpaceGlyph = glyph;
            }
        }

        SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
    }

    if (IsSyntheticBold()) {
        mMetrics->aveCharWidth += GetSyntheticBoldOffset();
        mMetrics->maxAdvance += GetSyntheticBoldOffset();
    }

    mFontFace = cairo_win32_font_face_create_for_logfontw_hfont(&logFont,
                                                                mFont);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);

    if (useCairoFakeItalic) {
        // Skew the matrix to do fake italic if it wasn't already applied
        // via the LOGFONT
        double skewfactor = OBLIQUE_SKEW_FACTOR;
        cairo_matrix_t style;
        cairo_matrix_init(&style,
                          1,                //xx
                          0,                //yx
                          -1 * skewfactor,  //xy
                          1,                //yy
                          0,                //x0
                          0);               //y0
        cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
    }

    cairo_font_options_t *fontOptions = cairo_font_options_create();
    if (mAntialiasOption != kAntialiasDefault) {
        cairo_font_options_set_antialias(fontOptions,
            GetCairoAntialiasOption(mAntialiasOption));
    }
    mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix,
                                           &ctm, fontOptions);
    cairo_font_options_destroy(fontOptions);

    if (!mScaledFont ||
        cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
#ifdef DEBUG
        char warnBuf[1024];
        sprintf(warnBuf, "Failed to create scaled font: %s status: %d",
                NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(),
                mScaledFont ? cairo_scaled_font_status(mScaledFont) : 0);
        NS_WARNING(warnBuf);
#endif
        mIsValid = false;
    } else {
        mIsValid = true;
    }

#if 0
    printf("Font: %p (%s) size: %f adjusted size: %f valid: %s\n", this,
           NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size, mAdjustedSize, (mIsValid ? "yes" : "no"));
    printf("    emHeight: %f emAscent: %f emDescent: %f\n", mMetrics->emHeight, mMetrics->emAscent, mMetrics->emDescent);
    printf("    maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics->maxAscent, mMetrics->maxDescent, mMetrics->maxAdvance);
    printf("    internalLeading: %f externalLeading: %f\n", mMetrics->internalLeading, mMetrics->externalLeading);
    printf("    spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics->spaceWidth, mMetrics->aveCharWidth, mMetrics->xHeight);
    printf("    uOff: %f uSize: %f stOff: %f stSize: %f supOff: %f subOff: %f\n",
           mMetrics->underlineOffset, mMetrics->underlineSize, mMetrics->strikeoutOffset, mMetrics->strikeoutSize,
           mMetrics->superscriptOffset, mMetrics->subscriptOffset);
#endif
}
Exemplo n.º 4
0
//*************************************************************************
// DoPaint -- this is the WM_PAINT action routine for the main window.
// It places the TrueType logo in the upper left corner of the window, draws
// a "fan hub" around it, and draws "fan leaves" of text out from the hub.
// These leaves are scaled to reach the bottom and the right edge of the
// window, by defining an ellipse centered on the TrueType logo which just
// touches those two edges.  The text strings span the distance from the
// hub to the ellipse along radial lines, and are both scaled and rotated.
//     Depending on user-set state variables, the ellipse and baselines
// for the text fan may be shown (ShowAlignmentMarks), and/or the text may
// be shadowed (ShadowAll).  Other attributes, such as bolding or
// italicization, may be selected from the font dialog box.
//*************************************************************************
void DoPaint()
{
    PAINTSTRUCT       PaintInfo;
    HDC               hDC;
    LOGFONT           FontRec;
    OUTLINETEXTMETRIC FontMetric;
    int               FontHeight, x, y, j, k;
    WORD              BaseWidth, DesiredExtent, FanTextLen;
    float             Theta;
    LPCSTR            P;
    RECT              R;
    long              TE;
    int               d;

    BeginPaint(hwnd, &PaintInfo);

    hDC = PaintInfo.hdc;
    P = ArcText;
    FanTextLen = strlen(FanText);

    // save device context; easiest way to preserve current state
    SaveDC(hDC);

    // set initial font data (for TrueType logo)
    FontRec = CornerFontRec;
    SetBkMode(hDC, TRANSPARENT);
    SetTextColor(hDC, RGB(128,128,128));
    FontRec.lfHeight = FontRec.lfHeight * 2;
    FontRec.lfWidth = floor(FontRec.lfWidth * 2.1);

    // create the TrueType logo
    SelectObject(hDC, CreateFontIndirect(&FontRec));
    TextOut(hDC, 18, 5, "T", 1);
    SetTextColor(hDC, RGB(0,0,0));
    TextOut(hDC, 32, 13,"T", 1);

    // determine window dimensions & set up fan text parameters
    GetClientRect(hwnd, &R);
    FontRec = MainFontRec;
    DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
    GetOutlineTextMetrics(hDC, sizeof(FontMetric), &FontMetric);
    FontHeight = FontMetric.otmTextMetrics.tmHeight;
    SetViewportOrg(hDC, FontHeight+2, 0);
    R.right -= FontHeight+2;
    BaseWidth = LOWORD(GetTextExtent(hDC, FanText, FanTextLen));

    // get a "black brush" for drawing operations
    SelectObject(hDC, GetStockObject(NULL_BRUSH));

    // if we want to show the alignment marks, draw the bounding ellipse
    if (ShowAlignmentMarks)
    {
        Ellipse(hDC, -R.right, -R.bottom, R.right, R.bottom);
    }

    // draw the "hub" of the fan
    Ellipse(hDC, -(Radius-5), -(Radius-5), (Radius-5), Radius-5);
    Ellipse(hDC, -(Radius-10), -(Radius-10), (Radius-10), Radius-10);

    SetTextColor(hDC, FanColor[0]);

    // loop over the "fan leaves"
    for ( d = 27; d <= 36; d++)
    {
        x = ROUND(Radius * cos(d * Deg2Rad));
        y = ROUND(Radius * sin(-d * Deg2Rad)); // -d because y axis is inverted

        Theta = -d * Deg2Rad;
        if (x)
        {
            Theta = atan((R.right / (R.bottom * 1.0)) * (y / (x * 1.0)));
        }

        j = ROUND(R.right * cos(Theta));
        k = ROUND(R.bottom * sin(Theta));

        if (ShowAlignmentMarks)
        {
            MoveTo(hDC, x,y);
            LineTo(hDC, j,k);
        }

        DesiredExtent = ROUND(sqrt(SQR(x*1.0 - j) + SQR(y*1.0 - k))) - 5;
        FontRec = MainFontRec;
        FontRec.lfEscapement = d * 100;
        FontRec.lfWidth = floor((FontMetric.otmTextMetrics.tmAveCharWidth) *
                                (DesiredExtent / (BaseWidth * 1.0)));
        DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
        TE = GetTextExtent(hDC, FanText, FanTextLen);

        for ( ;(LOWORD(TE) > DesiredExtent) && (FontRec.lfWidth);
             FontRec.lfWidth-- )
        {
            // Shave off some character width until the string fits 
            DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
            TE = GetTextExtent(hDC, FanText, FanTextLen);
        }

        // Expand the string if necessary to make it fit the desired extent 
        if (LOWORD(TE) < DesiredExtent)
          { SetTextJustification(hDC,DesiredExtent - LOWORD(TE), 3); }
        if (ShadowAll)
        {
            SetTextColor(hDC, RGB(0,0,0));
            TextOut(hDC, x+2, y+1, FanText, FanTextLen);
        }
        SetTextColor(hDC, FanColor[d - 27]);
        TextOut(hDC, x, y, FanText, FanTextLen);
        // clear justifier's internal error accumulator 
        SetTextJustification(hDC,0,0);

        if (P[0])
        {
            FontRec = CornerFontRec;
            FontRec.lfEscapement = (d+10) * 100;
            FontRec.lfWidth = 0;
            DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
            SetTextColor(hDC, 0);
            x = floor((Radius - FontHeight - 5) * cos(d * Deg2Rad));
            y = floor((Radius - FontHeight - 5) * sin(-d * Deg2Rad));
            TextOut(hDC, x, y, P, 1);
            P++;
        } // if
    } // for d

    // lose the fan font, selecting in the Borland text font
    DeleteObject(SelectObject(hDC, CreateFontIndirect(&BorlandFontRec)));
    TE = GetTextExtent(hDC, BorlandText, strlen(BorlandText));
    SetTextColor(hDC, RGB(0,0,0));
    // write the Borland text in the lower right corner, with a shadow effect
    TextOut(hDC, R.right - LOWORD(TE), R.bottom - HIWORD(TE), BorlandText,
            strlen(BorlandText));
    SetTextColor(hDC, RGB(255,0,0));
    TextOut(hDC, R.right - LOWORD(TE) - 5, R.bottom - HIWORD(TE), BorlandText,
            strlen(BorlandText));

    DeleteObject(SelectObject(hDC, GetStockObject(SYSTEM_FONT)));
    // restore the saved DC; easiest way to reset to entry state
    RestoreDC(hDC, -1);
    EndPaint(hwnd, &PaintInfo);
} // end of DoPaint()
Exemplo n.º 5
0
void
gfxGDIFont::Initialize()
{
    NS_ASSERTION(!mMetrics, "re-creating metrics? this will leak");

    LOGFONTW logFont;

    if (mAdjustedSize == 0.0) {
        mAdjustedSize = mStyle.size;
        if (mStyle.sizeAdjust != 0.0 && mAdjustedSize > 0.0) {
            // to implement font-size-adjust, we first create the "unadjusted" font
            FillLogFont(logFont, mAdjustedSize);
            mFont = ::CreateFontIndirectW(&logFont);

            // initialize its metrics so we can calculate size adjustment
            Initialize();

            // calculate the properly adjusted size, and then proceed
            // to recreate mFont and recalculate metrics
            gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
            mAdjustedSize = mStyle.GetAdjustedSize(aspect);

            // delete the temporary font and metrics
            ::DeleteObject(mFont);
            mFont = nsnull;
            delete mMetrics;
            mMetrics = nsnull;
        }
    }

    FillLogFont(logFont, mAdjustedSize);
    mFont = ::CreateFontIndirectW(&logFont);

    mMetrics = new gfxFont::Metrics;
    ::memset(mMetrics, 0, sizeof(*mMetrics));

    AutoDC dc;
    SetGraphicsMode(dc.GetDC(), GM_ADVANCED);
    AutoSelectFont selectFont(dc.GetDC(), mFont);

    // Get font metrics
    OUTLINETEXTMETRIC oMetrics;
    TEXTMETRIC& metrics = oMetrics.otmTextMetrics;

    if (0 < GetOutlineTextMetrics(dc.GetDC(), sizeof(oMetrics), &oMetrics)) {
        mMetrics->superscriptOffset = (double)oMetrics.otmptSuperscriptOffset.y;
        // Some fonts have wrong sign on their subscript offset, bug 410917.
        mMetrics->subscriptOffset = fabs((double)oMetrics.otmptSubscriptOffset.y);
        mMetrics->strikeoutSize = (double)oMetrics.otmsStrikeoutSize;
        mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
        mMetrics->underlineSize = (double)oMetrics.otmsUnderscoreSize;
        mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;

        const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
        GLYPHMETRICS gm;
        DWORD len = GetGlyphOutlineW(dc.GetDC(), PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &kIdentityMatrix);
        if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
            // 56% of ascent, best guess for true type
            mMetrics->xHeight =
                ROUND((double)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
        } else {
            mMetrics->xHeight = gm.gmptGlyphOrigin.y;
        }
        mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
        gfxFloat typEmHeight = (double)oMetrics.otmAscent - (double)oMetrics.otmDescent;
        mMetrics->emAscent = ROUND(mMetrics->emHeight * (double)oMetrics.otmAscent / typEmHeight);
        mMetrics->emDescent = mMetrics->emHeight - mMetrics->emAscent;
        if (oMetrics.otmEMSquare > 0) {
            mFUnitsConvFactor = float(GetAdjustedSize() / oMetrics.otmEMSquare);
        }
    } else {
        // Make a best-effort guess at extended metrics
        // this is based on general typographic guidelines
        
        // GetTextMetrics can fail if the font file has been removed
        // or corrupted recently.
        BOOL result = GetTextMetrics(dc.GetDC(), &metrics);
        if (!result) {
            NS_WARNING("Missing or corrupt font data, fasten your seatbelt");
            mIsValid = PR_FALSE;
            memset(mMetrics, 0, sizeof(*mMetrics));
            return;
        }

        mMetrics->xHeight =
            ROUND((float)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
        mMetrics->superscriptOffset = mMetrics->xHeight;
        mMetrics->subscriptOffset = mMetrics->xHeight;
        mMetrics->strikeoutSize = 1;
        mMetrics->strikeoutOffset = ROUND(mMetrics->xHeight * 0.5f); // 50% of xHeight
        mMetrics->underlineSize = 1;
        mMetrics->underlineOffset = -ROUND((float)metrics.tmDescent * 0.30f); // 30% of descent
        mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
        mMetrics->emAscent = metrics.tmAscent - metrics.tmInternalLeading;
        mMetrics->emDescent = metrics.tmDescent;
    }

    mMetrics->internalLeading = metrics.tmInternalLeading;
    mMetrics->externalLeading = metrics.tmExternalLeading;
    mMetrics->maxHeight = metrics.tmHeight;
    mMetrics->maxAscent = metrics.tmAscent;
    mMetrics->maxDescent = metrics.tmDescent;
    mMetrics->maxAdvance = metrics.tmMaxCharWidth;
    mMetrics->aveCharWidth = PR_MAX(1, metrics.tmAveCharWidth);
    // The font is monospace when TMPF_FIXED_PITCH is *not* set!
    // See http://msdn2.microsoft.com/en-us/library/ms534202(VS.85).aspx
    if (!(metrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
        mMetrics->maxAdvance = mMetrics->aveCharWidth;
    }

    // Cache the width of a single space.
    SIZE size;
    GetTextExtentPoint32W(dc.GetDC(), L" ", 1, &size);
    mMetrics->spaceWidth = ROUND(size.cx);

    // Cache the width of digit zero.
    // XXX MSDN (http://msdn.microsoft.com/en-us/library/ms534223.aspx)
    // does not say what the failure modes for GetTextExtentPoint32 are -
    // is it safe to assume it will fail iff the font has no '0'?
    if (GetTextExtentPoint32W(dc.GetDC(), L"0", 1, &size)) {
        mMetrics->zeroOrAveCharWidth = ROUND(size.cx);
    } else {
        mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
    }

    mSpaceGlyph = 0;
    if (metrics.tmPitchAndFamily & TMPF_TRUETYPE) {
        WORD glyph;
        DWORD ret = GetGlyphIndicesW(dc.GetDC(), L" ", 1, &glyph,
                                     GGI_MARK_NONEXISTING_GLYPHS);
        if (ret != GDI_ERROR && glyph != 0xFFFF) {
            mSpaceGlyph = glyph;
        }
    }

    SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);

    mFontFace = cairo_win32_font_face_create_for_logfontw_hfont(&logFont,
                                                                mFont);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);

    cairo_font_options_t *fontOptions = cairo_font_options_create();
    if (mAntialiasOption != kAntialiasDefault) {
        cairo_font_options_set_antialias(fontOptions,
            GetCairoAntialiasOption(mAntialiasOption));
    }
    mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix,
                                           &ctm, fontOptions);
    cairo_font_options_destroy(fontOptions);

    if (!mScaledFont ||
        cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
#ifdef DEBUG
        char warnBuf[1024];
        sprintf(warnBuf, "Failed to create scaled font: %s status: %d",
                NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(),
                mScaledFont ? cairo_scaled_font_status(mScaledFont) : 0);
        NS_WARNING(warnBuf);
#endif
    }

    mIsValid = PR_TRUE;

#if 0
    printf("Font: %p (%s) size: %f\n", this,
           NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size);
    printf("    emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
    printf("    maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance);
    printf("    internalLeading: %f externalLeading: %f\n", mMetrics.internalLeading, mMetrics.externalLeading);
    printf("    spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight);
    printf("    uOff: %f uSize: %f stOff: %f stSize: %f supOff: %f subOff: %f\n",
           mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize,
           mMetrics.superscriptOffset, mMetrics.subscriptOffset);
#endif
}
Exemplo n.º 6
0
//�������������������������������������������������������������������������Ŀ
// capture_tt                                                               �
//                                                                          �
// Captures a TrueType font into the output IFF (already open by main)      �
//���������������������������������������������������������������������������
void capture_tt(char *name, char *ttname,
                ushort width, ushort height,
                byte startc, ushort numc)
{
    int                 j;
    byte                *font, *fptr;
    ulong               fontSize;
    GBergFileFontHDR    header;
    byte                work[4096];

    assert(name != 0 && ttname != 0 && height > 0);

    memset(&header,0,sizeof(header));
    strncpy(header.name,name,sizeof(header.name));

    if (((int)startc+(int)numc-1) > 256)
    {
        cout << "��� Error: number of characters in set must fit in 128 or 256 chars";
        exit(1);
    }

    int numchars = (((int)startc+(int)numc-1) > 128) ? 256 : 128;

//��� Find and select font that meets input criteria
    HWND hWnd = GetDesktopWindow();
    assert(hWnd != 0);

    HDC hDC = GetDC(hWnd);
    assert(hDC != 0);

    HFONT               hFont, hOldFont;
    OUTLINETEXTMETRIC   tm;
    for(;;)
    {
        LOGFONT fontinfo;
        memset(&fontinfo,0,sizeof(fontinfo));
        fontinfo.lfHeight = height;
        if (Flags & FLAGS_TT_BOLD)
            fontinfo.lfWeight = FW_BOLD;
        if (Flags & FLAGS_TT_ITALIC)
            fontinfo.lfItalic = TRUE;
        if (Flags & FLAGS_TT_UNDERLINE)
            fontinfo.lfUnderline = TRUE;
        if (Flags & FLAGS_TT_STRIKEOUT)
            fontinfo.lfStrikeOut = TRUE;
        if (Flags & FLAGS_TT_OEMCHARSET)
            fontinfo.lfCharSet = OEM_CHARSET;
        fontinfo.lfOutPrecision = OUT_TT_ONLY_PRECIS;
        strncpy(fontinfo.lfFaceName,ttname,sizeof(fontinfo.lfFaceName));

        hFont = CreateFontIndirect(&fontinfo);
        if (!hFont)
        {
            cout << "��� Error: failed to get TrueType font with specified characteristics";
            ReleaseDC(hWnd,hDC);
            exit(1);
        }

        hOldFont = (HFONT__*)SelectObject(hDC,hFont);

        memset(&tm,0,sizeof(tm));
        GetOutlineTextMetrics(hDC,sizeof(tm),&tm);

        if (!width || tm.otmTextMetrics.tmMaxCharWidth <= width)
        {
            break;
        }
        else if (height <= 1)
        {
            cout << "��� Error: failed to get TrueType font with specified characteristics\n";
            SelectObject(hDC,hOldFont);
            DeleteObject(hFont);
            ReleaseDC(hWnd,hDC);
            exit(1);
        }
        else
        {
            height--;
            SelectObject(hDC,hOldFont);
        }
    }

//��� See if we can download bitmap for font...
    {
        GLYPHMETRICS glyph;
        MAT2 matrix;
        memset(&matrix,0,sizeof(matrix));
        matrix.eM11.value = 1;
        matrix.eM22.value = 1;

        if (GetGlyphOutline(hDC,0,GGO_BITMAP,&glyph,0,0,&matrix) == GDI_ERROR)
        {
            cout << "��� Error: Can't capture data for specified font characteristics\n";
            SelectObject(hDC,hOldFont);
            DeleteObject(hFont);
            ReleaseDC(hWnd,hDC);
            exit(1);
        }
    }

//��� Output information about selected font
    if (!(Flags & FLAGS_QUIET))
    {
        cout << "Capturing TrueType font '" << ttname << "'...\n";
        cout << "   Size: " << tm.otmTextMetrics.tmMaxCharWidth
             << " by " << tm.otmTextMetrics.tmHeight << endl;
        cout << "   Character #" << (int)startc << " to #" << ((int)startc+(int)numc-1) << endl;
        if (tm.otmfsType & 0x1)
            cout << "   *Licensed font*";
        cout << "   Attributes: ";

        switch (tm.otmTextMetrics.tmWeight)
        {
            case FW_THIN:
                cout << "Thin ";
                break;
            case FW_EXTRALIGHT:
                cout << "ExtraLight ";
                break;
            case FW_LIGHT:
                cout << "Light ";
                break;
            case FW_NORMAL:
                cout << "Normal ";
                break;
            case FW_MEDIUM:
                cout << "Medium ";
                break;
            case FW_SEMIBOLD:
                cout << "SemiBold ";
                break;
            case FW_BOLD:
                cout << "Bold ";
                break;
            case FW_EXTRABOLD:
                cout << "ExtraBold ";
                break;
            case FW_HEAVY:
                cout << "Heavy ";
                break;
            default:
                cout << "Wght(" << tm.otmTextMetrics.tmWeight << ") ";
                break;
        }
        if (tm.otmTextMetrics.tmItalic)
            cout << "Italic ";
        if (tm.otmTextMetrics.tmUnderlined)
            cout << "Underlined ";
        if (tm.otmTextMetrics.tmStruckOut)
            cout << "StruckOut ";
        if (tm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)
            cout << "Variable-pitch ";
        else
            cout << "Fixed-pitch ";
        cout << endl;

        cout << "   Family: ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_MODERN)
            cout << "Modern ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN)
            cout << "Roman ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT)
            cout << "Script ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_SWISS)
            cout << "Swiss ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_DECORATIVE)
            cout << "Decorative ";
        cout << endl;

        cout << "   CharSet: ";
        switch (tm.otmTextMetrics.tmCharSet)
        {
            case ANSI_CHARSET:
                cout << "ANSI ";
                break;
            case SYMBOL_CHARSET:
                cout << "Symbol ";
                break;
            case OEM_CHARSET:
                cout << "OEM ";
                break;
            default:
                cout << "#" << tm.otmTextMetrics.tmCharSet;
                break;
        }
        cout << endl;

        if ((numchars > 128) && (Flags & FLAGS_TT_CP850))
        {
            cout << "   Map special characters to Codepage 850\n";
        }
    }

    if (tm.otmTextMetrics.tmMaxCharWidth > 32)
    {
        cout << "��� Error: Maximum width must be less than or equal to 32";
        SelectObject(hDC,hOldFont);
        DeleteObject(hFont);
        ReleaseDC(hWnd,hDC);
        exit(1);
    }

//�� Font Header
    header.width = (ushort)tm.otmTextMetrics.tmMaxCharWidth;
    header.height = (ushort)tm.otmTextMetrics.tmHeight;

    // Only supports MONO non-COMPRESSED fonts
    header.compression = 0;
    if (tm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)
    {
        // Variable
        header.type = (numchars > 128) ? GBERG_FNT_MONOVARIABLEEX
                                       : GBERG_FNT_MONOVARIABLE;
        header.bpc = (ushort)((((header.width + 7) >> 3) * header.height) + 1);
    }
Exemplo n.º 7
0
CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, FX_BOOL bVert, FX_BOOL bTranslateName)
{
    pLogFont->lfHeight = -1000;
    pLogFont->lfWidth = 0;
    HGDIOBJ hFont = CreateFontIndirectA(pLogFont);
    HDC hDC = CreateCompatibleDC(NULL);
    hFont = SelectObject(hDC, hFont);
    int tm_size = GetOutlineTextMetrics(hDC, 0, NULL);
    if (tm_size == 0) {
        hFont = SelectObject(hDC, hFont);
        DeleteObject(hFont);
        DeleteDC(hDC);
        return NULL;
    }
    LPBYTE tm_buf = FX_Alloc(BYTE, tm_size);
    OUTLINETEXTMETRIC* ptm = (OUTLINETEXTMETRIC*)tm_buf;
    GetOutlineTextMetrics(hDC, tm_size, ptm);
    int flags = 0, italicangle, ascend, descend, capheight, bbox[4];
    if (pLogFont->lfItalic) {
        flags |= PDFFONT_ITALIC;
    }
    if ((pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH) {
        flags |= PDFFONT_FIXEDPITCH;
    }
    if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN) {
        flags |= PDFFONT_SERIF;
    }
    if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT) {
        flags |= PDFFONT_SCRIPT;
    }
    FX_BOOL bCJK = pLogFont->lfCharSet == CHINESEBIG5_CHARSET || pLogFont->lfCharSet == GB2312_CHARSET ||
                   pLogFont->lfCharSet == HANGEUL_CHARSET || pLogFont->lfCharSet == SHIFTJIS_CHARSET;
    CFX_ByteString basefont;
    if (bTranslateName && bCJK) {
        basefont = _FPDF_GetPSNameFromTT(hDC);
    }
    if (basefont.IsEmpty()) {
        basefont = pLogFont->lfFaceName;
    }
    italicangle = ptm->otmItalicAngle / 10;
    ascend = ptm->otmrcFontBox.top;
    descend = ptm->otmrcFontBox.bottom;
    capheight = ptm->otmsCapEmHeight;
    bbox[0] = ptm->otmrcFontBox.left;
    bbox[1] = ptm->otmrcFontBox.bottom;
    bbox[2] = ptm->otmrcFontBox.right;
    bbox[3] = ptm->otmrcFontBox.top;
    FX_Free(tm_buf);
    basefont.Replace(" ", "");
    CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary;
    pBaseDict->SetAtName("Type", "Font");
    CPDF_Dictionary* pFontDict = pBaseDict;
    if (!bCJK) {
        if (pLogFont->lfCharSet == ANSI_CHARSET || pLogFont->lfCharSet == DEFAULT_CHARSET ||
                pLogFont->lfCharSet == SYMBOL_CHARSET) {
            if (pLogFont->lfCharSet == SYMBOL_CHARSET) {
                flags |= PDFFONT_SYMBOLIC;
            } else {
                flags |= PDFFONT_NONSYMBOLIC;
            }
            pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
        } else {
            flags |= PDFFONT_NONSYMBOLIC;
            int i;
            for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++)
                if (g_FX_CharsetUnicodes[i].m_Charset == pLogFont->lfCharSet) {
                    break;
                }
            if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
                CPDF_Dictionary* pEncoding = FX_NEW CPDF_Dictionary;
                pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
                CPDF_Array* pArray = FX_NEW CPDF_Array;
                pArray->AddInteger(128);
                const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
                for (int j = 0; j < 128; j ++) {
                    CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
                    if (name.IsEmpty()) {
                        pArray->AddName(FX_BSTRC(".notdef"));
                    } else {
                        pArray->AddName(name);
                    }
                }
                pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
                AddIndirectObject(pEncoding);
                pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
            }
        }
        if (pLogFont->lfWeight > FW_MEDIUM && pLogFont->lfItalic) {
            basefont += ",BoldItalic";
        } else if (pLogFont->lfWeight > FW_MEDIUM) {
            basefont += ",Bold";
        } else if (pLogFont->lfItalic) {
            basefont += ",Italic";
        }
        pBaseDict->SetAtName("Subtype", "TrueType");
        pBaseDict->SetAtName("BaseFont", basefont);
        pBaseDict->SetAtNumber("FirstChar", 32);
        pBaseDict->SetAtNumber("LastChar", 255);
        int char_widths[224];
        GetCharWidth(hDC, 32, 255, char_widths);
        CPDF_Array* pWidths = FX_NEW CPDF_Array;
        for (int i = 0; i < 224; i ++) {
            pWidths->AddInteger(char_widths[i]);
        }
        pBaseDict->SetAt("Widths", pWidths);
    } else {
        flags |= PDFFONT_NONSYMBOLIC;
        pFontDict = FX_NEW CPDF_Dictionary;
        CFX_ByteString cmap;
        CFX_ByteString ordering;
        int supplement;
        CPDF_Array* pWidthArray = FX_NEW CPDF_Array;
        switch (pLogFont->lfCharSet) {
        case CHINESEBIG5_CHARSET:
            cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
            ordering = "CNS1";
            supplement = 4;
            pWidthArray->AddInteger(1);
            _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
            break;
        case GB2312_CHARSET:
            cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
            ordering = "GB1", supplement = 2;
            pWidthArray->AddInteger(7716);
            _InsertWidthArray(hDC, 0x20, 0x20, pWidthArray);
            pWidthArray->AddInteger(814);
            _InsertWidthArray(hDC, 0x21, 0x7e, pWidthArray);
            break;
        case HANGEUL_CHARSET:
            cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
            ordering = "Korea1";
            supplement = 2;
            pWidthArray->AddInteger(1);
            _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
            break;
        case SHIFTJIS_CHARSET:
            cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
            ordering = "Japan1";
            supplement = 5;
            pWidthArray->AddInteger(231);
            _InsertWidthArray(hDC, 0x20, 0x7d, pWidthArray);
            pWidthArray->AddInteger(326);
            _InsertWidthArray(hDC, 0xa0, 0xa0, pWidthArray);
            pWidthArray->AddInteger(327);
            _InsertWidthArray(hDC, 0xa1, 0xdf, pWidthArray);
            pWidthArray->AddInteger(631);
            _InsertWidthArray(hDC, 0x7e, 0x7e, pWidthArray);
            break;
        }
        pBaseDict->SetAtName("Subtype", "Type0");
        pBaseDict->SetAtName("BaseFont", basefont);
        pBaseDict->SetAtName("Encoding", cmap);
        pFontDict->SetAt("W", pWidthArray);
        pFontDict->SetAtName("Type", "Font");
        pFontDict->SetAtName("Subtype", "CIDFontType2");
        pFontDict->SetAtName("BaseFont", basefont);
        CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary;
        pCIDSysInfo->SetAtString("Registry", "Adobe");
        pCIDSysInfo->SetAtString("Ordering", ordering);
        pCIDSysInfo->SetAtInteger("Supplement", supplement);
        pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
        CPDF_Array* pArray = FX_NEW CPDF_Array;
        pBaseDict->SetAt("DescendantFonts", pArray);
        AddIndirectObject(pFontDict);
        pArray->AddReference(this, pFontDict);
    }
    AddIndirectObject(pBaseDict);
    CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary;
    pFontDesc->SetAtName("Type", "FontDescriptor");
    pFontDesc->SetAtName("FontName", basefont);
    pFontDesc->SetAtInteger("Flags", flags);
    CPDF_Array* pBBox = FX_NEW CPDF_Array;
    for (int i = 0; i < 4; i ++) {
        pBBox->AddInteger(bbox[i]);
    }
    pFontDesc->SetAt("FontBBox", pBBox);
    pFontDesc->SetAtInteger("ItalicAngle", italicangle);
    pFontDesc->SetAtInteger("Ascent", ascend);
    pFontDesc->SetAtInteger("Descent", descend);
    pFontDesc->SetAtInteger("CapHeight", capheight);
    pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5);
    AddIndirectObject(pFontDesc);
    pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
    hFont = SelectObject(hDC, hFont);
    DeleteObject(hFont);
    DeleteDC(hDC);
    return LoadFont(pBaseDict);
}
Exemplo n.º 8
0
void SimpleFontData::platformInit()
{
    m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
    m_scriptCache = 0;
    m_scriptFontProperties = 0;
    m_isSystemFont = false;

    if (m_platformData.useGDI())
       return initGDIFont();

    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    HDC hdc = GetDC(0);
    SaveDC(hdc);

    cairo_scaled_font_t* scaledFont = m_platformData.scaledFont();
    const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_platformData.size();

    cairo_win32_scaled_font_select_font(scaledFont, hdc);

    TEXTMETRIC textMetrics;
    GetTextMetrics(hdc, &textMetrics);
    float ascent = textMetrics.tmAscent * metricsMultiplier;
    float descent = textMetrics.tmDescent * metricsMultiplier;
    float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
    float lineGap = textMetrics.tmExternalLeading * metricsMultiplier;

    int faceLength = ::GetTextFace(hdc, 0, 0);
    Vector<WCHAR> faceName(faceLength);
    ::GetTextFace(hdc, faceLength, faceName.data());
    m_isSystemFont = !wcscmp(faceName.data(), L"Lucida Grande");
 
    ascent = ascentConsideringMacAscentHack(faceName.data(), ascent, descent);

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
    m_avgCharWidth = textMetrics.tmAveCharWidth * metricsMultiplier;
    m_maxCharWidth = textMetrics.tmMaxCharWidth * metricsMultiplier;

    OUTLINETEXTMETRIC metrics;
    if (GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics) > 0) {
        // This is a TrueType font.  We might be able to get an accurate xHeight
        GLYPHMETRICS gm;
        MAT2 mat = { 1, 0, 0, 1 };
        DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
        if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
            xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
    }

    m_fontMetrics.setXHeight(xHeight);
    cairo_win32_scaled_font_done_font(scaledFont);

    RestoreDC(hdc, -1);
    ReleaseDC(0, hdc);
}
Exemplo n.º 9
0
BOOL bTestGOTM (
    HDC     hdc
    )
{
    ULONG   row = 0;                    // screen row coordinate to print at
    HFONT   hfont;
    HFONT   hfontOriginal;
    LOGFONT lfnt;
    POUTLINETEXTMETRIC  potm;
    ULONG   cjotm;
    PSZ     pszPitch, pszFamily;


// Clear the screen to black.

    BitBlt(hdc, 0, 0, CX, CY, (HDC) 0, 0, 0, 0);

// Get a font.

    memset(&lfnt, 0, sizeof(lfnt));
    lstrcpy(lfnt.lfFaceName, "Arial");
    lfnt.lfHeight = -14;
    lfnt.lfWeight = 400;

    if ((hfont = CreateFontIndirect(&lfnt)) == NULL)
    {
        DbgPrint("ft!bTestGOTM(): Logical font creation failed.\n");
        return FALSE;
    }

    hfontOriginal = SelectObject(hdc, hfont);

// Determine size needed for OTM.

    if ( (cjotm = (ULONG) GetOutlineTextMetrics(hdc, 0, (POUTLINETEXTMETRIC) NULL)) == (ULONG) 0 )
    {
        DbgPrint("ft!bTestGOTM(): could not get size info from GetOutlineTextMetrics\n");
        return FALSE;
    }

// Allocate memory.

    if ( (potm = (POUTLINETEXTMETRIC) LocalAlloc(LPTR, cjotm)) == (POUTLINETEXTMETRIC) NULL )
    {
        DbgPrint("ft!bTestGOTM(): LocalAlloc(LPTR, 0x%lx) failed\n", cjotm);
        return FALSE;
    }

// Get the OTM.

    if ( GetOutlineTextMetrics(hdc, cjotm, potm) == (DWORD) 0 )
    {
        LocalFree(potm);

        DbgPrint("ft!bTestGOTM(): GetOutlineTextMetrics call failed\n");
        return FALSE;
    }

// Print TEXTMETRIC.

    vPrintTM(hdc, &potm->otmTextMetrics);
    DbgBreakPoint();

// Print TEXTMETRIC.

    vPrintOTM(hdc, potm);
    DbgBreakPoint();

// Restore the font.

    SelectObject(hdc, hfontOriginal);
    DeleteObject(hfont);

    LocalFree(potm);

    return TRUE;
}
Exemplo n.º 10
0
CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont,
                                         FX_BOOL bVert,
                                         FX_BOOL bTranslateName) {
  pLogFont->lfHeight = -1000;
  pLogFont->lfWidth = 0;
  HGDIOBJ hFont = CreateFontIndirectA(pLogFont);
  HDC hDC = CreateCompatibleDC(nullptr);
  hFont = SelectObject(hDC, hFont);
  int tm_size = GetOutlineTextMetrics(hDC, 0, nullptr);
  if (tm_size == 0) {
    hFont = SelectObject(hDC, hFont);
    DeleteObject(hFont);
    DeleteDC(hDC);
    return nullptr;
  }

  LPBYTE tm_buf = FX_Alloc(BYTE, tm_size);
  OUTLINETEXTMETRIC* ptm = reinterpret_cast<OUTLINETEXTMETRIC*>(tm_buf);
  GetOutlineTextMetrics(hDC, tm_size, ptm);
  int flags = CalculateFlags(false, pLogFont->lfItalic != 0,
                             (pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH,
                             (pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN,
                             (pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT,
                             pLogFont->lfCharSet == FXFONT_SYMBOL_CHARSET);

  bool bCJK = pLogFont->lfCharSet == FXFONT_CHINESEBIG5_CHARSET ||
              pLogFont->lfCharSet == FXFONT_GB2312_CHARSET ||
              pLogFont->lfCharSet == FXFONT_HANGUL_CHARSET ||
              pLogFont->lfCharSet == FXFONT_SHIFTJIS_CHARSET;
  CFX_ByteString basefont;
  if (bTranslateName && bCJK)
    basefont = FPDF_GetPSNameFromTT(hDC);

  if (basefont.IsEmpty())
    basefont = pLogFont->lfFaceName;

  int italicangle = ptm->otmItalicAngle / 10;
  int ascend = ptm->otmrcFontBox.top;
  int descend = ptm->otmrcFontBox.bottom;
  int capheight = ptm->otmsCapEmHeight;
  int bbox[4] = {ptm->otmrcFontBox.left, ptm->otmrcFontBox.bottom,
                 ptm->otmrcFontBox.right, ptm->otmrcFontBox.top};
  FX_Free(tm_buf);
  basefont.Replace(" ", "");
  CPDF_Dictionary* pBaseDict = new CPDF_Dictionary(m_pByteStringPool);
  pBaseDict->SetNameFor("Type", "Font");
  CPDF_Dictionary* pFontDict = pBaseDict;
  if (!bCJK) {
    if (pLogFont->lfCharSet == FXFONT_ANSI_CHARSET ||
        pLogFont->lfCharSet == FXFONT_DEFAULT_CHARSET ||
        pLogFont->lfCharSet == FXFONT_SYMBOL_CHARSET) {
      pBaseDict->SetNameFor("Encoding", "WinAnsiEncoding");
    } else {
      CalculateEncodingDict(pLogFont->lfCharSet, pBaseDict);
    }
    int char_widths[224];
    GetCharWidth(hDC, 32, 255, char_widths);
    CPDF_Array* pWidths = new CPDF_Array;
    for (size_t i = 0; i < 224; i++)
      pWidths->AddInteger(char_widths[i]);
    ProcessNonbCJK(pBaseDict, pLogFont->lfWeight > FW_MEDIUM,
                   pLogFont->lfItalic != 0, basefont, pWidths);
  } else {
    pFontDict =
        ProcessbCJK(pBaseDict, pLogFont->lfCharSet, bVert, basefont,
                    [&hDC](FX_WCHAR start, FX_WCHAR end, CPDF_Array* widthArr) {
                      InsertWidthArray(hDC, start, end, widthArr);
                    });
  }
  AddIndirectObject(pBaseDict);
  CPDF_Array* pBBox = new CPDF_Array;
  for (int i = 0; i < 4; i++)
    pBBox->AddInteger(bbox[i]);
  CPDF_Dictionary* pFontDesc =
      CalculateFontDesc(this, basefont, flags, italicangle, ascend, descend,
                        pBBox, pLogFont->lfWeight / 5);
  pFontDesc->SetIntegerFor("CapHeight", capheight);
  pFontDict->SetReferenceFor("FontDescriptor", this,
                             AddIndirectObject(pFontDesc));
  hFont = SelectObject(hDC, hFont);
  DeleteObject(hFont);
  DeleteDC(hDC);
  return LoadFont(pBaseDict);
}
Exemplo n.º 11
0
void font_instance::LoadGlyph(int glyph_id)
{
    if ( pFont == NULL ) {
        return;
    }
    InitTheFace();
#ifndef USE_PANGO_WIN32
    if ( !FT_IS_SCALABLE(theFace) ) {
        return; // bitmap font
    }
#endif

    if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
        Geom::PathBuilder path_builder;

        if ( nbGlyph >= maxGlyph ) {
            maxGlyph=2*nbGlyph+1;
            glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
        }
        font_glyph  n_g;
        n_g.pathvector=NULL;
        n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
        n_g.h_advance = 0;
        n_g.v_advance = 0;
        n_g.h_width = 0;
        n_g.v_width = 0;
        bool   doAdd=false;

#ifdef USE_PANGO_WIN32

#ifndef GGO_UNHINTED         // For compatibility with old SDKs.
#define GGO_UNHINTED 0x0100
#endif

        MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
        OUTLINETEXTMETRIC otm;
        GetOutlineTextMetrics(daddy->hScreenDC, sizeof(otm), &otm);
        GLYPHMETRICS metrics;
        DWORD bufferSize=GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
        double scale=1.0/daddy->fontSize;
        n_g.h_advance=metrics.gmCellIncX*scale;
        n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
        n_g.h_width=metrics.gmBlackBoxX*scale;
        n_g.v_width=metrics.gmBlackBoxY*scale;
        if ( bufferSize == GDI_ERROR) {
            // shit happened
        } else if ( bufferSize == 0) {
            // character has no visual representation, but is valid (eg whitespace)
            doAdd=true;
        } else {
            char *buffer = new char[bufferSize];
            if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
                // shit happened
            } else {
                // Platform SDK is rubbish, read KB87115 instead
                DWORD polyOffset=0;
                while ( polyOffset < bufferSize ) {
                    TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
                    if (polyOffset+polyHeader->cb > bufferSize) break;

                    if (polyHeader->dwType == TT_POLYGON_TYPE) {
                        path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
                        DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);

                        while ( curveOffset < polyOffset+polyHeader->cb ) {
                            TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
                            POINTFX const *p=polyCurve->apfx;
                            POINTFX const *endp=p+polyCurve->cpfx;

                            switch (polyCurve->wType) {
                            case TT_PRIM_LINE:
                                while ( p != endp )
                                    path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
                                break;

                            case TT_PRIM_QSPLINE:
                                {
                                    g_assert(polyCurve->cpfx >= 2);

                                    // The list of points specifies one or more control points and ends with the end point.
                                    // The intermediate points (on the curve) are the points between the control points.
                                    Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
                                    while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
                                        Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
                                        path_builder.quadTo(this_control, (new_control+this_control)/2);
                                        this_control = new_control;
                                    }
                                    Geom::Point end = pointfx_to_nrpoint(*p++, scale);
                                    path_builder.quadTo(this_control, end);
                                }
                                break;

                            case 3:  // TT_PRIM_CSPLINE
                                g_assert(polyCurve->cpfx % 3 == 0);
                                while ( p != endp ) {
                                    path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
                                                         pointfx_to_nrpoint(p[1], scale),
                                                         pointfx_to_nrpoint(p[2], scale));
                                    p += 3;
                                }
                                break;
                            }
                            curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
                        }
                    }
                    polyOffset += polyHeader->cb;
                }
                doAdd=true;
            }
            delete [] buffer;
        }
#else
        if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
            // shit happened
        } else {
            if ( FT_HAS_HORIZONTAL(theFace) ) {
                n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
                n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
            } else {
                n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
            }
            if ( FT_HAS_VERTICAL(theFace) ) {
                n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
                n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
            } else {
                n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
            }
            if ( theFace->glyph->format == ft_glyph_format_outline ) {
                FT_Outline_Funcs ft2_outline_funcs = {
                    ft2_move_to,
                    ft2_line_to,
                    ft2_conic_to,
                    ft2_cubic_to,
                    0, 0
                };
                FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
                FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
            }
            doAdd=true;
        }
#endif
        path_builder.finish();

        if ( doAdd ) {
            Geom::PathVector pv = path_builder.peek();
            // close all paths
            for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
                i->close();
            }
            if ( !pv.empty() ) {
                n_g.pathvector = new Geom::PathVector(pv);
                Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
                if (bounds) {
                    n_g.bbox[0] = bounds->left();
                    n_g.bbox[1] = bounds->top();
                    n_g.bbox[2] = bounds->right();
                    n_g.bbox[3] = bounds->bottom();
                }
            }
            glyphs[nbGlyph]=n_g;
            id_to_no[glyph_id]=nbGlyph;
            nbGlyph++;
        }
    } else {
    }
}
Exemplo n.º 12
0
LPTSTR ASSISTANT::Text::GetTtfName()
{   
   static _TCHAR tszTtfName[512];


   HKEY hKeyMachine; 
   LONG regErr = RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
                     _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), NULL,KEY_READ,&hKeyMachine); 
	if ( regErr != ERROR_SUCCESS )
   {
      LONG regErr = RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
                        _T("Software\\Microsoft\\Windows\\CurrentVersion\\Fonts"), NULL,KEY_READ,&hKeyMachine); 
      if ( regErr != ERROR_SUCCESS )
      {
         return NULL;
      }
	}

   DWORD subValues;
   regErr = RegQueryInfoKey(hKeyMachine, NULL, NULL, NULL, NULL, NULL, NULL, &subValues, NULL, NULL, NULL, NULL);
   if ( regErr != ERROR_SUCCESS )
   {
      return NULL;
   }

   HRESULT hr = ::CoInitialize(NULL);

   HDC hdc = ::CreateCompatibleDC(NULL);

   DWORD dwType;
   _TCHAR tszEntryName[512];
   _TCHAR tszEntryValue[512];
   
   HFONT font = CreateFontIndirect(&m_logFont);
   UINT cbData;       
   LPOUTLINETEXTMETRIC lpoltm;     
   SelectObject(hdc, font);
   cbData = GetOutlineTextMetrics (hdc, 0, NULL);
   DeleteObject(font);
   _TCHAR tszFontFace[512];
   if (cbData == 0) 
   {
      _tcscpy(tszFontFace, m_logFont.lfFaceName);
   }
   else
   {
      lpoltm = (LPOUTLINETEXTMETRIC)LocalAlloc (LPTR, cbData);
      GetOutlineTextMetrics (hdc, cbData, lpoltm);  
      _tcscpy(tszFontFace, (_TCHAR *)((DWORD) lpoltm + lpoltm->otmpFaceName));
   }

   bool bFoundFontInfo = false;
   for (int i = 0; i < subValues && !bFoundFontInfo; i++) 
   {       
      unsigned long entryNameLength = 512 * sizeof _TCHAR;
      unsigned long entryValueLength = 512 * sizeof _TCHAR;
      if (RegEnumValue(hKeyMachine, i, tszEntryName, &entryNameLength, 
         NULL, &dwType, (unsigned char *)tszEntryValue, &entryValueLength) != ERROR_SUCCESS)
      {
         continue;
      }
      
      _TCHAR tszFaceName[512];
      _tcscpy(tszFaceName, tszEntryName);
      _TCHAR *p = _tcsrchr(tszFaceName, '(');
      if (p != NULL)
         *p = '\0';

	  if (tszFaceName[_tcslen(tszFaceName) - 1] == _T(' '))
		  tszFaceName[_tcslen(tszFaceName) - 1] = _T('\0');

      if (_tcscmp(tszFontFace, tszFaceName) == 0)
      {
         bFoundFontInfo = true;
         UINT nStringLength = _tcslen(tszEntryValue);
         _tcscpy(tszTtfName, tszEntryValue);
         tszTtfName[nStringLength] = '\0';
      }

   }

   ::DeleteDC(hdc);
   ::CoUninitialize();

   RegCloseKey(hKeyMachine);

   if (bFoundFontInfo)
      return tszTtfName;
   else
      return NULL;

}