Use Color Processor for color bitmap text draws on gpu.
This change is here since previously color bitmap text was rendered using a
geometry processor in the coverage stage. The problem with this is that we
cannot correctly do xfer modes with this method. So I now make color bitmap text
draw using a color stage in the same was as a draw bitmap call.
One issue that arrises from this fix is that we end up adding this final color
processor after any previous color processors. Thus if we have a custom blend
implemented as a color processor it will be before this text one and we won't
blend correctly. This issue will get fixed once an xfer processor is fully
implemented. I have hacked a test locally to show that if we can add the text
color processor to the begining of the color stages we do blend correctly in all
cases (so the xfer processor will be a fix).
BUG=skia:
Review URL: https://codereview.chromium.org/689923004
diff --git a/gm/colortypexfermode.cpp b/gm/colortypexfermode.cpp
new file mode 100644
index 0000000..89656c4
--- /dev/null
+++ b/gm/colortypexfermode.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "gm.h"
+#include "SkBitmap.h"
+#include "SkGradientShader.h"
+#include "SkShader.h"
+#include "SkXfermode.h"
+#include "../src/fonts/SkGScalerContext.h"
+
+namespace skiagm {
+
+static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
+
+class ColorTypeXfermodeGM : public GM {
+ SkBitmap fBG;
+
+ virtual void onOnceBeforeDraw() SK_OVERRIDE {
+ fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType,
+ kOpaque_SkAlphaType), gData, 4);
+ }
+
+public:
+ const static int W = 64;
+ const static int H = 64;
+ ColorTypeXfermodeGM() {
+ const SkColor colors[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
+ SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW
+ };
+ SkMatrix local;
+ local.setRotate(180);
+ SkShader* s = SkGradientShader::CreateSweep(0,0, colors, NULL,
+ SK_ARRAY_COUNT(colors), 0, &local);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setShader(s)->unref();
+
+ SkTypeface* orig = sk_tool_utils::create_portable_typeface("Times",
+ SkTypeface::kBold);
+ if (NULL == orig) {
+ orig = SkTypeface::RefDefault();
+ }
+ fColorType = SkNEW_ARGS(SkGTypeface, (orig, paint));
+ orig->unref();
+ }
+
+ virtual ~ColorTypeXfermodeGM() {
+ fColorType->unref();
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("colortype_xfermodes");
+ }
+
+ virtual SkISize onISize() {
+ return SkISize::Make(400, 640);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+
+ const struct {
+ SkXfermode::Mode fMode;
+ const char* fLabel;
+ } gModes[] = {
+ { SkXfermode::kClear_Mode, "Clear" },
+ { SkXfermode::kSrc_Mode, "Src" },
+ { SkXfermode::kDst_Mode, "Dst" },
+ { SkXfermode::kSrcOver_Mode, "SrcOver" },
+ { SkXfermode::kDstOver_Mode, "DstOver" },
+ { SkXfermode::kSrcIn_Mode, "SrcIn" },
+ { SkXfermode::kDstIn_Mode, "DstIn" },
+ { SkXfermode::kSrcOut_Mode, "SrcOut" },
+ { SkXfermode::kDstOut_Mode, "DstOut" },
+ { SkXfermode::kSrcATop_Mode, "SrcATop" },
+ { SkXfermode::kDstATop_Mode, "DstATop" },
+
+ { SkXfermode::kXor_Mode, "Xor" },
+ { SkXfermode::kPlus_Mode, "Plus" },
+ { SkXfermode::kModulate_Mode, "Modulate" },
+ { SkXfermode::kScreen_Mode, "Screen" },
+ { SkXfermode::kOverlay_Mode, "Overlay" },
+ { SkXfermode::kDarken_Mode, "Darken" },
+ { SkXfermode::kLighten_Mode, "Lighten" },
+ { SkXfermode::kColorDodge_Mode, "ColorDodge" },
+ { SkXfermode::kColorBurn_Mode, "ColorBurn" },
+ { SkXfermode::kHardLight_Mode, "HardLight" },
+ { SkXfermode::kSoftLight_Mode, "SoftLight" },
+ { SkXfermode::kDifference_Mode, "Difference" },
+ { SkXfermode::kExclusion_Mode, "Exclusion" },
+ { SkXfermode::kMultiply_Mode, "Multiply" },
+ { SkXfermode::kHue_Mode, "Hue" },
+ { SkXfermode::kSaturation_Mode, "Saturation" },
+ { SkXfermode::kColor_Mode, "Color" },
+ { SkXfermode::kLuminosity_Mode, "Luminosity" },
+ };
+
+ const SkScalar w = SkIntToScalar(W);
+ const SkScalar h = SkIntToScalar(H);
+ SkMatrix m;
+ m.setScale(SkIntToScalar(6), SkIntToScalar(6));
+ SkShader* s = SkShader::CreateBitmapShader(fBG,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode,
+ &m);
+
+ SkPaint labelP;
+ labelP.setAntiAlias(true);
+ sk_tool_utils::set_portable_typeface(&labelP);
+ labelP.setTextAlign(SkPaint::kCenter_Align);
+
+ SkPaint textP;
+ textP.setAntiAlias(true);
+ textP.setTypeface(fColorType);
+ textP.setTextSize(SkIntToScalar(70));
+
+ const int W = 5;
+
+ SkScalar x0 = 0;
+ SkScalar y0 = 0;
+ SkScalar x = x0, y = y0;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
+ SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
+ SkAutoUnref aur(mode);
+ SkRect r;
+ r.set(x, y, x+w, y+h);
+
+ SkPaint p;
+ p.setStyle(SkPaint::kFill_Style);
+ p.setShader(s);
+ canvas->drawRect(r, p);
+
+ r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setShader(NULL);
+ canvas->drawRect(r, p);
+
+ textP.setXfermode(mode);
+ canvas->drawText("H", 1, x+ w/10.f, y + 7.f*h/8.f, textP);
+#if 1
+ canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
+ x + w/2, y - labelP.getTextSize()/2, labelP);
+#endif
+ x += w + SkIntToScalar(10);
+ if ((i % W) == W - 1) {
+ x = x0;
+ y += h + SkIntToScalar(30);
+ }
+ }
+ s->unref();
+ }
+
+ virtual uint32_t onGetFlags() const {
+ return kSkipPipe_Flag | kSkipPicture_Flag;
+ }
+
+private:
+ SkTypeface* fColorType;
+
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new ColorTypeXfermodeGM; }
+static GMRegistry reg(MyFactory);
+
+}