static void test_characterrange(void) { CharacterRange ranges[3]; INT count; GpStringFormat* format; GpStatus stat; stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, stat); stat = GdipSetStringFormatMeasurableCharacterRanges(NULL, 3, ranges); expect(InvalidParameter, stat); stat = GdipSetStringFormatMeasurableCharacterRanges(format, 0, ranges); expect(Ok, stat); stat = GdipSetStringFormatMeasurableCharacterRanges(format, 3, NULL); expect(InvalidParameter, stat); stat = GdipSetStringFormatMeasurableCharacterRanges(format, 3, ranges); expect(Ok, stat); stat = GdipGetStringFormatMeasurableCharacterRangeCount(format, &count); expect(Ok, stat); if (stat == Ok) expect(3, count); stat= GdipDeleteStringFormat(format); expect(Ok, stat); }
static void test_constructor(void) { GpStringFormat *format; GpStatus stat; INT n, count; StringAlignment align, valign; StringTrimming trimming; StringDigitSubstitute digitsub; LANGID digitlang; stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, stat); GdipGetStringFormatAlign(format, &align); GdipGetStringFormatLineAlign(format, &valign); GdipGetStringFormatHotkeyPrefix(format, &n); GdipGetStringFormatTrimming(format, &trimming); GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); GdipGetStringFormatMeasurableCharacterRangeCount(format, &count); expect(HotkeyPrefixNone, n); expect(StringAlignmentNear, align); expect(StringAlignmentNear, align); expect(StringTrimmingCharacter, trimming); expect(StringDigitSubstituteUser, digitsub); expect(LANG_NEUTRAL, digitlang); expect(0, count); stat = GdipDeleteStringFormat(format); expect(Ok, stat); }
static void test_stringformatflags(void) { GpStringFormat *format; GpStatus stat; INT flags; stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, stat); /* NULL args */ stat = GdipSetStringFormatFlags(NULL, 0); expect(InvalidParameter, stat); stat = GdipSetStringFormatFlags(format, 0); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect(0, flags); /* Check some valid flags */ stat = GdipSetStringFormatFlags(format, StringFormatFlagsDirectionRightToLeft); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect(StringFormatFlagsDirectionRightToLeft, flags); stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoFontFallback); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect(StringFormatFlagsNoFontFallback, flags); /* Check some flag combinations */ stat = GdipSetStringFormatFlags(format, StringFormatFlagsDirectionVertical | StringFormatFlagsNoFitBlackBox); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect((StringFormatFlagsDirectionVertical | StringFormatFlagsNoFitBlackBox), flags); stat = GdipSetStringFormatFlags(format, StringFormatFlagsDisplayFormatControl | StringFormatFlagsMeasureTrailingSpaces); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect((StringFormatFlagsDisplayFormatControl | StringFormatFlagsMeasureTrailingSpaces), flags); /* Check invalid flags */ stat = GdipSetStringFormatFlags(format, 0xdeadbeef); expect(Ok, stat); stat = GdipGetStringFormatFlags(format, &flags); expect(Ok, stat); expect(0xdeadbeef, flags); stat = GdipDeleteStringFormat(format); expect(Ok, stat); }
static GF_Err gdip_get_text_size(GF_FontReader *dr, const unsigned short *string, Fixed *width, Fixed *height) { GpPath *path_tmp; GpStringFormat *fmt; FontPriv *ctx = (FontPriv *)dr->udta; *width = *height = 0; if (!ctx->font) return GF_BAD_PARAM; GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &fmt); GdipCreatePath(FillModeAlternate, &path_tmp); RectF rc; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipAddPathString(path_tmp, (const WCHAR *)string, -1, ctx->font, ctx->font_style, ctx->em_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); adjust_white_space(string, &rc.Width, ctx->whitespace_width); *width = FLT2FIX(rc.Width); *height = FLT2FIX(rc.Height); GdipDeleteStringFormat(fmt); GdipDeletePath(path_tmp); return GF_OK; }
static M4Err gdip_get_text_size(FontRaster *dr, const unsigned short *string, Float *width, Float *height) { GpPath *path_tmp; GpStringFormat *fmt; FontPriv *ctx = (FontPriv *)dr->priv; *width = *height = 0.0; if (!ctx->font) return M4BadParam; GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &fmt); GdipCreatePath(FillModeAlternate, &path_tmp); RectF rc; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipAddPathString(path_tmp, string, -1, ctx->font, ctx->font_style, ctx->font_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); *width = rc.Width; *height = rc.Height; adjust_white_space(string, width, ctx->whitespace_width ); GdipDeleteStringFormat(fmt); GdipDeletePath(path_tmp); return M4OK; }
GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format) { GpStatus stat; if(!format) return InvalidParameter; stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox | StringFormatFlagsLineLimit | StringFormatFlagsNoClip, LANG_NEUTRAL, format); if(stat != Ok) return stat; (*format)->digitlang = LANG_NEUTRAL; (*format)->digitsub = StringDigitSubstituteUser; (*format)->trimming = StringTrimmingNone; (*format)->hkprefix = HotkeyPrefixNone; (*format)->align = StringAlignmentNear; (*format)->vertalign = StringAlignmentNear; (*format)->generic_typographic = TRUE; TRACE("%p => %p\n", format, *format); return Ok; }
static void test_digitsubstitution(void) { GpStringFormat *format; GpStatus stat; StringDigitSubstitute digitsub; LANGID digitlang; stat = GdipCreateStringFormat(0, LANG_RUSSIAN, &format); expect(Ok, stat); /* NULL arguments */ stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatDigitSubstitution(format, NULL, NULL); expect(Ok, stat); stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, &digitsub); expect(InvalidParameter, stat); stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, &digitsub); expect(InvalidParameter, stat); stat = GdipSetStringFormatDigitSubstitution(NULL, LANG_NEUTRAL, StringDigitSubstituteNone); expect(InvalidParameter, stat); /* try to get both and one by one */ stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); expect(Ok, stat); expect(StringDigitSubstituteUser, digitsub); expect(LANG_NEUTRAL, digitlang); digitsub = StringDigitSubstituteNone; stat = GdipGetStringFormatDigitSubstitution(format, NULL, &digitsub); expect(Ok, stat); expect(StringDigitSubstituteUser, digitsub); digitlang = LANG_RUSSIAN; stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, NULL); expect(Ok, stat); expect(LANG_NEUTRAL, digitlang); /* set/get */ stat = GdipSetStringFormatDigitSubstitution(format, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), StringDigitSubstituteUser); expect(Ok, stat); digitsub = StringDigitSubstituteNone; digitlang = LANG_RUSSIAN; stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); expect(Ok, stat); expect(StringDigitSubstituteUser, digitsub); expect(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), digitlang); stat = GdipDeleteStringFormat(format); expect(Ok, stat); }
GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format) { GpStatus stat; if (!format) return InvalidParameter; stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format); if(stat != Ok) return stat; (*format)->align = StringAlignmentNear; (*format)->vertalign = StringAlignmentNear; return Ok; }
static void test_constructor(void) { GpStringFormat *format; GpStatus stat; INT n; StringAlignment align, valign; StringTrimming trimming; stat = GdipCreateStringFormat(0, 0, &format); expect(Ok, stat); GdipGetStringFormatAlign(format, &align); GdipGetStringFormatLineAlign(format, &valign); GdipGetStringFormatHotkeyPrefix(format, &n); GdipGetStringFormatTrimming(format, &trimming); expect(HotkeyPrefixNone, n); expect(StringAlignmentNear, align); expect(StringAlignmentNear, align); expect(StringTrimmingCharacter, trimming); stat = GdipDeleteStringFormat(format); expect(Ok, stat); }
static void test_font_transform(void) { static const WCHAR string[] = { 'A',0 }; GpStatus status; HDC hdc; LOGFONTA lf; GpFont *font; GpGraphics *graphics; GpMatrix *matrix; GpStringFormat *format, *typographic; PointF pos[1] = { { 0,0 } }; REAL height, margin_y; RectF bounds, rect; hdc = CreateCompatibleDC(0); status = GdipCreateFromHDC(hdc, &graphics); expect(Ok, status); status = GdipSetPageUnit(graphics, UnitPixel); expect(Ok, status); status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, status); status = GdipStringFormatGetGenericTypographic(&typographic); expect(Ok, status); memset(&lf, 0, sizeof(lf)); lstrcpyA(lf.lfFaceName, "Tahoma"); lf.lfHeight = -100; lf.lfWidth = 100; status = GdipCreateFontFromLogfontA(hdc, &lf, &font); expect(Ok, status); margin_y = 100.0 / 8.0; /* identity matrix */ status = GdipCreateMatrix(&matrix); expect(Ok, status); status = GdipSetWorldTransform(graphics, matrix); expect(Ok, status); status = GdipGetLogFontA(font, graphics, &lf); expect(Ok, status); expect(-100, lf.lfHeight); expect(0, lf.lfWidth); expect(0, lf.lfEscapement); expect(0, lf.lfOrientation); status = GdipGetFontHeight(font, graphics, &height); expect(Ok, status); expectf(120.703125, height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); todo_wine expectf(height + margin_y, bounds.Height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); expectf_(height, bounds.Height, 1.0); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, NULL, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.05); expectf_(height, bounds.Height, 0.5); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, matrix, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.05); expectf_(height, bounds.Height, 0.5); /* scale matrix */ status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend); expect(Ok, status); status = GdipSetWorldTransform(graphics, matrix); expect(Ok, status); status = GdipGetLogFontA(font, graphics, &lf); expect(Ok, status); expect(-300, lf.lfHeight); expect(0, lf.lfWidth); expect(0, lf.lfEscapement); expect(0, lf.lfOrientation); status = GdipGetFontHeight(font, graphics, &height); expect(Ok, status); expectf(120.703125, height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); todo_wine expectf(height + margin_y, bounds.Height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); expectf_(height, bounds.Height, 0.05); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, NULL, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.05); expectf_(height, bounds.Height, 0.2); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, matrix, &bounds); expect(Ok, status); expectf(0.0, bounds.X); todo_wine expectf_(-300.0, bounds.Y, 0.15); todo_wine expectf(height * 3.0, bounds.Height); /* scale + ratate matrix */ status = GdipRotateMatrix(matrix, 45.0, MatrixOrderAppend); expect(Ok, status); status = GdipSetWorldTransform(graphics, matrix); expect(Ok, status); status = GdipGetLogFontA(font, graphics, &lf); expect(Ok, status); expect(-300, lf.lfHeight); expect(0, lf.lfWidth); expect_(3151, lf.lfEscapement, 1); expect_(3151, lf.lfOrientation, 1); status = GdipGetFontHeight(font, graphics, &height); expect(Ok, status); expectf(120.703125, height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); todo_wine expectf(height + margin_y, bounds.Height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); expectf_(height, bounds.Height, 0.05); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, NULL, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.05); expectf_(height, bounds.Height, 0.2); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, matrix, &bounds); expect(Ok, status); todo_wine expectf_(-43.814377, bounds.X, 0.05); todo_wine expectf_(-212.235611, bounds.Y, 0.05); todo_wine expectf_(340.847534, bounds.Height, 0.05); /* scale + ratate + shear matrix */ status = GdipShearMatrix(matrix, 4.0, 5.0, MatrixOrderAppend); expect(Ok, status); status = GdipSetWorldTransform(graphics, matrix); expect(Ok, status); status = GdipGetLogFontA(font, graphics, &lf); expect(Ok, status); todo_wine expect(1032, lf.lfHeight); expect(0, lf.lfWidth); expect_(3099, lf.lfEscapement, 1); expect_(3099, lf.lfOrientation, 1); status = GdipGetFontHeight(font, graphics, &height); expect(Ok, status); expectf(120.703125, height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); todo_wine expectf(height + margin_y, bounds.Height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); expectf_(height, bounds.Height, 0.2); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, NULL, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.2); expectf_(height, bounds.Height, 0.2); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, matrix, &bounds); expect(Ok, status); todo_wine expectf_(-636.706848, bounds.X, 0.05); todo_wine expectf_(-175.257523, bounds.Y, 0.05); todo_wine expectf_(1532.984985, bounds.Height, 0.05); /* scale + ratate + shear + translate matrix */ status = GdipTranslateMatrix(matrix, 10.0, 20.0, MatrixOrderAppend); expect(Ok, status); status = GdipSetWorldTransform(graphics, matrix); expect(Ok, status); status = GdipGetLogFontA(font, graphics, &lf); expect(Ok, status); todo_wine expect(1032, lf.lfHeight); expect(0, lf.lfWidth); expect_(3099, lf.lfEscapement, 1); expect_(3099, lf.lfOrientation, 1); status = GdipGetFontHeight(font, graphics, &height); expect(Ok, status); expectf(120.703125, height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); todo_wine expectf(height + margin_y, bounds.Height); set_rect_empty(&rect); set_rect_empty(&bounds); status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL); expect(Ok, status); expectf(0.0, bounds.X); expectf(0.0, bounds.Y); expectf_(height, bounds.Height, 0.1); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, NULL, &bounds); expect(Ok, status); expectf(0.0, bounds.X); expectf_(-100.0, bounds.Y, 0.2); expectf_(height, bounds.Height, 0.2); set_rect_empty(&bounds); status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos, DriverStringOptionsCmapLookup, matrix, &bounds); expect(Ok, status); todo_wine expectf_(-626.706848, bounds.X, 0.05); todo_wine expectf_(-155.257523, bounds.Y, 0.05); todo_wine expectf_(1532.984985, bounds.Height, 0.05); GdipDeleteMatrix(matrix); GdipDeleteFont(font); GdipDeleteGraphics(graphics); GdipDeleteStringFormat(typographic); GdipDeleteStringFormat(format); DeleteDC(hdc); }
static void test_tabstops(void) { GpStringFormat *format; GpStatus stat; INT count; REAL tabs[3]; REAL firsttab; stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, stat); /* NULL */ stat = GdipGetStringFormatTabStopCount(NULL, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStopCount(NULL, &count); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStopCount(format, NULL); expect(InvalidParameter, stat); stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, NULL); expect(InvalidParameter, stat); stat = GdipSetStringFormatTabStops(format, 0.0, 0, NULL); expect(InvalidParameter, stat); stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, tabstops); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(NULL, 0, NULL, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(format, 0, NULL, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(NULL, 0, &firsttab, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(NULL, 0, NULL, tabs); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(format, 0, &firsttab, NULL); expect(InvalidParameter, stat); stat = GdipGetStringFormatTabStops(format, 0, NULL, tabs); expect(InvalidParameter, stat); /* not NULL */ stat = GdipGetStringFormatTabStopCount(format, &count); expect(Ok, stat); expect(0, count); /* negative tabcount */ stat = GdipSetStringFormatTabStops(format, 0.0, -1, tabstops); expect(Ok, stat); count = -1; stat = GdipGetStringFormatTabStopCount(format, &count); expect(Ok, stat); expect(0, count); stat = GdipSetStringFormatTabStops(format, -10.0, 0, tabstops); expect(Ok, stat); stat = GdipSetStringFormatTabStops(format, -10.0, 1, tabstops); expect(NotImplemented, stat); firsttab = -1.0; tabs[0] = tabs[1] = tabs[2] = -1.0; stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs); expect(Ok, stat); expectf(-1.0, tabs[0]); expectf(-1.0, tabs[1]); expectf(-1.0, tabs[2]); expectf(0.0, firsttab); stat = GdipSetStringFormatTabStops(format, +0.0, 3, tabstops); expect(Ok, stat); count = 0; stat = GdipGetStringFormatTabStopCount(format, &count); expect(Ok, stat); expect(3, count); firsttab = -1.0; tabs[0] = tabs[1] = tabs[2] = -1.0; stat = GdipGetStringFormatTabStops(format, 3, &firsttab, tabs); expect(Ok, stat); expectf(0.0, tabs[0]); expectf(10.0, tabs[1]); expectf(2.0, tabs[2]); expectf(0.0, firsttab); stat = GdipSetStringFormatTabStops(format, 10.0, 3, tabstops); expect(Ok, stat); firsttab = -1.0; tabs[0] = tabs[1] = tabs[2] = -1.0; stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs); expect(Ok, stat); expectf(-1.0, tabs[0]); expectf(-1.0, tabs[1]); expectf(-1.0, tabs[2]); expectf(10.0, firsttab); /* zero tabcount, after valid setting to 3 */ stat = GdipSetStringFormatTabStops(format, 0.0, 0, tabstops); expect(Ok, stat); count = 0; stat = GdipGetStringFormatTabStopCount(format, &count); expect(Ok, stat); expect(3, count); stat = GdipDeleteStringFormat(format); expect(Ok, stat); }
static GF_Glyph *gdip_load_glyph(GF_FontReader *dr, u32 glyph_name) { GF_Rect bounds; GF_Glyph *glyph; GpPath *path_tmp; GpStringFormat *fmt; GpMatrix *mat; Float est_advance_h; unsigned short str[4]; int i; FontPriv *ctx = (FontPriv *)dr->udta; if (!ctx->font) return NULL; RectF rc; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipCreateStringFormat(StringFormatFlagsNoWrap | StringFormatFlagsNoFitBlackBox | StringFormatFlagsMeasureTrailingSpaces, LANG_NEUTRAL, &fmt); GdipSetStringFormatAlign(fmt, StringAlignmentNear); GdipCreatePath(FillModeAlternate, &path_tmp); if (glyph_name==0x20) { est_advance_h = ctx->whitespace_width; } else { /*to compute first glyph alignment (say 'x', we figure out its bounding full box by using the '_' char as wrapper (eg, "_x_") then the bounding box starting from xMin of the glyph ('x_'). The difference between both will give us a good approx of the glyph alignment*/ str[0] = glyph_name; str[1] = (unsigned short) '_'; str[2] = (unsigned short) 0; GdipAddPathString(path_tmp, (const WCHAR *)str, -1, ctx->font, ctx->font_style, ctx->em_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); est_advance_h = rc.Width - ctx->underscore_width; } GdipResetPath(path_tmp); str[0] = glyph_name; str[1] = (unsigned short) 0; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipAddPathString(path_tmp, (const WCHAR *)str, -1, ctx->font, ctx->font_style, ctx->em_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); /*flip so that we are in a font coordinate system - also move back the glyph to x=0 and y=baseline, GdiPlus doesn't do so*/ GdipCreateMatrix(&mat); GdipTranslateMatrix(mat, - rc.X, -ctx->ascent, MatrixOrderAppend); GdipScaleMatrix(mat, 1, -1, MatrixOrderAppend); GdipTransformPath(path_tmp, mat); GdipDeleteMatrix(mat); /*start enum*/ s32 count; GdipGetPointCount(path_tmp, &count); GpPointF *pts = new GpPointF[count]; BYTE *types = new BYTE[count]; GdipGetPathTypes(path_tmp, types, count); GdipGetPathPoints(path_tmp, pts, count); GF_SAFEALLOC(glyph, GF_Glyph); GF_SAFEALLOC(glyph->path, GF_Path); for (i=0; i<count; ) { BOOL closed = 0; s32 sub_type; sub_type = types[i] & PathPointTypePathTypeMask; if (sub_type == PathPointTypeStart) { gf_path_add_move_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y)); i++; } else if (sub_type == PathPointTypeLine) { gf_path_add_line_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y)); if (types[i] & PathPointTypeCloseSubpath) gf_path_close(glyph->path); i++; } else if (sub_type == PathPointTypeBezier) { assert(i+2<=count); gf_path_add_cubic_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y), FLT2FIX(pts[i+1].X), FLT2FIX(pts[i+1].Y), FLT2FIX(pts[i+2].X), FLT2FIX(pts[i+2].Y)); if (types[i+2] & PathPointTypeCloseSubpath) gf_path_close(glyph->path); i += 3; } else { assert(0); break; } } delete [] pts; delete [] types; GdipDeleteStringFormat(fmt); GdipDeletePath(path_tmp); glyph->ID = glyph_name; glyph->utf_name = glyph_name; glyph->vert_advance = (s32) (ctx->ascent-ctx->descent); glyph->horiz_advance = (s32) est_advance_h; gf_path_get_bounds(glyph->path, &bounds); glyph->width = FIX2INT(bounds.width); glyph->height = FIX2INT(bounds.height); return glyph; }
static M4Err gdip_add_text_to_path(FontRaster *dr, LPM4PATH path, Bool flipText, const unsigned short* string, Float left, Float top, Float x_scaling, Float y_scaling, Float ascent, M4Rect *bounds) { GpPath *path_tmp; GpMatrix *mat; GpStringFormat *fmt; Float real_start; unsigned short str[4]; FontPriv *ctx = (FontPriv *)dr->priv; if (!ctx->font) return M4BadParam; RectF rc; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; /*find first non-space char and estimate its glyph pos since GDIplus doesn't give this info*/ s32 len = utf8_wcslen(string); s32 i=0; for (; i<len; i++) { if (string[i] != (unsigned short) ' ') break; } if (i>=len) return M4OK; GdipCreateStringFormat(StringFormatFlagsNoWrap | StringFormatFlagsNoFitBlackBox | StringFormatFlagsMeasureTrailingSpaces, LANG_NEUTRAL, &fmt); GdipSetStringFormatAlign(fmt, StringAlignmentNear); GdipCreatePath(FillModeAlternate, &path_tmp); /*to compute first glyph alignment (say 'x', we figure out its bounding full box by using the '_' char as wrapper (eg, "_x_") then the bounding box starting from xMin of the glyph ('x_'). The difference between both will give us a good approx of the glyph alignment*/ str[0] = (unsigned short) '_'; str[1] = string[i]; str[2] = (unsigned short) '_'; str[3] = (unsigned short) 0; GdipAddPathString(path_tmp, str, -1, ctx->font, ctx->font_style, ctx->font_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); Float w1 = rc.Width - 2 * ctx->underscore_width; GdipResetPath(path_tmp); str[0] = string[i]; str[1] = (unsigned short) '_'; str[2] = (unsigned short) 0; rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipAddPathString(path_tmp, str, -1, ctx->font, ctx->font_style, ctx->font_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); real_start = w1 - (rc.Width - ctx->underscore_width); GdipResetPath(path_tmp); rc.X = rc.Y = 0; rc.Width = rc.Height = 0; GdipAddPathString(path_tmp, string, -1, ctx->font, ctx->font_style, ctx->font_size, &rc, fmt); GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL); GdipCreateMatrix(&mat); Float off_left = rc.X; Float off_left_real = rc.X; /*adjust all white space at begin*/ adjust_white_space(string, &off_left, -1*ctx->whitespace_width); if (flipText) { /*first translate in local system*/ GdipTranslateMatrix(mat, left - off_left + real_start, -top, MatrixOrderAppend); /*then scale as specified*/ GdipScaleMatrix(mat, x_scaling, -y_scaling, MatrixOrderAppend); } else { /*first translate in local system*/ GdipTranslateMatrix(mat, left - off_left + real_start, top-ascent, MatrixOrderAppend); /*then scale as specified*/ GdipScaleMatrix(mat, x_scaling, y_scaling, MatrixOrderAppend); } GdipTransformPath(path_tmp, mat); /*start enum*/ s32 count; GdipGetPointCount(path_tmp, &count); GpPointF *pts = new GpPointF[count]; BYTE *types = new BYTE[count]; GdipGetPathTypes(path_tmp, types, count); GdipGetPathPoints(path_tmp, pts, count); for (i=0; i<count; ) { BOOL closed = 0; s32 sub_type; sub_type = types[i] & PathPointTypePathTypeMask; if (sub_type == PathPointTypeStart) { m4_path_add_move_to(path, pts[i].X, pts[i].Y); i++; } else if (sub_type == PathPointTypeLine) { m4_path_add_line_to(path, pts[i].X, pts[i].Y); if (types[i] & PathPointTypeCloseSubpath) m4_path_close(path); i++; } else if (sub_type == PathPointTypeBezier) { assert(i+2<=count); m4_path_add_cubic_to(path, pts[i].X, pts[i].Y, pts[i+1].X, pts[i+1].Y, pts[i+2].X, pts[i+2].Y); if (types[i+2] & PathPointTypeCloseSubpath) m4_path_close(path); i += 3; } else { assert(0); break; } } delete [] pts; delete [] types; GdipResetPath(path_tmp); adjust_white_space(string, &rc.Width, ctx->whitespace_width); rc.X = off_left_real; rc.X = off_left; /*special case where string is just space*/ if (!rc.Height) rc.Height = 1; GdipAddPathRectangles(path_tmp, &rc, 1); GdipGetPathWorldBounds(path_tmp, &rc, mat, NULL); bounds->x = rc.X; bounds->y = rc.Y; bounds->width = rc.Width; bounds->height = rc.Height; GdipDeleteStringFormat(fmt); GdipDeletePath(path_tmp); GdipDeleteMatrix(mat); return M4OK; }