bug 473577 - make test plugin usable for reftests. r=josh
authorTed Mielczarek <ted.mielczarek@gmail.com>
Fri, 16 Jan 2009 15:03:24 -0500
changeset 23823 86c69da673eb2d764406ad8704a111df0437e96e
parent 23822 2de42ef0e5a907fe1e8dc9fc13ca19c7725077be
child 23824 786c7e01d14824f390176c776d57a5ebc1cf383e
push id4745
push usertmielczarek@mozilla.com
push dateFri, 16 Jan 2009 20:07:07 +0000
treeherdermozilla-central@86c69da673eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh
bugs473577
milestone1.9.2a1pre
bug 473577 - make test plugin usable for reftests. r=josh
layout/reftests/reftest.list
modules/plugin/test/reftest/div-sanity.html
modules/plugin/test/reftest/plugin-sanity.html
modules/plugin/test/reftest/reftest.list
modules/plugin/test/testplugin/nptest.cpp
modules/plugin/test/testplugin/nptest.h
modules/plugin/test/testplugin/nptest_macosx.mm
modules/plugin/test/testplugin/nptest_utils.cpp
modules/plugin/test/testplugin/nptest_utils.h
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -90,16 +90,19 @@ include object/reftest.list
 include ogg-video/reftest.list
 
 # percent-overflow-sizing/
 include percent-overflow-sizing/reftest.list
 
 # pixel-rounding/
 include pixel-rounding/reftest.list
 
+# plugin/
+include ../../modules/plugin/test/reftest/reftest.list
+
 # printing
 include printing/reftest.list
 include pagination/reftest.list
 
 # svg/
 include svg/reftest.list
 
 # svg-integration/
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/reftest/div-sanity.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html><head>
+<title>div boxes</title>
+<style>
+div {
+  width: 400px;
+  height: 400px;
+  display: inline-block;
+}
+</style>
+</head>
+<body>
+<div style="background-color: #FF0000;"></div> <!-- red   -->
+<div style="background-color: #00FF00;"></div> <!-- green -->
+<div style="background-color: #0000FF;"></div> <!-- blue  -->
+<div style="background-color: #999999;"></div> <!-- gray  -->
+</body></html>
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/reftest/plugin-sanity.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html><head>
+<title>Plugin boxes</title>
+</head>
+<body>
+<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FFFF0000"></embed> <!-- red -->
+<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF00FF00"></embed> <!-- green -->
+<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF0000FF"></embed> <!-- blue -->
+<embed type="application/x-test" width="400" height="400" drawmode="solid" color="FF999999"></embed> <!-- gray -->
+</body></html>
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/reftest/reftest.list
@@ -0,0 +1,3 @@
+# basic sanity checking
+random-if(!haveTestPlugin||MOZ_WIDGET_TOOLKIT!="cocoa") != plugin-sanity.html about:blank
+fails-if(!haveTestPlugin||MOZ_WIDGET_TOOLKIT!="cocoa") == plugin-sanity.html div-sanity.html
--- a/modules/plugin/test/testplugin/nptest.cpp
+++ b/modules/plugin/test/testplugin/nptest.cpp
@@ -230,16 +230,30 @@ NPP_New(NPMIMEType pluginType, NPP insta
   if (!scriptableObject) {
     printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n");
     return NPERR_GENERIC_ERROR;
   }
   NPN_RetainObject(scriptableObject);
   scriptableObject->npp = instance;
   instanceData->scriptableObject = scriptableObject;
 
+  scriptableObject->drawMode = DM_DEFAULT;
+  scriptableObject->drawColor = 0;
+
+  // handle extra params
+  for (int i = 0; i < argc; i++) {
+    if (strcmp(argn[i], "drawmode") == 0) {
+      if (strcmp(argv[i], "solid") == 0)
+        scriptableObject->drawMode = DM_SOLID_COLOR;    
+    }
+    else if (strcmp(argn[i], "color") == 0) {
+      scriptableObject->drawColor = parseHexColor(argv[i]);
+    }
+  }
+
   // do platform-specific initialization
   NPError err = pluginInstanceInit(instanceData);
   if (err != NPERR_NO_ERROR)
     return err;
 
   return NPERR_NO_ERROR;
 }
 
