テキストの構造とスタイル

Glass API では、シェイプや表のセルにテキストを含めることができます。テキストの操作やスタイル設定を行う前に、テキストの構造とスタイル設定の仕組みを理解しておく必要があります。

このページでは、Slides API でテキストがどのように表されるかについて説明します。

テキスト要素のシーケンス

シェイプまたは表のセルに含まれるテキストは、一連の TextElement 構造体で構成されます。このシーケンスは、テキストの構造を、始まりから終わりまで見える順に表します。

たとえば、このスライドの内容がすべて 1 つのテキスト ボックスに含まれているとします。

簡単なスライドのスクリーンショット

上のスライドにはテキスト ボックスが 1 つあり、その text フィールドには、次の図に示すように一連のテキスト要素が含まれています。

テキスト要素のシーケンスを示す図

具体的には、この一連のテキストは、Slides API では次のように表示されます。

"textElements": [ {
    "endIndex": 224,
    "paragraphMarker": { "style": {} }
  }, {
    "endIndex": 130,
    "textRun": { "content": "Li lingues differe in li grammatica e li vocabules. Omnicos directe al desirabilite de un nov ", "style": {} }
  }, {
    "endIndex": 143,
    "startIndex": 130,
    "textRun": { "content": "lingua franca", "style": { "italic": True } }
  }, {
    "endIndex": 224,
    "startIndex": 143,
    "textRun": { "content": ": solmen va esser necessi far:\n", "style": {} }
  }, {
    "endIndex": 243,
    "startIndex": 224,
    "paragraphMarker": {
      "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
      "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
  }, {
    "endIndex": 243,
    "startIndex": 224,
    "textRun": { "content": "uniform grammatica\n", "style": {} }
  }, {
    "endIndex": 257,
    "startIndex": 243,
    "paragraphMarker": {
        "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
        "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
}, {
    "endIndex": 257,
    "startIndex": 243,
    "textRun": { "content": "Pronunciation\n", "style": {} }
}, {
    "endIndex": 277,
    "startIndex": 257,
    "paragraphMarker": {
        "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
        "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
}, {
    "endIndex": 277,
    "startIndex": 257,
    "textRun": { "content": "plu sommun paroles.\n", "style": {} }
}, {
    "endIndex": 500,
    "startIndex": 277,
    "paragraphMarker": { "style": {} }
}, {
    "endIndex": 500,
    "startIndex": 277,
    "textRun": { "content": "Ka swu thefognay, tay waddeant varpa u inzo.\n", "style": {} }
}]

TextElement のコンテンツ

各テキスト要素には、ゼロから始まる開始インデックスと終了インデックスが含まれます。これらはページ要素のテキスト内での要素の位置を表し、次のいずれかの種類のテキスト オブジェクトと一緒に記述されます。

テキストの種類 説明
ParagraphMarker このテキスト要素は、新しい段落の始まりを表します。テキスト要素の開始インデックスと終了インデックスは、段落を終了する改行文字を含む、段落全体を表します。ある段落が他の段落と重なることはありません。段落は常に改行文字で終わるため、図形や表のセルのテキスト コンテンツの末尾には常に改行があります。

段落は、箇条書きまたは番号付きリストに含めることができます。その場合、ParagraphMarker.bullet フィールドの内容にリスト ID が含まれます。この ID は、TextElement シーケンスとともに TextContent 内に存在するリスト要素を参照します。同じ論理リスト内の段落は、同じリスト ID を参照します。
TextRun このテキスト要素は、すべてが同じテキスト スタイルを持つ、連続した文字列を表します。テキストは段落の境界をまたがることはありません。1 段落の終わりのテキストのスタイルが次の段落で始まるテキストと同じであっても、コンテンツは改行文字の後に分割され、別々のテキストが実行されます。

ページ要素内のテキスト文字列全体を処理する必要がある場合は、すべてのテキスト要素を反復処理して、すべてのテキスト実行で見つかった文字列を連結します。
AutoText 定型文とは、文脈に応じて動的に変化するテキスト内の場所を指します。スライドでは、現在のスライド番号をテキストで表すのに使用されます。

テキスト コンテンツの変更

Slides API を使用してテキストを変更する必要がある場合、適切なテキスト要素をすべて明示的に作成する必要はありません。代わりに、スライド エディタと同じようにテキストの操作を行うことができます。具体的には、テキストの挿入、範囲の削除、範囲のスタイルの更新を行います。これらのオペレーションでは、変更を反映するために、必要に応じて ParagraphMarker 要素と TextRun 要素が暗黙的に作成されます。

テキストの挿入

インデックスにテキストを挿入するには、batchUpdate の呼び出しで InsertTextRequest リクエストを使用します。このメソッドの insertionIndex フィールドは、テキストを挿入する場所を指定します。このインデックスは、テキスト要素内の開始インデックス フィールドと終了インデックス フィールドを使用して計算できます。

テキスト挿入には、スライド エディタの動作を反映する副作用があります。

  • 改行文字を挿入すると暗黙的に新しい段落が作成され、改行のインデックスで始まり次の改行で終わる ParagraphMarker テキスト要素が作成されます。箇条書きやリストの詳細を含む段落スタイルが、現在の段落から新しい段落にコピーされます。
  • 挿入される文字のスタイルは、自動的に決定されます。通常は、挿入インデックスに存在していたテキスト スタイルが維持されます。その結果、テキストは通常、そのインデックスの既存の TextRun に挿入されます。このスタイルは、UpdateTextStyle リクエストを使用して後で更新できます。

テキストを削除しています

テキストの範囲を削除するには、batchUpdate 呼び出しで DeleteTextRequest メッセージを使用します。テキストの削除には、次のような細かな特徴があります。

  • 段落の境界を越える削除では 2 つの段落が結合され、分離している ParagraphMarker テキスト要素が削除されます。
  • 結合された新しい段落では、スライド エディタの動作に合わせて、統合された段落スタイルが使用されます。
  • テキスト実行を含む範囲を削除すると、テキスト実行からすべてのコンテンツが削除され、テキスト実行自体も削除されます。
  • 範囲が AutoText 要素を含む削除では、AutoText 要素が削除されます。

テキスト スタイルを更新しています

スライド内のテキストのレンダリングの外観は、テキスト スタイルのプロパティによって決まります。

  • インデント、配置、箇条書きのグリフなどの段落スタイルは、段落マーカーのプロパティによって定義されます。
  • 太字、斜体、下線などの文字スタイルは、個々のテキスト実行のプロパティによって定義されます。

文字スタイルを更新しています

文字スタイルを更新するには、batchUpdate 呼び出しで UpdateTextStyleRequest メッセージを使用します。

他のテキスト処理と同様に、文字スタイルはテキストの範囲に適用され、必要に応じて新しい TextRun オブジェクトが暗黙的に作成されます。

一部の文字スタイルを設定すると、スライド エディタでの動作に合わせて、他の関連するスタイルが暗黙的に更新されます。たとえば、リンクを追加すると、テキストの前景の色と下線のプロパティが自動的に変更されます。詳しくは、TextStyle のリファレンス ドキュメントをご覧ください。

段落のスタイルを更新しています

段落のスタイルを更新するには、batchUpdate 呼び出しで UpdateParagraphStyleRequest メッセージを使用します。

Google スライド API では、スライド エディタの箇条書きプリセットの機能を反映した CreateParagraphBulletsRequest をサポートしています。これにより、箇条書きリストや番号付きリストを作成できます。同様に、DeleteParagraphBulletsRequest を使用すると、段落内の既存の箇条書きがすべて削除されます。

継承されるスタイル

「プレースホルダ」placeholdersと呼ばれる一部のシェイプは、他の親シェイプからテキスト スタイルを継承できます。シェイプの継承について詳しくは、placeholdersをご覧ください。

このセクションでは、スタイルの継承によってスライドに表示される最終的なテキスト スタイルが作成される仕組みについて説明します。

プレースホルダでのスタイル表現

親シェイプと子シェイプ間の継承の仕組みについては、placeholdersのセクションをご覧ください。テキスト スタイルの継承は、継承モデル内の追加機能によって処理されます。

  • ParagraphMaker のテキスト要素のプロパティは、段落の書式設定を定義します。
  • TextRun テキスト要素のプロパティは文字の書式設定を定義します。
  • 親プレースホルダのコンテンツには、このような ParagraphMarker と TextRun のペアが 8 個含まれています(8 レベルのリストのネストをサポート)。
  • 子プレースホルダは、親のテキスト コンテンツのこれらのテキスト要素からデフォルトのテキスト プロパティを継承します。

次の図は、これらの関係を可視化する 1 つの方法を示しています。

テキスト プロパティを継承する子シェイプの図

親シェイプの最初の ParagraphMarker と TextRun は、継承されるテキスト スタイル設定のほとんどを決定します。残りの 7 つのペアのスタイル設定は、段階的にネストされている箇条書きレベルの段落にのみ影響します。

親テキスト要素のペア 子書式が制御する項目
最初の ParagraphMarker
最初の TextRun
レベル 0(最も外側)のリスト段落とすべてのリスト以外の段落のテキスト スタイル。
第 2 ParagraphMarker
第 2 TextRun
残りの(ネストされた)リストレベル 1 ~ 7 のテキスト スタイル
第 3 ParagraphMarker
第 3 TextRun
第 4 ParagraphMarker
第 4 TextRun
5 日 ParagraphMarker
5 日 TextRun
6 日 ParagraphMarker
6 日 TextRun
7 日ParagraphMarker
7 TextRun
8 回目ParagraphMarker
8 回目のTextRun

これらのテキスト要素のペアにアクセスするには、以下のスニペットに示すように、textElements フィールド内で明示的なインデックスを使用します。この例では、レベル 0 とリスト以外の段落にデフォルトの(継承可能な)スタイルを設定しています。

"text": {
  "textElements": [  {
     "startIndex": 0,
     "endIndex": 1,
     "paragraphMarker": {
       "style": {  "alignment": "START",  ...  },
       "bullet": {  "nestingLevel": 0,  ...  }
     }
   },{
     "startIndex": 0,
     "endIndex": 1,
     "textRun": {
       "content": "\n",
       "style": {  "foregroundColor": {  "opaqueColor": {  "themeColor": "DARK1"  }  },  }
     }
   },{
     ...
   } ]
 }

親シェイプの TextRuncontent フィールドは、常に 1 つの改行文字で構成されます。

継承されたスタイルはオーバーライドできます

子シェイプでは、そのコンテンツ内の ParagraphMarker 要素と TextRun 要素のスタイル設定プロパティを指定できます。ローカルに指定されたこれらのプロパティは、ローカル スコープ内で継承されたプロパティをオーバーライドします。スタイルが指定されていない要素は、親から継承された対応するスタイルを使用します。

子シェイプから明示的なスタイル プロパティを削除して設定を解除すると、プロパティは親から継承されます。

上の図の継承について、シェイプ ParentPlaceholder に次のテキスト コンテンツがあるとします。

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {"alignment": "START", ...},
        "bullet": {"nestingLevel": 0, ...}
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, }
        ...
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {"alignment": "END", ...},
        "bullet": {"nestingLevel": 1, ...}
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "LIGHT1"} }, ...}
      }
    },
   ...
  ]
}

