Пример #1
0
bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
#if !(SDLMAME_SDL2)
	TTF_Font *ttffont;
	SDL_Surface *drawsurf;
	SDL_Color fcol = { 0xff, 0xff, 0xff };
	UINT16 ustr[16];

	ttffont = (TTF_Font *)font;

	memset(ustr,0,sizeof(ustr));
	ustr[0] = (UINT16)chnum;
	drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);

	// was nothing returned?
	if (drawsurf)
	{
		// allocate a MAME destination bitmap
		bitmap.allocate(drawsurf->w, drawsurf->h);

		// copy the rendered character image into it
		for (int y = 0; y < bitmap.height(); y++)
		{
			UINT32 *dstrow = &bitmap.pix32(y);
			UINT8 *srcrow = (UINT8 *)drawsurf->pixels;

			srcrow += (y * drawsurf->pitch);

			for (int x = 0; x < drawsurf->w; x++)
			{
				dstrow[x] = srcrow[x] ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(0x00,0xff,0xff,0xff);
			}
		}

		// what are these?
		xoffs = yoffs = 0;
		width = drawsurf->w;

		SDL_FreeSurface(drawsurf);
	}

	return bitmap.valid();
#else
	return false;
#endif
}
Пример #2
0
bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
   UniChar uni_char;
   CGGlyph glyph;
   CTFontRef ct_font = (CTFontRef)font;
   const CFIndex count = 1;
   CGRect bounding_rect, success_rect;
   CGContextRef context_ref;

   if( chnum == ' ' )
   {
      uni_char = 'n';
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
      uni_char = chnum;
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
   }
   else
   {
      uni_char = chnum;
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
   }

   if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
   {
      size_t bitmap_width;
      size_t bitmap_height;

      bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
      bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;

      bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);

      xoffs = yoffs = 0;
      width = bitmap_width;

      size_t bits_per_component;
      CGColorSpaceRef color_space;
      CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;

      color_space = CGColorSpaceCreateDeviceRGB();
      bits_per_component = 8;

      bitmap.allocate(bitmap_width, bitmap_height);

      context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );

      if( context_ref != NULL )
      {
         CGFontRef font_ref;
         font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
         CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
         CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
         CGContextSetFont( context_ref, font_ref );
         CGContextSetFontSize( context_ref, POINT_SIZE );
         CGContextShowGlyphs( context_ref, &glyph, count );
         CGFontRelease( font_ref );
         CGContextRelease( context_ref );
      }

      CGColorSpaceRelease( color_space );
   }

   return bitmap.valid();
}
Пример #3
0
	virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) override
	{
		const int MEM_ALIGN_CONST = 31;
		const int BITMAP_PAD = 50;

		HRESULT result;
		UINT cbData;
		BYTE* pixels = nullptr;

		ComPtr<ID2D1BitmapRenderTarget>     target;
		ComPtr<ID2D1SolidColorBrush>        pWhiteBrush;
		ComPtr<IWICBitmap>                  wicBitmap;
		ComPtr<IWICBitmapLock>              lock;

		ComPtr<IDWriteFontFace> face;
		HR_RET0(m_font->CreateFontFace(face.GetAddressOf()));

		// get the GDI metrics
		DWRITE_FONT_METRICS gdi_metrics;
		HR_RET0(face->GetGdiCompatibleMetrics(
			m_fontEmHeightInDips,
			1.0f,
			nullptr,
			&gdi_metrics));

		FontDimensionFactory fdf(gdi_metrics.designUnitsPerEm, m_fontEmHeightInDips);

		UINT32 tempChar = chnum;
		UINT16 glyphIndex;
		HR_RET0(face->GetGlyphIndicesW(&tempChar, 1, &glyphIndex));

		// get the width of this character
		DWRITE_GLYPH_METRICS glyph_metrics = { 0 };
		HR_RET0(face->GetGdiCompatibleGlyphMetrics(
			m_fontEmHeightInDips,
			1.0f,
			nullptr,
			FALSE,
			&glyphIndex,
			1,
			&glyph_metrics));

		// The height is the ascent added to the descent
		// By definition, the Em is equal to Cell Height minus Internal Leading (topSide bearing).
		//auto cellheight = fdf.FromDesignUnit(gdi_metrics.ascent + gdi_metrics.descent + gdi_metrics.);
		auto ascent = fdf.FromDesignUnit(gdi_metrics.ascent);
		auto descent = fdf.FromDesignUnit(gdi_metrics.descent);
		auto charHeight = ascent + descent;

		auto abc = fdf.CreateAbcWidths(
			glyph_metrics.advanceWidth,
			glyph_metrics.leftSideBearing,
			glyph_metrics.rightSideBearing);

		width = abc.abcA().Dips() + abc.abcB().Dips() + abc.abcC().Dips();

		// determine desired bitmap size
		int bmwidth = (BITMAP_PAD + abc.abcA().Dips() + abc.abcB().Dips() + abc.abcC().Dips() + BITMAP_PAD + MEM_ALIGN_CONST) & ~MEM_ALIGN_CONST;
		int bmheight = BITMAP_PAD + charHeight.Dips() + BITMAP_PAD;

		// GUID_WICPixelFormat8bppAlpha is 8 bits per pixel
		const REFWICPixelFormatGUID     source_bitmap_wic_format = GUID_WICPixelFormat8bppAlpha;
		const DXGI_FORMAT               source_bitmap_dxgi_format = DXGI_FORMAT_A8_UNORM;
		const D2D1_ALPHA_MODE           source_bitmap_d2d_alpha_mode = D2D1_ALPHA_MODE_STRAIGHT;

		// describe the bitmap we want
		HR_RET0(m_wicFactory->CreateBitmap(
			bmwidth,
			bmheight,
			source_bitmap_wic_format,
			WICBitmapCacheOnLoad,
			wicBitmap.GetAddressOf()));

		D2D1_RENDER_TARGET_PROPERTIES targetProps;
		targetProps = D2D1::RenderTargetProperties();
		targetProps.pixelFormat = D2D1::PixelFormat(source_bitmap_dxgi_format, source_bitmap_d2d_alpha_mode);

		// create a DIB to render to
		HR_RET0(this->m_d2dfactory->CreateWicBitmapRenderTarget(
			wicBitmap.Get(),
			&targetProps,
			reinterpret_cast<ID2D1RenderTarget**>(target.GetAddressOf())));

		target->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);

		// Create our brush
		HR_RET0(target->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), pWhiteBrush.GetAddressOf()));

		// Signal the start of the frame
		target->BeginDraw();

		// clear the bitmap
		// In the alpha mask, it will look like 0x00 per pixel
		target->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));

		// now draw the character
		DWRITE_GLYPH_RUN run = { nullptr };
		DWRITE_GLYPH_OFFSET offsets;
		offsets.advanceOffset = 0;
		offsets.ascenderOffset = 0;
		float advanceWidth = abc.advanceWidth().Dips();

		run.fontEmSize = m_fontEmHeightInDips;
		run.fontFace = face.Get();
		run.glyphCount = 1;
		run.glyphIndices = &glyphIndex;
		run.glyphAdvances = &advanceWidth;
		run.glyphOffsets = &offsets;

		auto baseline_origin = D2D1::Point2F(BITMAP_PAD + abc.abcA().Dips() + 1, BITMAP_PAD + ascent.Dips());
		target->DrawGlyphRun(
			baseline_origin,
			&run,
			pWhiteBrush.Get(),
			DWRITE_MEASURING_MODE_GDI_CLASSIC);

		HR_RET0(target->EndDraw());

