} else if (strokeServerType == nsISVGGeometrySource::PAINT_TYPE_PATTERN) { nsCOMPtr<nsISVGPattern> aPat; mSource->GetStrokePattern(getter_AddRefs(aPat));   nsCOMPtr<nsISVGGeometrySource> aGsource = do_QueryInterface(mSource); cairo_pattern_t *pattern = CairoPattern(canvas, aPat, aGsource); if (pattern) { cairo_set_source(ctx, pattern); cairo_stroke(ctx); cairo_pattern_destroy(pattern); }
nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas){  nsCOMPtr<nsISVGCairoCanvas> cairoCanvas = do_QueryInterface(canvas);  NS_ASSERTION(cairoCanvas, "wrong svg render context for geometry!");  if (!cairoCanvas) return NS_ERROR_FAILURE;  nsAutoString text;  mSource->GetCharacterData(text);  if (!text.Length())    return NS_OK;  nsSVGCharacterPosition *cp;  mSource->GetCharacterPosition(&cp);    if (NS_FAILED(mSource->GetCharacterPosition(&cp)))    return NS_ERROR_FAILURE;  cairo_t *ctx = cairoCanvas->GetContext();  /* get the metrics */  nsCOMPtr<nsISVGCairoGlyphMetrics> metrics;  {    nsCOMPtr<nsISVGRendererGlyphMetrics> xpmetrics;    mSource->GetMetrics(getter_AddRefs(xpmetrics));    metrics = do_QueryInterface(xpmetrics);    NS_ASSERTION(metrics, "wrong metrics object!");    if (!metrics) {      delete [] cp;      return NS_ERROR_FAILURE;    }  }  PRUint16 renderMode;  cairo_matrix_t matrix;  canvas->GetRenderMode(&renderMode);  if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {    /* save/pop the state so we don't screw up the xform */    cairo_save(ctx);  }  else {    cairo_get_matrix(ctx, &matrix);  }  GetGlobalTransform(ctx, cairoCanvas);  metrics->SelectFont(ctx);  float x,y;  mSource->GetX(&x);  mSource->GetY(&y);  cairo_move_to(ctx, x, y);  if (renderMode != nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {    PRUint16 rule;    mSource->GetClipRule(&rule);    if (rule == nsISVGGeometrySource::FILL_RULE_EVENODD)      cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_EVEN_ODD);    else      cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_WINDING);    LOOP_CHARS(cairo_text_path)    cairo_set_matrix(ctx, &matrix);    delete [] cp;    return NS_OK;  }  PRBool hasFill = PR_FALSE;  PRUint16 filltype;  mSource->GetFillPaintType(&filltype);  PRUint16 fillServerType = 0;  if (filltype != nsISVGGeometrySource::PAINT_TYPE_NONE) {    hasFill = PR_TRUE;    if (filltype == nsISVGGeometrySource::PAINT_TYPE_SERVER) {      if (NS_FAILED(mSource->GetFillPaintServerType(&fillServerType)))        hasFill = PR_FALSE;    }  }  PRBool hasStroke = PR_FALSE;  PRUint16 stroketype;  mSource->GetStrokePaintType(&stroketype);  PRUint16 strokeServerType = 0;  if (stroketype != nsISVGGeometrySource::PAINT_TYPE_NONE) {    hasStroke = PR_TRUE;    if (stroketype == nsISVGGeometrySource::PAINT_TYPE_SERVER) {      if (NS_FAILED(mSource->GetStrokePaintServerType(&strokeServerType)))        hasStroke = PR_FALSE;    }  }  if (!hasFill && !hasStroke) {    delete [] cp;    return NS_OK; // nothing to paint  }  if (hasFill) {      nscolor rgb;      mSource->GetFillPaint(&rgb);      float opacity;      mSource->GetFillOpacity(&opacity);            cairo_set_source_rgba(ctx,                            NS_GET_R(rgb)/255.0,                            NS_GET_G(rgb)/255.0,                            NS_GET_B(rgb)/255.0,                            opacity);            nsAutoString text;      mSource->GetCharacterData(text);      if (filltype == nsISVGGeometrySource::PAINT_TYPE_SOLID_COLOR) {        LOOP_CHARS(cairo_show_text)      } else if (filltype == nsISVGGeometrySource::PAINT_TYPE_SERVER) {        if (fillServerType == nsISVGGeometrySource::PAINT_TYPE_GRADIENT) {          nsCOMPtr<nsISVGGradient> aGrad;          mSource->GetFillGradient(getter_AddRefs(aGrad));          cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);          cairo_set_source(ctx, gradient);          LOOP_CHARS(cairo_show_text)          cairo_pattern_destroy(gradient);        }      }  }  cairo_move_to(ctx, x, y);  if (hasStroke) {    nscolor rgb;    mSource->GetStrokePaint(&rgb);    float opacity;    mSource->GetStrokeOpacity(&opacity);    cairo_set_source_rgba(ctx,                          NS_GET_R(rgb)/255.0,                          NS_GET_G(rgb)/255.0,                          NS_GET_B(rgb)/255.0,                          opacity);    float width;    mSource->GetStrokeWidth(&width);    cairo_set_line_width(ctx, double(width));    PRUint16 capStyle;    mSource->GetStrokeLinecap(&capStyle);    switch (capStyle) {    case nsISVGGeometrySource::STROKE_LINECAP_BUTT:      cairo_set_line_cap(ctx, CAIRO_LINE_CAP_BUTT);      break;    case nsISVGGeometrySource::STROKE_LINECAP_ROUND:      cairo_set_line_cap(ctx, CAIRO_LINE_CAP_ROUND);      break;    case nsISVGGeometrySource::STROKE_LINECAP_SQUARE:      cairo_set_line_cap(ctx, CAIRO_LINE_CAP_SQUARE);      break;    }    float miterlimit;    mSource->GetStrokeMiterlimit(&miterlimit);    cairo_set_miter_limit(ctx, double(miterlimit));    PRUint16 joinStyle;    mSource->GetStrokeLinejoin(&joinStyle);    switch(joinStyle) {    case nsISVGGeometrySource::STROKE_LINEJOIN_MITER:      cairo_set_line_join(ctx, CAIRO_LINE_JOIN_MITER);      break;    case nsISVGGeometrySource::STROKE_LINEJOIN_ROUND:      cairo_set_line_join(ctx, CAIRO_LINE_JOIN_ROUND);      break;    case nsISVGGeometrySource::STROKE_LINEJOIN_BEVEL:      cairo_set_line_join(ctx, CAIRO_LINE_JOIN_BEVEL);      break;    }    float *dashArray, offset;    PRUint32 count;    mSource->GetStrokeDashArray(&dashArray, &count);    if (count > 0) {      double *dashes = new double[count];      for (unsigned i=0; i<count; i++)        dashes[i] = dashArray[i];      mSource->GetStrokeDashoffset(&offset);      cairo_set_dash(ctx, dashes, count, double(offset));      nsMemory::Free(dashArray);      delete [] dashes;    }    LOOP_CHARS(cairo_text_path)    if (stroketype == nsISVGGeometrySource::PAINT_TYPE_SOLID_COLOR) {      cairo_stroke(ctx);    } else if (stroketype == nsISVGGeometrySource::PAINT_TYPE_SERVER) {      if (strokeServerType == nsISVGGeometrySource::PAINT_TYPE_GRADIENT) {        nsCOMPtr<nsISVGGradient> aGrad;        mSource->GetStrokeGradient(getter_AddRefs(aGrad));        cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);        cairo_set_source(ctx, gradient);        cairo_stroke(ctx);        cairo_pattern_destroy(gradient);      }    }  }  delete [] cp;  cairo_restore(ctx);    return NS_OK;}