また、シェイプ ChildPlaceholder に次のテキスト コンテンツがあるとします。

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {},
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "This is my first paragraph\n",
        "style": {},
      }
      ...
    },
    {  "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {},
        "bullet": {
          "nestingLevel": 1,
          "listId": "someListId",
          "glyph": "●"
        }
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "This paragraph is in a list\n",
        "style": {},
        ...
      }
    }
  ]
}

その結果として、以下の段落で説明します。

シンプルな段落のスタイルの継承

「This is my first paragraph」というテキストを含む子シェイプの最初の段落は、(リストにない)シンプルな段落です。テキスト コンテンツのどの要素にもスタイル プロパティが指定されていないため、文字と段落のスタイルはすべて親から継承されます。これにより、次のレンダリングが行われます。

  • テキスト: 「これは最初の段落です」は、レンダリングされたテキストです。テキスト自体が継承されることはありません。
  • 位置揃え: テキストは、親の最初の ParagraphMarker から継承された START 位置揃えでレンダリングされます。
  • 前景色: 親の最初の TextRun から継承した DARK1 前景色でテキストがレンダリングされます。

リストの段落のスタイルの継承

「この段落はリストにあります」というテキストを含む次の段落は、ネストレベル 1 の箇条書きリストにあります。これは、対応する ParagraphMarkerbullet フィールドがこのレベルに設定されているためです。その結果、親のネストレベル 1 からテキストと段落のスタイルを継承します。これにより、次のレンダリングになります。

  • テキスト: 「この段落はリストにあります」は、レンダリングされたテキストです。テキスト自体が継承されることはありません。
  • 配置: テキストは、親の 2 番目の ParagraphMarker から継承された「END」配置でレンダリングされます。
  • 前景色: 親の 2 番目の TextRun から継承した LIGHT1 テキストの前景色で、テキストがレンダリングされます。

