From ecfea7dfbf60953b418a5f9382e0f51ead8fb06c Mon Sep 17 00:00:00 2001 From: "tor%cs.brown.edu" Date: Wed, 19 Jan 2005 19:15:31 +0000 Subject: [PATCH] Make cairo text "live". --- .../src/cairo/nsSVGCairoGlyphGeometry.cpp | 140 +++++++++++++++++- .../src/cairo/nsSVGCairoPathGeometry.cpp | 2 + 2 files changed, 134 insertions(+), 8 deletions(-) diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp index a327182c9d5..0ec48d4b61c 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp @@ -86,6 +86,9 @@ public: protected: nsCOMPtr mSource; + +private: + nsCOMPtr mCoveredRegion; }; /** @} */ @@ -164,7 +167,7 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) metrics = do_QueryInterface(xpmetrics); NS_ASSERTION(metrics, "wrong metrics object!"); if (!metrics) - return NS_ERROR_FAILURE; + return NS_ERROR_FAILURE; } cairo_font_t *font = metrics->GetFont(); @@ -195,8 +198,6 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) if (!hasFill && !hasStroke) return NS_OK; // nothing to paint - - if (hasFill) { nscolor rgb; mSource->GetFillPaint(&rgb); @@ -204,9 +205,9 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) mSource->GetFillOpacity(&opacity); cairo_set_rgb_color(ctx, - NS_GET_R(rgb)/255.0, - NS_GET_G(rgb)/255.0, - NS_GET_B(rgb)/255.0); + NS_GET_R(rgb)/255.0, + NS_GET_G(rgb)/255.0, + NS_GET_B(rgb)/255.0); cairo_set_alpha(ctx, double(opacity)); nsAutoString text; @@ -318,6 +319,45 @@ nsSVGCairoGlyphGeometry::Update(PRUint32 updatemask, nsISVGRendererRegion **_ret { *_retval = nsnull; + const unsigned long strokemask = + nsISVGGlyphMetricsSource::UPDATEMASK_FONT | + nsISVGGlyphMetricsSource::UPDATEMASK_CHARACTER_DATA | + nsISVGGlyphGeometrySource::UPDATEMASK_METRICS | + nsISVGGlyphGeometrySource::UPDATEMASK_X | + nsISVGGlyphGeometrySource::UPDATEMASK_Y | + nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT_TYPE | + nsISVGGeometrySource::UPDATEMASK_STROKE_WIDTH | + nsISVGGeometrySource::UPDATEMASK_STROKE_LINECAP | + nsISVGGeometrySource::UPDATEMASK_STROKE_LINEJOIN | + nsISVGGeometrySource::UPDATEMASK_STROKE_MITERLIMIT | + nsISVGGeometrySource::UPDATEMASK_STROKE_DASH_ARRAY | + nsISVGGeometrySource::UPDATEMASK_STROKE_DASHOFFSET | + nsISVGGeometrySource::UPDATEMASK_CANVAS_TM; + + const unsigned long regionsmask = + nsISVGGlyphGeometrySource::UPDATEMASK_METRICS | + nsISVGGlyphGeometrySource::UPDATEMASK_X | + nsISVGGlyphGeometrySource::UPDATEMASK_Y | + nsISVGGeometrySource::UPDATEMASK_CANVAS_TM; + + if ((updatemask & regionsmask) || (updatemask & strokemask)) { + nsCOMPtr after; + GetCoveredRegion(getter_AddRefs(after)); + + if (mCoveredRegion) { + if (after) + after->Combine(mCoveredRegion, _retval); + } else { + *_retval = after; + NS_IF_ADDREF(*_retval); + } + mCoveredRegion = after; + } + else if (updatemask != nsISVGGeometrySource::UPDATEMASK_NOTHING) { + *_retval = mCoveredRegion; + NS_IF_ADDREF(*_retval); + } + return NS_OK; } @@ -325,7 +365,91 @@ nsSVGCairoGlyphGeometry::Update(PRUint32 updatemask, nsISVGRendererRegion **_ret NS_IMETHODIMP nsSVGCairoGlyphGeometry::GetCoveredRegion(nsISVGRendererRegion **_retval) { - return NS_NewSVGCairoRectRegion(_retval, -10000, -10000, 20000, 20000); + *_retval = nsnull; + cairo_t *ctx = cairo_create(); + + /* get the metrics */ + nsCOMPtr metrics; + { + nsCOMPtr xpmetrics; + mSource->GetMetrics(getter_AddRefs(xpmetrics)); + metrics = do_QueryInterface(xpmetrics); + NS_ASSERTION(metrics, "wrong metrics object!"); + if (!metrics) + return NS_ERROR_FAILURE; + } + + cairo_font_t *font = metrics->GetFont(); + cairo_set_font(ctx, font); + + GetGlobalTransform(ctx); + float x,y; + mSource->GetX(&x); + mSource->GetY(&y); + cairo_move_to(ctx, x, y); + + PRUint16 type; + mSource->GetFillPaintType(&type); + PRBool hasCoveredFill = type != nsISVGGeometrySource::PAINT_TYPE_NONE; + mSource->GetStrokePaintType(&type); + bool hasCoveredStroke = type != nsISVGGeometrySource::PAINT_TYPE_NONE; + + if (!hasCoveredFill && !hasCoveredStroke) return NS_OK; + + nsAutoString text; + mSource->GetCharacterData(text); + cairo_text_path(ctx, (unsigned char*)NS_ConvertUCS2toUTF8(text).get()); + + double xmin, ymin, xmax, ymax; + + if (hasCoveredStroke) { + 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; + } + + cairo_stroke_extents(ctx, &xmin, &ymin, &xmax, &ymax); + } else { + cairo_fill_extents(ctx, &xmin, &ymin, &xmax, &ymax); + } + + cairo_transform_point(ctx, &xmin, &ymin); + cairo_transform_point(ctx, &xmax, &ymax); + + cairo_destroy(ctx); + + return NS_NewSVGCairoRectRegion(_retval, xmin, ymin, xmax-xmin, ymax-ymin); } /** Implements boolean containsPoint(in float x, in float y); */ @@ -342,7 +466,7 @@ nsSVGCairoGlyphGeometry::ContainsPoint(float x, float y, PRBool *_retval) metrics = do_QueryInterface(xpmetrics); NS_ASSERTION(metrics, "wrong metrics object!"); if (!metrics) - return NS_ERROR_FAILURE; + return NS_ERROR_FAILURE; } cairo_font_t *font = metrics->GetFont(); diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp index 01421097767..483cf74cda6 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp @@ -394,6 +394,8 @@ nsSVGCairoPathGeometry::Update(PRUint32 updatemask, nsISVGRendererRegion **_retv NS_IMETHODIMP nsSVGCairoPathGeometry::GetCoveredRegion(nsISVGRendererRegion **_retval) { + *_retval = nsnull; + cairo_t *ctx = cairo_create(); GeneratePath(ctx);