--- a/modules/plugin/test/testplugin/nptest.h
+++ b/modules/plugin/test/testplugin/nptest.h
@@ -35,18 +35,26 @@
 #define nptest_h_
 
 #include "mozilla-config.h"
 
 #include "npapi.h"
 #include "npfunctions.h"
 #include "npruntime.h"
 
+typedef enum  {
+  DM_DEFAULT,
+  DM_SOLID_COLOR
+} DrawMode;
+
 typedef struct TestNPObject : NPObject {
   NPP npp;
+  DrawMode drawMode;
+  // 0xAARRGGBB
+  PRUint32 drawColor;
 } TestNPObject;
 
 typedef struct InstanceData {
   NPP npp;
   NPWindow window;
   TestNPObject* scriptableObject;
 } InstanceData;
 
--- a/modules/plugin/test/testplugin/nptest_macosx.mm
+++ b/modules/plugin/test/testplugin/nptest_macosx.mm
@@ -55,113 +55,144 @@ pluginHandleEvent(InstanceData* instance
   EventRecord* carbonEvent = (EventRecord*)event;
   if (carbonEvent && (carbonEvent->what == updateEvt)) {
     pluginDraw(instanceData);
     return 1;
   }
   return 0;
 }
 
+static void 
+GetColorsFromRGBA(PRUint32 rgba, float* r, float* g, float* b, float* a)
+{
+  *b = (rgba & 0xFF) / 255.0;
+  *g = ((rgba & 0xFF00) >> 8) / 255.0;
+  *r = ((rgba & 0xFF0000) >> 16) / 255.0;
+  *a = ((rgba & 0xFF000000) >> 24) / 255.0;
+}
+
 void
 pluginDraw(InstanceData* instanceData)
 {
   if (!instanceData)
     return;
 
   NPP npp = instanceData->npp;
   if (!npp)
     return;
-
+  
   const char* uaString = NPN_UserAgent(npp);
   if (!uaString)
     return;
 
   NPWindow window = instanceData->window;
-
   CGContextRef cgContext = ((NP_CGContext*)(window.window))->context;
 
-  CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
-
   float windowWidth = window.width;
   float windowHeight = window.height;
 
-  // save the cgcontext gstate
-  CGContextSaveGState(cgContext);
+  switch(instanceData->scriptableObject->drawMode) {
+  case DM_DEFAULT: {
+    CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
+    // save the cgcontext gstate
+    CGContextSaveGState(cgContext);
 
-  // we get a flipped context
-  CGContextTranslateCTM(cgContext, 0.0, windowHeight);
-  CGContextScaleCTM(cgContext, 1.0, -1.0);
+    // we get a flipped context
+    CGContextTranslateCTM(cgContext, 0.0, windowHeight);
+    CGContextScaleCTM(cgContext, 1.0, -1.0);
 
-  // draw a gray background for the plugin
-  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
-  CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
-  CGContextDrawPath(cgContext, kCGPathFill);
+    // draw a gray background for the plugin
+    CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
+    CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
+    CGContextDrawPath(cgContext, kCGPathFill);
 
-  // draw a black frame around the plugin
-  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
-  CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
-  CGContextSetLineWidth(cgContext, 6.0);
-  CGContextStrokePath(cgContext);
+    // draw a black frame around the plugin
+    CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
+    CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
+    CGContextSetLineWidth(cgContext, 6.0);
+    CGContextStrokePath(cgContext);
 
-  // draw the UA string using ATSUI
-  CGContextSetGrayFillColor(cgContext, 0.0, 1.0);
-  ATSUStyle atsuStyle;
-  ATSUCreateStyle(&atsuStyle);
-  CFIndex stringLength = CFStringGetLength(uaCFString);
-  UniChar* unicharBuffer = (UniChar*)malloc((stringLength + 1) * sizeof(UniChar));
-  CFStringGetCharacters(uaCFString, CFRangeMake(0, stringLength), unicharBuffer);
-  UniCharCount runLengths = kATSUToTextEnd;
-  ATSUTextLayout atsuLayout;
-  ATSUCreateTextLayoutWithTextPtr(unicharBuffer,
-                                  kATSUFromTextBeginning,
-                                  kATSUToTextEnd,
-                                  stringLength,
-                                  1,
-                                  &runLengths,
-                                  &atsuStyle,
-                                  &atsuLayout);
-  ATSUAttributeTag contextTag = kATSUCGContextTag;
-  ByteCount byteSize = sizeof(CGContextRef);
-  ATSUAttributeValuePtr contextATSUPtr = &cgContext;
-  ATSUSetLayoutControls(atsuLayout, 1, &contextTag, &byteSize, &contextATSUPtr);
-  ATSUTextMeasurement lineAscent, lineDescent;
-  ATSUGetLineControl(atsuLayout,
-                     kATSUFromTextBeginning,
-                     kATSULineAscentTag,
-                     sizeof(ATSUTextMeasurement),
-                     &lineAscent,
-                     &byteSize);
-  ATSUGetLineControl(atsuLayout,
-                     kATSUFromTextBeginning,
-                     kATSULineDescentTag,
-                     sizeof(ATSUTextMeasurement),
-                     &lineDescent,
-                     &byteSize);
-  float lineHeight = FixedToFloat(lineAscent) + FixedToFloat(lineDescent);
-  ItemCount softBreakCount;
-  ATSUBatchBreakLines(atsuLayout,
-                      kATSUFromTextBeginning,
-                      stringLength,
-                      FloatToFixed(windowWidth - 10.0),
-                      &softBreakCount);
-  ATSUGetSoftLineBreaks(atsuLayout,
+    // draw the UA string using ATSUI
+    CGContextSetGrayFillColor(cgContext, 0.0, 1.0);
+    ATSUStyle atsuStyle;
+    ATSUCreateStyle(&atsuStyle);
+    CFIndex stringLength = CFStringGetLength(uaCFString);
+    UniChar* unicharBuffer = (UniChar*)malloc((stringLength + 1) * sizeof(UniChar));
+    CFStringGetCharacters(uaCFString, CFRangeMake(0, stringLength), unicharBuffer);
+    UniCharCount runLengths = kATSUToTextEnd;
+    ATSUTextLayout atsuLayout;
+    ATSUCreateTextLayoutWithTextPtr(unicharBuffer,
+                                    kATSUFromTextBeginning,
+                                    kATSUToTextEnd,
+                                    stringLength,
+                                    1,
+                                    &runLengths,
+                                    &atsuStyle,
+                                    &atsuLayout);
+    ATSUAttributeTag contextTag = kATSUCGContextTag;
+    ByteCount byteSize = sizeof(CGContextRef);
+    ATSUAttributeValuePtr contextATSUPtr = &cgContext;
+    ATSUSetLayoutControls(atsuLayout, 1, &contextTag, &byteSize, &contextATSUPtr);
+    ATSUTextMeasurement lineAscent, lineDescent;
+    ATSUGetLineControl(atsuLayout,
+                       kATSUFromTextBeginning,
+                       kATSULineAscentTag,
+                       sizeof(ATSUTextMeasurement),
+                       &lineAscent,
+                       &byteSize);
+    ATSUGetLineControl(atsuLayout,
+                       kATSUFromTextBeginning,
+                       kATSULineDescentTag,
+                       sizeof(ATSUTextMeasurement),
+                       &lineDescent,
+                       &byteSize);
+    float lineHeight = FixedToFloat(lineAscent) + FixedToFloat(lineDescent);
+    ItemCount softBreakCount;
+    ATSUBatchBreakLines(atsuLayout,
                         kATSUFromTextBeginning,
-                        kATSUToTextEnd,
-                        0, NULL, &softBreakCount);
-  UniCharArrayOffset* softBreaks = (UniCharArrayOffset*)malloc(softBreakCount * sizeof(UniCharArrayOffset));
-  ATSUGetSoftLineBreaks(atsuLayout,
-                        kATSUFromTextBeginning,
-                        kATSUToTextEnd,
-                        softBreakCount, softBreaks, &softBreakCount);
-  UniCharArrayOffset currentDrawOffset = kATSUFromTextBeginning;
-  unsigned int i = 0;
-  while (i < softBreakCount) {
-    ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
-    currentDrawOffset = softBreaks[i];
-    i++;
+                        stringLength,
+                        FloatToFixed(windowWidth - 10.0),
+                        &softBreakCount);
+    ATSUGetSoftLineBreaks(atsuLayout,
+                          kATSUFromTextBeginning,
+                          kATSUToTextEnd,
+                          0, NULL, &softBreakCount);
+    UniCharArrayOffset* softBreaks = (UniCharArrayOffset*)malloc(softBreakCount * sizeof(UniCharArrayOffset));
+    ATSUGetSoftLineBreaks(atsuLayout,
+                          kATSUFromTextBeginning,
+                          kATSUToTextEnd,
+                          softBreakCount, softBreaks, &softBreakCount);
+    UniCharArrayOffset currentDrawOffset = kATSUFromTextBeginning;
+    unsigned int i = 0;
+    while (i < softBreakCount) {
+      ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
+      currentDrawOffset = softBreaks[i];
+      i++;
+    }
+    ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
+    free(unicharBuffer);
+    free(softBreaks);
+
+    // restore the cgcontext gstate
+    CGContextRestoreGState(cgContext);
   }
-  ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
-  free(unicharBuffer);
-  free(softBreaks);
+  case DM_SOLID_COLOR: {
+    // save the cgcontext gstate
+    CGContextSaveGState(cgContext);
+
+    // we get a flipped context
+    CGContextTranslateCTM(cgContext, 0.0, windowHeight);
+    CGContextScaleCTM(cgContext, 1.0, -1.0);
+
+    // draw a solid background for the plugin
+    CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
 
-  // restore the cgcontext gstate
-  CGContextRestoreGState(cgContext);
+    float r,g,b,a;
+    GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a);
+    CGContextSetRGBFillColor(cgContext, r, g, b, a);
+    CGContextDrawPath(cgContext, kCGPathFill);
+
+    // restore the cgcontext gstate
+    CGContextRestoreGState(cgContext);
+    break;
+  }
+  }
 }
