How to I find out if a text element in PDF is filled or stroked?

Q: Starting from your ElementEdit sample, I am trying to edit an
existing PDF document by changing all color spaces and all colorant to
gray (i.e. I want to change the entire colro PDF to grayscale PDF).
For some reason IsStroked()/IsFilled() is not working for text. How to
I find out if a text element is filled/stroked ? I develop in C++.

#include <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <PDF/ElementWriter.h>
#include <PDF/ElementReader.h>
#include <PDF/Element.h>
#include <PDF/Font.h>
#include <Filters/FilterReader.h>
#include <PDF/Image/Image2RGB.h>

#include <iostream>
#include <assert.h>

using namespace std;

using namespace pdftron;
using namespace PDF;
using namespace SDF;
using namespace Common;
using namespace Filters;

char m_buf[4000];

int main(int argc, char *argv[])
{
      int ret = 0;
      PDFNet::Initialize();
      PDFNet::SetResourcesPath("../../../resources");

      // Relative path to the folder containing test files.
      string input_path = "../../TestFiles/";
      string output_path = "../../TestFiles/Output/";

      try
      {
            PDFDoc doc((input_path + "foo.pdf").c_str());
            doc.InitSecurityHandler();

            int num_pages = doc.GetPageCount();

            ElementWriter writer;
            ElementReader reader;
            Element element;

            for(int i=1; i<=num_pages; ++i)
            {
                  PageIterator itr = doc.GetPageIterator(i);
                  Page page = itr.Current();
                  reader.Begin(page);

                  Page new_page = doc.PageCreate();
                  PageIterator next_page = itr;
                  next_page.Next();
                  doc.PageInsert(next_page, new_page );

                  writer.Begin(new_page);
                  while (element = reader.Next()) // Read page
contents
                  {
                        GState gs;
                        switch(element.GetType())
                        {
                        case Element::e_path:
                             if(element.IsFilled())
                             {
                                   gs = element.GetGState();
                                   ColorSpace cs = gs.GetFillColorSpace
();
                                   if(cs.GetType() !=
ColorSpace::e_device_gray)
                                   {
                                         ColorPt in = gs.GetFillColor
();
                                         ColorPt out;
                                         cs.Convert2Gray(in,out);
                                         gs.SetFillColorSpace
(ColorSpace::CreateDeviceGray());
                                         gs.SetFillColor(out);
                                   }
                             }
                             if(element.IsStroked())
                             {
                                   gs = element.GetGState();
                                   ColorSpace cs =
gs.GetStrokeColorSpace();
                                   if(cs.GetType() !=
ColorSpace::e_device_gray)
                                   {
                                         ColorPt in = gs.GetStrokeColor
();
                                         ColorPt out;
                                         cs.Convert2Gray(in,out);
                                         gs.SetStrokeColorSpace
(ColorSpace::CreateDeviceGray());
                                         gs.SetStrokeColor(out);
                                   }
                             }
                             break;
                        case Element::e_text:
                             if(element.IsFilled())
                             {
                                   gs = element.GetGState();
                                   ColorSpace cs = gs.GetFillColorSpace
();
                                   if(cs.GetType() !=
ColorSpace::e_device_gray)
                                   {
                                         ColorPt in = gs.GetFillColor
();
                                         ColorPt out;
                                         cs.Convert2Gray(in,out);
                                         gs.SetFillColorSpace
(ColorSpace::CreateDeviceGray());
                                         gs.SetFillColor(out);
                                   }
                             }
                             if(element.IsStroked())
                             {
                                   gs = element.GetGState();
                                   ColorSpace cs =
gs.GetStrokeColorSpace();
                                   if(cs.GetType() !=
ColorSpace::e_device_gray)
                                   {
                                         ColorPt in = gs.GetStrokeColor
();
                                         ColorPt out;
                                         cs.Convert2Gray(in,out);
                                         gs.SetStrokeColorSpace
(ColorSpace::CreateDeviceGray());
                                         gs.SetStrokeColor(out);
                                   }
                             }
                             break;
                        }
                        //else if (element.GetType() ==
Element::e_image)
                        //{
                        // // remove all images
                        // continue;
                        //}

                        writer.WriteElement(element);
                  }

                  writer.End();
                  reader.End();
                  new_page.SetMediaBox(page.GetCropBox());
                  doc.PageRemove(doc.GetPageIterator(i));
            }

            doc.Save((output_path + "MA015RM.pdf").c_str(),
SDFDoc::e_remove_unused , 0);
            // doc.Save((output_path + "newsletter_edited.pdf").c_str
(), Doc::e_linearized , 0);
            cout << "Done. Result saved in newsletter_edited.pdf..."
<< endl;
      }
      catch(Common::Exception& e)
      {
            cout << e << endl;
            ret = 1;
      }
      catch(...)
      {
            cout << "Unknown Exception" << endl;
            ret = 1;
      }

      PDFNet::Terminate();
      return ret;
}
-------
A: To find out if a text text element is filled, stroked, or clipped
use GetTextRenderingMode() in the graphics state. IsFiled()/IsStroked
() methods apply only to path elements.

case Element::e_text:
  {
    bool is_clipped, is_stroked, is_filled;
    GState::TextRenderingMode tr = gs->GetTextRenderMode();
    if (tr == GState::e_invisible_text) continue;
    switch (tr)
    {
    case GState::e_clip_text :
      is_clipped = true;
      is_stroked = false;
      is_filled = false;
      break;
    case GState::e_fill_clip_text:
      is_clipped = true;
      is_stroked = false;
      is_filled = true;
      break;
    case GState::e_fill_stroke_clip_text:
      is_clipped = true;
      is_stroked = true;
      is_filled = true;
      break;
    case GState::e_fill_stroke_text:
      is_stroked = true;
      is_filled = true;
      break;
    case GState::e_fill_text:
      is_stroked = false;
      is_filled = true;
      break;
    case GState::e_stroke_clip_text:
      is_clipped = true;
      is_stroked = true;
      is_filled = false;
      break;
    case GState::e_stroke_text:
      is_stroked = true;
      is_filled = false;
      break;
    default: assert(false);
    }

    if(is_filled)
    {
      gs = element->GetGState();
      ColorSpace cs = gs->GetFillColorSpace();
      if(cs.GetType() != ColorSpace::e_device_gray)
      {
        ColorPt in = gs->GetFillColor();
        ColorPt out;
        cs.Convert2Gray(in,out);
        gs->SetFillColorSpace(ColorSpace::CreateDeviceGray());
        gs->SetFillColor(out);
      }
    }
    if(is_stroked)
    {
      gs = element->GetGState();
      ColorSpace cs = gs->GetStrokeColorSpace();
      if(cs.GetType() != ColorSpace::e_device_gray)
      {
        ColorPt in = gs->GetStrokeColor();
        ColorPt out;
        cs.Convert2Gray(in,out);
        gs->SetStrokeColorSpace(ColorSpace::CreateDeviceGray());
        gs->SetStrokeColor(out);
      }
    }
  }
  break;
}