Beispiel #1
0
nsFontMetrics::nsFontMetrics(const nsFont& aFont, const Params& aParams,
                             nsDeviceContext *aContext)
    : mFont(aFont)
    , mLanguage(aParams.language)
    , mDeviceContext(aContext)
    , mP2A(aContext->AppUnitsPerDevPixel())
    , mOrientation(aParams.orientation)
    , mTextRunRTL(false)
    , mVertical(false)
    , mTextOrientation(0)
{
    gfxFontStyle style(aFont.style,
                       aFont.weight,
                       aFont.stretch,
                       gfxFloat(aFont.size) / mP2A,
                       aParams.language,
                       aParams.explicitLanguage,
                       aFont.sizeAdjust,
                       aFont.systemFont,
                       mDeviceContext->IsPrinterSurface(),
                       aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
                       aFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
                       aFont.languageOverride);

    aFont.AddFontFeaturesToStyle(&style);

    gfxFloat devToCssSize = gfxFloat(mP2A) /
        gfxFloat(mDeviceContext->AppUnitsPerCSSPixel());
    mFontGroup = gfxPlatform::GetPlatform()->
        CreateFontGroup(aFont.fontlist, &style, aParams.textPerf,
                        aParams.userFontSet, devToCssSize);
}
Beispiel #2
0
nsresult
nsFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
                    nsDeviceContext *aContext,
                    gfxUserFontSet *aUserFontSet)
{
    NS_ABORT_IF_FALSE(mP2A == -1, "already initialized");

    mFont = aFont;
    mLanguage = aLanguage;
    mDeviceContext = aContext;
    mP2A = mDeviceContext->AppUnitsPerDevPixel();

    gfxFontStyle style(aFont.style,
                       aFont.weight,
                       aFont.stretch,
                       gfxFloat(aFont.size) / mP2A,
                       aLanguage,
                       aFont.sizeAdjust,
                       aFont.systemFont,
                       mDeviceContext->IsPrinterSurface(),
                       aFont.featureSettings,
                       aFont.languageOverride);

    mFontGroup = gfxPlatform::GetPlatform()->
        CreateFontGroup(aFont.name, &style, aUserFontSet);
    if (mFontGroup->FontListLength() < 1)
        return NS_ERROR_UNEXPECTED;

    return NS_OK;
}
Beispiel #3
0
nsresult
nsFontMetrics::Init(const nsFont& aFont,
                    nsIAtom* aLanguage, bool aExplicitLanguage,
                    gfxFont::Orientation aOrientation,
                    nsDeviceContext *aContext,
                    gfxUserFontSet *aUserFontSet,
                    gfxTextPerfMetrics *aTextPerf)
{
    MOZ_ASSERT(mP2A == 0, "already initialized");

    mFont = aFont;
    mLanguage = aLanguage;
    mOrientation = aOrientation;
    mDeviceContext = aContext;
    mP2A = mDeviceContext->AppUnitsPerDevPixel();

    gfxFontStyle style(aFont.style,
                       aFont.weight,
                       aFont.stretch,
                       gfxFloat(aFont.size) / mP2A,
                       aLanguage,
                       aExplicitLanguage,
                       aFont.sizeAdjust,
                       aFont.systemFont,
                       mDeviceContext->IsPrinterSurface(),
                       aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
                       aFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
                       aFont.languageOverride);

    aFont.AddFontFeaturesToStyle(&style);

    mFontGroup = gfxPlatform::GetPlatform()->
        CreateFontGroup(aFont.fontlist, &style, aTextPerf, aUserFontSet);
    return NS_OK;
}
nsresult
nsFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
                    nsDeviceContext *aContext,
                    gfxUserFontSet *aUserFontSet,
                    gfxTextPerfMetrics *aTextPerf)
{
    NS_ABORT_IF_FALSE(mP2A == 0, "already initialized");

    mFont = aFont;
    mLanguage = aLanguage;
    mDeviceContext = aContext;
    mP2A = mDeviceContext->AppUnitsPerDevPixel();

    gfxFontStyle style(aFont.style,
                       aFont.weight,
                       aFont.stretch,
                       gfxFloat(aFont.size) / mP2A,
                       aLanguage,
                       aFont.sizeAdjust,
                       aFont.systemFont,
                       mDeviceContext->IsPrinterSurface(),
                       aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
                       aFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
                       aFont.languageOverride);

    aFont.AddFontFeaturesToStyle(&style);

    mFontGroup = gfxPlatform::GetPlatform()->
        CreateFontGroup(aFont.fontlist, &style, aUserFontSet);
    mFontGroup->SetTextPerfMetrics(aTextPerf);
    if (mFontGroup->FontListLength() < 1)
        return NS_ERROR_UNEXPECTED;

    return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
                          nsIDeviceContext *aContext, 
                          gfxUserFontSet *aUserFontSet)
{
    mFont = aFont;
    mLangGroup = aLangGroup;
    mDeviceContext = (nsThebesDeviceContext*)aContext;
    mP2A = mDeviceContext->AppUnitsPerDevPixel();
    mIsRightToLeft = PR_FALSE;
    mTextRunRTL = PR_FALSE;

    gfxFloat size = gfxFloat(aFont.size) / mP2A;

    nsCString langGroup;
    if (aLangGroup) {
        const char* lg;
        mLangGroup->GetUTF8String(&lg);
        langGroup.Assign(lg);
    }

    PRBool printerFont = mDeviceContext->IsPrinterSurface();
    mFontStyle = new gfxFontStyle(aFont.style, aFont.weight, aFont.stretch,
                                  size, langGroup,
                                  aFont.sizeAdjust, aFont.systemFont,
                                  aFont.familyNameQuirks,
                                  printerFont);

    mFontGroup =
        gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle, 
                                                    aUserFontSet);
    if (mFontGroup->FontListLength() < 1) 
        return NS_ERROR_UNEXPECTED;

    return NS_OK;
}
void
gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext    *aContext,
                                       const gfxRect& aRect,
                                       uint32_t       aChar,
                                       uint32_t       aAppUnitsPerDevPixel)
{
    aContext->Save();

    gfxRGBA currentColor;
    if (!aContext->GetDeviceColor(currentColor)) {
        // We're currently drawing with some kind of pattern... Just draw
        // the missing-glyph data in black.
        currentColor = gfxRGBA(0,0,0,1);
    }

    // Stroke a rectangle so that the stroke's left edge is inset one pixel
    // from the left edge of the glyph box and the stroke's right edge
    // is inset one pixel from the right edge of the glyph box.
    gfxFloat halfBorderWidth = BOX_BORDER_WIDTH / 2.0;
    gfxFloat borderLeft = aRect.X() + BOX_HORIZONTAL_INSET + halfBorderWidth;
    gfxFloat borderRight = aRect.XMost() - BOX_HORIZONTAL_INSET - halfBorderWidth;
    gfxRect borderStrokeRect(borderLeft, aRect.Y() + halfBorderWidth,
                             borderRight - borderLeft,
                             aRect.Height() - 2.0 * halfBorderWidth);
    if (!borderStrokeRect.IsEmpty()) {
        aContext->SetLineWidth(BOX_BORDER_WIDTH);
        aContext->SetDash(gfxContext::gfxLineSolid);
        aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
        aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
        gfxRGBA color = currentColor;
        color.a *= BOX_BORDER_OPACITY;
        aContext->SetDeviceColor(color);
        aContext->NewPath();
        aContext->Rectangle(borderStrokeRect);

#ifdef MOZ_GFX_OPTIMIZE_MOBILE
        aContext->Fill();
#else
        aContext->Stroke();
#endif
    }

#ifndef MOZ_GFX_OPTIMIZE_MOBILE
    gfxPoint center(aRect.X() + aRect.Width() / 2,
                    aRect.Y() + aRect.Height() / 2);
    gfxFloat halfGap = HEX_CHAR_GAP / 2.0;
    gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
    aContext->SetDeviceColor(currentColor);
    aContext->Translate(center);
    // We always want integer scaling, otherwise the "bitmap" glyphs will look
    // even uglier than usual when zoomed
    int32_t scale =
        std::max<int32_t>(1, nsDeviceContext::AppUnitsPerCSSPixel() /
                             aAppUnitsPerDevPixel);
    aContext->Scale(gfxFloat(scale), gfxFloat(scale));
    if (aChar < 0x10000) {
        if (aRect.Width() >= 2 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
            aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
            // Draw 4 digits for BMP
            gfxFloat left = -(MINIFONT_WIDTH + halfGap);
            DrawHexChar(aContext,
                        gfxPoint(left, top), (aChar >> 12) & 0xF);
            DrawHexChar(aContext,
                        gfxPoint(halfGap, top), (aChar >> 8) & 0xF);
            DrawHexChar(aContext,
                        gfxPoint(left, halfGap), (aChar >> 4) & 0xF);
            DrawHexChar(aContext,
                        gfxPoint(halfGap, halfGap), aChar & 0xF);
        }
    } else {
nsresult
nsThebesImage::ThebesDrawTile(gfxContext *thebesContext,
                              nsIDeviceContext* dx,
                              const gfxPoint& offset,
                              const gfxRect& targetRect,
                              const nsIntRect& aSubimageRect,
                              const PRInt32 xPadding,
                              const PRInt32 yPadding)
{
    NS_ASSERTION(xPadding >= 0 && yPadding >= 0, "negative padding");

    if (targetRect.size.width <= 0.0 || targetRect.size.height <= 0.0)
        return NS_OK;

    // don't do anything if we have a transparent pixel source
    if (mSinglePixel && mSinglePixelColor.a == 0.0)
        return NS_OK;

    PRBool doSnap = !(thebesContext->CurrentMatrix().HasNonTranslation());
    PRBool hasPadding = ((xPadding != 0) || (yPadding != 0));
    gfxImageSurface::gfxImageFormat format = mFormat;
    
    gfxPoint tmpOffset = offset;

    if (mSinglePixel && !hasPadding) {
        thebesContext->SetDeviceColor(mSinglePixelColor);
    } else {
        nsRefPtr<gfxASurface> surface;
        PRInt32 width, height;

        if (hasPadding) {
            /* Ugh we have padding; create a temporary surface that's the size of the surface + pad area,
             * and render the image into it first.  Then we'll tile that surface. */
            width = mWidth + xPadding;
            height = mHeight + yPadding;

            // Reject over-wide or over-tall images.
            if (!AllowedImageSize(width, height))
                return NS_ERROR_FAILURE;

            format = gfxASurface::ImageFormatARGB32;
            surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
                    gfxIntSize(width, height), format);
            if (!surface || surface->CairoStatus()) {
                return NS_ERROR_OUT_OF_MEMORY;
            }

            gfxContext tmpContext(surface);
            if (mSinglePixel) {
                tmpContext.SetDeviceColor(mSinglePixelColor);
            } else {
                tmpContext.SetSource(ThebesSurface());
            }
            tmpContext.SetOperator(gfxContext::OPERATOR_SOURCE);
            tmpContext.Rectangle(gfxRect(0, 0, mWidth, mHeight));
            tmpContext.Fill();
        } else {
            width = mWidth;
            height = mHeight;
            surface = ThebesSurface();
        }
        
        // Scale factor to account for CSS pixels; note that the offset (and 
        // therefore p0) is in device pixels, while the width and height are in
        // CSS pixels.
        gfxFloat scale = gfxFloat(dx->AppUnitsPerDevPixel()) /
                         gfxFloat(nsIDeviceContext::AppUnitsPerCSSPixel());

        if ((aSubimageRect.width < width || aSubimageRect.height < height) &&
            (thebesContext->CurrentMatrix().HasNonTranslation() || scale != 1.0)) {
            // Some of the source image should not be drawn, and we're going
            // to be doing more than just translation, so we might accidentally
            // sample the non-drawn pixels. Avoid that by creating a
            // temporary image representing the portion that will be drawn,
            // with built-in padding since we can't use EXTEND_PAD and
            // EXTEND_REPEAT at the same time for different axes.
            PRInt32 padX = aSubimageRect.width < width ? 1 : 0;
            PRInt32 padY = aSubimageRect.height < height ? 1 : 0;
            PRInt32 tileWidth = PR_MIN(aSubimageRect.width, width);
            PRInt32 tileHeight = PR_MIN(aSubimageRect.height, height);
            
            // This tmpSurface will contain a snapshot of the repeated
            // tile image at (aSubimageRect.x, aSubimageRect.y,
            // tileWidth, tileHeight), with padX padding added to the left
            // and right sides and padY padding added to the top and bottom
            // sides.
            nsRefPtr<gfxASurface> tmpSurface;
            tmpSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
                    gfxIntSize(tileWidth + 2*padX, tileHeight + 2*padY), format);
            if (!tmpSurface || tmpSurface->CairoStatus()) {
                return NS_ERROR_OUT_OF_MEMORY;
            }

            gfxContext tmpContext(tmpSurface);
            tmpContext.SetOperator(gfxContext::OPERATOR_SOURCE);
            gfxPattern pat(surface);
            pat.SetExtend(gfxPattern::EXTEND_REPEAT);
            
            // Copy the needed portion of the source image to the temporary
            // surface. We also copy over horizontal and/or vertical padding
            // strips one pixel wide, plus the corner pixels if necessary.
            // So in the most general case the temporary surface ends up
            // looking like
            //     P P P ... P P P
            //     P X X ... X X P
            //     P X X ... X X P
            //     ...............
            //     P X X ... X X P
            //     P X X ... X X P
            //     P P P ... P P P
            // Where each P pixel has the color of its nearest source X
            // pixel. We implement this as a loop over all nine possible
            // areas, [padding, body, padding] x [padding, body, padding].
            // Note that we will not need padding on both axes unless
            // we are painting just a single tile, in which case this
            // will hardly ever get called since nsCSSRendering converts
            // the single-tile case to nsLayoutUtils::DrawImage. But this
            // could be called on other paths (XUL trees?) and it's simpler
            // and clearer to do it the general way.
            PRInt32 destY = 0;
            for (PRInt32 y = -1; y <= 1; ++y) {
                PRInt32 stripHeight = y == 0 ? tileHeight : padY;
                if (stripHeight == 0)
                    continue;
                PRInt32 srcY = y == 1 ? aSubimageRect.YMost() - padY : aSubimageRect.y;
                
                PRInt32 destX = 0;
                for (PRInt32 x = -1; x <= 1; ++x) {
                    PRInt32 stripWidth = x == 0 ? tileWidth : padX;
                    if (stripWidth == 0)
                        continue;
                    PRInt32 srcX = x == 1 ? aSubimageRect.XMost() - padX : aSubimageRect.x;

                    gfxMatrix patMat;
                    patMat.Translate(gfxPoint(srcX - destX, srcY - destY));
                    pat.SetMatrix(patMat);
                    tmpContext.SetPattern(&pat);
                    tmpContext.Rectangle(gfxRect(destX, destY, stripWidth, stripHeight));
                    tmpContext.Fill();
                    tmpContext.NewPath();
                    
                    destX += stripWidth;
                }
                destY += stripHeight;
            }

            // tmpOffset was the top-left of the old tile image. Make it
            // the top-left of the new tile image. Note that tmpOffset is
            // in destination coordinate space so we have to scale our
            // CSS pixels.
            tmpOffset += gfxPoint(aSubimageRect.x - padX, aSubimageRect.y - padY)/scale;
            
            surface = tmpSurface;
        }

        gfxMatrix patMat;
        gfxPoint p0;

        p0.x = - floor(tmpOffset.x + 0.5);
        p0.y = - floor(tmpOffset.y + 0.5);
        patMat.Scale(scale, scale);
        patMat.Translate(p0);

        gfxPattern pat(surface);
        pat.SetExtend(gfxPattern::EXTEND_REPEAT);
        pat.SetMatrix(patMat);

#ifndef XP_MACOSX
        if (scale < 1.0) {
            // See bug 324698.  This is a workaround.  See comments
            // by the earlier SetFilter call.
            pat.SetFilter(0);
        }
#endif

        thebesContext->SetPattern(&pat);
    }

    gfxContext::GraphicsOperator op = thebesContext->CurrentOperator();
    if (op == gfxContext::OPERATOR_OVER && format == gfxASurface::ImageFormatRGB24)
        thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);

    thebesContext->NewPath();
    thebesContext->Rectangle(targetRect, doSnap);
    thebesContext->Fill();

    thebesContext->SetOperator(op);
    thebesContext->SetDeviceColor(gfxRGBA(0,0,0,0));

    return NS_OK;
}