Пример #1
0
glyph_metrics_t QFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition,
                                                            const QTransform &matrix,
                                                            GlyphFormat /*format*/)
{
    glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance

    UINT16 glyphIndex = glyph;
    FLOAT glyphAdvance = 0;

    DWRITE_GLYPH_OFFSET glyphOffset;
    glyphOffset.advanceOffset = 0;
    glyphOffset.ascenderOffset = 0;

    DWRITE_GLYPH_RUN glyphRun;
    glyphRun.fontFace = m_directWriteFontFace;
    glyphRun.fontEmSize = fontDef.pixelSize;
    glyphRun.glyphCount = 1;
    glyphRun.glyphIndices = &glyphIndex;
    glyphRun.glyphAdvances = &glyphAdvance;
    glyphRun.isSideways = false;
    glyphRun.bidiLevel = 0;
    glyphRun.glyphOffsets = &glyphOffset;

    DWRITE_MATRIX transform;
    transform.dx = subPixelPosition.toReal();
    transform.dy = 0;
    transform.m11 = matrix.m11();
    transform.m12 = matrix.m12();
    transform.m21 = matrix.m21();
    transform.m22 = matrix.m22();

    IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
    HRESULT hr = m_directWriteFactory->CreateGlyphRunAnalysis(
                &glyphRun,
                1.0f,
                &transform,
                DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
                DWRITE_MEASURING_MODE_NATURAL,
                0.0, 0.0,
                &glyphAnalysis
                );

    if (SUCCEEDED(hr)) {
        RECT rect;
        glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
        glyphAnalysis->Release();

        return glyph_metrics_t(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
                               bbox.xoff, bbox.yoff);
    } else {
        return glyph_metrics_t();
    }
}
Пример #2
0
QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t,
                                             QFixed subPixelPosition,
                                             int margin,
                                             const QTransform &xform)
{
    UINT16 glyphIndex = t;
    FLOAT glyphAdvance = 0;

    DWRITE_GLYPH_OFFSET glyphOffset;
    glyphOffset.advanceOffset = 0;
    glyphOffset.ascenderOffset = 0;

    DWRITE_GLYPH_RUN glyphRun;
    glyphRun.fontFace = m_directWriteFontFace;
    glyphRun.fontEmSize = fontDef.pixelSize;
    glyphRun.glyphCount = 1;
    glyphRun.glyphIndices = &glyphIndex;
    glyphRun.glyphAdvances = &glyphAdvance;
    glyphRun.isSideways = false;
    glyphRun.bidiLevel = 0;
    glyphRun.glyphOffsets = &glyphOffset;

    DWRITE_MATRIX transform;
    transform.dx = subPixelPosition.toReal();
    transform.dy = 0;
    transform.m11 = xform.m11();
    transform.m12 = xform.m12();
    transform.m21 = xform.m21();
    transform.m22 = xform.m22();

    IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
    HRESULT hr = m_directWriteFactory->CreateGlyphRunAnalysis(
                &glyphRun,
                1.0f,
                &transform,
                DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
                DWRITE_MEASURING_MODE_NATURAL,
                0.0, 0.0,
                &glyphAnalysis
                );

    if (SUCCEEDED(hr)) {
        RECT rect;
        glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);

        rect.left -= margin;
        rect.top -= margin;
        rect.right += margin;
        rect.bottom += margin;

        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;

        int size = width * height * 3;
        if (size > 0) {
            BYTE *alphaValues = new BYTE[size];
            qMemSet(alphaValues, size, 0);

            hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
                                                   &rect,
                                                   alphaValues,
                                                   size);

            if (SUCCEEDED(hr)) {
                QImage img(width, height, QImage::Format_RGB32);
                img.fill(0xffffffff);

                for (int y=0; y<height; ++y) {
                    uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
                    BYTE *src = alphaValues + width * 3 * y;

                    for (int x=0; x<width; ++x) {
                        dest[x] = *(src) << 16
                                | *(src + 1) << 8
                                | *(src + 2);

                        src += 3;
                    }
                }

                delete[] alphaValues;
                glyphAnalysis->Release();

                return img;
            } else {
                delete[] alphaValues;
                glyphAnalysis->Release();

                qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed");
            }
        }
    } else {
        qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateGlyphRunAnalysis failed");
    }

    return QImage();
}
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
        QFixed subPixelPosition,
        int margin,
        const QTransform &xform)
{
    glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform);
    int width = (metrics.width + margin * 2 + 4).ceil().toInt() ;
    int height = (metrics.height + margin * 2 + 4).ceil().toInt();

    UINT16 glyphIndex = t;
    FLOAT glyphAdvance = metrics.xoff.toReal();

    DWRITE_GLYPH_OFFSET glyphOffset;
    glyphOffset.advanceOffset = 0;
    glyphOffset.ascenderOffset = 0;

    DWRITE_GLYPH_RUN glyphRun;
    glyphRun.fontFace = m_directWriteFontFace;
    glyphRun.fontEmSize = fontDef.pixelSize;
    glyphRun.glyphCount = 1;
    glyphRun.glyphIndices = &glyphIndex;
    glyphRun.glyphAdvances = &glyphAdvance;
    glyphRun.isSideways = false;
    glyphRun.bidiLevel = 0;
    glyphRun.glyphOffsets = &glyphOffset;

    QFixed x = margin - metrics.x.floor() + subPixelPosition;
    QFixed y = margin - metrics.y.floor();

    DWRITE_MATRIX transform;
    transform.dx = x.toReal();
    transform.dy = y.toReal();
    transform.m11 = xform.m11();
    transform.m12 = xform.m12();
    transform.m21 = xform.m21();
    transform.m22 = xform.m22();

    IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
    HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
                     &glyphRun,
                     1.0f,
                     &transform,
                     DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
                     DWRITE_MEASURING_MODE_NATURAL,
                     0.0, 0.0,
                     &glyphAnalysis
                 );

    if (SUCCEEDED(hr)) {
        RECT rect;
        rect.left = 0;
        rect.top = 0;
        rect.right = width;
        rect.bottom = height;

        int size = width * height * 3;
        BYTE *alphaValues = new BYTE[size];
        memset(alphaValues, size, 0);

        hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
                                               &rect,
                                               alphaValues,
                                               size);

        if (SUCCEEDED(hr)) {
            QImage img(width, height, QImage::Format_RGB32);
            img.fill(0xffffffff);

            for (int y=0; y<height; ++y) {
                uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
                BYTE *src = alphaValues + width * 3 * y;

                for (int x=0; x<width; ++x) {
                    dest[x] = *(src) << 16
                              | *(src + 1) << 8
                              | *(src + 2);

                    src += 3;
                }
            }

            delete[] alphaValues;
            glyphAnalysis->Release();

            return img;
        } else {
            delete[] alphaValues;
            glyphAnalysis->Release();

            qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
        }

    } else {
        qErrnoWarning("%s: CreateGlyphRunAnalysis failed", __FUNCTION__);
    }

    return QImage();
}
Пример #4
0
cairo_warn cairo_int_status_t
_cairo_dwrite_scaled_show_glyphs(void			*scaled_font,
				 cairo_operator_t	 op,
				 const cairo_pattern_t	*pattern,
				 cairo_surface_t	*generic_surface,
				 int			 source_x,
				 int			 source_y,
				 int			 dest_x,
				 int			 dest_y,
				 unsigned int		 width,
				 unsigned int		 height,
				 cairo_glyph_t		*glyphs,
				 int			 num_glyphs,
				 cairo_region_t		*clip_region,
				 int			*remaining_glyphs)
{
    cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
    cairo_int_status_t status;

    if (width == 0 || height == 0)
	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;

    if (_cairo_surface_is_win32 (generic_surface) &&
	surface->format == CAIRO_FORMAT_RGB24 &&
	op == CAIRO_OPERATOR_OVER) {

	    //XXX: we need to set the clip region here

	status = (cairo_int_status_t)_cairo_dwrite_show_glyphs_on_surface (surface, op, pattern,
									  glyphs, num_glyphs, 
									  (cairo_scaled_font_t*)scaled_font, NULL);

	return status;
    } else {
	cairo_dwrite_scaled_font_t *dwritesf =
	    static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
	UINT16 *indices = new UINT16[num_glyphs];
	DWRITE_GLYPH_OFFSET *offsets = new DWRITE_GLYPH_OFFSET[num_glyphs];
	FLOAT *advances = new FLOAT[num_glyphs];
	BOOL transform = FALSE;

	DWRITE_GLYPH_RUN run;
	run.bidiLevel = 0;
	run.fontFace = ((cairo_dwrite_font_face_t*)dwritesf->base.font_face)->dwriteface;
	run.glyphIndices = indices;
	run.glyphCount = num_glyphs;
	run.isSideways = FALSE;
	run.glyphOffsets = offsets;
	run.glyphAdvances = advances;
    	IDWriteGlyphRunAnalysis *analysis;

	if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
	    dwritesf->mat.xx == dwritesf->base.font_matrix.xx && 
	    dwritesf->mat.yy == dwritesf->base.font_matrix.yy) {

	    for (int i = 0; i < num_glyphs; i++) {
		indices[i] = (WORD) glyphs[i].index;
		// Since we will multiply by our ctm matrix later for rotation effects
		// and such, adjust positions by the inverse matrix now.
		offsets[i].ascenderOffset = (FLOAT)dest_y - (FLOAT)glyphs[i].y;
		offsets[i].advanceOffset = (FLOAT)glyphs[i].x - dest_x;
		advances[i] = 0.0;
	    }
	    run.fontEmSize = (FLOAT)dwritesf->base.font_matrix.yy;
	} else {
	    transform = TRUE;

	    for (int i = 0; i < num_glyphs; i++) {
		indices[i] = (WORD) glyphs[i].index;
		double x = glyphs[i].x - dest_x;
		double y = glyphs[i].y - dest_y;
		cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
		// Since we will multiply by our ctm matrix later for rotation effects
		// and such, adjust positions by the inverse matrix now.
		offsets[i].ascenderOffset = -(FLOAT)y;
		offsets[i].advanceOffset = (FLOAT)x;
		advances[i] = 0.0;
	    }
	    run.fontEmSize = 1.0f;
	}

	if (!transform) {
	    DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
							      1.0f,
							      NULL,
							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
							      DWRITE_MEASURING_MODE_NATURAL,
							      0,
							      0,
							      &analysis);
	} else {
	    DWRITE_MATRIX dwmatrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
	    DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
							      1.0f,
							      &dwmatrix,
							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
							      DWRITE_MEASURING_MODE_NATURAL,
							      0,
							      0,
							      &analysis);
	}

	RECT r;
	r.left = 0;
	r.top = 0;
	r.right = width;
	r.bottom = height;

	BYTE *surface = new BYTE[width * height * 3];

	analysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &r, surface, width * height * 3);

	cairo_image_surface_t *mask_surface = 
	    (cairo_image_surface_t*)cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);

	cairo_surface_flush(&mask_surface->base);

	for (unsigned int y = 0; y < height; y++) {
	    for (unsigned int x = 0; x < width; x++) {
		mask_surface->data[y * mask_surface->stride + x * 4] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 1] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 2] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 3] = surface[y * width * 3 + x * 3 + 1];
	    }
	}
	cairo_surface_mark_dirty(&mask_surface->base);

	pixman_image_set_component_alpha(mask_surface->pixman_image, 1);

	cairo_surface_pattern_t mask;
	_cairo_pattern_init_for_surface (&mask, &mask_surface->base);

	status = (cairo_int_status_t)_cairo_surface_composite (op, pattern,
							       &mask.base,
							       generic_surface,
							       source_x, source_y,
							       0, 0,
							       dest_x, dest_y,
							       width, height,
							       clip_region);

	_cairo_pattern_fini (&mask.base);

	analysis->Release();
	delete [] surface;
	delete [] indices;
	delete [] offsets;
	delete [] advances;

	cairo_surface_destroy (&mask_surface->base);
	*remaining_glyphs = 0;

	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
    }
}