From 0dceb1c79eca8fc44d2b55ca0375b270addc3da5 Mon Sep 17 00:00:00 2001 From: Massimo Del Fedele Date: Sun, 18 Jul 2010 12:26:10 +0200 Subject: [PATCH] DIB Engine: fixes clipping, text and more --- dlls/winedib.drv/bitblt.c | 22 +++- dlls/winedib.drv/clipping.c | 63 +++++---- dlls/winedib.drv/dc.c | 16 ++- dlls/winedib.drv/dib.c | 41 +++++- dlls/winedib.drv/dibdrv.h | 27 +++- dlls/winedib.drv/font.c | 68 ++++++++-- dlls/winedib.drv/freetype.c | 6 + dlls/winedib.drv/freetype.h | 4 + dlls/winedib.drv/graphics.c | 204 +++++++++++++++++++++------- dlls/winedib.drv/palette.c | 16 ++- dlls/winedib.drv/pen_brush.c | 13 ++ dlls/winedib.drv/primitives.c | 18 +-- dlls/winedib.drv/primitives_bitblt.c | 26 ++-- dlls/winedib.drv/primitives_convert.c | 24 ++-- dlls/winedib.drv/primitives_font.c | 242 +++++++++++++++++++++++++--------- dlls/winedib.drv/primitives_rop3.c | 2 +- dlls/winedib.drv/text.c | 239 ++++++++++++++++++--------------- 17 files changed, 738 insertions(+), 293 deletions(-) diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c index 05c9392e85c..db661428005 100644 --- a/dlls/winedib.drv/bitblt.c +++ b/dlls/winedib.drv/bitblt.c @@ -261,6 +261,12 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, SIZE szSrc, szDst; int iRec; RECT dstClip, srcClip; + + /* converts to device spaces */ + _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst); + _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst); + _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc); + _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc); /* first clip on physical DC sizes */ setPoint(&pd, xDst, yDst); @@ -320,7 +326,6 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width xDst, yDst, widthDst, heightDst, physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "", xSrc, ySrc, widthSrc, heightSrc)); - /* if sizes are null or negative, returns false */ if(widthSrc <= 0 || heightSrc <= 0 || widthDst <= 0 || heightDst <= 0) @@ -422,6 +427,12 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, int iRec; RECT dstClip, srcClip; + /* converts to device spaces */ + _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst); + _DIBDRV_Sizes_ws2ds(physDevDst, &width, &height); + if(physDevSrc) + _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc); + /* first clip on physical DC sizes */ setPoint(&pd, xDst, yDst); setPoint(&ps, xSrc, ySrc); @@ -633,6 +644,15 @@ BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, int iRec; RECT dstClip, srcClip; + /* converts to device spaces */ + _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst); + _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst); + if(physDevSrc) + { + _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc); + _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc); + } + /* first clip on physical DC sizes */ setPoint(&pd, xDst, yDst); setPoint(&ps, xSrc, ySrc); diff --git a/dlls/winedib.drv/clipping.c b/dlls/winedib.drv/clipping.c index ed10b920f13..ada1f7f56ba 100644 --- a/dlls/winedib.drv/clipping.c +++ b/dlls/winedib.drv/clipping.c @@ -36,39 +36,44 @@ void DIBDRV_SetDeviceClipping( DIBDRVPHYSDEV *physDev, HRGN vis_rgn, HRGN clip_r MAYBE(TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn)); - /* sets the region for X11 driver anyways... we may change bitmap later on */ - _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn); - - /* then we set the region for DIB engine, same reason */ + if(physDev->hasDIB) + { + /* DIB section selected in, use DIB Engine */ - CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY ); + CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY ); - /* get region rectangles */ - if(!(size = GetRegionData(physDev->region, 0, NULL))) - return; - data = HeapAlloc(GetProcessHeap(), 0, size); - if (!GetRegionData(physDev->region, size, data)) - { - HeapFree( GetProcessHeap(), 0, data ); - return; - } - - /* frees any previous regions rectangles in DC */ - if(physDev->regionData) - HeapFree(GetProcessHeap(), 0, physDev->regionData); + /* get region rectangles */ + if(!(size = GetRegionData(physDev->region, 0, NULL))) + return; + data = HeapAlloc(GetProcessHeap(), 0, size); + if (!GetRegionData(physDev->region, size, data)) + { + HeapFree( GetProcessHeap(), 0, data ); + return; + } - /* sets the rectangles on physDev */ - physDev->regionData = data; - physDev->regionRects = (RECT *)data->Buffer; - physDev->regionRectCount = data->rdh.nCount; - - if(TRACE_ON(dibdrv)) - { - TRACE("Region dump : %d rectangles\n", physDev->regionRectCount); - for(iRect = 0; iRect < physDev->regionRectCount; iRect++) + /* frees any previous regions rectangles in DC */ + if(physDev->regionData) + HeapFree(GetProcessHeap(), 0, physDev->regionData); + + /* sets the rectangles on physDev */ + physDev->regionData = data; + physDev->regionRects = (RECT *)data->Buffer; + physDev->regionRectCount = data->rdh.nCount; + + if(TRACE_ON(dibdrv)) { - RECT *r = physDev->regionRects + iRect; - TRACE("Rect #%03d, x1:%4d, y1:%4d, x2:%4d, y2:%4d\n", iRect, r->left, r->top, r->right, r->bottom); + TRACE("Region dump : %d rectangles\n", physDev->regionRectCount); + for(iRect = 0; iRect < physDev->regionRectCount; iRect++) + { + RECT *r = physDev->regionRects + iRect; + TRACE("Rect #%03d, x1:%4d, y1:%4d, x2:%4d, y2:%4d\n", iRect, r->left, r->top, r->right, r->bottom); + } } } + else + { + /* DDB selected in, use X11 driver */ + _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn); + } } diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c index 8212d42794c..9ffceee13a3 100644 --- a/dlls/winedib.drv/dc.c +++ b/dlls/winedib.drv/dc.c @@ -43,11 +43,12 @@ static int device_init_done; /* NOTE : Removing TC_RA_ABLE avoids bitmapped fonts, so FT_Face is always non-NULL + UPDATE : remove TC_RA_ABLE seems unneeded Adding TC_VA_ABLE forces to use gdi fonts always, so we can get an FT_Face */ unsigned int text_caps = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE | TC_CR_ANY | TC_SA_DOUBLE | TC_SA_INTEGER | - TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE /* | TC_RA_ABLE */ | TC_VA_ABLE); + TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE); /* X11R6 adds TC_SF_X_YINDEP, Xrender adds TC_VA_ABLE */ @@ -119,6 +120,10 @@ static void device_init(void) device_init_done = TRUE; } +/* dummy null function for pen and brush */ +static void dummy3(DIBDRVPHYSDEV *p, int a, int b, int c) {} +static void dummy4(DIBDRVPHYSDEV *p, int a, int b, int c, int d) {} + /********************************************************************** * DIBDRV_CreateDC */ @@ -178,12 +183,19 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev physDev->penColor = 0; _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->penAnd, &physDev->penXor); + physDev->penStyle = PS_NULL; + physDev->penHLine = dummy3; + physDev->penVLine = dummy3; + physDev->penLine = dummy4; + physDev->penPattern = NULL; + physDev->brushColor = 0; _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->brushAnd, &physDev->brushXor); physDev->brushAnds = NULL; physDev->brushXors = NULL; physDev->brushStyle = BS_NULL; + physDev->brushHLine = dummy3; physDev->isBrushBitmap = FALSE; _DIBDRVBITMAP_Clear(&physDev->brushBitmap); @@ -193,8 +205,10 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev physDev->textColor = 0; physDev->textBackground = 0; +#ifdef DIBDRV_ANTIALIASED_FONTS /* text color table for antialiased fonts */ memset(physDev->textColorTable, 0, 256); +#endif /* freetype face associated to current DC HFONT */ physDev->face = NULL; diff --git a/dlls/winedib.drv/dib.c b/dlls/winedib.drv/dib.c index b72c34afe66..653148d8c16 100644 --- a/dlls/winedib.drv/dib.c +++ b/dlls/winedib.drv/dib.c @@ -65,15 +65,46 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan, UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count, const RGBQUAD *colors ) { - UINT res; + DIBDRVBITMAP *dib = &physDev->physBitmap; MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev, start, count, colors)); /* SetDIBColorTable operates on a DIB, so we use the engine */ - ONCE(FIXME("STUB\n")); - res = 0; - - return res; + + /* if bpp > 8, some error occurred... */ + if(dib->bitCount > 8) + { + ERR("Called for BPP > 8\n"); + return 0; + } + + /* if dib hasn't a color table, or has a small one, we must before + create/extend it */ + if(!(dib->colorTable)) + { + dib->colorTableSize = (1 << dib->bitCount); + dib->colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(RGBQUAD) * dib->colorTableSize); + } + else if(dib->colorTableSize < (1 << dib->bitCount)) + { + int newSize = (1 << dib->bitCount); + RGBQUAD *newTable = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RGBQUAD) * newSize); + memcpy(newTable, dib->colorTable, sizeof(RGBQUAD) * dib->colorTableSize); + HeapFree(GetProcessHeap(), 0, dib->colorTable); + dib->colorTable = newTable; + dib->colorTableSize = newSize; + } + + /* sanity check */ + if(start + count > dib->colorTableSize) + { + ERR("Out of range setting color table, size is %d, requested is %d\n", dib->colorTableSize, start+count); + return 0; + } + memcpy(dib->colorTable + start, colors, sizeof(RGBQUAD) * count); + dib->colorTableGrabbed = TRUE; + + return TRUE; } /*********************************************************************** diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h index b0f128ecbcd..66cc1140676 100644 --- a/dlls/winedib.drv/dibdrv.h +++ b/dlls/winedib.drv/dibdrv.h @@ -44,6 +44,9 @@ /* enable this if you want debugging (i.e. TRACEs) output */ #define DIBDRV_ENABLE_MAYBE +/* enable this if you want antialiased fonts */ +#define DIBDRV_ANTIALIASED_FONTS + /* provide a way to make debugging output appear only once. Usage example: ONCE(FIXME("Some message\n")); */ @@ -102,7 +105,7 @@ typedef struct _DIBDRV_PRIMITIVE_FUNCS const struct _DIBDRVPHYSDEV *physDevSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, DWORD rop ); /* font drawing helper */ - void (* FreetypeBlit) ( struct _DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp); + void (* FreetypeBlit) ( struct _DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp); } DIBDRV_PRIMITIVE_FUNCS; @@ -225,6 +228,9 @@ typedef struct _DIBDRVPHYSDEV DWORD curDash, leftInDash; enum MARKSPACE { mark, space } markSpace; + /* pen style */ + UINT penStyle; + /* pen drawing functions */ void (* penHLine) (struct _DIBDRVPHYSDEV *physDev, int x1, int x2, int y); void (* penVLine) (struct _DIBDRVPHYSDEV *physDev, int x, int y1, int y2); @@ -250,8 +256,10 @@ typedef struct _DIBDRVPHYSDEV COLORREF textColor; COLORREF textBackground; +#ifdef DIBDRV_ANTIALIASED_FONTS /* text color table for antialiased fonts */ COLORREF textColorTable[256]; +#endif /* freetype face associated to current DC HFONT */ FT_Face face; @@ -388,4 +396,21 @@ HBITMAP _DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc, HDC hdcDst, int xSrc, int ySrc, * DIBDRV_GetDeviceCaps */ INT DIBDRV_GetDeviceCaps( DIBDRVPHYSDEV *physDev, INT cap ); +/* ********************************************************************* + * GEOMETRIC UTILITIES + * ********************************************************************/ + +/* intersect 2 rectangles (just to not use USER32 one...) */ +BOOL _DIBDRV_IntersectRect(RECT *d, const RECT *s1, const RECT *s2); + +/* converts positions from Word space to Device space */ +void _DIBDRV_Position_ws2ds(DIBDRVPHYSDEV *physDev, int *x, int *y); +void _DIBDRV_Positions_ws2ds(DIBDRVPHYSDEV *physDev, int *x1, int *y1, int *x2, int *y2); + +/* converts sizes from Word space to Device space */ +void _DIBDRV_Sizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h); + +/* converts a rectangle form Word space to Device space */ +void _DIBDRV_Rect_ws2ds(DIBDRVPHYSDEV *physDev, const RECT *src, RECT *dst); + #endif diff --git a/dlls/winedib.drv/font.c b/dlls/winedib.drv/font.c index 215b27dff9a..f7ea8dc965a 100644 --- a/dlls/winedib.drv/font.c +++ b/dlls/winedib.drv/font.c @@ -26,14 +26,56 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); + +#if 0 +/* prints out some info about face */ +void PrintFaceInfo(FT_Face face) +{ + int i; + + fprintf(stderr, "----------------------------------------------------------\n"); + fprintf(stderr, "Family name :%s\n", face->family_name); + fprintf(stderr, "Style name :%s\n", face->style_name); + fprintf(stderr, "Num fixed sizes : %d\n", face->num_fixed_sizes); + if(face->num_fixed_sizes) + { + fprintf(stderr, "Fixed sizes :"); + for(i = 0; i < face->num_fixed_sizes; i++) + fprintf(stderr, " (%d, %d)", face->available_sizes[i].width, face->available_sizes[i].height); + fprintf(stderr, "\n"); + } + fprintf(stderr, "Face flags: "); + if(face->face_flags & FT_FACE_FLAG_SCALABLE ) fprintf(stderr, "FT_FACE_FLAG_SCALABLE "); + if(face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) fprintf(stderr, "FT_FACE_FLAG_FIXED_SIZES "); + if(face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) fprintf(stderr, "FT_FACE_FLAG_FIXED_WIDTH "); + if(face->face_flags & FT_FACE_FLAG_SFNT ) fprintf(stderr, "FT_FACE_FLAG_SFNT "); + if(face->face_flags & FT_FACE_FLAG_HORIZONTAL ) fprintf(stderr, "FT_FACE_FLAG_HORIZONTAL "); + if(face->face_flags & FT_FACE_FLAG_VERTICAL ) fprintf(stderr, "FT_FACE_FLAG_VERTICAL "); + if(face->face_flags & FT_FACE_FLAG_KERNING ) fprintf(stderr, "FT_FACE_FLAG_KERNING "); + if(face->face_flags & FT_FACE_FLAG_FAST_GLYPHS ) fprintf(stderr, "FT_FACE_FLAG_FAST_GLYPHS "); + if(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) fprintf(stderr, "FT_FACE_FLAG_MULTIPLE_MASTERS "); + if(face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) fprintf(stderr, "FT_FACE_FLAG_GLYPH_NAMES "); + if(face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) fprintf(stderr, "FT_FACE_FLAG_EXTERNAL_STREAM "); + if(face->face_flags & FT_FACE_FLAG_HINTER ) fprintf(stderr, "FT_FACE_FLAG_HINTER "); + if(face->face_flags & FT_FACE_FLAG_CID_KEYED ) fprintf(stderr, "FT_FACE_FLAG_CID_KEYED "); + if(face->face_flags & FT_FACE_FLAG_TRICKY ) fprintf(stderr, "FT_FACE_FLAG_TRICKY "); + fprintf(stderr, "\n"); + + fprintf(stderr, "Style flags: "); + if(face->style_flags & FT_STYLE_FLAG_ITALIC) fprintf(stderr, "FT_STYLE_FLAG_ITALIC "); + if(face->style_flags & FT_STYLE_FLAG_BOLD) fprintf(stderr, "FT_STYLE_FLAG_BOLD "); + fprintf(stderr, "\n"); + fprintf(stderr, "----------------------------------------------------------\n"); +} +#endif + + /********************************************************************** * DIBDRV_SetTextColor */ COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color ) { COLORREF res; - INT r, g, b; - INT i; MAYBE(TRACE("physDev:%p, color:%08x\n", physDev, color)); @@ -45,24 +87,30 @@ COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color ) if(color == physDev->textColor) return color; - /* stores old color */ + /* stores old color and sets new one */ res = physDev->textColor; - + physDev->textColor = color; + +#ifdef DIBDRV_ANTIALIASED_FONTS /* fills the text color table used on antialiased font display */ if(physDev->physBitmap.funcs) { + BYTE r, g, b; + INT i; + r = GetRValue(color); g = GetGValue(color); b = GetBValue(color); for(i = 0; i < 256; i++) { physDev->textColorTable[i] = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, RGB( - MulDiv(r, i, 256), - MulDiv(g, i, 256), - MulDiv(b, i, 256) + MulDiv(r, i, 255), + MulDiv(g, i, 255), + MulDiv(b, i, 255) )); } } +#endif /* returns previous text color */ return res; @@ -111,7 +159,11 @@ HFONT DIBDRV_SelectFont( DIBDRVPHYSDEV *physDev, HFONT hfont, GdiFont *gdiFont ) FIXME("Error, null Ft_Face\n"); return hfont; } - + +#if 0 + /* prints out some info about face */ + if(TRACE_ON(dibdrv)) MAYBE(PrintFaceInfo(physDev->face)); +#endif /* setup the correct charmap.... maybe */ for (i = 0; i < physDev->face->num_charmaps; ++i) { diff --git a/dlls/winedib.drv/freetype.c b/dlls/winedib.drv/freetype.c index 111a18b6980..f1cd7b4cc2d 100644 --- a/dlls/winedib.drv/freetype.c +++ b/dlls/winedib.drv/freetype.c @@ -46,6 +46,9 @@ MAKE_FUNCPTR(FT_Set_Pixel_Sizes) MAKE_FUNCPTR(FT_Get_First_Char) MAKE_FUNCPTR(FT_Render_Glyph) MAKE_FUNCPTR(FT_Glyph_Transform) +MAKE_FUNCPTR(FT_Bitmap_New) +MAKE_FUNCPTR(FT_Bitmap_Done) +MAKE_FUNCPTR(FT_Bitmap_Convert) #undef MAKE_FUNCPTR /* freetype initialization flag */ @@ -95,6 +98,9 @@ BOOL _DIBDRV_FreeType_Init(void) LOAD_FUNCPTR(FT_Get_First_Char) LOAD_FUNCPTR(FT_Render_Glyph) LOAD_FUNCPTR(FT_Glyph_Transform) + LOAD_FUNCPTR(FT_Bitmap_New) + LOAD_FUNCPTR(FT_Bitmap_Done) + LOAD_FUNCPTR(FT_Bitmap_Convert) #undef LOAD_FUNCPTR error = pFT_Init_FreeType(&DIBDRV_ftLibrary); diff --git a/dlls/winedib.drv/freetype.h b/dlls/winedib.drv/freetype.h index 93619ff93f0..3517af551f8 100644 --- a/dlls/winedib.drv/freetype.h +++ b/dlls/winedib.drv/freetype.h @@ -28,6 +28,7 @@ #include FT_TRUETYPE_TABLES_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H +#include FT_BITMAP_H /* freetype library handle */ extern FT_Library DIBDRV_ftLibrary; @@ -179,6 +180,9 @@ MAKE_FUNCPTR(FT_Set_Pixel_Sizes) MAKE_FUNCPTR(FT_Get_First_Char) MAKE_FUNCPTR(FT_Render_Glyph) MAKE_FUNCPTR(FT_Glyph_Transform) +MAKE_FUNCPTR(FT_Bitmap_New) +MAKE_FUNCPTR(FT_Bitmap_Done) +MAKE_FUNCPTR(FT_Bitmap_Convert) #undef MAKE_FUNCPTR #endif /* HAVE_FREETYPE */ diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c index fba34f5f31a..f62149c87e2 100644 --- a/dlls/winedib.drv/graphics.c +++ b/dlls/winedib.drv/graphics.c @@ -295,7 +295,7 @@ static BOOL ScanPolygon(const POINT *pt, int count, int ys, POINT **scans, int * } /* gets bounding box of a polygon */ -void PolygonBoundingBox(const POINT *pt, int count, RECT *bBox) +static void PolygonBoundingBox(const POINT *pt, int count, RECT *bBox) { const POINT *p; int iPoint; @@ -311,6 +311,76 @@ void PolygonBoundingBox(const POINT *pt, int count, RECT *bBox) } } +/* intersect 2 rectangles (just to not use USER32 one...) + bottom and tight sides are considered OUTSIDE */ +BOOL _DIBDRV_IntersectRect(RECT *d, const RECT *s1, const RECT *s2) +{ + if(s1->right <= s2->left || + s2->right <= s1->left || + s1->bottom <= s2->top || + s2->bottom <= s1->top + ) + return FALSE; + d->left = s1->left > s2->left ? s1->left : s2->left; + d->top = s1->top > s2->top ? s1->top : s2->top; + d->right = s1->right < s2->right ? s1->right : s2->right; + d->bottom = s1->bottom < s2->bottom ? s1->bottom : s2->bottom; + return TRUE; +} + +/* converts a rectangle form Word space to Device space */ +void _DIBDRV_Rect_ws2ds(DIBDRVPHYSDEV *physDev, const RECT *src, RECT *dst) +{ + POINT pts[2]; + pts[0].x = src->left; + pts[0].y = src->top; + pts[1].x = src->right; + pts[1].y = src->bottom; + LPtoDP(physDev->hdc, pts, 2); + dst->left = pts[0].x; + dst->top = pts[0].y; + dst->right = pts[1].x; + dst->bottom = pts[1].y; +} + +/* converts positions from Word space to Device space */ +void _DIBDRV_Position_ws2ds(DIBDRVPHYSDEV *physDev, int *x, int *y) +{ + POINT p; + p.x = *x; + p.y = *y; + LPtoDP(physDev->hdc, &p, 1); + *x = p.x; + *y = p.y; +} + +void _DIBDRV_Positions_ws2ds(DIBDRVPHYSDEV *physDev, int *x1, int *y1, int *x2, int *y2) +{ + POINT pts[2]; + pts[0].x = *x1; + pts[0].y = *y1; + pts[1].x = *x2; + pts[1].y = *y2; + LPtoDP(physDev->hdc, pts, 2); + *x1 = pts[0].x; + *y1 = pts[0].y; + *x2 = pts[1].x; + *y2 = pts[1].y; +} + +/* converts sizes from Word space to Device space */ +void _DIBDRV_Sizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h) +{ + POINT pts[2]; + pts[0].x = 0; + pts[0].y = 0; + pts[1].x = *w; + pts[1].y = *h; + LPtoDP(physDev->hdc, pts, 2); + *w = pts[1].x - pts[0].x; + *h = pts[1].y - pts[0].y; +} + /*********************************************************************** * DIBDRV_Arc */ @@ -446,6 +516,7 @@ COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y ) if(physDev->hasDIB) { + _DIBDRV_Position_ws2ds(physDev, &x, &y); res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y); } else @@ -463,22 +534,44 @@ BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, int x, int y ) { BOOL res; POINT curPos; + RECT *r; + int iRec; + POINT p1, p2, pc1, pc2; MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y)); if(physDev->hasDIB) { + res = FALSE; GetCurrentPositionEx(physDev->hdc, &curPos); - _DIBDRV_ResetDashOrigin(physDev); + /* converts position to device space */ + p1.x = curPos.x; p1.y = curPos.y; + p2.x = x; p2.y = y; + LPtoDP(physDev->hdc, &p1, 1); + LPtoDP(physDev->hdc, &p2, 1); - if(curPos.y == y) - physDev->penHLine(physDev, curPos.x, x, y); - else if(curPos.x == x) - physDev->penVLine(physDev, x, curPos.y, y); - else - physDev->penLine(physDev, curPos.x, curPos.y, x, y); - res = TRUE; + /* cycle on all current clipping rectangles */ + r = physDev->regionRects; + for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++) + { + _DIBDRV_ResetDashOrigin(physDev); + + /* clipe line on current region area */ + if(ClipLine(&p1, &p2, r, &pc1, &pc2)) + { + if(pc1.y == pc2.y) + physDev->penHLine(physDev, pc1.x, pc2.x, pc1.y); + else if(pc1.x == pc2.x) + physDev->penVLine(physDev, pc1.x, pc1.y, pc2.y); + else + physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y); + res = TRUE; + } + } + + /* moves current position to next point */ + MoveToEx(physDev->hdc, x, y, NULL); } else { @@ -583,7 +676,7 @@ BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count ) POINT pc1, pc2; MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count)); - + if(physDev->hasDIB) { /* DIB section selected in, use DIB Engine */ @@ -771,58 +864,67 @@ BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD* */ BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2) { - BOOL res = TRUE; + BOOL res; int i; - DIBDRVBITMAP *bmp = &physDev->physBitmap; + RECT rWorld, rDevice, rClipped; + RECT *r; + int iRec; MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n", physDev, x1, y1, x2, y2)); if(physDev->hasDIB) { + res = FALSE; + OrderInt(&x1, &x2); OrderInt(&y1, &y2); - /* temporary fix.... should be done by clipping */ - if(x1 < 0) x1 = 0; - if(x2 < 0) x2 = 0; - if(y1 < 0) y1 = 0; - if(y2 < 0) y2 = 0; - if(x1 >= bmp->width) x1 = bmp->width - 1; - if(y1 >= bmp->height) y1 = bmp->height - 1; - if(x2 > bmp->width) x2 = bmp->width; - if(y2 > bmp->height) y2 = bmp->height ; - if(x1 >= x2 || y1 >= y2) - goto fin; + /* converts to device space */ + rWorld.left = x1; rWorld.top = y1; rWorld.right = x2; rWorld.bottom = y2; + _DIBDRV_Rect_ws2ds(physDev, &rWorld, &rDevice); - _DIBDRV_ResetDashOrigin(physDev); - - /* particular case where the rectangle - degenerates to a line or a point */ - if(x1 >= x2 - 1) - { - physDev->penVLine(physDev, x1, y1, y2); - goto fin; - } - else if (y1 >= y2 -1) + /* loop on all clip region rectangles */ + r = physDev->regionRects; + for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++) { - physDev->penHLine(physDev, x1, x2, y1); - goto fin; - } - - /* Draw the perimeter */ - physDev->penHLine(physDev, x1 , x2 , y1 ); - physDev->penHLine(physDev, x1 , x2 , y2 - 1); - physDev->penVLine(physDev, x1 , y1 + 1, y2 - 1); - physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1); - - /* fill the inside */ - if(x2 >= x1 + 2) - for (i = y1 + 1; i < y2 - 1; i++) - physDev->brushHLine(physDev, x1 + 1, x2 - 1, i); + /* clips rectangle to current region */ + if(_DIBDRV_IntersectRect(&rClipped, &rDevice, r)) + { + x1 = rClipped.left; y1 = rClipped.top; + x2 = rClipped.right; y2 = rClipped.bottom; + + _DIBDRV_ResetDashOrigin(physDev); + + /* fill the inside, if not null brush */ + if(physDev->brushStyle != BS_NULL) + { + if(x2 > x1) + for (i = y1; i < y2; i++) + physDev->brushHLine(physDev, x1, x2, i); + } - res = TRUE; -fin: - ; + /* draw perimeter, if not null pen */ + if(physDev->penStyle != PS_NULL) + { + + /* particular case where the rectangle + degenerates to a line or a point */ + if(x1 >= x2 - 1) + physDev->penVLine(physDev, x1, y1, y2); + else if (y1 >= y2 -1) + physDev->penHLine(physDev, x1, x2, y1); + else + { + /* Draw the perimeter */ + physDev->penHLine(physDev, x1 , x2 , y1 ); + physDev->penHLine(physDev, x1 , x2 , y2 - 1); + physDev->penVLine(physDev, x1 , y1 + 1, y2 - 1); + physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1); + } + } + res = TRUE; + } + } } else { @@ -870,6 +972,8 @@ COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color ) if(physDev->hasDIB) { + _DIBDRV_Position_ws2ds(physDev, &x, &y); + /* gets previous pixel */ res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y); diff --git a/dlls/winedib.drv/palette.c b/dlls/winedib.drv/palette.c index 148a6d5b605..a1aa64804df 100644 --- a/dlls/winedib.drv/palette.c +++ b/dlls/winedib.drv/palette.c @@ -30,18 +30,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); */ UINT DIBDRV_RealizePalette( DIBDRVPHYSDEV *physDev, HPALETTE hpal, BOOL primary ) { - UINT res; + UINT res = 0; MAYBE(TRACE("physDev:%p, hpal:%p, primary:%s\n", physDev, hpal, (primary ? "TRUE" : "FALSE"))); - /* we should in any case call X11 function, as UnrealizePalette() doesn't - * take a physDev parameter */ - res = _DIBDRV_GetDisplayDriver()->pRealizePalette(physDev->X11PhysDev, hpal, primary); - - if(physDev->hasDIB) + if(physDev && physDev->hasDIB) { /* DIB section selected in, additional (if needed) engine code */ ONCE(FIXME("STUB\n")); + res = 0; + } + else + { + /* we should in any case call X11 function, as UnrealizePalette() doesn't + * take a physDev parameter */ + res = _DIBDRV_GetDisplayDriver()->pRealizePalette(physDev ? physDev->X11PhysDev : NULL, hpal, primary); + } return res; diff --git a/dlls/winedib.drv/pen_brush.c b/dlls/winedib.drv/pen_brush.c index 31c9cd28adf..7b15ece11e5 100644 --- a/dlls/winedib.drv/pen_brush.c +++ b/dlls/winedib.drv/pen_brush.c @@ -290,6 +290,12 @@ static void PatternBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y) physDev->physBitmap.funcs->PatternHLine(&physDev->physBitmap, x1, x2, y, and, xor, physDev->brushBitmap.width, x1 % physDev->brushBitmap.width); } +/* null function for PS_NULL and BS_NULL pen and brush styles */ +void NullPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y) {} +void NullPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2) {} +void NullPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2) {} +void NullBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y) {} + /*********************************************************************** * DIBDRV_SelectPen */ @@ -335,6 +341,12 @@ HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen ) physDev->penPattern = &dashPatterns[logpen.lopnStyle - PS_DASH]; _DIBDRV_ResetDashOrigin(physDev); break; + case PS_NULL: + physDev->penHLine = NullPenHLine; + physDev->penVLine = NullPenVLine; + physDev->penLine = NullPenLine; + physDev->penPattern = NULL; + break; } res = hpen; } @@ -484,6 +496,7 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush ) { MAYBE(TRACE("NULL Pattern\n")); physDev->brushColorref = 0; + physDev->brushHLine = NullBrushHLine; goto solid; } diff --git a/dlls/winedib.drv/primitives.c b/dlls/winedib.drv/primitives.c index a2fa04a93a3..2b0fc6e05cf 100644 --- a/dlls/winedib.drv/primitives.c +++ b/dlls/winedib.drv/primitives.c @@ -139,15 +139,15 @@ BOOL _DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, /* ------------------------------------------------------------*/ /* FREETYPE FONT BITMAP BLITTING */ -void _DIBDRV_freetype_blit_8888 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_32_RGB (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_24 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_16_RGB (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_8 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_4 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); -void _DIBDRV_freetype_blit_1 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_8888 (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_32_RGB (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_24 (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_16_RGB (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_8 (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_4 (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); +void _DIBDRV_freetype_blit_1 (DIBDRVPHYSDEV *dib, int x, int y, RECT *clipRec, FT_Bitmap *bmp); DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_RGB = { diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c index 7540dad8190..7feeb49ddef 100644 --- a/dlls/winedib.drv/primitives_bitblt.c +++ b/dlls/winedib.drv/primitives_bitblt.c @@ -216,7 +216,7 @@ BOOL _DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, PemultiplyLine(strBuf, widthDst, constAlpha); /* blends source on dest */ - BlendLine(dBuf, sBuf, widthDst); + BlendLine(dBuf, strBuf, widthDst); /* puts dest line back */ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf); @@ -391,6 +391,10 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000)); useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000)); + /* sanity check -- MSN messenger crashes without */ + if(useSrc && !physDevSrc) + return FALSE; + /* gets source, dest and pattern bitmaps, if available */ if(usePat && physDevDst->isBrushBitmap) patBmp = &physDevDst->brushBmpCache; @@ -501,8 +505,8 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, { srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, dBuf); patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf); - wDstPnt = sBuf; - wSrcPnt = sBuf; + wDstPnt = dBuf; + wSrcPnt = dBuf; wPatPnt = pBuf; for(i = width; i > 0 ; i--) { @@ -521,8 +525,8 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++) { srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, dBuf); - wDstPnt = sBuf; - wSrcPnt = sBuf; + wDstPnt = dBuf; + wSrcPnt = dBuf; for(i = width; i > 0 ; i--) { *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, 0, rop); @@ -538,9 +542,9 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, goto error; for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++) { - dstBmp->funcs->GetLine(srcBmp, ys, xDst, width, dBuf); + dstBmp->funcs->GetLine(dstBmp, ys, xDst, width, dBuf); patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf); - wDstPnt = sBuf; + wDstPnt = dBuf; wPatPnt = pBuf; for(i = width; i > 0 ; i--) { @@ -558,8 +562,8 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, MAYBE(TRACE("BitBlt use: dst\n")); for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++) { - dstBmp->funcs->GetLine(srcBmp, ys, xDst, width, dBuf); - wDstPnt = sBuf; + dstBmp->funcs->GetLine(dstBmp, ys, xDst, width, dBuf); + wDstPnt = dBuf; for(i = width; i > 0 ; i--) { *wDstPnt = _DIBDRV_ROP3(patColor, 0, *wDstPnt, rop); @@ -638,6 +642,10 @@ BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000)); useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000)); + /* sanity check -- MSN messenger crashes without */ + if(useSrc && !physDevSrc) + return FALSE; + /* gets source, dest and pattern bitmaps, if available */ if(usePat && physDevDst->isBrushBitmap) patBmp = &physDevDst->brushBmpCache; diff --git a/dlls/winedib.drv/primitives_convert.c b/dlls/winedib.drv/primitives_convert.c index 800e3fd19b0..f8f87ce9220 100644 --- a/dlls/winedib.drv/primitives_convert.c +++ b/dlls/winedib.drv/primitives_convert.c @@ -292,7 +292,7 @@ BOOL _DIBDRV_GetLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3)); /* get first partial byte, if any */ - startx = (8 - (startx & 0x03)) & 0x03; + startx = (8 - (startx & 0x07)) & 0x07; width -= startx; if(startx) { @@ -322,7 +322,7 @@ BOOL _DIBDRV_GetLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, } /* last partial byte, if any */ - if(width) + if(width > 0) { b = *src; while(width--) @@ -398,13 +398,17 @@ BOOL _DIBDRV_PutLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, DWORD *dwBuf = (DWORD *)buf; WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx); DWORD c; + + BYTE bShift = 8 - bmp->blueLen; + BYTE gShift = 16 - bmp->greenLen; + BYTE rShift = 24 - bmp->redLen; for(; width; width--) { c = *dwBuf++; *dst++ = - ((( c & 0x000000ff) << bmp->blueShift) & bmp->blueMask) | - ((((c & 0x0000ff00) >> 8) << bmp->greenShift) & bmp->greenMask) | - ((((c & 0x00ff0000) >> 16) << bmp->redShift) & bmp->redMask); + ((((c & 0x000000ff) >> bShift) << bmp->blueShift) & bmp->blueMask) | + ((((c & 0x0000ff00) >> gShift) << bmp->greenShift) & bmp->greenMask) | + ((((c & 0x00ff0000) >> rShift) << bmp->redShift) & bmp->redMask); } return TRUE; } @@ -480,7 +484,7 @@ BOOL _DIBDRV_PutLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, } /* last nibble, if any */ - if(width) + if(width > 0) { c = *dwBuf; @@ -500,14 +504,14 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, BYTE b, mask; char i; DWORD c; - + /* get foreground color */ DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff; /* put first partial byte, if any */ - startx &= 0x03; + startx &= 0x07; mask = 0x80 >> startx; - startx = (8 - startx) & 0x03; + startx = (8 - startx) & 0x07; if(startx) { width -= startx; @@ -540,7 +544,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, } /* last partial byte, if any */ - if(width) + if(width > 0) { b = *dst; mask = 0x80; diff --git a/dlls/winedib.drv/primitives_font.c b/dlls/winedib.drv/primitives_font.c index dd1d64b3fcb..e604a39b9f9 100644 --- a/dlls/winedib.drv/primitives_font.c +++ b/dlls/winedib.drv/primitives_font.c @@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); /* ------------------------------------------------------------*/ /* FREETYPE FONT BITMAP BLITTING */ -void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -35,13 +35,20 @@ void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; - DWORD c; + int xMin, xMax, yMin, yMax; DWORD *ptr; +#ifdef DIBDRV_ANTIALIASED_FONTS + DWORD c; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif - /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + /* gets clip limits */ + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -50,9 +57,21 @@ void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap ptr = (DWORD *)((BYTE *)dib->bits + (dibY * dib->stride) + x * 4); for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; + if(*buf < 255) + { + negColor = 255 - *buf; + r = (*ptr >> 16) & 0xff; + g = (*ptr >> 8) & 0xff; + b = *ptr & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif *ptr = c; } buf++; @@ -61,7 +80,7 @@ void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap } } -void _DIBDRV_freetype_blit_32_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_32_RGB(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -69,30 +88,52 @@ void _DIBDRV_freetype_blit_32_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitma int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; + int xMin, xMax, yMin, yMax; + DWORD *ptr; +#ifdef DIBDRV_ANTIALIASED_FONTS DWORD c; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++) { + ptr = (DWORD *)((BYTE *)dib->bits + (dibY * dib->stride) + x * 4); for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; - dib->funcs->SetPixel(dib, dibX, dibY, 0, c); + if(*buf < 255) + { + negColor = 255 - *buf; + r = (*ptr >> 16) & 0xff; + g = (*ptr >> 8) & 0xff; + b = *ptr & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif + *ptr = c; } buf++; + ptr++; } } } -void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -100,12 +141,20 @@ void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; + int xMin, xMax, yMin, yMax; +#ifdef DIBDRV_ANTIALIASED_FONTS DWORD c; + COLORREF pix; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -113,9 +162,22 @@ void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; + if(*buf < 255) + { + negColor = 255 - *buf; + pix = dib->funcs->GetPixel(dib, dibX, dibY); + r = pix & 0xff; + g = (pix >> 8) & 0xff; + b = (pix >> 16) & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif dib->funcs->SetPixel(dib, dibX, dibY, 0, c); } buf++; @@ -123,7 +185,7 @@ void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT } } -void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -131,12 +193,20 @@ void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *b int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; + int xMin, xMax, yMin, yMax; +#ifdef DIBDRV_ANTIALIASED_FONTS DWORD c; + COLORREF pix; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -144,9 +214,22 @@ void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *b { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; + if(*buf < 255) + { + negColor = 255 - *buf; + pix = dib->funcs->GetPixel(dib, dibX, dibY); + r = pix & 0xff; + g = (pix >> 8) & 0xff; + b = (pix >> 16) & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif dib->funcs->SetPixel(dib, dibX, dibY, 0, c); } buf++; @@ -154,7 +237,7 @@ void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *b } } -void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -162,12 +245,20 @@ void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitma int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; + int xMin, xMax, yMin, yMax; +#ifdef DIBDRV_ANTIALIASED_FONTS DWORD c; + COLORREF pix; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -175,9 +266,22 @@ void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitma { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; + if(*buf < 255) + { + negColor = 255 - *buf; + pix = dib->funcs->GetPixel(dib, dibX, dibY); + r = pix & 0xff; + g = (pix >> 8) & 0xff; + b = (pix >> 16) & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif dib->funcs->SetPixel(dib, dibX, dibY, 0, c); } buf++; @@ -185,7 +289,7 @@ void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitma } } -void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -193,12 +297,20 @@ void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; + int xMin, xMax, yMin, yMax; +#ifdef DIBDRV_ANTIALIASED_FONTS DWORD c; + COLORREF pix; + BYTE r, g, b, negColor; +#else + DWORD c = dib->funcs->ColorToPixel(dib, physDev->textColor); +#endif /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -206,9 +318,22 @@ void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) { +#ifdef DIBDRV_ANTIALIASED_FONTS c = physDev->textColorTable[*buf]; + if(*buf < 255) + { + negColor = 255 - *buf; + pix = dib->funcs->GetPixel(dib, dibX, dibY); + r = pix & 0xff; + g = (pix >> 8) & 0xff; + b = (pix >> 16) & 0xff; + c += MulDiv(r, 255 - *buf, 255) << 16 | + MulDiv(g, 255 - *buf, 255) << 8 | + MulDiv(r, 255 - *buf, 255); + } +#endif dib->funcs->SetPixel(dib, dibX, dibY, 0, c); } buf++; @@ -216,7 +341,7 @@ void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT } } -void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -224,12 +349,14 @@ void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; - DWORD c; + int xMin, xMax, yMin, yMax; + DWORD c = physDev->textColor; /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -237,17 +364,14 @@ void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) - { - c = physDev->textColorTable[*buf]; + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) dib->funcs->SetPixel(dib, dibX, dibY, 0, c); - } buf++; } } } -void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -255,12 +379,14 @@ void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; - DWORD c; + int xMin, xMax, yMin, yMax; + DWORD c = physDev->textColor; /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -268,17 +394,14 @@ void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) - { - c = physDev->textColorTable[*buf]; + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) dib->funcs->SetPixel(dib, dibX, dibY, 0, c); - } buf++; } } } -void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp) +void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec, FT_Bitmap *bmp) { /* FIXME : MUST BE OPTIMIZED !!! */ @@ -286,12 +409,14 @@ void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm int bmpX, bmpY; BYTE *buf; int dibX, dibY; - int DIBX, DIBY; - DWORD c; + int xMin, xMax, yMin, yMax; + DWORD c = physDev->textColor; /* gets DIB limits */ - DIBX = dib->width; - DIBY = dib->height; + xMin = clipRec->left; + yMin = clipRec->top; + xMax = clipRec->right; + yMax = clipRec->bottom; /* loop for every pixel in bitmap */ buf = bmp->buffer; @@ -299,11 +424,8 @@ void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bm { for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++) { - if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf) - { - c = physDev->textColorTable[*buf]; + if(dibX < xMax && dibY < yMax && dibX >= xMin && dibY >= yMin && *buf) dib->funcs->SetPixel(dib, dibX, dibY, 0, c); - } buf++; } } diff --git a/dlls/winedib.drv/primitives_rop3.c b/dlls/winedib.drv/primitives_rop3.c index 398258b81e6..05ce4947d56 100644 --- a/dlls/winedib.drv/primitives_rop3.c +++ b/dlls/winedib.drv/primitives_rop3.c @@ -413,7 +413,7 @@ DWORD _DIBDRV_ROP3(DWORD p, DWORD s, DWORD d, BYTE rop) return (0x123456) & 0x00ffffff; case 0x85: /* PDSPnoaxn */ - return (0x123456) & 0x00ffffff; + return (~(p ^ (d & (s | ~p)))) & 0x00ffffff; case 0x86: /* DSPDSoaxx */ return (0x123456) & 0x00ffffff; diff --git a/dlls/winedib.drv/text.c b/dlls/winedib.drv/text.c index e2cea0c1c9c..0ae3575c6b6 100644 --- a/dlls/winedib.drv/text.c +++ b/dlls/winedib.drv/text.c @@ -25,19 +25,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); -/* converts font sizes from Word space to Device space */ -static void FontSizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h) -{ - POINT pts[2]; - pts[0].x = 0; - pts[0].y = 0; - pts[1].x = abs(*w); - pts[1].y = abs(*h); - LPtoDP(physDev->hdc, pts, 2); - *w = pts[1].x - pts[0].x; - *h = pts[1].y - pts[0].y; -} - /*********************************************************************** * DIBDRV_ExtTextOut */ @@ -57,12 +44,17 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags, LPCWSTR wstrPnt; FT_Glyph glyph; - FT_BitmapGlyph bitmap; + FT_BitmapGlyph bitmapGlyph; + FT_Bitmap *bitmap, bitmap8; double cosEsc, sinEsc; FT_Matrix matrix; FT_Vector start; int dx, dy; + RECT *r; + int iRec; + RECT clipRec; + DWORD backPixel; MAYBE(TRACE("physDev:%p, x:%d, y:%d, flags:%x, lprect:%p, wstr:%s, count:%d, lpDx:%p\n", physDev, x, y, flags, lprect, debugstr_w(wstr), count, lpDx)); @@ -94,114 +86,155 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags, HeapFree(GetProcessHeap(), 0, str); } + /* gets background pixel value for opaque text */ + backPixel = physDev->backgroundColor; + /* gets font data, etc */ GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf); /* convert sizes to device space */ - w = lf.lfWidth; h = lf.lfHeight; - FontSizes_ws2ds(physDev, &w, &h); - - /* if opaque, paint the font background */ -/* - if(flags | ETO_OPAQUE) - { - int iLine; - for(iLine = lprect->top; iLine < lprect->bottom; iLine++) - physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, - lprect->left, lprect->right-1, iLine, 0, physDev->backgroundColor); - } -*/ - /* sets character pixel size */ - error = pFT_Set_Pixel_Sizes( - face, - MulDiv(w, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSX)), - MulDiv(h, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSY)) - ); - if(error) - ERR("Couldn't set char size to (%d,%d)\n", lf.lfWidth, lf.lfHeight); - - /* transformation matrix and vector */ - start.x = 0; - start.y = 0; - if(lf.lfEscapement != 0) + w = abs(lf.lfWidth); h = abs(lf.lfHeight); + _DIBDRV_Sizes_ws2ds(physDev, &w, &h); + + /* loop on all clip region rectangles */ + r = physDev->regionRects; + for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++) { - cosEsc = cos(lf.lfEscapement * M_PI / 1800); - sinEsc = sin(lf.lfEscapement * M_PI / 1800); - } - else - { - cosEsc = 1; - sinEsc = 0; - } - matrix.xx = (FT_Fixed)( cosEsc * 0x10000L ); - matrix.xy = (FT_Fixed)(-sinEsc * 0x10000L ); - matrix.yx = (FT_Fixed)( sinEsc * 0x10000L ); - matrix.yy = (FT_Fixed)( cosEsc * 0x10000L ); - - /* outputs characters one by one */ - wstrPnt = wstr; - for ( n = 0; n < count; n++ ) - { - /* retrieve glyph index from character code */ - if(flags & ETO_GLYPH_INDEX) - glyph_index = *wstrPnt++; + /* if clipped on text rect, intersect with current region */ + if(flags & ETO_CLIPPED) + { + if(!_DIBDRV_IntersectRect(&clipRec, r, lprect)) + continue; + } else - glyph_index = pFT_Get_Char_Index( face, *wstrPnt++); + memcpy(&clipRec, r, sizeof(RECT)); + + /* if opaque, paint the font background */ + if(flags & ETO_OPAQUE) + { + int iLine; + RECT tr; + + /* clips text rectangle */ + if(_DIBDRV_IntersectRect(&tr, r, lprect)) + { + /* paints the backgound */ + for(iLine = tr.top; iLine < tr.bottom; iLine++) + physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, + tr.left, tr.right-1, iLine, 0, backPixel); + } + } - /* load glyph image into the slot (erase previous one) */ - error = pFT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); + /* sets character pixel size */ + error = pFT_Set_Pixel_Sizes(face, w, h); if(error) + ONCE(ERR("Couldn't set char size to (%d,%d), code %d\n", lf.lfWidth, lf.lfHeight, error)); + + /* transformation matrix and vector */ + start.x = 0; + start.y = 0; + if(lf.lfEscapement != 0) { - ERR("Couldn't load glyph at index %d\n", glyph_index); - /* ignore errors */ - continue; + cosEsc = cos(lf.lfEscapement * M_PI / 1800); + sinEsc = sin(lf.lfEscapement * M_PI / 1800); } - error = pFT_Get_Glyph(face->glyph, &glyph); - if ( error ) + else { - FIXME("Couldn't get glyph\n"); - continue; + cosEsc = 1; + sinEsc = 0; } - - /* apply transformation to glyph */ - if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) - pFT_Glyph_Transform(glyph, &matrix, &start ); - - /* gets advance BEFORE transforming... */ - dx = glyph->advance.x; - dy = glyph->advance.y; - - /* convert to an anti-aliased bitmap, if needed */ - if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) + matrix.xx = (FT_Fixed)( cosEsc * 0x10000L ); + matrix.xy = (FT_Fixed)(-sinEsc * 0x10000L ); + matrix.yx = (FT_Fixed)( sinEsc * 0x10000L ); + matrix.yy = (FT_Fixed)( cosEsc * 0x10000L ); + + /* outputs characters one by one */ + wstrPnt = wstr; + for ( n = 0; n < count; n++ ) { - error = pFT_Glyph_To_Bitmap( - &glyph, - FT_RENDER_MODE_NORMAL, - 0, /* no additional translation */ - 1 /* destroy copy in "image" */ - ); - - /* ignore errors */ - if ( error ) + /* retrieve glyph index from character code */ + if(flags & ETO_GLYPH_INDEX) + glyph_index = *wstrPnt++; + else + glyph_index = pFT_Get_Char_Index( face, *wstrPnt++); + + /* load glyph image into the slot (erase previous one) */ + error = pFT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); + if(error) { - FIXME("Couldn't render glyph\n"); - pFT_Done_Glyph(glyph); + ERR("Couldn't load glyph at index %d\n", glyph_index); + /* ignore errors */ continue; } - } + error = pFT_Get_Glyph(face->glyph, &glyph); + if ( error ) + { + FIXME("Couldn't get glyph\n"); + continue; + } + + /* apply transformation to glyph */ + if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) + pFT_Glyph_Transform(glyph, &matrix, &start ); + + /* gets advance BEFORE transforming... */ + dx = glyph->advance.x; + dy = glyph->advance.y; + + /* convert to an anti-aliased bitmap, if needed */ + if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) + { + error = pFT_Glyph_To_Bitmap( + &glyph, + #ifdef DIBDRV_ANTIALIASED_FONTS + physDev->physBitmap.bitCount > 8 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, + #else + FT_RENDER_MODE_MONO, + #endif + 0, /* no additional translation */ + 1 /* destroy copy in "image" */ + ); + + /* ignore errors */ + if ( error ) + { + FIXME("Couldn't render glyph\n"); + pFT_Done_Glyph(glyph); + continue; + } + } + bitmapGlyph = (FT_BitmapGlyph)glyph; + + /* convert the bitmap in an 8bpp 1 byte aligned one if needed */ + bitmap = &bitmapGlyph->bitmap; + if(bitmap->pixel_mode != FT_PIXEL_MODE_GRAY) + { + pFT_Bitmap_New(&bitmap8); + if(pFT_Bitmap_Convert(glyph->library, bitmap, &bitmap8, 1)) + { + FIXME("Couldn't convert bitmap to 8 bit grayscale\n"); + pFT_Done_Glyph(glyph); + continue; + } + bitmap = &bitmap8; + } - /* now, draw to our target surface */ - bitmap = (FT_BitmapGlyph)glyph; - physDev->physBitmap.funcs->FreetypeBlit(physDev, x+bitmap->left, y-bitmap->top, &bitmap->bitmap); + /* now, draw to our target surface */ + physDev->physBitmap.funcs->FreetypeBlit(physDev, x+bitmapGlyph->left, y-bitmapGlyph->top, &clipRec, bitmap); + + /* frees converted bitmap, if any */ + if(bitmap != &bitmapGlyph->bitmap) + pFT_Bitmap_Done(glyph->library, bitmap); - /* increment pen position */ - x += dx>>16; - y -= dy>>16; + /* increment pen position */ + x += dx>>16; + y -= dy>>16; - pFT_Done_Glyph(glyph); - - res = TRUE; - } + pFT_Done_Glyph(glyph); + + res = TRUE; + } + } /* end region rects loop */ } else { -- 2.11.4.GIT