#ifdef DWRITE_DEBUGGING
		// Save to file for debugging
		SaveBitmap(wicBitmap.Get(), GUID_WICPixelFormatBlackWhite, L"C:\\temp\\ddraw_step1.bmp");
#endif

		// characters are expected to be full-height
		rectangle actbounds;
		actbounds.min_y = BITMAP_PAD;
		actbounds.max_y = BITMAP_PAD + charHeight.Dips() - 1;

		// Lock the bitmap and get the data pointer
		WICRect rect = { 0, 0, bmwidth, bmheight };
		HR_RET0(wicBitmap->Lock(&rect, WICBitmapLockRead, lock.GetAddressOf()));
		HR_RET0(lock->GetDataPointer(&cbData, static_cast<BYTE**>(&pixels)));

		// determine the actual left of the character
		for (actbounds.min_x = 0; actbounds.min_x < bmwidth; actbounds.min_x++)
		{
			BYTE *offs = pixels + actbounds.min_x;
			UINT8 summary = 0;
			for (int y = 0; y < bmheight; y++)
				summary |= offs[y * bmwidth];
			if (summary != 0)
			{
				break;
			}
		}

		// determine the actual right of the character
		// Start from the right edge, and move in until we find a pixel
		for (actbounds.max_x = bmwidth - 1; actbounds.max_x >= 0; actbounds.max_x--)
		{
			BYTE *offs = pixels + actbounds.max_x;
			UINT8 summary = 0;

			// Go through the entire column and build a summary
			for (int y = 0; y < bmheight; y++)
				summary |= offs[y * bmwidth];
			if (summary != 0)
			{
				break;
			}
		}

		// allocate a new bitmap
		if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
		{
			bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);

			// copy the bits into it
			for (int y = 0; y < bitmap.height(); y++)
			{
				UINT32 *dstrow = &bitmap.pix32(y);
				UINT8 *srcrow = &pixels[(y + actbounds.min_y) * bmwidth];
				for (int x = 0; x < bitmap.width(); x++)
				{
					int effx = x + actbounds.min_x;
					dstrow[x] = rgb_t(srcrow[effx], 0xff, 0xff, 0xff);
				}
			}

			// set the final offset values
			xoffs = actbounds.min_x - (BITMAP_PAD + abc.abcA().Dips());
			yoffs = actbounds.max_y - (BITMAP_PAD + ascent.Dips());