テキストと段落のスタイルの更新と継承の相互関係

子シェイプで設定されていないテキスト スタイルは、親から値を継承します。子内で設定されたテキスト スタイルは、一部のローカル スコープ内の親値を「オーバーライド」します。

UpdateTextStyleRequest を使用して子シェイプのテキスト スタイルの設定を解除すると、子シェイプはローカルでオーバーライドされなくなり、親シェイプからシルトを継承します。また、子のテキスト スタイルを親から継承した値に合わせて更新すると、スタイルが暗黙的に解除され、継承された値が使用されます。

更新直後のテキストの外観には影響ありませんが、後で親プレースホルダの段落やテキスト スタイルを更新する場合は、これが重要になります。この継承動作はスライド エディタの動作と一致しているため、API を使用する前に、スタイルの変更による影響をテストできます。

前の例で、ChildPlaceholderParentPlaceholder の定義について考えてみましょう。

次の UpdateTextStyleRequest を送信したとします。

{ "updateTextStyle": {
    "objectId": "ChildPlaceholder",
    "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
    "textRange": { "type": "ALL" },
    "fields": "foregroundColor"
  }
}

このリクエストでは、DARK1 foregroundColor をすべての ChildPlaceholder のテキストに設定しようとします。その際、フィールド マスクを使用して、要素の前景の色のみを変更するように指定します。このリクエストの結果は次のとおりです。

  • 最初の段落: 新しい foregroundColor は継承された foregroundColor と一致するため、このスタイルは変更されず、引き続き継承されます。
  • 2 番目の段落: 新しい foregroundColor は継承された foregroundColor と一致しないため、2 番目の段落の前景の色は DARK1 に更新されます。

ChildPlaceholder のテキスト コンテンツは次のようになります。

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {},
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "This is my first paragraph\n",
        "style": {},
      }
      ...
    },
    { "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {},
        "bullet": {"nestingLevel": 1, "listId": "someListId", "glyph": "●" }
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "This paragraph is in a list\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
        ...
      }
    }
  ]
}

箇条書きグリフのテキスト スタイル

標準テキストと同様に、箇条書きのグリフには、グリフのレンダリング方法を制御するテキスト スタイルがあります。これらのテキスト スタイルは、Slides API を使用して直接変更することはできません。ただし、UpdateTextStyleRequest を使用して箇条書きを含む段落全体を更新すると、Slides API によって箇条書きグリフのテキスト スタイルがそれに応じて更新されます。

箇条書きグリフのテキスト スタイルは、通常のテキスト スタイルとは若干異なる継承階層に従います。

  1. 特定のネスト レベルの箇条書きは、まず、箇条書きの List オブジェクト内の NestingLevel.bullet_style フィールドに設定されている TextStyle を継承します。
  2. 次に、親プレースホルダの List で、対応する NestingLevel.bullet_style を継承します。
  3. 最後に、残りの親プレースホルダ オブジェクトから継承しようとします。