RT_B RT_API RtGdipStretchBitmap(RT_H hBitmap, RT_H hDc, RT_N nWidth, RT_N nHeight, RT_GDIP_INTERPOLATION_MODE nInterpolationMode) { GpGraphics* lpGraphics; GpBitmap* lpBitmap; GpBrush* lpBrush; GpStatus nStatus; RT_B bResult; lpGraphics = RT_NULL; lpBitmap = RT_NULL; lpBrush = RT_NULL; /* Create destination graphics hDc. */ nStatus = GdipCreateFromHDC(hDc, &lpGraphics); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } /* Adjust quality. */ nStatus = GdipSetInterpolationMode(lpGraphics, (InterpolationMode)nInterpolationMode); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } /* Create a brush to fill the background. */ nStatus = GdipCreateSolidFill(0xFFFFFFFF, &lpBrush); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } /* Fill the destination DC with a background. Necessary to avoid edges artifacts. */ nStatus = GdipFillRectangleI(lpGraphics, lpBrush, 0, 0, nWidth, nHeight); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } /* Create source image/bitmap from hBitmap. */ nStatus = GdipCreateBitmapFromHBITMAP(hBitmap, RT_NULL, &lpBitmap); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } /* Stretch. */ nStatus = GdipDrawImageRectI(lpGraphics, lpBitmap, 0, 0, nWidth, nHeight); if (nStatus) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } bResult = RT_TRUE; goto free_resources; handle_error: bResult = RT_FALSE; free_resources: if (lpGraphics) { nStatus = GdipDeleteGraphics(lpGraphics); lpGraphics = RT_NULL; if (nStatus && bResult) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } } if (lpBitmap) { nStatus = GdipDisposeImage(lpBitmap); lpBitmap = RT_NULL; if (nStatus && bResult) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } } if (lpBrush) { nStatus = GdipDeleteBrush(lpBrush); lpBrush = RT_NULL; if (nStatus && bResult) { RtGdipSetLastErrorFromGpStatus(nStatus); goto handle_error; } } return bResult; }
void win_emoji_show(int x, int y, wchar * efn, int elen, ushort lattr) { GpStatus s; static GdiplusStartupInput gi = (GdiplusStartupInput){1, NULL, FALSE, FALSE}; static ULONG_PTR gis = 0; if (!gis) { s = GdiplusStartup(&gis, &gi, NULL); gpcheck("startup", s); } bool use_stream = true; IStream * fs = 0; if (use_stream) { s = GdipCreateStreamOnFile(efn, 0 /* FileMode.Open */, &fs); gpcheck("stream", s); } else s = NotImplemented; GpImage * img = 0; if (s == Ok) { s = GdipLoadImageFromStream(fs, &img); gpcheck("load stream", s); } else { // This is reported to generate a memory leak, so rather use the stream. s = GdipLoadImageFromFile(efn, &img); gpcheck("load file", s); } int col = PADDING + x * cell_width; int row = PADDING + y * cell_height; if ((lattr & LATTR_MODE) >= LATTR_BOT) row -= cell_height; int w = elen * cell_width; if ((lattr & LATTR_MODE) != LATTR_NORM) w *= 2; int h = cell_height; if ((lattr & LATTR_MODE) >= LATTR_TOP) h *= 2; if (cfg.emoji_placement) { uint iw, ih; s = GdipGetImageWidth(img, &iw); gpcheck("width", s); s = GdipGetImageHeight(img, &ih); gpcheck("height", s); // consider aspect ratio so that ih/iw == h/w; // if EMPL_FULL, always adjust w // if ih/iw > h/w, make w smaller // if iw/ih > w/h, make h smaller if (cfg.emoji_placement == EMPL_FULL && ih * w != h * iw) { w = h * iw / ih; } else if (ih * w > h * iw) { int w0 = w; w = h * iw / ih; if (cfg.emoji_placement == EMPL_MIDDLE) { // horizontally center col += (w0 - w) / 2; } } else if (iw * h > w * ih) { int h0 = h; h = w * ih / iw; // vertically center row += (h0 - h) / 2; } } GpGraphics * gr; s = GdipCreateFromHDC(GetDC(wnd), &gr); gpcheck("hdc", s); s = GdipDrawImageRectI(gr, img, col, row, w, h); gpcheck("draw", s); s = GdipFlush(gr, FlushIntentionFlush); gpcheck("flush", s); s = GdipDeleteGraphics(gr); gpcheck("delete gr", s); s = GdipDisposeImage(img); gpcheck("dispose img", s); if (fs) { // Release stream resources, close file. fs->lpVtbl->Release(fs); } }