#ifdef DWRITE_DEBUGGING
			SaveBitmap2(bitmap, L"C:\\temp\\dwrite_final.bmp");
#endif
		}

		BOOL success = bitmap.valid();

#ifdef DWRITE_DEBUGGING
		osd_printf_debug(
			"dwr: %s, c'%S' w%i x%i y%i asc%i dsc%i a%ib%ic%i\n",
			success ? "Success" : "Error",
			(WCHAR*)&chnum,
			width,
			xoffs,
			yoffs,
			ascent.Dips(),
			descent.Dips(),
			abc.abcA().Dips(),
			abc.abcB().Dips(),
			abc.abcC().Dips());
#endif
		return success;
	}
Пример #4
0
bool osd_font_windows::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
    // create a dummy DC to work with
    HDC dummyDC = CreateCompatibleDC(NULL);
    HGDIOBJ oldfont = SelectObject(dummyDC, m_font);

    // get the text metrics
    TEXTMETRIC metrics = { 0 };
    GetTextMetrics(dummyDC, &metrics);

    // get the width of this character
    ABC abc;
    if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
    {
        abc.abcA = 0;
        abc.abcC = 0;
        GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
    }
    width = abc.abcA + abc.abcB + abc.abcC;

    // determine desired bitmap size
    int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
    int bmheight = 50 + metrics.tmHeight + 50;

    // describe the bitmap we want
    BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
    BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
    info.bmiHeader.biSize = sizeof(info.bmiHeader);
    info.bmiHeader.biWidth = bmwidth;
    info.bmiHeader.biHeight = -bmheight;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 1;
    info.bmiHeader.biCompression = BI_RGB;
    info.bmiHeader.biSizeImage = 0;
    info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
    info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
    info.bmiHeader.biClrUsed = 0;
    info.bmiHeader.biClrImportant = 0;
    RGBQUAD col1 = info.bmiColors[0];
    RGBQUAD col2 = info.bmiColors[1];
    col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
    col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;

    // create a DIB to render to
    BYTE *bits;
    HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);

    if (dib)
    {
        HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);

        // clear the bitmap
        int rowbytes = bmwidth / 8;
        memset(bits, 0, rowbytes * bmheight);

        // now draw the character
        WCHAR tempchar = chnum;
        SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
        SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
        ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);

        // characters are expected to be full-height
        rectangle actbounds;
        actbounds.min_y = 50;
        actbounds.max_y = 50 + metrics.tmHeight - 1;

        // determine the actual left of the character
        for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
        {
            BYTE *offs = bits + actbounds.min_x;
            UINT8 summary = 0;
            for (int y = 0; y < bmheight; y++)
                summary |= offs[y * rowbytes];
            if (summary != 0)
            {
                actbounds.min_x *= 8;
                if (!(summary & 0x80)) actbounds.min_x++;
                if (!(summary & 0xc0)) actbounds.min_x++;
                if (!(summary & 0xe0)) actbounds.min_x++;
                if (!(summary & 0xf0)) actbounds.min_x++;
                if (!(summary & 0xf8)) actbounds.min_x++;
                if (!(summary & 0xfc)) actbounds.min_x++;
                if (!(summary & 0xfe)) actbounds.min_x++;
                break;
            }
        }

        // determine the actual right of the character
        for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
        {
            BYTE *offs = bits + actbounds.max_x;
            UINT8 summary = 0;
            for (int y = 0; y < bmheight; y++)
                summary |= offs[y * rowbytes];
            if (summary != 0)
            {
                actbounds.max_x *= 8;
                if (summary & 0x7f) actbounds.max_x++;
                if (summary & 0x3f) actbounds.max_x++;
                if (summary & 0x1f) actbounds.max_x++;
                if (summary & 0x0f) actbounds.max_x++;
                if (summary & 0x07) actbounds.max_x++;
                if (summary & 0x03) actbounds.max_x++;
                if (summary & 0x01) actbounds.max_x++;
                break;
            }
        }

        // allocate a new bitmap
        if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
        {
            bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);

            // copy the bits into it
            for (int y = 0; y < bitmap.height(); y++)
            {
                UINT32 *dstrow = &bitmap.pix32(y);
                UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
                for (int x = 0; x < bitmap.width(); x++)
                {
                    int effx = x + actbounds.min_x;
                    dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
                }
            }

            // set the final offset values
            xoffs = actbounds.min_x - (50 + abc.abcA);
            yoffs = actbounds.max_y - (50 + metrics.tmAscent);
        }

        // de-select the font and release the DC
        SelectObject(dummyDC, oldbitmap);
        DeleteObject(dib);
    }

    SelectObject(dummyDC, oldfont);
    DeleteDC(dummyDC);
    return bitmap.valid();
}