/* FIXME: Sometimes when fillPath is non-null and stroke path is null, the native * version of this function returns NotImplemented. I cannot figure out why. */ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* strokePath, GpLineCap baseCap, REAL baseInset, GpCustomLineCap **customCap) { GpPathData *pathdata; TRACE("%p %p %d %f %p\n", fillPath, strokePath, baseCap, baseInset, customCap); if(!customCap || !(fillPath || strokePath)) return InvalidParameter; *customCap = GdipAlloc(sizeof(GpCustomLineCap)); if(!*customCap) return OutOfMemory; if(strokePath){ (*customCap)->fill = FALSE; pathdata = &strokePath->pathdata; } else{ (*customCap)->fill = TRUE; pathdata = &fillPath->pathdata; } (*customCap)->pathdata.Points = GdipAlloc(pathdata->Count * sizeof(PointF)); (*customCap)->pathdata.Types = GdipAlloc(pathdata->Count); if((!(*customCap)->pathdata.Types || !(*customCap)->pathdata.Points) && pathdata->Count){ GdipFree((*customCap)->pathdata.Points); GdipFree((*customCap)->pathdata.Types); GdipFree(*customCap); return OutOfMemory; } memcpy((*customCap)->pathdata.Points, pathdata->Points, pathdata->Count * sizeof(PointF)); memcpy((*customCap)->pathdata.Types, pathdata->Types, pathdata->Count); (*customCap)->pathdata.Count = pathdata->Count; (*customCap)->inset = baseInset; (*customCap)->cap = baseCap; (*customCap)->join = LineJoinMiter; (*customCap)->scale = 1.0; return Ok; }
GpStatus gdip_adjust_arrowcap_destroy (GpCustomLineCap *cap) { if (!cap) return InvalidParameter; GdipFree (cap); return Ok; }
GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points, INT count, GpWrapMode wrap, GpPathGradient **grad) { COLORREF col = ARGB2COLORREF(0xffffffff); if(!points || !grad) return InvalidParameter; if(count <= 0) return OutOfMemory; *grad = GdipAlloc(sizeof(GpPathGradient)); if (!*grad) return OutOfMemory; (*grad)->pathdata.Count = count; (*grad)->pathdata.Points = GdipAlloc(count * sizeof(PointF)); (*grad)->pathdata.Types = GdipAlloc(count); if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){ GdipFree((*grad)->pathdata.Points); GdipFree((*grad)->pathdata.Types); GdipFree(*grad); return OutOfMemory; } memcpy((*grad)->pathdata.Points, points, count * sizeof(PointF)); memset((*grad)->pathdata.Types, PathPointTypeLine, count); (*grad)->brush.lb.lbStyle = BS_SOLID; (*grad)->brush.lb.lbColor = col; (*grad)->brush.lb.lbHatch = 0; (*grad)->brush.gdibrush = CreateSolidBrush(col); (*grad)->brush.bt = BrushTypePathGradient; (*grad)->centercolor = 0xffffffff; (*grad)->wrap = wrap; (*grad)->gamma = FALSE; (*grad)->center.X = 0.0; (*grad)->center.Y = 0.0; (*grad)->focus.X = 0.0; (*grad)->focus.Y = 0.0; return Ok; }
GpStatus cairo_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc, GDIPCONST GpStringFormat *format, GpBrush *brush) { cairo_matrix_t SavedMatrix; GpStringFormat *fmt; GpStringDetailStruct *StringDetails; WCHAR *CleanString; GpDrawTextData data; /* avoid recomputation of stuff done while measuring */ int StringLen = length; GpStatus status = AllocStringData (&CleanString, &StringDetails, length); if (status != Ok) return status; /* a NULL format is valid, it means get the generic default values (and free them later) */ if (!format) { GdipStringFormatGetGenericDefault ((GpStringFormat **)&fmt); } else { fmt = (GpStringFormat *)format; } /* is the following ok ? */ cairo_get_font_matrix (graphics->ct, &SavedMatrix); status = MeasureString (graphics, stringUnicode, &StringLen, font, rc, fmt, brush, NULL, NULL, NULL, CleanString, StringDetails, &data); if ((status == Ok) && (StringLen > 0)) { status = DrawString (graphics, stringUnicode, StringLen, font, rc, fmt, brush, CleanString, StringDetails, &data); } /* Restore matrix to original values */ cairo_set_font_matrix (graphics->ct, &SavedMatrix); /* Cleanup */ GdipFree (CleanString); GdipFree (StringDetails); /* we must delete the default stringformat (when one wasn't provided by the caller) */ if (format != fmt) GdipDeleteStringFormat (fmt); return status; }
/***************************************************************************** * GdipDeleteFontFamily [GDIPLUS.@] * * Removes the specified FontFamily * * PARAMS * *FontFamily [I] The family to delete * * RETURNS * SUCCESS: Ok * FAILURE: InvalidParameter if FontFamily is NULL. * */ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily) { if (!FontFamily) return InvalidParameter; TRACE("Deleting %p (%s)\n", FontFamily, debugstr_w(FontFamily->FamilyName)); GdipFree (FontFamily); return Ok; }
/* free all nodes including argument */ static void free_path_list(path_list_node_t *node) { path_list_node_t *n = node; while(n) { n = n->next; GdipFree(node); node = n; } }
/***************************************************************************** * GdipCombineRegionRect [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect, CombineMode mode) { GpRegion *rect_region; region_element *left, *right = NULL; GpStatus stat; TRACE("%p %s %d\n", region, debugstr_rectf(rect), mode); if (!(region && rect)) return InvalidParameter; stat = GdipCreateRegionRect(rect, &rect_region); if (stat != Ok) return stat; /* simply replace region data */ if(mode == CombineModeReplace){ delete_element(®ion->node); memcpy(region, rect_region, sizeof(GpRegion)); GdipFree(rect_region); return Ok; } left = GdipAlloc(sizeof(region_element)); if (left) { memcpy(left, ®ion->node, sizeof(region_element)); stat = clone_element(&rect_region->node, &right); if (stat == Ok) { fuse_region(region, left, right, mode); GdipDeleteRegion(rect_region); return Ok; } } else stat = OutOfMemory; GdipFree(left); GdipDeleteRegion(rect_region); return stat; }
/* FIXME: path gradient brushes not truly supported (drawn as solid brushes) */ GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path, GpPathGradient **grad) { COLORREF col = ARGB2COLORREF(0xffffffff); if(!path || !grad) return InvalidParameter; *grad = GdipAlloc(sizeof(GpPathGradient)); if (!*grad) return OutOfMemory; (*grad)->pathdata.Count = path->pathdata.Count; (*grad)->pathdata.Points = GdipAlloc(path->pathdata.Count * sizeof(PointF)); (*grad)->pathdata.Types = GdipAlloc(path->pathdata.Count); if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){ GdipFree((*grad)->pathdata.Points); GdipFree((*grad)->pathdata.Types); GdipFree(*grad); return OutOfMemory; } memcpy((*grad)->pathdata.Points, path->pathdata.Points, path->pathdata.Count * sizeof(PointF)); memcpy((*grad)->pathdata.Types, path->pathdata.Types, path->pathdata.Count); (*grad)->brush.lb.lbStyle = BS_SOLID; (*grad)->brush.lb.lbColor = col; (*grad)->brush.lb.lbHatch = 0; (*grad)->brush.gdibrush = CreateSolidBrush(col); (*grad)->brush.bt = BrushTypePathGradient; (*grad)->centercolor = 0xffffffff; (*grad)->wrap = WrapModeClamp; (*grad)->gamma = FALSE; /* FIXME: this should be set to the "centroid" of the path by default */ (*grad)->center.X = 0.0; (*grad)->center.Y = 0.0; (*grad)->focus.X = 0.0; (*grad)->focus.Y = 0.0; return Ok; }
/******************************************************************************* * GdipCreateFont [GDIPLUS.@] * * Create a new font based off of a FontFamily * * PARAMS * *fontFamily [I] Family to base the font off of * emSize [I] Size of the font * style [I] Bitwise OR of FontStyle enumeration * unit [I] Unit emSize is measured in * **font [I] the resulting Font object * * RETURNS * SUCCESS: Ok * FAILURE: InvalidParameter if fontfamily or font is NULL. * FAILURE: FontFamilyNotFound if an invalid FontFamily is given * * NOTES * UnitDisplay is unsupported. * emSize is stored separately from lfHeight, to hold the fraction. */ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, REAL emSize, INT style, Unit unit, GpFont **font) { HFONT hfont; OUTLINETEXTMETRICW otm; LOGFONTW lfw; HDC hdc; GpStatus stat; int ret; if (!fontFamily || !font || emSize < 0.0) return InvalidParameter; TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily, debugstr_w(fontFamily->FamilyName), emSize, style, unit, font); memset(&lfw, 0, sizeof(lfw)); stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL); if (stat != Ok) return stat; lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi); lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR; lfw.lfItalic = style & FontStyleItalic; lfw.lfUnderline = style & FontStyleUnderline; lfw.lfStrikeOut = style & FontStyleStrikeout; hfont = CreateFontIndirectW(&lfw); hdc = CreateCompatibleDC(0); SelectObject(hdc, hfont); otm.otmSize = sizeof(otm); ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm); DeleteDC(hdc); DeleteObject(hfont); if (!ret) return NotTrueTypeFont; *font = GdipAlloc(sizeof(GpFont)); if (!*font) return OutOfMemory; (*font)->unit = unit; (*font)->emSize = emSize; (*font)->otm = otm; stat = clone_font_family(fontFamily, &(*font)->family); if (stat != Ok) { GdipFree(*font); return stat; } TRACE("<-- %p\n", *font); return Ok; }
/***************************************************************************** * GdipCombineRegionPath [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode) { GpRegion *path_region; region_element *left, *right = NULL; GpStatus stat; TRACE("%p %p %d\n", region, path, mode); if (!(region && path)) return InvalidParameter; stat = GdipCreateRegionPath(path, &path_region); if (stat != Ok) return stat; /* simply replace region data */ if(mode == CombineModeReplace){ delete_element(®ion->node); memcpy(region, path_region, sizeof(GpRegion)); GdipFree(path_region); return Ok; } left = GdipAlloc(sizeof(region_element)); if (left) { *left = region->node; stat = clone_element(&path_region->node, &right); if (stat == Ok) { fuse_region(region, left, right, mode); GdipDeleteRegion(path_region); return Ok; } } else stat = OutOfMemory; GdipFree(left); GdipDeleteRegion(path_region); return stat; }
/******************************************************************************* * GdipDeleteFont [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font) { TRACE("(%p)\n", font); if(!font) return InvalidParameter; GdipFree(font); return Ok; }
GpStatus cairo_MeasureString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc, GDIPCONST GpStringFormat *format, RectF *boundingBox, int *codepointsFitted, int *linesFilled) { cairo_matrix_t SavedMatrix; GpStringFormat *fmt; GpStringDetailStruct *StringDetails; WCHAR *CleanString; int StringLen = length; GpStatus status; status = AllocStringData (&CleanString, &StringDetails, length); if (status != Ok) return status; /* a NULL format is valid, it means get the generic default values (and free them later) */ if (!format) { GdipStringFormatGetGenericDefault ((GpStringFormat **)&fmt); } else { fmt = (GpStringFormat *)format; } /* is the following ok ? */ cairo_get_font_matrix (graphics->ct, &SavedMatrix); status = MeasureString (graphics, stringUnicode, &StringLen, font, rc, fmt, NULL, boundingBox, codepointsFitted, linesFilled, CleanString, StringDetails, NULL); /* Restore matrix to original values */ cairo_set_font_matrix (graphics->ct, &SavedMatrix); /* Cleanup */ GdipFree (CleanString); GdipFree (StringDetails); /* we must delete the default stringformat (when one wasn't provided by the caller) */ if (format != fmt) GdipDeleteStringFormat (fmt); return status; }
/***************************************************************************** * GdipDeleteRegion [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipDeleteRegion(GpRegion *region) { TRACE("%p\n", region); if (!region) return InvalidParameter; delete_element(®ion->node); GdipFree(region); return Ok; }
/* Transforms GpRegion elements with given matrix */ static GpStatus transform_region_element(region_element* element, GpMatrix *matrix) { GpStatus stat; switch(element->type) { case RegionDataEmptyRect: case RegionDataInfiniteRect: return Ok; case RegionDataRect: { /* We can't transform a rectangle, so convert it to a path. */ GpRegion *new_region; GpPath *path; stat = GdipCreatePath(FillModeAlternate, &path); if (stat == Ok) { stat = GdipAddPathRectangle(path, element->elementdata.rect.X, element->elementdata.rect.Y, element->elementdata.rect.Width, element->elementdata.rect.Height); if (stat == Ok) stat = GdipCreateRegionPath(path, &new_region); GdipDeletePath(path); } if (stat == Ok) { /* Steal the element from the created region. */ memcpy(element, &new_region->node, sizeof(region_element)); GdipFree(new_region); } else return stat; } /* Fall-through to do the actual conversion. */ case RegionDataPath: if (!element->elementdata.path->pathdata.Count) return Ok; stat = GdipTransformMatrixPoints(matrix, element->elementdata.path->pathdata.Points, element->elementdata.path->pathdata.Count); return stat; default: stat = transform_region_element(element->elementdata.combine.left, matrix); if (stat == Ok) stat = transform_region_element(element->elementdata.combine.right, matrix); return stat; } }
/***************************************************************************** * GdipCombineRegionRegion [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2, CombineMode mode) { region_element *left, *right = NULL; GpStatus stat; GpRegion *reg2copy; TRACE("%p %p %d\n", region1, region2, mode); if(!(region1 && region2)) return InvalidParameter; /* simply replace region data */ if(mode == CombineModeReplace){ stat = GdipCloneRegion(region2, ®2copy); if(stat != Ok) return stat; delete_element(®ion1->node); memcpy(region1, reg2copy, sizeof(GpRegion)); GdipFree(reg2copy); return Ok; } left = GdipAlloc(sizeof(region_element)); if (!left) return OutOfMemory; *left = region1->node; stat = clone_element(®ion2->node, &right); if (stat != Ok) { GdipFree(left); return OutOfMemory; } fuse_region(region1, left, right, mode); region1->num_children += region2->num_children; return Ok; }
/* coverity[+alloc : arg-*2] */ GpStatus WINGDIPAPI GdipCreateTexture (GpImage *image, GpWrapMode wrapMode, GpTexture **texture) { cairo_surface_t *imageSurface = NULL; GpTexture *result; GpStatus status; if (!image || !texture) return InvalidParameter; if ((wrapMode < WrapModeTile) || (wrapMode > WrapModeClamp)) return OutOfMemory; if (image->type != ImageTypeBitmap) return NotImplemented; result = gdip_texture_new (); if (!result) return OutOfMemory; result->image = NULL; status = GdipCloneImage (image, &result->image); if (status != Ok) goto failure; /* note: we must keep the scan0 alive, so we must use the cloned image (and not the original) see bug #80971 */ imageSurface = cairo_image_surface_create_for_data ((BYTE*)result->image->active_bitmap->scan0, image->cairo_format, image->active_bitmap->width, image->active_bitmap->height, image->active_bitmap->stride); if (!imageSurface) goto failure; result->wrapMode = wrapMode; if (result->image->surface) cairo_surface_destroy (result->image->surface); result->image->surface = imageSurface; result->rectangle.X = 0; result->rectangle.Y = 0; result->rectangle.Width = image->active_bitmap->width; result->rectangle.Height = image->active_bitmap->height; *texture = result; return Ok; failure: if (result->image) GdipDisposeImage (result->image); if (imageSurface) cairo_surface_destroy (imageSurface); GdipFree (result); *texture = NULL; return status; }
GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush) { if(!brush) return InvalidParameter; switch(brush->bt) { case BrushTypePathGradient: GdipFree(((GpPathGradient*) brush)->pathdata.Points); GdipFree(((GpPathGradient*) brush)->pathdata.Types); break; case BrushTypeSolidColor: case BrushTypeLinearGradient: case BrushTypeTextureFill: default: break; } DeleteObject(brush->gdibrush); GdipFree(brush); return Ok; }
GpStatus GdipDeleteBrush (GpBrush *brush) { GpStatus status; if (!brush) return InvalidParameter; status = brush->vtable->destroy (brush); GdipFree (brush); return status; }
GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat) { if(!format || !newFormat) return InvalidParameter; *newFormat = GdipAlloc(sizeof(GpStringFormat)); if(!*newFormat) return OutOfMemory; **newFormat = *format; if(format->tabcount > 0){ (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount); if(!(*newFormat)->tabs){ GdipFree(*newFormat); return OutOfMemory; } memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount); } else (*newFormat)->tabs = NULL; if(format->range_count > 0){ (*newFormat)->character_ranges = GdipAlloc(sizeof(CharacterRange) * format->range_count); if(!(*newFormat)->character_ranges){ GdipFree((*newFormat)->tabs); GdipFree(*newFormat); return OutOfMemory; } memcpy((*newFormat)->character_ranges, format->character_ranges, sizeof(CharacterRange) * format->range_count); } else (*newFormat)->character_ranges = NULL; TRACE("%p %p\n",format,newFormat); return Ok; }
GpStatus GdipDeletePathIter (GpPathIterator *iterator) { if (!iterator) return InvalidParameter; if (iterator->path) { GdipDeletePath (iterator->path); iterator->path = NULL; } GdipFree (iterator); return Ok; }
GpStatus WINGDIPAPI GdipDeleteStringFormat (GpStringFormat *format) { if (!format) return InvalidParameter; // These are singletons cleared on shutdown. if (format == &stringFormatDefault || format == &stringFormatTypographic) return Ok; gdip_string_format_clear (format); GdipFree (format); return Ok; }
static GpStatus AllocStringData (WCHAR **clean_string, GpStringDetailStruct **details, int length) { *details = gdip_calloc (length + 1, sizeof (GpStringDetailStruct)); if (!*details) return OutOfMemory; *clean_string = GdipAlloc (sizeof (WCHAR) * (length + 1)); if (!*clean_string) { GdipFree (*details); return OutOfMemory; } return Ok; }
GpStatus WINGDIPAPI GdipDeletePen (GpPen *pen) { if (!pen) return InvalidParameter; if (pen->dash_count != 0 && pen->own_dash_array) { GdipFree (pen->dash_array); pen->dash_count = 0; pen->dash_array = NULL; } if (pen->own_brush && pen->brush) { GdipDeleteBrush (pen->brush); pen->brush = NULL; } if (pen->compound_count != 0) { GdipFree (pen->compound_array); pen->compound_array = NULL; pen->compound_count = 0; } if (pen->custom_start_cap != NULL) { GdipDeleteCustomLineCap (pen->custom_start_cap); pen->custom_start_cap = NULL; } if (pen->custom_end_cap != NULL) { GdipDeleteCustomLineCap (pen->custom_end_cap); pen->custom_end_cap = NULL; } GdipFree (pen); return Ok; }
GpStatus metafile_FillRectanglesI (GpGraphics *graphics, GpBrush *brush, GDIPCONST GpRect *rects, int count) { /* every rectangle must fit into a INT16 or we must use the float version */ if (!GpRectArrayFitInInt16 (rects, count)) { GpStatus status; GpRectF *rf = convert_rects (rects, count); if (!rf) return OutOfMemory; status = metafile_FillRectangles (graphics, brush, rf, count); GdipFree (rf); return status; } /* TODO */ return Ok; }
/* Currently not used */ static int CalculateStringWidthsUTF8 (cairo_t *ct, GDIPCONST GpFont *gdiFont, const BYTE *utf8, unsigned long StringDetailElements, GpStringDetailStruct *StringDetails) { FT_Face face; size_t i; gunichar *ucs4 = NULL; cairo_font_face_t *Font; GpStringDetailStruct *CurrentDetail; glong NumOfGlyphs; cairo_matrix_t matrix; #ifdef DRAWSTRING_DEBUG printf("CalculateStringWidths(font, %s, %d, details) called\n", utf8, StringDetailElements); #endif Font = (cairo_font_face_t *)gdiFont->cairofnt; face = gdip_cairo_ft_font_lock_face(Font); if (!face) return 0; cairo_get_font_matrix(ct, &matrix); cairo_matrix_scale(&matrix, gdiFont->sizeInPixels, gdiFont->sizeInPixels); ucs4 = g_utf8_to_ucs4 ((const gchar *) utf8, (glong)-1, NULL, &NumOfGlyphs, NULL); if ((NumOfGlyphs == 0) || (ucs4 == NULL)) { return 0; } CurrentDetail=StringDetails; for (i = 0; i < NumOfGlyphs; i++) { FT_Load_Glyph (face, FT_Get_Char_Index (face, ucs4[i]), FT_LOAD_DEFAULT); CurrentDetail->Width = DOUBLE_FROM_26_6 (face->glyph->advance.x); CurrentDetail++; } gdip_cairo_ft_font_unlock_face(Font); GdipFree(ucs4); #ifdef DRAWSTRING_DEBUG printf("CalculateStringWidths: string >%s< translated into %d glyphs\n", utf8, NumOfGlyphs); #endif return NumOfGlyphs; }
GpStatus GdipPrivateAddFontFile (GpFontCollection *font_collection, GDIPCONST WCHAR *filename) { BYTE *file; if (!font_collection || !filename) return InvalidParameter; file = (BYTE*) ucs2_to_utf8 ((const gunichar2 *)filename, -1); if (!file) return OutOfMemory; FcConfigAppFontAddFile (font_collection->config, file); GdipFree (file); return Ok; }
static void test_fontfamily (void) { GpFontFamily** family = NULL; WCHAR itsName[LF_FACESIZE]; GpStatus stat; /* FontFamily can not be NULL */ stat = GdipCreateFontFamilyFromName (arial , NULL, family); expect (InvalidParameter, stat); family = GdipAlloc (sizeof (GpFontFamily*)); /* FontFamily must be able to actually find the family. * If it can't, any subsequent calls should fail * * We currently fail (meaning we don't) because we don't actually * test to see if we can successfully get a family */ stat = GdipCreateFontFamilyFromName (nonexistant, NULL, family); expect (FontFamilyNotFound, stat); stat = GdipGetFamilyName (*family,itsName, LANG_NEUTRAL); expect (InvalidParameter, stat); ok ((lstrcmpiW(itsName,nonexistant) != 0), "Expected a non-zero value for nonexistant font!\n"); stat = GdipDeleteFontFamily(*family); expect (InvalidParameter, stat); stat = GdipCreateFontFamilyFromName (arial, NULL, family); expect (Ok, stat); stat = GdipGetFamilyName (*family, itsName, LANG_NEUTRAL); expect (Ok, stat); expect (0, lstrcmpiW(itsName,arial)); if (0) { /* Crashes on Windows XP SP2, Vista, and so Wine as well */ stat = GdipGetFamilyName (*family, NULL, LANG_NEUTRAL); expect (Ok, stat); } stat = GdipDeleteFontFamily(*family); expect (Ok, stat); if (family) GdipFree (family); }
/******************************************************************************* * GdipCloneFont [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont) { GpStatus stat; TRACE("(%p, %p)\n", font, cloneFont); if(!font || !cloneFont) return InvalidParameter; *cloneFont = GdipAlloc(sizeof(GpFont)); if(!*cloneFont) return OutOfMemory; **cloneFont = *font; stat = GdipCloneFontFamily(font->family, &(*cloneFont)->family); if (stat != Ok) GdipFree(*cloneFont); return stat; }
GpStatus gdip_texture_clone (GpBrush *brush, GpBrush **clonedBrush) { GpTexture *result; GpTexture *texture; GpStatus status; if (!brush || !clonedBrush) return InvalidParameter; result = (GpTexture *) GdipAlloc (sizeof (GpTexture)); if (result == NULL) { return OutOfMemory; } texture = (GpTexture *) brush; result->base = texture->base; result->wrapMode = texture->wrapMode; /* Let the clone create its own pattern. */ result->pattern = NULL; result->base.changed = TRUE; gdip_cairo_matrix_copy (&result->matrix, &texture->matrix); result->rectangle.X = texture->rectangle.X; result->rectangle.Y = texture->rectangle.Y; result->rectangle.Width = texture->rectangle.Width; result->rectangle.Height = texture->rectangle.Height; result->image = NULL; status = GdipCloneImage (texture->image, &result->image); if (status != Ok) { if (result->image) GdipDisposeImage (result->image); GdipFree (result); result = NULL; } else { cairo_surface_reference (result->image->surface); } *clonedBrush = (GpBrush *) result; return status; }
gchar * ucs2_to_utf8(const gunichar2 *ucs2, int length) { const gunichar2 *ptr; const gunichar2 *end; gunichar *dest; gunichar *uni; gchar *utf8; /* Count length */ if (length == -1) { ptr = ucs2; length = 0; while (*ptr != 0) { ptr++; length++; } } uni = GdipAlloc((length + 1) * sizeof(gunichar)); if (uni == NULL) { return NULL; } dest = uni; ptr = ucs2; end = ptr + length; while (ptr != end) { if (*ptr < 0xd800 || *ptr >= 0xe000) { *dest = *ptr; dest++; } ptr++; } *dest = 0; dest++; utf8 = (gchar *) g_ucs4_to_utf8 ((const gunichar *)uni, -1, NULL, NULL, NULL); GdipFree(uni); return utf8; }