--- a/modules/plugin/test/testplugin/nptest_utils.cpp
+++ b/modules/plugin/test/testplugin/nptest_utils.cpp
@@ -78,8 +78,42 @@ NPIdentifier
 doubleVariantToIdentifier(NPVariant variant)
 {
   assert(NPVARIANT_IS_DOUBLE(variant));
   double value = NPVARIANT_TO_DOUBLE(variant);
   // sadly there is no "getdoubleidentifier"
   int32_t integer = static_cast<int32_t>(value);
   return NPN_GetIntIdentifier(integer);
 }
+
+/*
+ * Parse a color in hex format, like AARRGGBB
+ * If the string is short, portions to the left are assumed omitted.
+ * R G B default to 0, A defaults to 0xFF
+ */
+PRUint32
+parseHexColor(char* color)
+{
+  int len = strlen(color);
+  PRUint8 bgra[4] = { 0, 0, 0, 0xFF };
+  int i = 0;
+
+  // start from the right and work to the left
+  while (len > 0) {
+    char byte[3];
+    if (len > 1) {
+      // parse two hex digits
+      byte[0] = color[len - 2];
+      byte[1] = color[len - 1];
+    }
+    else {
+      // only one digit left
+      byte[0] = '0';
+      byte[1] = color[len - 1];
+    }
+    byte[2] = '\0';
+
+    bgra[i] = (PRUint8)(strtoul(byte, NULL, 16) & 0xFF);
+    i++;
+    len -= 2;
+  }
+  return (bgra[3] << 24) | (bgra[2] << 16) | (bgra[1] << 8) | bgra[0];
+}
--- a/modules/plugin/test/testplugin/nptest_utils.h
+++ b/modules/plugin/test/testplugin/nptest_utils.h
@@ -35,9 +35,11 @@
 
 NPUTF8* createCStringFromNPVariant(const NPVariant* variant);
 
 NPIdentifier variantToIdentifier(NPVariant variant);
 NPIdentifier stringVariantToIdentifier(NPVariant variant);
 NPIdentifier int32VariantToIdentifier(NPVariant variant);
 NPIdentifier doubleVariantToIdentifier(NPVariant variant);
 
+PRUint32 parseHexColor(char* color);
+
 #endif // nptest_utils_h_