diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo/cdcairo.c | 136 | ||||
-rw-r--r-- | src/gdiplus/cdwinp.cpp | 34 |
2 files changed, 126 insertions, 44 deletions
diff --git a/src/cairo/cdcairo.c b/src/cairo/cdcairo.c index 6ff389c..960a0d1 100644 --- a/src/cairo/cdcairo.c +++ b/src/cairo/cdcairo.c @@ -589,6 +589,33 @@ static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) /******************************************************/ +static void sSetTransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + { + cairo_matrix_t mtx; + + /* configure a bottom-up coordinate system */ + mtx.xx = 1; mtx.yx = 0; + mtx.xy = 0; mtx.yy = -1; + mtx.x0 = 0; mtx.y0 = (ctxcanvas->canvas->h-1); + cairo_transform(ctxcanvas->cr, &mtx); + + mtx.xx = matrix[0]; mtx.yx = matrix[1]; + mtx.xy = matrix[2]; mtx.yy = matrix[3]; + mtx.x0 = matrix[4]; mtx.y0 = matrix[5]; + cairo_transform(ctxcanvas->cr, &mtx); + } + else if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + /* the rotation must be corrected because of the Y axis orientation */ + cairo_translate(ctxcanvas->cr, ctxcanvas->rotate_center_x, _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); + cairo_rotate(ctxcanvas->cr, (double)-ctxcanvas->rotate_angle * CD_DEG2RAD); + cairo_translate(ctxcanvas->cr, -ctxcanvas->rotate_center_x, -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); + } +} + static void cdclear(cdCtxCanvas* ctxcanvas) { cairo_save (ctxcanvas->cr); @@ -763,10 +790,71 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); } +static void sGetTransformTextHeight(cdCanvas* canvas, int x, int y, int w, int h, int *hbox) +{ + int xmin, xmax, ymin, ymax; + int baseline, height, ascent; + + /* distance from bottom to baseline */ + cdgetfontdim(canvas->ctxcanvas, NULL, &height, &ascent, NULL); + baseline = height - ascent; + + /* move to bottom-left */ + cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin); + + xmax = xmin + w-1; + ymax = ymin + h-1; + + if (canvas->text_orientation) + { + double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + int rectY[4]; + + cdRotatePointY(canvas, xmin, ymin, x, y, &rectY[0], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymin, x, y, &rectY[1], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymax, x, y, &rectY[2], sin_theta, cos_theta); + cdRotatePointY(canvas, xmin, ymax, x, y, &rectY[3], sin_theta, cos_theta); + + ymin = ymax = rectY[0]; + if (rectY[1] < ymin) ymin = rectY[1]; + if (rectY[2] < ymin) ymin = rectY[2]; + if (rectY[3] < ymin) ymin = rectY[3]; + if (rectY[1] > ymax) ymax = rectY[1]; + if (rectY[2] > ymax) ymax = rectY[2]; + if (rectY[3] > ymax) ymax = rectY[3]; + } + + *hbox = ymax-ymin+1; +} + +static void sSetTextTransform(cdCtxCanvas* ctxcanvas, double *x, double *y, int w, int h) +{ + int hbox; + cairo_matrix_t mtx; + + sGetTransformTextHeight(ctxcanvas->canvas, (int)*x, (int)*y, w, h, &hbox); + + /* move to (x,y) and remove a vertical offset since text reference point is top-left */ + mtx.xx = 1; mtx.yx = 0; + mtx.xy = 0; mtx.yy = 1; + mtx.x0 = *x; mtx.y0 = *y - (hbox-1); + cairo_transform(ctxcanvas->cr, &mtx); + + /* invert the text vertical orientation, relative to itself */ + mtx.xx = 1; mtx.yx = 0; + mtx.xy = 0; mtx.yy = -1; + mtx.x0 = 0; mtx.y0 = hbox-1; + cairo_transform(ctxcanvas->cr, &mtx); + + *x = 0; + *y = 0; +} + static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) { PangoFontMetrics* metrics; - int w, h, desc, dir = -1; + int w, h, desc, dir = -1, reset_transform = 0; pango_layout_set_text(ctxcanvas->fontlayout, sStrConvertToUTF8(ctxcanvas, s, len), -1); @@ -774,14 +862,25 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i metrics = pango_context_get_metrics(ctxcanvas->fontcontext, ctxcanvas->fontdesc, pango_context_get_language(ctxcanvas->fontcontext)); desc = (((pango_font_metrics_get_descent(metrics)) + PANGO_SCALE/2) / PANGO_SCALE); - if (ctxcanvas->canvas->text_orientation) + if (ctxcanvas->canvas->text_orientation || + ctxcanvas->canvas->use_matrix || + ctxcanvas->rotate_angle) + reset_transform = 1; + + if (reset_transform) { cairo_save (ctxcanvas->cr); + cairo_identity_matrix(ctxcanvas->cr); + } + + if (ctxcanvas->canvas->text_orientation) + { cairo_translate(ctxcanvas->cr, x, y); cairo_rotate(ctxcanvas->cr, -ctxcanvas->canvas->text_orientation*CD_DEG2RAD); cairo_translate(ctxcanvas->cr, -x, -y); } + /* move to top-left corner of the text */ switch (ctxcanvas->canvas->text_alignment) { case CD_BASE_RIGHT: @@ -831,6 +930,15 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i break; } + if (ctxcanvas->canvas->use_matrix) + { + double* matrix = ctxcanvas->canvas->matrix; + sSetTransform(ctxcanvas, matrix); + sSetTextTransform(ctxcanvas, &x, &y, w, h); + } + else + sSetTransform(ctxcanvas, NULL); + /* Inform Pango to re-layout the text with the new transformation */ pango_cairo_update_layout(ctxcanvas->cr, ctxcanvas->fontlayout); @@ -839,7 +947,7 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i cairo_move_to(ctxcanvas->cr, x, y); pango_cairo_show_layout(ctxcanvas->cr, ctxcanvas->fontlayout); - if (ctxcanvas->canvas->text_orientation) + if (reset_transform) cairo_restore(ctxcanvas->cr); pango_font_metrics_unref(metrics); @@ -1547,29 +1655,9 @@ static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) ctxcanvas->canvas->invert_yaxis = 1; if (matrix) - { - cairo_matrix_t mtx; - - /* configure a bottom-up coordinate system */ - mtx.xx = 1; mtx.yx = 0; - mtx.xy = 0; mtx.yy = -1; - mtx.x0 = 0; mtx.y0 = (ctxcanvas->canvas->h-1); - cairo_transform(ctxcanvas->cr, &mtx); ctxcanvas->canvas->invert_yaxis = 0; - mtx.xx = matrix[0]; mtx.yx = matrix[1]; - mtx.xy = matrix[2]; mtx.yy = matrix[3]; - mtx.x0 = matrix[4]; mtx.y0 = matrix[5]; - cairo_transform(ctxcanvas->cr, &mtx); - } - else if (ctxcanvas->rotate_angle) - { - /* rotation = translate to point + rotation + translate back */ - /* the rotation must be corrected because of the Y axis orientation */ - cairo_translate(ctxcanvas->cr, ctxcanvas->rotate_center_x, _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); - cairo_rotate(ctxcanvas->cr, (double)-ctxcanvas->rotate_angle * CD_DEG2RAD); - cairo_translate(ctxcanvas->cr, -ctxcanvas->rotate_center_x, -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); - } + sSetTransform(ctxcanvas, matrix); } /******************************************************************/ diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp index 52c19a1..6827f53 100644 --- a/src/gdiplus/cdwinp.cpp +++ b/src/gdiplus/cdwinp.cpp @@ -65,13 +65,14 @@ void cdwpKillCanvas(cdCtxCanvas* ctxcanvas) /* ctxcanvas eŽ liberado em cada driver */ } -static int cdwpSetTransform(cdCtxCanvas* ctxcanvas, Matrix &transformMatrix, const double* matrix) +static int sAddTransform(cdCtxCanvas* ctxcanvas, Matrix &transformMatrix, const double* matrix) { if (matrix) { // configure a bottom-up coordinate system Matrix Matrix1((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1)); transformMatrix.Multiply(&Matrix1); + // add the global transform Matrix Matrix2((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]); transformMatrix.Multiply(&Matrix2); @@ -89,11 +90,11 @@ static int cdwpSetTransform(cdCtxCanvas* ctxcanvas, Matrix &transformMatrix, con return 0; } -static void cdwpUpdateTransform(cdCtxCanvas* ctxcanvas) +static void sUpdateTransform(cdCtxCanvas* ctxcanvas) { Matrix transformMatrix; ctxcanvas->graphics->ResetTransform(); // reset to the identity. - if (cdwpSetTransform(ctxcanvas, transformMatrix, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL)) + if (sAddTransform(ctxcanvas, transformMatrix, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL)) ctxcanvas->graphics->SetTransform(&transformMatrix); } @@ -1304,7 +1305,7 @@ static void sTextBox(cdCtxCanvas* ctxcanvas, WCHAR *ws, int len, int x, int y, i *ymin += ydir * (*h); } -static void cdwpCanvasGetTextHeight(cdCanvas* canvas, int x, int y, int w, int h, int *hbox) +static void sGetTransformTextHeight(cdCanvas* canvas, int x, int y, int w, int h, int *hbox) { int xmin, xmax, ymin, ymax; @@ -1340,21 +1341,12 @@ static void cdwpCanvasGetTextHeight(cdCanvas* canvas, int x, int y, int w, int h *hbox = ymax-ymin+1; } -static void cdwpTextTransform(cdCtxCanvas* ctxcanvas, int *x, int *y, int w, int h, Matrix &transformMatrix) +static void sAddTextTransform(cdCtxCanvas* ctxcanvas, int *x, int *y, int w, int h, Matrix &transformMatrix) { int hbox; - double* matrix = ctxcanvas->canvas->matrix; Matrix m1; - cdwpCanvasGetTextHeight(ctxcanvas->canvas, *x, *y, w, h, &hbox); - - // configure a bottom-up coordinate system - m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1)); - transformMatrix.Multiply(&m1); - - // add the global transform - m1.SetElements((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]); - transformMatrix.Multiply(&m1); + sGetTransformTextHeight(ctxcanvas->canvas, *x, *y, w, h, &hbox); // move to (x,y) and remove a vertical offset since text reference point is top-left m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)1, (REAL)*x, (REAL)(*y - (hbox-1))); @@ -1387,10 +1379,12 @@ static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s, int len) if (ctxcanvas->canvas->use_matrix) { - cdwpTextTransform(ctxcanvas, &x, &y, w, h, transformMatrix); + double* matrix = ctxcanvas->canvas->matrix; + sAddTransform(ctxcanvas, transformMatrix, matrix); + sAddTextTransform(ctxcanvas, &x, &y, w, h, transformMatrix); use_transform = 1; } - else if (cdwpSetTransform(ctxcanvas, transformMatrix, NULL)) + else if (sAddTransform(ctxcanvas, transformMatrix, NULL)) use_transform = 1; if (ctxcanvas->canvas->new_region) @@ -1419,7 +1413,7 @@ static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s, int len) ctxcanvas->lineBrush); if (use_transform) - cdwpUpdateTransform(ctxcanvas); // reset transform + sUpdateTransform(ctxcanvas); // reset transform ctxcanvas->dirty = 1; } @@ -1616,7 +1610,7 @@ static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) else ctxcanvas->canvas->invert_yaxis = 1; - if (cdwpSetTransform(ctxcanvas, transformMatrix, matrix)) + if (sAddTransform(ctxcanvas, transformMatrix, matrix)) ctxcanvas->graphics->SetTransform(&transformMatrix); } @@ -2691,7 +2685,7 @@ void cdwpUpdateCanvas(cdCtxCanvas* ctxcanvas) else set_aa_attrib(ctxcanvas, NULL); - cdwpUpdateTransform(ctxcanvas); + sUpdateTransform(ctxcanvas); } /* |